From 5fc2a6d40c91e6f7e2d86a60fcdc25e611785ab5 Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Wed, 11 Mar 2020 09:58:24 +0000 Subject: [PATCH 001/303] Printing numeric format --- app/models/asset.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index c3f53e79..e1d72fc5 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -174,6 +174,18 @@ def study_name return '' end + def machine_barcode? + asset.facts.where(predicate: 'barcodeFormat', object: 'machine_barcode').count > 0 + end + + def barcode_formatted_for_printing + if machine_barcode? + mbarcode = SBCF::SangerBarcode.from_human(barcode).machine_barcode + return mbarcode if mbarcode + end + barcode + end + def printable_object(username = 'unknown') return nil if barcode.nil? if (kind_of_plate?) @@ -188,8 +200,8 @@ def printable_object(username = 'unknown') } end return {:label => { - :barcode => barcode, - :barcode2d => barcode, + :barcode => barcode_formatted_for_printing, + :barcode2d => barcode_formatted_for_printing, :top_line => barcode, :middle_line => kit_type, :bottom_line => info_line From a540618ffcbc99f26661bf12fbda76835907947d Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Wed, 11 Mar 2020 10:42:57 +0000 Subject: [PATCH 002/303] Print machine barcode when barcodeFormat=machine_barcode --- app/models/asset.rb | 2 +- spec/models/asset_spec.rb | 78 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index e1d72fc5..a8b7fad9 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -175,7 +175,7 @@ def study_name end def machine_barcode? - asset.facts.where(predicate: 'barcodeFormat', object: 'machine_barcode').count > 0 + facts.where(predicate: 'barcodeFormat', object: 'machine_barcode').count > 0 end def barcode_formatted_for_printing diff --git a/spec/models/asset_spec.rb b/spec/models/asset_spec.rb index d110bbb3..6c9b72b6 100644 --- a/spec/models/asset_spec.rb +++ b/spec/models/asset_spec.rb @@ -26,6 +26,84 @@ end end + context '#machine_barcode?' do + let(:asset) { create(:asset)} + it 'returns true when the asset has a barcode format of machine barcode' do + asset.facts << create(:fact, predicate: 'barcodeFormat', object: 'machine_barcode', + literal: true) + expect(asset.machine_barcode?).to be_truthy + end + it 'returns false when the asset does not have a setting' do + expect(asset.machine_barcode?).to be_falsy + end + end + + context '#barcode_formatted_for_printing' do + let(:human_barcode) { "EG1234E" } + let(:machine_barcode) { 1420001234690 } + let(:asset) { create(:asset, barcode: human_barcode)} + + context 'when no specific barcode format has been selected' do + it 'returns the human barcode' do + expect(asset.barcode_formatted_for_printing).to eq(human_barcode) + end + end + context 'when machine barcode has been selected' do + before do + asset.facts << create(:fact, predicate: 'barcodeFormat', object: 'machine_barcode', + literal: true) + end + context 'when we can generate the machine barcode' do + it 'returns the machine barcode' do + expect(asset.barcode_formatted_for_printing).to eq(machine_barcode) + end + end + end + end + + context '#printable_object' do + let(:human_barcode) { "EG1234E" } + let(:machine_barcode) { 1420001234690 } + let(:asset) { create(:asset, barcode: human_barcode)} + + context 'when is a plate' do + before do + asset.facts << create(:fact, predicate: 'a', object: 'Plate', literal: true) + end + it 'generates a plate printable object' do + expect(asset.printable_object[:label].has_key?(:top_left)) + end + end + context 'when is a tube' do + before do + asset.facts << create(:fact, predicate: 'a', object: 'Tube', literal: true) + end + it 'generates a tube printable object' do + expect(asset.printable_object[:label].has_key?(:barcode2d)) + end + context 'when no machine barcode has been selected' do + it 'generates a tube printable object' do + expect(asset.printable_object[:label].has_key?(:barcode2d)) + end + end + context 'when machine barcode has been selected' do + before do + asset.facts << create(:fact, predicate: 'barcodeFormat', + object: 'machine_barcode', literal: true) + end + it 'prints the human barcode in the top line' do + expect(asset.printable_object[:label][:top_line]).to eq(human_barcode) + end + it 'prints the machine barcode as barcode' do + expect(asset.printable_object[:label][:barcode]).to eq(machine_barcode) + end + it 'prints the machine barcode as barcode 2d' do + expect(asset.printable_object[:label][:barcode2d]).to eq(machine_barcode) + end + end + end + end + context '#study_name' do let(:study) { 'A STUDY'} context 'if it is a tube' do From d6bcf217d23032028cf2161eff2a6a5a2f5603ae Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Wed, 11 Mar 2020 12:19:23 +0000 Subject: [PATCH 003/303] Removed readme readded --- README.md | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 47a2f01c..85e3d4ca 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,111 @@ A workflow processor and management tool supported in metadata annotations that - Redis - Mysql -## To start: +## Installation + +## Setup a development environment in local + +This installation procedure is prepared for a MacOS environment: + +### Redis + +1. Install redis as we will need it (for example, using Homebrew): + +``` + # brew install redis +``` + +2. Start redis + +``` + # redis-server +``` + + +### Print_my_barcode config + +1. Add the barcode printers that you would like to use in the server. In a MacOS environment open Settings/Printers & Scanners and add the barcode printers making sure they are defined with protocol LPD. + +2. In the rails console, run the following command to add the printer we require into the database: + +``` + > Printer.create(name: PRINTER_NAME) +``` + +3. In print_my_barcode folder, start the server + +``` + # rails s -p10000 +``` + +4. In Samples Extraction project folder, run the following command to create the required label templates into print_my_barcode: + +```bash + # rake label_templates:setup +``` + +### mysql + +1. Start the server + +``` + # mysql.server start +``` + +### Sequencescape + +1. Start the delayed jobs: + +``` + # rake jobs:work +``` + +2. Start the Sequencescape server: + +``` + # rails s +``` + +### Samples extraction config + +1. Install all the dependencies for the project + +``` + # gem install bundler + + # bundle install + + # bundle exec rake db:setup + + # yarn +``` + +2. From the project folder, run the command + +``` + # rake secret +``` + +3. Copy the resulting string and create a config/secrets.yml file and paste the string as value from secret_key_base attribute: + +``` +development: + secret_key_base: +``` + +4. Run the delayed job for Samples extraction + +``` + # rake jobs:work +``` + +5. Run the server in a different port than the other services + +``` + # rails s -p9000 +``` + +## Starting procedure: First, start all the required service applications and configure their endpoints by defining the following environment variables: @@ -137,6 +241,14 @@ A set of controls is provided so the user can perform the following actions: Changes are broadcasted to the user interface by websockets with the support of a Redis database. The interface is updated with the changes in the database. All changes in available groups, assets, metadata and rules to apply are updated in the user interface automatically. +To do it, the browser joins a websockets channel that is broadcasting from the specific activity it is being displayed. It can emit 2 different types of messages to the channel: + + - AssetGroup message : this message modifies the contents of the asset group. It is sent whenever the user changes the contents of the asset group in the UI. + - Activity message: this message modifies the selected information that is returned by a server update. It is sent when the user clicks on Show/Hide links. + +The server can emit 1 type of message into the channel: + + - Activity React state message : this message renders the UI state as it should be displayed by React. It is sent every time the activity updated_at timestamp has changed (when the activity is saved). #### Data model: From a661c48c4b89d5b6a4c59f82a900888338960fc8 Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Wed, 11 Mar 2020 12:23:14 +0000 Subject: [PATCH 004/303] Readme with install/start instructions --- README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.md b/README.md index 85e3d4ca..daf5b159 100644 --- a/README.md +++ b/README.md @@ -241,15 +241,6 @@ A set of controls is provided so the user can perform the following actions: Changes are broadcasted to the user interface by websockets with the support of a Redis database. The interface is updated with the changes in the database. All changes in available groups, assets, metadata and rules to apply are updated in the user interface automatically. -To do it, the browser joins a websockets channel that is broadcasting from the specific activity it is being displayed. It can emit 2 different types of messages to the channel: - - - AssetGroup message : this message modifies the contents of the asset group. It is sent whenever the user changes the contents of the asset group in the UI. - - Activity message: this message modifies the selected information that is returned by a server update. It is sent when the user clicks on Show/Hide links. - -The server can emit 1 type of message into the channel: - - - Activity React state message : this message renders the UI state as it should be displayed by React. It is sent every time the activity updated_at timestamp has changed (when the activity is saved). - #### Data model: ```text From b117e03936373a4be9120b53d001849f858a25c6 Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Wed, 11 Mar 2020 13:39:24 +0000 Subject: [PATCH 005/303] Docker config --- .github/workflows/docker.yml | 3 +-- Dockerfile | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 24ae0a98..f368baac 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -4,10 +4,9 @@ on: branches: - develop - master - - release-2.0.8-docker env: - IMAGE_NAME: ${{ github.repository }}/latest + IMAGE_NAME: ${{ github.repository }}/${{ github.event.repository.name }} jobs: build_and_publish: diff --git a/Dockerfile b/Dockerfile index 7ec31d38..095bea65 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,6 @@ FROM starefossen/ruby-node RUN apt-get update -qq && apt-get install -y +RUN apt-get -y install git vim WORKDIR /samples_extraction ADD Gemfile /samples_extraction ADD Gemfile.lock /samples_extraction @@ -8,7 +9,7 @@ ADD yarn.lock /samples_extraction RUN gem install bundler RUN bundle install RUN yarn install -RUN apt-get -y install git vim + ADD . /samples_extraction/ # Compiling assets @@ -19,4 +20,3 @@ RUN RAILS_ENV=production bundle exec rake webpacker:compile RUN git rev-parse HEAD > REVISION RUN git tag -l --points-at HEAD --sort -version:refname | head -1 > TAG RUN git rev-parse --abbrev-ref HEAD > BRANCH - From acd1b5f9649486fcf8f9b83954be4e792c11f10a Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Wed, 11 Mar 2020 14:25:09 +0000 Subject: [PATCH 006/303] Generate docker image on tag --- .github/workflows/docker.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index f368baac..92472c81 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -4,6 +4,10 @@ on: branches: - develop - master + tags: + - release-* + - uat-* + - dev-* env: IMAGE_NAME: ${{ github.repository }}/${{ github.event.repository.name }} From fbd934469c9523059bb4c51d45ea7b4bd3725424 Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Wed, 11 Mar 2020 14:27:09 +0000 Subject: [PATCH 007/303] Test cache for docker --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 92472c81..66354e50 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -25,7 +25,7 @@ jobs: path: /var/lib/docker key: ${{ runner.os }}-docker-${{ hashFiles('Dockerfile') }} restore-keys: | - ${{ runner.os }}-docker- + ${{ runner.os }}-docker-${{ hashFiles('Dockerfile') }} - name: Build and tag the Docker image run: docker build . --file Dockerfile --tag docker.pkg.github.com/${IMAGE_NAME}:${GITHUB_REF##*/} - name: Tag (latest) the Docker image From 3307c7b048767f9c0417ccbc9974da53a02861e7 Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Thu, 12 Mar 2020 11:01:08 +0000 Subject: [PATCH 008/303] Before printing barcodes, convert to the right format depending on how it was originally stored. --- app/models/asset.rb | 8 +++---- lib/token_util.rb | 24 +++++++++++++++++++ spec/lib/token_util_spec.rb | 48 +++++++++++++++++++++++++++++++++++++ spec/models/asset_spec.rb | 12 +++++----- 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index a8b7fad9..20c36afd 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -174,13 +174,13 @@ def study_name return '' end - def machine_barcode? + def print_machine_barcode? facts.where(predicate: 'barcodeFormat', object: 'machine_barcode').count > 0 end def barcode_formatted_for_printing - if machine_barcode? - mbarcode = SBCF::SangerBarcode.from_human(barcode).machine_barcode + if print_machine_barcode? + mbarcode = TokenUtil.machine_barcode(barcode) return mbarcode if mbarcode end barcode @@ -202,7 +202,7 @@ def printable_object(username = 'unknown') return {:label => { :barcode => barcode_formatted_for_printing, :barcode2d => barcode_formatted_for_printing, - :top_line => barcode, + :top_line => TokenUtil.human_barcode(barcode), :middle_line => kit_type, :bottom_line => info_line } diff --git a/lib/token_util.rb b/lib/token_util.rb index 7a07421d..b0f50366 100644 --- a/lib/token_util.rb +++ b/lib/token_util.rb @@ -7,6 +7,30 @@ def self.fluidx_barcode_prefix 'F' end + def self.MACHINE_BARCODE + /^\d*$/ + end + + def self.machine_barcode?(barcode) + return false if barcode.nil? + barcode.to_s.match?(TokenUtil.MACHINE_BARCODE) + end + + def self.human_barcode?(barcode) + return false if barcode.nil? + !barcode.to_s.match?(TokenUtil.MACHINE_BARCODE) + end + + def self.machine_barcode(barcode) + return barcode.to_s if machine_barcode?(barcode) + SBCF::SangerBarcode.from_human(barcode).machine_barcode.to_s + end + + def self.human_barcode(barcode) + return SBCF::SangerBarcode.from_machine(barcode).human_barcode if machine_barcode?(barcode) + barcode + end + def self.WILDCARD_REGEXP /\?\w*/ end diff --git a/spec/lib/token_util_spec.rb b/spec/lib/token_util_spec.rb index b7ab2891..a078ed71 100644 --- a/spec/lib/token_util_spec.rb +++ b/spec/lib/token_util_spec.rb @@ -97,4 +97,52 @@ end end end + + context '#machine_barcode' do + it 'returns the barcode to_s if the barcode is already machine barcode' do + expect(TokenUtil.machine_barcode(3981337734769)).to eq("3981337734769") + end + it 'returns the barcode if the barcode is already machine barcode' do + expect(TokenUtil.machine_barcode("3981337734769")).to eq("3981337734769") + end + it 'returns the converted barcode if is not a machine barcode' do + expect(TokenUtil.machine_barcode("NT1337734L")).to eq("3981337734769") + end + end + + context '#human_barcode' do + it 'returns the human barcode if the barcode is already human barcode' do + expect(TokenUtil.human_barcode("D12345678")).to eq("D12345678") + end + it 'returns the converted barcode from numeric machine barcode' do + expect(TokenUtil.human_barcode(3981337734769)).to eq("NT1337734L") + end + it 'returns the converted barcode from string machine barcode' do + expect(TokenUtil.human_barcode("3981337734769")).to eq("NT1337734L") + end + end + + context '#machine_barcode?' do + it 'returns true if the barcode is machine barcode numeric' do + expect(TokenUtil.machine_barcode?(12345678)).to eq(true) + end + it 'returns true if the barcode is machine barcode string' do + expect(TokenUtil.machine_barcode?("12345678")).to eq(true) + end + it 'returns false any other case' do + expect(TokenUtil.machine_barcode?("D12345678")).to eq(false) + end + end + + context '#human_barcode?' do + it 'returns true if the barcode is human barcode' do + expect(TokenUtil.human_barcode?("D12345678")).to eq(true) + end + it 'returns false if machine barcode numeric' do + expect(TokenUtil.human_barcode?(12345678)).to eq(false) + end + it 'returns false if machine barcode string' do + expect(TokenUtil.human_barcode?("12345678")).to eq(false) + end + end end diff --git a/spec/models/asset_spec.rb b/spec/models/asset_spec.rb index 6c9b72b6..b21e19a0 100644 --- a/spec/models/asset_spec.rb +++ b/spec/models/asset_spec.rb @@ -26,15 +26,15 @@ end end - context '#machine_barcode?' do + context '#print_machine_barcode?' do let(:asset) { create(:asset)} it 'returns true when the asset has a barcode format of machine barcode' do asset.facts << create(:fact, predicate: 'barcodeFormat', object: 'machine_barcode', literal: true) - expect(asset.machine_barcode?).to be_truthy + expect(asset.print_machine_barcode?).to be_truthy end it 'returns false when the asset does not have a setting' do - expect(asset.machine_barcode?).to be_falsy + expect(asset.print_machine_barcode?).to be_falsy end end @@ -55,7 +55,7 @@ end context 'when we can generate the machine barcode' do it 'returns the machine barcode' do - expect(asset.barcode_formatted_for_printing).to eq(machine_barcode) + expect(asset.barcode_formatted_for_printing).to eq(machine_barcode.to_s) end end end @@ -95,10 +95,10 @@ expect(asset.printable_object[:label][:top_line]).to eq(human_barcode) end it 'prints the machine barcode as barcode' do - expect(asset.printable_object[:label][:barcode]).to eq(machine_barcode) + expect(asset.printable_object[:label][:barcode]).to eq(machine_barcode.to_s) end it 'prints the machine barcode as barcode 2d' do - expect(asset.printable_object[:label][:barcode2d]).to eq(machine_barcode) + expect(asset.printable_object[:label][:barcode2d]).to eq(machine_barcode.to_s) end end end From e1272a469acb111950ea5ddaf01cd28e7ee10b34 Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Thu, 12 Mar 2020 11:50:11 +0000 Subject: [PATCH 009/303] Convert barcodes to human barcode if input is machine barcode --- app/models/assets/import.rb | 1 + .../asset_groups_controller_spec.rb | 2 +- spec/models/assets/import_spec.rb | 18 +++++++++--------- test/factories/barcode_creatable.rb | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index a87017b9..ee0cf80e 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -195,6 +195,7 @@ def find_asset_with_barcode(barcode) end def find_or_import_asset_with_barcode(barcode) + barcode = TokenUtil.human_barcode(barcode) if TokenUtil.machine_barcode?(barcode) find_asset_with_barcode(barcode) || import_barcode(barcode) end diff --git a/spec/controllers/asset_groups_controller_spec.rb b/spec/controllers/asset_groups_controller_spec.rb index 7b4c04d5..abb6f625 100644 --- a/spec/controllers/asset_groups_controller_spec.rb +++ b/spec/controllers/asset_groups_controller_spec.rb @@ -55,7 +55,7 @@ end context "when the asset is not in the database" do - let(:barcode) { '1234' } + let(:barcode) { generate :barcode } let(:uuid) { SecureRandom.uuid } let(:SequencescapeClient) { double('sequencescape_client')} let(:remote_asset) { build_remote_tube(barcode: barcode, uuid: uuid) } diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 9d58f2a2..5986dd4d 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -140,7 +140,7 @@ end context 'when importing a local asset' do setup do - @barcode_plate = "1" + @barcode_plate = "DN1" @asset = Asset.create!(barcode: @barcode_plate) end it 'should return the local asset when looking by its barcode' do @@ -155,14 +155,14 @@ setup do - @remote_plate_asset = build_remote_plate(barcode: '2') + @remote_plate_asset = build_remote_plate(barcode: generate(:barcode)) @barcode_plate = @remote_plate_asset.barcode stub_client_with_asset(SequencescapeClient, @remote_plate_asset) end context 'when the asset is a tube' do setup do - @remote_tube_asset = build_remote_tube(barcode: '1') + @remote_tube_asset = build_remote_tube(barcode: generate(:barcode)) stub_client_with_asset(SequencescapeClient, @remote_tube_asset) end it 'should try to obtain a tube' do @@ -173,7 +173,7 @@ context 'when the asset is a plate' do setup do - @remote_plate_asset = build_remote_plate(barcode: '2') + @remote_plate_asset = build_remote_plate(barcode: generate(:barcode)) stub_client_with_asset(SequencescapeClient, @remote_plate_asset) end it 'should try to obtain a plate' do @@ -197,7 +197,7 @@ build_remote_sample(sample_metadata: double('sample_metadata', sample_common_name: 'species', supplier_name: 'a supplier name')))]) ] - @remote_plate_asset_without_supplier = build_remote_plate(barcode: '5', wells: wells) + @remote_plate_asset_without_supplier = build_remote_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_plate_asset_without_supplier) end it 'imports the information of the wells that have a supplier name' do @@ -211,7 +211,7 @@ context 'when the asset is a tube' do context 'when the supplier name has not been provided' do setup do - @remote_tube_asset_without_supplier = build_remote_tube(barcode: '5', aliquots: [ + @remote_tube_asset_without_supplier = build_remote_tube(barcode: generate(:barcode), aliquots: [ build_remote_aliquot(sample: build_remote_sample(sample_metadata: double('sample_metadata', supplier_name: nil, sample_common_name: 'species'))) ]) @@ -226,7 +226,7 @@ end context 'when the supplier name has been provided' do setup do - @remote_tube_asset_with_supplier = build_remote_tube(barcode: '5') + @remote_tube_asset_with_supplier = build_remote_tube(barcode: generate(:barcode)) stub_client_with_asset(SequencescapeClient, @remote_tube_asset_with_supplier) end @@ -247,7 +247,7 @@ context 'when the plate does not have aliquots in its wells' do setup do wells = ['A1','B1'].map {|l| build_remote_well(l, aliquots: []) } - @remote_plate_asset_without_aliquots = build_remote_plate(barcode: '3', wells: wells) + @remote_plate_asset_without_aliquots = build_remote_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_plate_asset_without_aliquots) end it 'creates the wells with the same uuid as in the remote asset' do @@ -259,7 +259,7 @@ context 'when the plate does not have samples in its wells' do setup do wells = ['A1','B1'].map {|l| build_remote_well(l, aliquots: [build_remote_aliquot(sample: nil)]) } - @remote_plate_asset_without_samples = build_remote_plate(barcode: '4', wells: wells) + @remote_plate_asset_without_samples = build_remote_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_plate_asset_without_samples) end it 'creates the wells with the same uuid as in the remote asset' do diff --git a/test/factories/barcode_creatable.rb b/test/factories/barcode_creatable.rb index 158c658c..d48253c5 100644 --- a/test/factories/barcode_creatable.rb +++ b/test/factories/barcode_creatable.rb @@ -1,6 +1,6 @@ FactoryBot.define do sequence :barcode do |n| - n + "DN#{n}" end sequence :barcode_creatable do |n| From ef2a08679638114a30e2853c2e084877053a2720 Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Thu, 12 Mar 2020 11:53:20 +0000 Subject: [PATCH 010/303] Added barcode generate for test --- spec/models/assets/import_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 5986dd4d..5aac274f 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -140,7 +140,7 @@ end context 'when importing a local asset' do setup do - @barcode_plate = "DN1" + @barcode_plate = generate(:barcode) @asset = Asset.create!(barcode: @barcode_plate) end it 'should return the local asset when looking by its barcode' do From 0eed585a0d6c9e22b91bc93f2a259967a21dd441 Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Thu, 12 Mar 2020 15:06:40 +0000 Subject: [PATCH 011/303] More token util --- lib/token_util.rb | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/token_util.rb b/lib/token_util.rb index b0f50366..bcee8833 100644 --- a/lib/token_util.rb +++ b/lib/token_util.rb @@ -11,24 +11,34 @@ def self.MACHINE_BARCODE /^\d*$/ end + def self.HUMAN_BARCODE + /^\w*$/ + end + + def self.invalid_barcode?(barcode) + barcode.nil? || (barcode.kind_of?(String) && barcode.to_s.empty?) || + barcode.to_s.empty? + end + def self.machine_barcode?(barcode) - return false if barcode.nil? + return false if invalid_barcode?(barcode) barcode.to_s.match?(TokenUtil.MACHINE_BARCODE) end def self.human_barcode?(barcode) - return false if barcode.nil? - !barcode.to_s.match?(TokenUtil.MACHINE_BARCODE) + return false if invalid_barcode?(barcode) + # If we change the next line, we should change it to check the regexp + !machine_barcode?(barcode) end def self.machine_barcode(barcode) - return barcode.to_s if machine_barcode?(barcode) - SBCF::SangerBarcode.from_human(barcode).machine_barcode.to_s + return SBCF::SangerBarcode.from_human(barcode).machine_barcode.to_s if human_barcode?(barcode) + barcode.to_s end def self.human_barcode(barcode) - return SBCF::SangerBarcode.from_machine(barcode).human_barcode if machine_barcode?(barcode) - barcode + return SBCF::SangerBarcode.from_machine(barcode).human_barcode.to_s if machine_barcode?(barcode) + barcode.to_s end def self.WILDCARD_REGEXP From 666fb893f13a4c9cf30723448361430f2ae1a1c2 Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Thu, 12 Mar 2020 15:15:25 +0000 Subject: [PATCH 012/303] Removes unneeded condition --- lib/token_util.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/token_util.rb b/lib/token_util.rb index bcee8833..982e2763 100644 --- a/lib/token_util.rb +++ b/lib/token_util.rb @@ -16,8 +16,7 @@ def self.HUMAN_BARCODE end def self.invalid_barcode?(barcode) - barcode.nil? || (barcode.kind_of?(String) && barcode.to_s.empty?) || - barcode.to_s.empty? + barcode.nil? || (barcode.kind_of?(String) && barcode.to_s.empty?) end def self.machine_barcode?(barcode) From 87c265b626159279ceef33bb1a4e5c005c7b9f88 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Fri, 22 May 2020 15:19:58 +0100 Subject: [PATCH 013/303] Tube Rack can now be imported into Samples Extraction from Sequencescape - probably not handling samples correctly yet - add tube rack to sequenecscape_client 'find_by' method, so when the use enters a barcode it checks tube racks as well as plates, tubes and wells - add tube rack to sequencescape_client_v2.rb, so JSON API Client knows what they are --- app/assets/javascripts/barcode_reader.js | 53 ++++++++++++------------ lib/sequencescape_client.rb | 6 +-- lib/sequencescape_client_v2.rb | 4 ++ 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/app/assets/javascripts/barcode_reader.js b/app/assets/javascripts/barcode_reader.js index a5d11fa9..18c70171 100644 --- a/app/assets/javascripts/barcode_reader.js +++ b/app/assets/javascripts/barcode_reader.js @@ -1,13 +1,13 @@ (function($, undefined) { - function BarcodeReader(node, params) { - this.node = $(node); - this.input = $('input', node); - this.button = $('button', node); + function BarcodeReader(node, params) { + this.node = $(node); + this.input = $('input', node); + this.button = $('button', node); - this.attachHandlers(); - }; + this.attachHandlers(); + }; - var proto = BarcodeReader.prototype; + var proto = BarcodeReader.prototype; proto.readInput = function(e) { if ((e.keyCode === 9) || (e.keyCode == 13)) { @@ -15,27 +15,26 @@ } }; + proto.attachHandlers = function() { + this.input.on('keydown', $.proxy(this.readInput, this)); + this.button.on('click', $.proxy(this.send, this)); + }; - proto.attachHandlers = function() { - this.input.on('keydown', $.proxy(this.readInput, this)); - this.button.on('click', $.proxy(this.send, this)); - }; - - proto.readBarcodes = function(str) { - return str.split(' ').map(function(val) { - return val.replace(/\"\'/, ''); - }); - }; + proto.readBarcodes = function(str) { + return str.split(' ').map(function(val) { + return val.replace(/\"\'/, ''); + }); + }; - proto.send = function(e) { - e.preventDefault(); - this.readBarcodes(this.input.val()).forEach($.proxy(function(barcode) { - $(this.node).trigger('barcode.barcode_reader', {barcode: barcode}); - }, this)); - this.input.val(''); - }; + proto.send = function(e) { + e.preventDefault(); + this.readBarcodes(this.input.val()).forEach($.proxy(function(barcode) { + $(this.node).trigger('barcode.barcode_reader', {barcode: barcode}); + }, this)); + this.input.val(''); + }; - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'BarcodeReader': BarcodeReader}); - }); + $(document).ready(function() { + $(document).trigger('registerComponent.builder', {'BarcodeReader': BarcodeReader}); + }); }(jQuery)); diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 5994e993..d24ec119 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -69,7 +69,8 @@ def self.find_by(search_conditions) [ SequencescapeClientV2::Plate, SequencescapeClientV2::Tube, - SequencescapeClientV2::Well + SequencescapeClientV2::Well, + SequencescapeClientV2::TubeRack ].each do |klass| begin search = klass.where(search_conditions) @@ -81,8 +82,5 @@ def self.find_by(search_conditions) end nil end - - - end diff --git a/lib/sequencescape_client_v2.rb b/lib/sequencescape_client_v2.rb index 5c61194b..634536a3 100644 --- a/lib/sequencescape_client_v2.rb +++ b/lib/sequencescape_client_v2.rb @@ -17,6 +17,10 @@ class SequencescapeClientV2::Plate < SequencescapeClientV2::Model has_one :plate_purpose end + class SequencescapeClientV2::TubeRack < SequencescapeClientV2::Model + has_one :plate_purpose + end + class SequencescapeClientV2::Well < SequencescapeClientV2::Model has_many :aliquots has_many :studies, through: :aliquot From 03f386fc9a4bd9e8ba0032dc2da405107016599a Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Tue, 26 May 2020 14:19:27 +0100 Subject: [PATCH 014/303] switch to referencing 'purpose' rather than plate_purpose - this is what the relationship is called in Sequencescape's Plate resource file - the fact 'purpose' was not getting set on plates on import --- app/models/assets/import.rb | 4 ++-- lib/sequencescape_client_v2.rb | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index ee0cf80e..53dc94a4 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -207,8 +207,8 @@ def update_asset_from_remote_asset(asset, remote_asset, fact_changes) if keep_sync_with_sequencescape?(remote_asset) updates.replace_remote(asset, 'pushTo', 'Sequencescape') - if remote_asset.try(:plate_purpose) - updates.replace_remote(asset, 'purpose', remote_asset.plate_purpose.name) + if remote_asset.try(:purpose) + updates.replace_remote(asset, 'purpose', remote_asset.purpose.name) end end updates.replace_remote(asset, 'is', 'NotStarted') diff --git a/lib/sequencescape_client_v2.rb b/lib/sequencescape_client_v2.rb index 634536a3..ca803c02 100644 --- a/lib/sequencescape_client_v2.rb +++ b/lib/sequencescape_client_v2.rb @@ -14,11 +14,14 @@ class SequencescapeClientV2::Plate < SequencescapeClientV2::Model has_many :wells has_many :studies, through: :well has_many :samples, through: :well - has_one :plate_purpose + has_one :purpose end class SequencescapeClientV2::TubeRack < SequencescapeClientV2::Model - has_one :plate_purpose + has_one :purpose + end + + class SequencescapeClientV2::Purpose < SequencescapeClientV2::Model end class SequencescapeClientV2::Well < SequencescapeClientV2::Model @@ -51,6 +54,4 @@ class SequencescapeClientV2::Sample < SequencescapeClientV2::Model class SequencescapeClientV2::SampleMetadatum < SequencescapeClientV2::Model belongs_to :sample end - - end From a151300eae4d816ed3235f15c18c6a24df02d020 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Tue, 26 May 2020 15:40:04 +0100 Subject: [PATCH 015/303] access racked_tubes from a tube rack through the api --- app/models/assets/import.rb | 21 +++++++++++++++++++++ lib/sequencescape_client_v2.rb | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 53dc94a4..3e98eb59 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -215,6 +215,7 @@ def update_asset_from_remote_asset(asset, remote_asset, fact_changes) annotate_container(asset, remote_asset, updates) annotate_wells(asset, remote_asset, updates) + annotate_tubes(asset, remote_asset, updates) annotate_study_name(asset, remote_asset, updates) asset.update_digest_with_remote(remote_asset) @@ -357,6 +358,26 @@ def _annotate_wells(asset, remote_asset, fact_changes) end end + def annotate_tubes(asset, remote_asset, fact_changes) + fact_changes.tap do |updates| + if remote_asset.try(:tubes) + remote_asset.tubes.each do |tube| + local_tube = Asset.find_or_create_by!(:uuid => tube.uuid) + + updates.replace_remote(asset, 'contains', local_tube) + + # Updated wells will also mean that the plate is out of date, so we'll set it in the asset + updates.replace_remote(local_tube, 'a', 'SampleTube') + # updates.replace_remote(local_tube, 'location', tube.position['name']) # should come from racked tube - sort out + updates.replace_remote(local_tube, 'parent', asset) + + if (tube.try(:aliquots)&.first&.sample&.sample_metadata&.supplier_name) + annotate_container(local_tube, tube, fact_changes) + end + end + end + end + end def sequencescape_type_for_asset(remote_asset) return nil unless remote_asset.type diff --git a/lib/sequencescape_client_v2.rb b/lib/sequencescape_client_v2.rb index ca803c02..4b57fb1b 100644 --- a/lib/sequencescape_client_v2.rb +++ b/lib/sequencescape_client_v2.rb @@ -18,6 +18,7 @@ class SequencescapeClientV2::Plate < SequencescapeClientV2::Model end class SequencescapeClientV2::TubeRack < SequencescapeClientV2::Model + has_many :racked_tubes has_one :purpose end @@ -36,6 +37,9 @@ class SequencescapeClientV2::Tube < SequencescapeClientV2::Model has_many :samples, through: :aliquot end + class SequencescapeClientV2::RackedTube < SequencescapeClientV2::Model + end + class SequencescapeClientV2::Aliquot < SequencescapeClientV2::Model belongs_to :asset has_one :study From 6c0f69179ea17545b3e26683db9bf82815025f15 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Tue, 26 May 2020 15:51:03 +0100 Subject: [PATCH 016/303] can now get 'location' (coordinate) off racked_tube - calling it location to keep it matching well terminology --- app/models/assets/import.rb | 15 ++++++++------- lib/sequencescape_client_v2.rb | 2 ++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 3e98eb59..ddbd80ae 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -360,19 +360,20 @@ def _annotate_wells(asset, remote_asset, fact_changes) def annotate_tubes(asset, remote_asset, fact_changes) fact_changes.tap do |updates| - if remote_asset.try(:tubes) - remote_asset.tubes.each do |tube| - local_tube = Asset.find_or_create_by!(:uuid => tube.uuid) + if remote_asset.try(:racked_tubes) + remote_asset.racked_tubes.each do |racked_tube| + remote_tube = racked_tube.tube + local_tube = Asset.find_or_create_by!(:uuid => remote_tube.uuid) updates.replace_remote(asset, 'contains', local_tube) - # Updated wells will also mean that the plate is out of date, so we'll set it in the asset + # Updated tubes will also mean that the plate is out of date, so we'll set it in the asset updates.replace_remote(local_tube, 'a', 'SampleTube') - # updates.replace_remote(local_tube, 'location', tube.position['name']) # should come from racked tube - sort out + updates.replace_remote(local_tube, 'location', racked_tube.coordinate) updates.replace_remote(local_tube, 'parent', asset) - if (tube.try(:aliquots)&.first&.sample&.sample_metadata&.supplier_name) - annotate_container(local_tube, tube, fact_changes) + if (remote_tube.try(:aliquots)&.first&.sample&.sample_metadata&.supplier_name) + annotate_container(local_tube, remote_tube, fact_changes) end end end diff --git a/lib/sequencescape_client_v2.rb b/lib/sequencescape_client_v2.rb index 4b57fb1b..fca7777d 100644 --- a/lib/sequencescape_client_v2.rb +++ b/lib/sequencescape_client_v2.rb @@ -38,6 +38,8 @@ class SequencescapeClientV2::Tube < SequencescapeClientV2::Model end class SequencescapeClientV2::RackedTube < SequencescapeClientV2::Model + has_one :tube + has_one :tube_rack end class SequencescapeClientV2::Aliquot < SequencescapeClientV2::Model From dcc836f8aa73f82d4db07ef5caa4bdd54d174902 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Tue, 26 May 2020 16:03:11 +0100 Subject: [PATCH 017/303] bring back study for tube racks as well as plates --- app/models/assets/import.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index ddbd80ae..6576e7dd 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -312,6 +312,10 @@ def annotate_study_name(asset, remote_asset, fact_changes) remote_asset.wells.detect do |w| annotate_study_name_from_aliquots(asset, w, fact_changes) end + elsif remote_asset.try(:racked_tubes) + remote_asset.racked_tubes.detect do |rt| + annotate_study_name_from_aliquots(asset, rt.tube, fact_changes) + end else annotate_study_name_from_aliquots(asset, remote_asset, fact_changes) end From 8ff39a7a312e3c9b91e7b718542b08e0376a968c Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Tue, 26 May 2020 16:23:15 +0100 Subject: [PATCH 018/303] added what looks sensible for the json_for_remote method - need to work out how to test it --- app/models/assets/import.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 6576e7dd..2e6bf7b2 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -45,6 +45,25 @@ def json_for_remote(remote_asset) end end + # FOR A TUBE RACK + if remote_asset.respond_to?(:racked_tubes) && remote_asset.racked_tubes + # to_a because racked_tubes relation does not act as an array + list_tubes = remote_asset.racked_tubes.map do |racked_tube| + racked_tube.tube + end.to_a + + if list_tubes + # aliquots.to_a, same reason + listal = list_tubes.compact.map(&:aliquots).map(&:to_a) + if listal + listsa = listal.flatten.compact.map{|al| al.sample } + if listsa + distinct+=listsa.compact.map(&:attributes).to_json + end + end + end + end + distinct end From 71ab9fac1e6d32192ec0da26e603a3193b3ad1cf Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Tue, 26 May 2020 16:45:43 +0100 Subject: [PATCH 019/303] Get rid of these duplicated, unused methods - they were added previously by emr but are now not needed --- app/models/assets/import.rb | 76 ------------------------------------- 1 file changed, 76 deletions(-) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 2e6bf7b2..6a8fb128 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -241,28 +241,6 @@ def update_asset_from_remote_asset(asset, remote_asset, fact_changes) end end - - def _update_asset_from_remote_asset(asset, remote_asset, fact_changes) - fact_changes.tap do |updates| - class_name = sequencescape_type_for_asset(remote_asset) - updates.replace_remote(asset, 'a', class_name) - - if keep_sync_with_sequencescape?(remote_asset) - updates.replace_remote(asset, 'pushTo', 'Sequencescape') - if remote_asset.try(:plate_purpose, nil) - updates.replace_remote(asset, 'purpose', remote_asset.plate_purpose.name) - end - end - updates.replace_remote(asset, 'is', 'NotStarted') - - annotate_container(asset, remote_asset, updates) - annotate_wells(asset, remote_asset, updates) - annotate_study_name(asset, remote_asset, updates) - - asset.update_digest_with_remote(remote_asset) - end - end - def annotate_container(asset, remote_asset, fact_changes) fact_changes.tap do |updates| if remote_asset.try(:aliquots) @@ -278,21 +256,6 @@ def annotate_container(asset, remote_asset, fact_changes) end end - def _annotate_container(asset, remote_asset, fact_changes) - fact_changes.tap do |updates| - if remote_asset.try(:aliquots, nil) - remote_asset.aliquots.each do |aliquot| - updates.replace_remote(asset, 'sample_tube', asset) - updates.replace_remote(asset, 'sanger_sample_id', aliquot&.sample&.sanger&.sample_id) - updates.replace_remote(asset, 'sample_uuid', TokenUtil.quote(aliquot&.sample&.sanger&.sample_uuid), literal: true) - updates.replace_remote(asset, 'sanger_sample_name', aliquot&.sample&.sanger&.name) - - updates.replace_remote(asset, 'supplier_sample_name', aliquot&.sample&.supplier&.sample_name) - end - end - end - end - def sample_id_to_study_name(sample_id) sample_id.gsub(/\d*$/,'').gsub('-', '') end @@ -313,19 +276,6 @@ def annotate_study_name_from_aliquots(asset, remote_asset, fact_changes) end end - def _annotate_study_name_from_aliquots(asset, remote_asset, fact_changes) - fact_changes.tap do |updates| - if remote_asset.try(:aliquots, nil) - if ((remote_asset.aliquots.count == 1) && (remote_asset.aliquots.first.sample)) - study_name = sample_id_to_study_name(remote_asset.aliquots.first.sample.sanger.sample_id) - #study_uuid = get_study_uuid(study_name) - updates.replace_remote(asset, 'study_name', study_name) - end - end - end - end - - def annotate_study_name(asset, remote_asset, fact_changes) if remote_asset.try(:wells) remote_asset.wells.detect do |w| @@ -361,26 +311,6 @@ def annotate_wells(asset, remote_asset, fact_changes) end end - def _annotate_wells(asset, remote_asset, fact_changes) - fact_changes.tap do |updates| - if remote_asset.try(:wells, nil) - remote_asset.wells.each do |well| - local_well = Asset.find_or_create_by!(:uuid => well.uuid) - if (well.try(:aliquots, nil)&.first&.sample&.supplier&.sample_name) - updates.replace_remote(asset, 'contains', local_well) - - # Updated wells will also mean that the plate is out of date, so we'll set it in the asset - updates.replace_remote(local_well, 'a', 'Well') - updates.replace_remote(local_well, 'location', well.location) - updates.replace_remote(local_well, 'parent', asset) - - annotate_container(local_well, well, fact_changes) - end - end - end - end - end - def annotate_tubes(asset, remote_asset, fact_changes) fact_changes.tap do |updates| if remote_asset.try(:racked_tubes) @@ -410,12 +340,6 @@ def sequencescape_type_for_asset(remote_asset) return type end - def _sequencescape_type_for_asset(remote_asset) - type = remote_asset.class.to_s.gsub(/Sequencescape::/,'') - return 'SampleTube' if type == 'Tube' - return type - end - def keep_sync_with_sequencescape?(remote_asset) class_name = sequencescape_type_for_asset(remote_asset) (class_name != 'SampleTube') From 5b2e093ce8cf520b2beb20ae4277b0e51571fe5b Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Tue, 26 May 2020 17:02:43 +0100 Subject: [PATCH 020/303] add some whitespace to the test class to improve readability --- spec/models/assets/import_spec.rb | 54 ++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 5aac274f..1afa60c6 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -4,7 +4,6 @@ RSpec.describe 'Assets::Import' do include RemoteAssetsHelper - context '#refresh!' do let(:asset) { create :asset } let(:plate) { build_remote_plate } @@ -24,23 +23,28 @@ expect(asset).not_to have_received(:_process_refresh) end end + context 'when it is a remote asset' do before do allow(asset).to receive(:is_remote_asset?).and_return(true) end + context 'when the asset has changed' do before do allow(asset).to receive(:changed_remote?).and_return(true) end + it 'refreshes the asset' do asset.refresh! expect(asset).to have_received(:_process_refresh) end end + context 'when the asset has not changed' do before do allow(asset).to receive(:changed_remote?).and_return(false) end + it 'refreshes the asset' do asset.refresh! expect(asset).to have_received(:_process_refresh) @@ -48,28 +52,34 @@ end end end + context '#refresh' do let(:asset) { create :asset } let(:plate) { build_remote_plate } + before do allow(SequencescapeClient).to receive(:find_by_uuid).and_return(true) allow(asset).to receive(:changed_remote?).and_return(false) end + it 'recognises a plate' do asset.facts << create(:fact, predicate: 'a', object: 'TubeRack', is_remote?: true) asset.refresh expect(SequencescapeClient).to have_received(:find_by_uuid).with(asset.uuid) end + it 'recognises a tube' do asset.facts << create(:fact, predicate: 'a', object: 'Tube', is_remote?: true) asset.refresh expect(SequencescapeClient).to have_received(:find_by_uuid).with(asset.uuid) end + context 'when actually updating' do before do allow(SequencescapeClient).to receive(:find_by_uuid).and_return(plate) allow(asset).to receive(:changed_remote?).and_return(true) end + it 'does not destroy remote facts that have not changed' do fact = create(:fact, predicate: 'a', object: 'Plate', is_remote?: true) asset.facts << fact @@ -77,6 +87,7 @@ expect{fact.reload}.not_to raise_error expect(asset.facts.with_predicate('a').first.object).to eq('Plate') end + it 'destroys and refreshes remote facts that have changed' do fact = create(:fact, predicate: 'a', object: 'Tube', is_remote?: true) asset.facts << fact @@ -84,6 +95,7 @@ expect{fact.reload}.to raise_error(ActiveRecord::RecordNotFound) expect(asset.facts.with_predicate('a').first.object).to eq('Plate') end + it 'does not destroy local facts' do fact = create(:fact, predicate: 'is', object: 'Red', is_remote?: false) asset.facts << fact @@ -91,6 +103,7 @@ expect{fact.reload}.not_to raise_error expect(asset.facts.with_predicate('is').first.object).to eq('Red') end + it 'does not destroy the assets linked by remote facts' do asset2 = create(:asset) fact = create(:fact, predicate: 'contains', object_asset_id: asset2.id, is_remote?: true) @@ -100,6 +113,7 @@ expect{asset.reload}.not_to raise_error expect{asset2.reload}.not_to raise_error end + it 'replaces the local facts of the assets linked with remote facts that are changing' do asset2 = create(:asset, uuid: plate.wells.first.uuid) fact_well = create(:fact, predicate: 'location', object: 'A01', is_remote?: false) @@ -128,33 +142,38 @@ context 'when importing an asset that does not exist' do setup do allow(SequencescapeClient).to receive(:get_remote_asset).and_return(nil) - end + end + it 'should return nil' do expect(Asset.find_or_import_asset_with_barcode('NOT_FOUND')).to eq(nil) - end + end + it 'should not create a new asset' do expect(Asset.all.count).to eq(0) Asset.find_or_import_asset_with_barcode('NOT_FOUND') expect(Asset.all.count).to eq(0) end - end + end + context 'when importing a local asset' do setup do @barcode_plate = generate(:barcode) @asset = Asset.create!(barcode: @barcode_plate) - end + end + it 'should return the local asset when looking by its barcode' do expect(Asset.find_or_import_asset_with_barcode(@barcode_plate)).to eq(@asset) - end + end + it 'should return the local asset when looking by its barcode' do expect(Asset.find_or_import_asset_with_barcode(@asset.uuid)).to eq(@asset) end - end + end + context 'when importing a remote asset' do let(:SequencescapeClient) { double('sequencescape_client') } setup do - @remote_plate_asset = build_remote_plate(barcode: generate(:barcode)) @barcode_plate = @remote_plate_asset.barcode stub_client_with_asset(SequencescapeClient, @remote_plate_asset) @@ -165,6 +184,7 @@ @remote_tube_asset = build_remote_tube(barcode: generate(:barcode)) stub_client_with_asset(SequencescapeClient, @remote_tube_asset) end + it 'should try to obtain a tube' do @asset = Asset.find_or_import_asset_with_barcode(@remote_tube_asset.barcode) expect(SequencescapeClient).to have_received(:find_by_uuid).with(@remote_tube_asset.uuid) @@ -176,6 +196,7 @@ @remote_plate_asset = build_remote_plate(barcode: generate(:barcode)) stub_client_with_asset(SequencescapeClient, @remote_plate_asset) end + it 'should try to obtain a plate' do @asset = Asset.find_or_import_asset_with_barcode(@remote_plate_asset.barcode) expect(SequencescapeClient).to have_received(:find_by_uuid).with(@remote_plate_asset.uuid) @@ -200,6 +221,7 @@ @remote_plate_asset_without_supplier = build_remote_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_plate_asset_without_supplier) end + it 'imports the information of the wells that have a supplier name' do @asset = Asset.find_or_import_asset_with_barcode(@remote_plate_asset_without_supplier.barcode) wells = @asset.facts.with_predicate('contains').map(&:object_asset) @@ -208,6 +230,7 @@ expect(locations_with_info).to eq(['C1','D1']) end end + context 'when the asset is a tube' do context 'when the supplier name has not been provided' do setup do @@ -224,6 +247,7 @@ expect(@asset.facts.with_predicate('supplier_sample_name').count).to eq(0) end end + context 'when the supplier name has been provided' do setup do @remote_tube_asset_with_supplier = build_remote_tube(barcode: generate(:barcode)) @@ -250,18 +274,21 @@ @remote_plate_asset_without_aliquots = build_remote_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_plate_asset_without_aliquots) end + it 'creates the wells with the same uuid as in the remote asset' do @asset = Asset.find_or_import_asset_with_barcode(@remote_plate_asset_without_aliquots.barcode) wells = @asset.facts.with_predicate('contains').map(&:object_asset) expect(wells.zip(@remote_plate_asset_without_aliquots.wells).all?{|w,w2| w.uuid == w2.uuid}).to eq(true) end end + context 'when the plate does not have samples in its wells' do setup do wells = ['A1','B1'].map {|l| build_remote_well(l, aliquots: [build_remote_aliquot(sample: nil)]) } @remote_plate_asset_without_samples = build_remote_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_plate_asset_without_samples) end + it 'creates the wells with the same uuid as in the remote asset' do @asset = Asset.find_or_import_asset_with_barcode(@remote_plate_asset_without_samples.barcode) wells = @asset.facts.with_predicate('contains').map(&:object_asset) @@ -293,21 +320,25 @@ Asset.find_or_import_asset_with_barcode(@barcode_plate) expect(Asset.count>0).to eq(true) end - end + end + context 'when is already imported' do context 'when the remote source is not present anymore' do setup do @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) allow(SequencescapeClient).to receive(:find_by_uuid).and_return(nil) end + it 'should raise an exception' do expect{Asset.find_or_import_asset_with_barcode(@barcode_plate)}.to raise_exception Assets::Import::RefreshSourceNotFoundAnymore end end + context 'when the remote source is present' do setup do @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) - end + end + it 'should not create a new local asset' do count = Asset.count Asset.find_or_import_asset_with_barcode(@barcode_plate) @@ -332,7 +363,8 @@ @dependant_fact = create :fact, predicate: 'some', object: 'Moredata', is_remote?: true @well_changed.facts << @dependant_fact @fact_changed.update_attributes(object_asset_id: @well_changed.id) - end + end + it 'should destroy any remote facts that has changed' do Asset.find_or_import_asset_with_barcode(@barcode_plate) expect{@fact_changed.reload}.to raise_exception ActiveRecord::RecordNotFound From 64dc319e622e50d067bbff663827da3187370acd Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Wed, 27 May 2020 14:52:38 +0100 Subject: [PATCH 021/303] fix failing test due to change to 'update_asset_from_remote_asset' to call 'purpose' rather than 'plate_purpose' --- spec/remote_assets_helper.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index a28f7f26..2de0b826 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -4,7 +4,7 @@ def build_remote_plate(opts = {}) obj = { uuid: SecureRandom.uuid, wells: [build_remote_well('A1'), build_remote_well('A4')], - plate_purpose: purpose, + purpose: purpose, type: 'plates' }.merge(opts) my_double = double('remote_asset', obj) @@ -62,10 +62,9 @@ def build_remote_sample(opts={}) def stub_client_with_asset(double, asset) type = (asset.class==Sequencescape::Plate) ? :plate : :tube - allow(double).to receive(:find_by_uuid).with(asset.uuid).and_return(asset) - allow(double).to receive(:get_remote_asset) { nil } + allow(double).to receive(:find_by_uuid).with(asset.uuid).and_return(asset) + allow(double).to receive(:get_remote_asset) { nil } allow(double).to receive(:get_remote_asset).with(asset.barcode).and_return(asset) allow(double).to receive(:get_remote_asset).with(asset.uuid).and_return(asset) end - end From b3b6a23f7ad22a62434ba5fdb79a0f027d3586c7 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Wed, 27 May 2020 16:11:14 +0100 Subject: [PATCH 022/303] rearrange tests so there are shared examples for plates and racks - add some mocking for tube racks - all the shared examples pass apart from the 'store the study uuid in a safe format' one - look at that next --- spec/models/assets/import_spec.rb | 184 +++++++++++++++++------------- spec/remote_assets_helper.rb | 40 +++++-- 2 files changed, 135 insertions(+), 89 deletions(-) diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 1afa60c6..1aad82ff 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -138,6 +138,100 @@ end end + shared_examples 'a plate or tube rack' do + it 'should create the corresponding facts from the json' do + @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) + @asset.facts.reload + + predicates = ["a", "pushTo", "purpose", "is", "contains", "contains", "study_name", "study_uuid"] + + expect(predicates.all? do |predicate| + puts "DEBUG: predicate: #{predicate}" if @asset.facts.where(predicate: predicate).count == 0 + @asset.facts.where(predicate: predicate).count > 0 + end).to eq(true) + end + + it 'should store the study uuid in a safe format' do + @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) + study_uuid = @remote_plate_asset.wells.first.aliquots.first.study.uuid + @asset.facts.reload + + asset_study_uuid = @asset.facts.where(predicate: 'study_uuid').first.object + expect(asset_study_uuid).to eq(TokenUtil.quote(study_uuid)) + end + + context 'for the first time' do + it 'should create the local asset' do + expect(Asset.count).to eq(0) + Asset.find_or_import_asset_with_barcode(@barcode_plate) + + expect(Asset.count>0).to eq(true) + end + end + + context 'when is already imported' do + context 'when the remote source is not present anymore' do + setup do + @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) + allow(SequencescapeClient).to receive(:find_by_uuid).and_return(nil) + end + + it 'should raise an exception' do + expect{Asset.find_or_import_asset_with_barcode(@barcode_plate)}.to raise_exception Assets::Import::RefreshSourceNotFoundAnymore + end + end + + context 'when the remote source is present' do + setup do + @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) + end + + it 'should not create a new local asset' do + count = Asset.count + Asset.find_or_import_asset_with_barcode(@barcode_plate) + expect(Asset.count).to eq(count) + end + + context 'when the local copy is up to date' do + it 'should not destroy any remote facts' do + remote_facts = @asset.facts.from_remote_asset + remote_facts.each(&:reload) + Asset.find_or_import_asset_with_barcode(@barcode_plate) + expect{remote_facts.each(&:reload)}.not_to raise_error + end + end + + context 'when the local copy is out of date' do + before do + @asset.update_attributes(remote_digest: 'RANDOM') + @fact_changed = @asset.facts.from_remote_asset.where(predicate: 'contains').first + + @well_changed = create :asset + @dependant_fact = create :fact, predicate: 'some', object: 'Moredata', is_remote?: true + @well_changed.facts << @dependant_fact + @fact_changed.update_attributes(object_asset_id: @well_changed.id) + end + + it 'should destroy any remote facts that has changed' do + Asset.find_or_import_asset_with_barcode(@barcode_plate) + expect{@fact_changed.reload}.to raise_exception ActiveRecord::RecordNotFound + end + + it 'should destroy any contains dependant remote facts' do + Asset.find_or_import_asset_with_barcode(@barcode_plate) + expect{@dependant_fact.reload}.to raise_exception ActiveRecord::RecordNotFound + end + + it 'should re-create new remote facts' do + @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) + @asset.facts.reload + expect(@asset.facts.from_remote_asset.all?{|f| f.object_asset != @well_changed}) + end + end + end + end + end + context '#find_or_import_asset_with_barcode' do context 'when importing an asset that does not exist' do setup do @@ -297,92 +391,18 @@ end end - it 'should create the corresponding facts from the json' do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) - @asset.facts.reload - predicates = ["a", "pushTo", "purpose", "is", "contains", "contains", "study_name", "study_uuid"] - expect(predicates.all? do |predicate| - @asset.facts.where(predicate: predicate).count > 0 - end).to eq(true) - end - - it 'should store the study uuid in a safe format' do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) - study_uuid = @remote_plate_asset.wells.first.aliquots.first.study.uuid - @asset.facts.reload - asset_study_uuid = @asset.facts.where(predicate: 'study_uuid').first.object - expect(asset_study_uuid).to eq(TokenUtil.quote(study_uuid)) - end - - context 'for the first time' do - it 'should create the local asset' do - expect(Asset.count).to eq(0) - Asset.find_or_import_asset_with_barcode(@barcode_plate) - expect(Asset.count>0).to eq(true) - end - end - - context 'when is already imported' do - context 'when the remote source is not present anymore' do - setup do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) - allow(SequencescapeClient).to receive(:find_by_uuid).and_return(nil) - end - - it 'should raise an exception' do - expect{Asset.find_or_import_asset_with_barcode(@barcode_plate)}.to raise_exception Assets::Import::RefreshSourceNotFoundAnymore - end + context 'when the asset is a tube rack' do + setup do + @remote_rack_asset = build_remote_tube_rack(barcode: generate(:barcode)) + @barcode_plate = @remote_rack_asset.barcode + stub_client_with_asset(SequencescapeClient, @remote_rack_asset) end - context 'when the remote source is present' do - setup do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) - end - - it 'should not create a new local asset' do - count = Asset.count - Asset.find_or_import_asset_with_barcode(@barcode_plate) - expect(Asset.count).to eq(count) - end - - context 'when the local copy is up to date' do - it 'should not destroy any remote facts' do - remote_facts = @asset.facts.from_remote_asset - remote_facts.each(&:reload) - Asset.find_or_import_asset_with_barcode(@barcode_plate) - expect{remote_facts.each(&:reload)}.not_to raise_error - end - end - - context 'when the local copy is out of date' do - before do - @asset.update_attributes(remote_digest: 'RANDOM') - @fact_changed = @asset.facts.from_remote_asset.where(predicate: 'contains').first - - @well_changed = create :asset - @dependant_fact = create :fact, predicate: 'some', object: 'Moredata', is_remote?: true - @well_changed.facts << @dependant_fact - @fact_changed.update_attributes(object_asset_id: @well_changed.id) - end - - it 'should destroy any remote facts that has changed' do - Asset.find_or_import_asset_with_barcode(@barcode_plate) - expect{@fact_changed.reload}.to raise_exception ActiveRecord::RecordNotFound - end + it_behaves_like 'a plate or tube rack' + end - it 'should destroy any contains dependant remote facts' do - Asset.find_or_import_asset_with_barcode(@barcode_plate) - expect{@dependant_fact.reload}.to raise_exception ActiveRecord::RecordNotFound - end + it_behaves_like 'a plate or tube rack' - it 'should re-create new remote facts' do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) - @asset.facts.reload - expect(@asset.facts.from_remote_asset.all?{|f| f.object_asset != @well_changed}) - end - end - end - end end end end diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index 2de0b826..4c6ad306 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -7,9 +7,9 @@ def build_remote_plate(opts = {}) purpose: purpose, type: 'plates' }.merge(opts) + my_double = double('remote_asset', obj) allow(my_double).to receive(:attributes).and_return(obj) - allow(my_double).to receive(:class).and_return(Sequencescape::Plate) my_double @@ -19,23 +19,49 @@ def build_remote_well(location, opts={}) double('well', {aliquots: [build_remote_aliquot], location: location, position: { "name" => location }, uuid: SecureRandom.uuid}.merge(opts)) end - def build_remote_tube(opts = {}) + def build_remote_tube_rack(opts = {}) purpose = double('purpose', name: 'A purpose') - obj = { uuid: SecureRandom.uuid, - type: 'tubes', - plate_purpose: purpose, - aliquots: [build_remote_aliquot] - }.merge(opts) + racked_tubes: [build_remote_racked_tube('A1'), build_remote_racked_tube('A4')], + purpose: purpose, + type: 'tube_racks' + }.merge(opts) my_double = double('remote_asset', obj) allow(my_double).to receive(:attributes).and_return(obj) + my_double + end + + def build_remote_racked_tube(coordinate, tube = nil) + obj = { + coordinate: coordinate, + tube: tube || double('tube', tube_standard_options) + } + + my_double = double('racked_tube', obj) + end + + def build_remote_tube(opts = {}) + my_double = double('remote_asset', tube_standard_options(opts)) + + allow(my_double).to receive(:attributes).and_return(obj) allow(my_double).to receive(:class).and_return(Sequencescape::Tube) + my_double end + def tube_standard_options(opts = {}) + purpose = double('purpose', name: 'A purpose') + { + uuid: SecureRandom.uuid, + type: 'tubes', + plate_purpose: purpose, + aliquots: [build_remote_aliquot] + }.merge(opts) + end + def build_remote_aliquot(opts={}) double('aliquot', {sample: build_remote_sample, study: build_study}.merge(opts)) end From 63d78c5968076fb5eddfafa9191e58a3d3d18b5e Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Thu, 28 May 2020 10:29:18 +0100 Subject: [PATCH 023/303] bugfix - had an isolated 'obj' --- spec/remote_assets_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index 4c6ad306..45deba56 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -44,7 +44,8 @@ def build_remote_racked_tube(coordinate, tube = nil) end def build_remote_tube(opts = {}) - my_double = double('remote_asset', tube_standard_options(opts)) + obj = tube_standard_options(opts) + my_double = double('remote_asset', obj) allow(my_double).to receive(:attributes).and_return(obj) allow(my_double).to receive(:class).and_return(Sequencescape::Tube) From 0d1219f06e29f2b2d14f2b431e74cf9c7a635945 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Thu, 28 May 2020 10:38:39 +0100 Subject: [PATCH 024/303] adapt study_uuid test to work with racks as well as plates - all shared examples pass now for racks as well as plates --- spec/models/assets/import_spec.rb | 51 ++++++++++++++++--------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 1aad82ff..7757bd9e 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -146,18 +146,21 @@ predicates = ["a", "pushTo", "purpose", "is", "contains", "contains", "study_name", "study_uuid"] expect(predicates.all? do |predicate| - puts "DEBUG: predicate: #{predicate}" if @asset.facts.where(predicate: predicate).count == 0 @asset.facts.where(predicate: predicate).count > 0 end).to eq(true) end it 'should store the study uuid in a safe format' do @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) - study_uuid = @remote_plate_asset.wells.first.aliquots.first.study.uuid + expected_study_uuid = if @remote_asset.respond_to?(:wells) + @remote_asset.wells.first.aliquots.first.study.uuid + else + @remote_asset.racked_tubes.first.tube.aliquots.first.study.uuid + end @asset.facts.reload asset_study_uuid = @asset.facts.where(predicate: 'study_uuid').first.object - expect(asset_study_uuid).to eq(TokenUtil.quote(study_uuid)) + expect(asset_study_uuid).to eq(TokenUtil.quote(expected_study_uuid)) end context 'for the first time' do @@ -268,9 +271,9 @@ let(:SequencescapeClient) { double('sequencescape_client') } setup do - @remote_plate_asset = build_remote_plate(barcode: generate(:barcode)) - @barcode_plate = @remote_plate_asset.barcode - stub_client_with_asset(SequencescapeClient, @remote_plate_asset) + @remote_asset = build_remote_plate(barcode: generate(:barcode)) + @barcode_plate = @remote_asset.barcode + stub_client_with_asset(SequencescapeClient, @remote_asset) end context 'when the asset is a tube' do @@ -287,13 +290,13 @@ context 'when the asset is a plate' do setup do - @remote_plate_asset = build_remote_plate(barcode: generate(:barcode)) - stub_client_with_asset(SequencescapeClient, @remote_plate_asset) + @remote_asset = build_remote_plate(barcode: generate(:barcode)) + stub_client_with_asset(SequencescapeClient, @remote_asset) end it 'should try to obtain a plate' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_plate_asset.barcode) - expect(SequencescapeClient).to have_received(:find_by_uuid).with(@remote_plate_asset.uuid) + @asset = Asset.find_or_import_asset_with_barcode(@remote_asset.barcode) + expect(SequencescapeClient).to have_received(:find_by_uuid).with(@remote_asset.uuid) end context 'when the supplier sample name has not been provided to some samples' do @@ -312,12 +315,12 @@ build_remote_sample(sample_metadata: double('sample_metadata', sample_common_name: 'species', supplier_name: 'a supplier name')))]) ] - @remote_plate_asset_without_supplier = build_remote_plate(barcode: generate(:barcode), wells: wells) - stub_client_with_asset(SequencescapeClient, @remote_plate_asset_without_supplier) + @remote_asset_without_supplier = build_remote_plate(barcode: generate(:barcode), wells: wells) + stub_client_with_asset(SequencescapeClient, @remote_asset_without_supplier) end it 'imports the information of the wells that have a supplier name' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_plate_asset_without_supplier.barcode) + @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_supplier.barcode) wells = @asset.facts.with_predicate('contains').map(&:object_asset) wells_with_info = wells.select{|w| w.facts.where(predicate: 'supplier_sample_name').count > 0} locations_with_info = wells_with_info.map{|w| w.facts.with_predicate('location').first.object} @@ -365,37 +368,37 @@ context 'when the plate does not have aliquots in its wells' do setup do wells = ['A1','B1'].map {|l| build_remote_well(l, aliquots: []) } - @remote_plate_asset_without_aliquots = build_remote_plate(barcode: generate(:barcode), wells: wells) - stub_client_with_asset(SequencescapeClient, @remote_plate_asset_without_aliquots) + @remote_asset_without_aliquots = build_remote_plate(barcode: generate(:barcode), wells: wells) + stub_client_with_asset(SequencescapeClient, @remote_asset_without_aliquots) end it 'creates the wells with the same uuid as in the remote asset' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_plate_asset_without_aliquots.barcode) + @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_aliquots.barcode) wells = @asset.facts.with_predicate('contains').map(&:object_asset) - expect(wells.zip(@remote_plate_asset_without_aliquots.wells).all?{|w,w2| w.uuid == w2.uuid}).to eq(true) + expect(wells.zip(@remote_asset_without_aliquots.wells).all?{|w,w2| w.uuid == w2.uuid}).to eq(true) end end context 'when the plate does not have samples in its wells' do setup do wells = ['A1','B1'].map {|l| build_remote_well(l, aliquots: [build_remote_aliquot(sample: nil)]) } - @remote_plate_asset_without_samples = build_remote_plate(barcode: generate(:barcode), wells: wells) - stub_client_with_asset(SequencescapeClient, @remote_plate_asset_without_samples) + @remote_asset_without_samples = build_remote_plate(barcode: generate(:barcode), wells: wells) + stub_client_with_asset(SequencescapeClient, @remote_asset_without_samples) end it 'creates the wells with the same uuid as in the remote asset' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_plate_asset_without_samples.barcode) + @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_samples.barcode) wells = @asset.facts.with_predicate('contains').map(&:object_asset) - expect(wells.zip(@remote_plate_asset_without_samples.wells).all?{|w,w2| w.uuid == w2.uuid}).to eq(true) + expect(wells.zip(@remote_asset_without_samples.wells).all?{|w,w2| w.uuid == w2.uuid}).to eq(true) end end end context 'when the asset is a tube rack' do setup do - @remote_rack_asset = build_remote_tube_rack(barcode: generate(:barcode)) - @barcode_plate = @remote_rack_asset.barcode - stub_client_with_asset(SequencescapeClient, @remote_rack_asset) + @remote_asset = build_remote_tube_rack(barcode: generate(:barcode)) + @barcode_plate = @remote_asset.barcode + stub_client_with_asset(SequencescapeClient, @remote_asset) end it_behaves_like 'a plate or tube rack' From ee6d722101630a9ff08922938b7adcca6d14c984 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Thu, 28 May 2020 11:15:42 +0100 Subject: [PATCH 025/303] Refactoring / tidying up - no real code changes here - mostly reorganising nesting of contexts --- spec/models/assets/import_spec.rb | 179 ++++++++++++++---------------- spec/remote_assets_helper.rb | 2 +- 2 files changed, 87 insertions(+), 94 deletions(-) diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 7757bd9e..e2874b9e 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -138,9 +138,16 @@ end end + shared_examples 'an attempted import' do + it 'should try to obtain the asset through the Sequencescape API' do + @asset = Asset.find_or_import_asset_with_barcode(@remote_asset.barcode) + expect(SequencescapeClient).to have_received(:find_by_uuid).with(@remote_asset.uuid) + end + end + shared_examples 'a plate or tube rack' do it 'should create the corresponding facts from the json' do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) + @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) @asset.facts.reload predicates = ["a", "pushTo", "purpose", "is", "contains", "contains", "study_name", "study_uuid"] @@ -151,7 +158,7 @@ end it 'should store the study uuid in a safe format' do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) + @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) expected_study_uuid = if @remote_asset.respond_to?(:wells) @remote_asset.wells.first.aliquots.first.study.uuid else @@ -166,7 +173,7 @@ context 'for the first time' do it 'should create the local asset' do expect(Asset.count).to eq(0) - Asset.find_or_import_asset_with_barcode(@barcode_plate) + Asset.find_or_import_asset_with_barcode(@barcode_asset) expect(Asset.count>0).to eq(true) end @@ -175,23 +182,23 @@ context 'when is already imported' do context 'when the remote source is not present anymore' do setup do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) + @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) allow(SequencescapeClient).to receive(:find_by_uuid).and_return(nil) end it 'should raise an exception' do - expect{Asset.find_or_import_asset_with_barcode(@barcode_plate)}.to raise_exception Assets::Import::RefreshSourceNotFoundAnymore + expect{Asset.find_or_import_asset_with_barcode(@barcode_asset)}.to raise_exception Assets::Import::RefreshSourceNotFoundAnymore end end context 'when the remote source is present' do setup do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) + @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) end it 'should not create a new local asset' do count = Asset.count - Asset.find_or_import_asset_with_barcode(@barcode_plate) + Asset.find_or_import_asset_with_barcode(@barcode_asset) expect(Asset.count).to eq(count) end @@ -199,7 +206,7 @@ it 'should not destroy any remote facts' do remote_facts = @asset.facts.from_remote_asset remote_facts.each(&:reload) - Asset.find_or_import_asset_with_barcode(@barcode_plate) + Asset.find_or_import_asset_with_barcode(@barcode_asset) expect{remote_facts.each(&:reload)}.not_to raise_error end end @@ -216,17 +223,17 @@ end it 'should destroy any remote facts that has changed' do - Asset.find_or_import_asset_with_barcode(@barcode_plate) + Asset.find_or_import_asset_with_barcode(@barcode_asset) expect{@fact_changed.reload}.to raise_exception ActiveRecord::RecordNotFound end it 'should destroy any contains dependant remote facts' do - Asset.find_or_import_asset_with_barcode(@barcode_plate) + Asset.find_or_import_asset_with_barcode(@barcode_asset) expect{@dependant_fact.reload}.to raise_exception ActiveRecord::RecordNotFound end it 'should re-create new remote facts' do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_plate) + @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) @asset.facts.reload expect(@asset.facts.from_remote_asset.all?{|f| f.object_asset != @well_changed}) end @@ -254,15 +261,15 @@ context 'when importing a local asset' do setup do - @barcode_plate = generate(:barcode) - @asset = Asset.create!(barcode: @barcode_plate) + @barcode_asset = generate(:barcode) + @asset = Asset.create!(barcode: @barcode_asset) end it 'should return the local asset when looking by its barcode' do - expect(Asset.find_or_import_asset_with_barcode(@barcode_plate)).to eq(@asset) + expect(Asset.find_or_import_asset_with_barcode(@barcode_asset)).to eq(@asset) end - it 'should return the local asset when looking by its barcode' do + it 'should return the local asset when looking by its uuid' do expect(Asset.find_or_import_asset_with_barcode(@asset.uuid)).to eq(@asset) end end @@ -270,98 +277,86 @@ context 'when importing a remote asset' do let(:SequencescapeClient) { double('sequencescape_client') } - setup do - @remote_asset = build_remote_plate(barcode: generate(:barcode)) - @barcode_plate = @remote_asset.barcode - stub_client_with_asset(SequencescapeClient, @remote_asset) - end - context 'when the asset is a tube' do setup do - @remote_tube_asset = build_remote_tube(barcode: generate(:barcode)) - stub_client_with_asset(SequencescapeClient, @remote_tube_asset) + @remote_asset = build_remote_tube(barcode: generate(:barcode)) + @asset_barcode = @remote_asset.barcode + stub_client_with_asset(SequencescapeClient, @remote_asset) end - it 'should try to obtain a tube' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_tube_asset.barcode) - expect(SequencescapeClient).to have_received(:find_by_uuid).with(@remote_tube_asset.uuid) + it_behaves_like 'an attempted import' + + context 'when the supplier name has not been provided' do + setup do + sample_no_supplier_name = build_remote_sample( + sample_metadata: double('sample_metadata', + supplier_name: nil, + sample_common_name: 'species' + ) + ) + @remote_tube_asset_without_supplier = build_remote_tube( + barcode: generate(:barcode), + aliquots: [build_remote_aliquot(sample: sample_no_supplier_name)] + ) + stub_client_with_asset(SequencescapeClient, @remote_tube_asset_without_supplier) + end + + it 'imports the information of the tube but does not set any supplier name' do + @asset = Asset.find_or_import_asset_with_barcode(@remote_tube_asset_without_supplier.barcode) + @asset.facts.reload + expect(@asset.facts.with_predicate('supplier_sample_name').count).to eq(0) + end + end + + context 'when the supplier name has been provided' do + it 'imports the supplier name' do + @asset = Asset.find_or_import_asset_with_barcode(@asset_barcode) + expect(@asset.facts.with_predicate('supplier_sample_name').count).to eq(1) + end + + it 'imports the common name' do + @asset = Asset.find_or_import_asset_with_barcode(@asset_barcode) + expect(@asset.facts.with_predicate('sample_common_name').count).to eq(1) + end end end context 'when the asset is a plate' do setup do @remote_asset = build_remote_plate(barcode: generate(:barcode)) + @barcode_asset = @remote_asset.barcode stub_client_with_asset(SequencescapeClient, @remote_asset) end - it 'should try to obtain a plate' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_asset.barcode) - expect(SequencescapeClient).to have_received(:find_by_uuid).with(@remote_asset.uuid) - end + it_behaves_like 'a plate or tube rack' + it_behaves_like 'an attempted import' context 'when the supplier sample name has not been provided to some samples' do - context 'when the asset is a plate' do - setup do - wells = [ - build_remote_well('A1', aliquots: [build_remote_aliquot(sample: - build_remote_sample(sample_metadata: nil))]), - build_remote_well('B1', aliquots: [build_remote_aliquot(sample: - build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: nil)))]), - build_remote_well('C1', aliquots: [build_remote_aliquot(sample: - build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: 'a supplier name')))]), - build_remote_well('D1', aliquots: [build_remote_aliquot(sample: - build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: 'a supplier name')))]) - ] - @remote_asset_without_supplier = build_remote_plate(barcode: generate(:barcode), wells: wells) - stub_client_with_asset(SequencescapeClient, @remote_asset_without_supplier) - end - - it 'imports the information of the wells that have a supplier name' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_supplier.barcode) - wells = @asset.facts.with_predicate('contains').map(&:object_asset) - wells_with_info = wells.select{|w| w.facts.where(predicate: 'supplier_sample_name').count > 0} - locations_with_info = wells_with_info.map{|w| w.facts.with_predicate('location').first.object} - expect(locations_with_info).to eq(['C1','D1']) - end + setup do + wells = [ + build_remote_well('A1', aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: nil))]), + build_remote_well('B1', aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: double('sample_metadata', + sample_common_name: 'species', supplier_name: nil)))]), + build_remote_well('C1', aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: double('sample_metadata', + sample_common_name: 'species', supplier_name: 'a supplier name')))]), + build_remote_well('D1', aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: double('sample_metadata', + sample_common_name: 'species', supplier_name: 'a supplier name')))]) + ] + @remote_asset_without_supplier = build_remote_plate(barcode: generate(:barcode), wells: wells) + stub_client_with_asset(SequencescapeClient, @remote_asset_without_supplier) end - context 'when the asset is a tube' do - context 'when the supplier name has not been provided' do - setup do - @remote_tube_asset_without_supplier = build_remote_tube(barcode: generate(:barcode), aliquots: [ - build_remote_aliquot(sample: build_remote_sample(sample_metadata: - double('sample_metadata', supplier_name: nil, sample_common_name: 'species'))) - ]) - stub_client_with_asset(SequencescapeClient, @remote_tube_asset_without_supplier) - end - - it 'imports the information of the tube but does not set any supplier name' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_tube_asset_without_supplier.barcode) - @asset.facts.reload - expect(@asset.facts.with_predicate('supplier_sample_name').count).to eq(0) - end - end - - context 'when the supplier name has been provided' do - setup do - @remote_tube_asset_with_supplier = build_remote_tube(barcode: generate(:barcode)) - stub_client_with_asset(SequencescapeClient, @remote_tube_asset_with_supplier) - end - - it 'imports the supplier name' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_tube_asset_with_supplier.barcode) - expect(@asset.facts.with_predicate('supplier_sample_name').count).to eq(1) - end - - it 'imports the common name' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_tube_asset_with_supplier.barcode) - expect(@asset.facts.with_predicate('sample_common_name').count).to eq(1) - end - end + it 'imports the information of the wells that have a supplier name' do + @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_supplier.barcode) + wells = @asset.facts.with_predicate('contains').map(&:object_asset) + wells_with_info = wells.select{|w| w.facts.where(predicate: 'supplier_sample_name').count > 0} + locations_with_info = wells_with_info.map{|w| w.facts.with_predicate('location').first.object} + expect(locations_with_info).to eq(['C1','D1']) end end @@ -397,15 +392,13 @@ context 'when the asset is a tube rack' do setup do @remote_asset = build_remote_tube_rack(barcode: generate(:barcode)) - @barcode_plate = @remote_asset.barcode + @barcode_asset = @remote_asset.barcode stub_client_with_asset(SequencescapeClient, @remote_asset) end it_behaves_like 'a plate or tube rack' + it_behaves_like 'an attempted import' end - - it_behaves_like 'a plate or tube rack' - end end end diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index 45deba56..4d3d57e4 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -75,7 +75,7 @@ def build_remote_sample(opts={}) attrs_for_sample = { sanger_sample_id: 'TEST-123', name: 'a sample name', - sample_metadata: double('sample_metadata', {supplier_name: 'a supplier', sample_common_name: 'specie'}), + sample_metadata: double('sample_metadata', {supplier_name: 'a supplier', sample_common_name: 'species'}), #sanger: double('sanger', { sample_id: 'TEST-123', name: 'a sample name'}), uuid: SecureRandom.uuid, #supplier: double('supplier', {sample_name: 'a supplier'}), From 7e0ae1621ea7a7df6dcdaec02bdb6a8df08ca0f9 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Thu, 28 May 2020 12:00:30 +0100 Subject: [PATCH 026/303] adapt supplier sample name missing test for tube racks --- spec/models/assets/import_spec.rb | 29 +++++++++++++++++++++++++++++ spec/remote_assets_helper.rb | 20 ++++++++------------ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index e2874b9e..4dad9797 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -398,6 +398,35 @@ it_behaves_like 'a plate or tube rack' it_behaves_like 'an attempted import' + + context 'when the supplier sample name has not been provided to some samples' do + setup do + racked_tubes = [ + build_remote_racked_tube('A1', build_remote_tube(aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: nil))])), + build_remote_racked_tube('B1', build_remote_tube(aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: double('sample_metadata', + sample_common_name: 'species', supplier_name: nil)))])), + build_remote_racked_tube('C1', build_remote_tube(aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: double('sample_metadata', + sample_common_name: 'species', supplier_name: 'a supplier name')))])), + build_remote_racked_tube('D1', build_remote_tube(aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: double('sample_metadata', + sample_common_name: 'species', supplier_name: 'a supplier name')))])) + ] + @remote_asset_without_supplier = build_remote_tube_rack(barcode: generate(:barcode), racked_tubes: racked_tubes) + stub_client_with_asset(SequencescapeClient, @remote_asset_without_supplier) + end + + it 'imports the information of the tubes that have a supplier name' do + @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_supplier.barcode) + tubes = @asset.facts.with_predicate('contains').map(&:object_asset) + tubes_with_info = tubes.select{|t| t.facts.where(predicate: 'supplier_sample_name').count > 0} + locations_with_info = tubes_with_info.map{|t| t.facts.with_predicate('location').first.object} + + expect(locations_with_info).to eq(['C1','D1']) + end + end end end end diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index 4d3d57e4..51776a08 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -37,30 +37,26 @@ def build_remote_tube_rack(opts = {}) def build_remote_racked_tube(coordinate, tube = nil) obj = { coordinate: coordinate, - tube: tube || double('tube', tube_standard_options) + tube: tube || build_remote_tube } my_double = double('racked_tube', obj) end def build_remote_tube(opts = {}) - obj = tube_standard_options(opts) - my_double = double('remote_asset', obj) - - allow(my_double).to receive(:attributes).and_return(obj) - allow(my_double).to receive(:class).and_return(Sequencescape::Tube) - - my_double - end - - def tube_standard_options(opts = {}) purpose = double('purpose', name: 'A purpose') - { + obj = { uuid: SecureRandom.uuid, type: 'tubes', plate_purpose: purpose, aliquots: [build_remote_aliquot] }.merge(opts) + my_double = double('remote_asset', obj) + + allow(my_double).to receive(:attributes).and_return(obj) + allow(my_double).to receive(:class).and_return(Sequencescape::Tube) + + my_double end def build_remote_aliquot(opts={}) From d41e838e86a9966ef173c8330eb5e37cc9f0339f Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Thu, 28 May 2020 12:03:19 +0100 Subject: [PATCH 027/303] remove code duplication by making shared_example --- spec/models/assets/import_spec.rb | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 4dad9797..8b69123f 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -242,6 +242,17 @@ end end + shared_examples 'a partial import of samples' do + it 'imports the information of the tubes that have a supplier name' do + @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_supplier.barcode) + tubes = @asset.facts.with_predicate('contains').map(&:object_asset) + tubes_with_info = tubes.select{|t| t.facts.where(predicate: 'supplier_sample_name').count > 0} + locations_with_info = tubes_with_info.map{|t| t.facts.with_predicate('location').first.object} + + expect(locations_with_info).to eq(['C1','D1']) + end + end + context '#find_or_import_asset_with_barcode' do context 'when importing an asset that does not exist' do setup do @@ -350,14 +361,7 @@ stub_client_with_asset(SequencescapeClient, @remote_asset_without_supplier) end - it 'imports the information of the wells that have a supplier name' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_supplier.barcode) - wells = @asset.facts.with_predicate('contains').map(&:object_asset) - wells_with_info = wells.select{|w| w.facts.where(predicate: 'supplier_sample_name').count > 0} - locations_with_info = wells_with_info.map{|w| w.facts.with_predicate('location').first.object} - - expect(locations_with_info).to eq(['C1','D1']) - end + it_behaves_like 'a partial import of samples' end context 'when the plate does not have aliquots in its wells' do @@ -418,14 +422,7 @@ stub_client_with_asset(SequencescapeClient, @remote_asset_without_supplier) end - it 'imports the information of the tubes that have a supplier name' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_supplier.barcode) - tubes = @asset.facts.with_predicate('contains').map(&:object_asset) - tubes_with_info = tubes.select{|t| t.facts.where(predicate: 'supplier_sample_name').count > 0} - locations_with_info = tubes_with_info.map{|t| t.facts.with_predicate('location').first.object} - - expect(locations_with_info).to eq(['C1','D1']) - end + it_behaves_like 'a partial import of samples' end end end From 14172c4dc334ce71c4c73e1ea9a80ef0dd73f2b4 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Mon, 1 Jun 2020 11:38:16 +0100 Subject: [PATCH 028/303] tidy up export_spec a bit --- spec/models/assets/export_spec.rb | 470 +++++++++++++++--------------- 1 file changed, 233 insertions(+), 237 deletions(-) diff --git a/spec/models/assets/export_spec.rb b/spec/models/assets/export_spec.rb index 33c6781f..80cac6b6 100644 --- a/spec/models/assets/export_spec.rb +++ b/spec/models/assets/export_spec.rb @@ -4,250 +4,246 @@ RSpec.describe 'Assets::Export' do include RemoteAssetsHelper - describe 'Export' do - context '#racking_info' do - it 'unquotes sample uuid and sample_tube, ignoring unrelated attributes' do - uuid = SecureRandom.uuid - asset = create(:asset) - well1 = create(:asset) - well2 = create(:asset) - - sample_tube = create(:asset) - well1.facts << [ - create(:fact, predicate: 'sample_uuid', object: TokenUtil.quote(uuid)), - create(:fact, predicate: 'this will be ignored', object: 'for sure') - ] - well2.facts << [ - create(:fact, predicate: 'sample_tube', object_asset: sample_tube), - create(:fact, predicate: 'study_uuid', object: TokenUtil.quote(uuid)), - create(:fact, predicate: 'sanger_sample_name', object: "name1") - ] - - asset.facts << [ - create(:fact, predicate: 'contains', object_asset: well1), - create(:fact, predicate: 'contains', object_asset: well2) - ] - - expect(asset.racking_info(well1)).to eq({sample_uuid: TokenUtil.unquote(uuid)}) - expect(asset.racking_info(well2)).to eq({ - sample_tube_uuid: sample_tube.uuid, - sanger_sample_name: 'name1' - }) - end - - it 'generates an attribute object for a well' do - facts = %Q{ - :s1 :a :SampleTube . - :s2 :a :SampleTube . - :s3 :a :SampleTube . - :s4 :a :SampleTube . - :tube1 :a :Tube ; - :location "A1" ; - :sample_tube :s1 . - :tube2 :a :Tube ; - :location "B1" ; - :sample_tube :s2 . - :tube3 :a :Tube ; - :location "C1" ; - :sample_tube :s3 . - :tube4 :a :Tube ; - :location "D1" ; - :sample_tube :s4 . - - :rack1 :a :TubeRack ; - :contains :tube1, :tube2, :tube3, :tube4 . - } - @assets = SupportN3::parse_facts(facts) - - @rack1 = Asset.find_by(uuid: 'rack1') - expect(@rack1.attributes_to_update).to eq([ - {sample_tube_uuid: "s1", location: "A1"}, - {sample_tube_uuid: "s2", location: "B1"}, - {sample_tube_uuid: "s3", location: "C1"}, - {sample_tube_uuid: "s4", location: "D1"}]) - end + context '#racking_info' do + it 'unquotes sample_uuid and sample_tube, ignoring unrelated attributes' do + uuid = SecureRandom.uuid + asset = create(:asset) + well1 = create(:asset) + well2 = create(:asset) + + sample_tube = create(:asset) + well1.facts << [ + create(:fact, predicate: 'sample_uuid', object: TokenUtil.quote(uuid)), + create(:fact, predicate: 'this will be ignored', object: 'for sure') + ] + well2.facts << [ + create(:fact, predicate: 'sample_tube', object_asset: sample_tube), + create(:fact, predicate: 'study_uuid', object: TokenUtil.quote(uuid)), + create(:fact, predicate: 'sanger_sample_name', object: "name1") + ] + + asset.facts << [ + create(:fact, predicate: 'contains', object_asset: well1), + create(:fact, predicate: 'contains', object_asset: well2) + ] + + expect(asset.racking_info(well1)).to eq({sample_uuid: TokenUtil.unquote(uuid)}) + expect(asset.racking_info(well2)).to eq({ + sample_tube_uuid: sample_tube.uuid, + sanger_sample_name: 'name1' + }) + end + + it 'generates an attribute object for a well' do + facts = %Q{ + :s1 :a :SampleTube . + :s2 :a :SampleTube . + :s3 :a :SampleTube . + :s4 :a :SampleTube . + :tube1 :a :Tube ; + :location "A1" ; + :sample_tube :s1 . + :tube2 :a :Tube ; + :location "B1" ; + :sample_tube :s2 . + :tube3 :a :Tube ; + :location "C1" ; + :sample_tube :s3 . + :tube4 :a :Tube ; + :location "D1" ; + :sample_tube :s4 . + + :rack1 :a :TubeRack ; + :contains :tube1, :tube2, :tube3, :tube4 . + } + @assets = SupportN3::parse_facts(facts) + + @rack1 = Asset.find_by(uuid: 'rack1') + expect(@rack1.attributes_to_update).to eq([ + {sample_tube_uuid: "s1", location: "A1"}, + {sample_tube_uuid: "s2", location: "B1"}, + {sample_tube_uuid: "s3", location: "C1"}, + {sample_tube_uuid: "s4", location: "D1"}]) + end + end + + context '#update_plate' do + let(:step_type) { create :step_type } + let(:step) { create :step, step_type: step_type, state: Step::STATE_RUNNING } + let(:updates) { FactChanges.new } + let(:plate) { build_remote_plate } + let(:asset) { create :asset } + + it 'updates all wells uuids at same location' do + well = create :asset + well.facts << Fact.create(predicate: 'location', object: 'A1') + well2 = create :asset + well2.facts << Fact.create(predicate: 'location', object: 'A4') + asset.facts << Fact.create(predicate: 'contains', object_asset_id: well.id) + asset.facts << Fact.create(predicate: 'contains', object_asset_id: well2.id) + + expect(well.uuid).not_to eq(plate.wells.first.uuid) + expect(well2.uuid).not_to eq(plate.wells.last.uuid) + + asset.update_plate(plate, updates) + updates.apply(step) + expect(asset.facts.with_predicate('contains').count).to eq(plate.wells.count) + well.reload + well2.reload + expect(well.uuid).to eq(plate.wells.first.uuid) + expect(well2.uuid).to eq(plate.wells.last.uuid) + end + end + context '#update_sequencescape' do + let(:step_type) { create :step_type } + let(:step) { create :step, step_type: step_type, state: Step::STATE_RUNNING } + let(:user) { create :user, username: 'test' } + let(:print_config) { {"Plate"=>'Pum', "Tube"=>'Pim'} } + let(:plate) { build_remote_plate } + let(:asset) { create :asset } + + it 'updates a plate in sequencescape' do + allow(SequencescapeClient).to receive(:version_1_find_by_uuid).with(asset.uuid).and_return(nil) + allow(SequencescapeClient).to receive(:version_1_find_by_uuid).with(plate.uuid).and_return(plate) + allow(SequencescapeClient).to receive(:find_by_uuid).with(asset.uuid).and_return(nil) + allow(SequencescapeClient).to receive(:find_by_uuid).with(plate.uuid).and_return(plate) + allow(SequencescapeClient).to receive(:create_plate).and_return(plate) + barcode = double('barcode') + allow(barcode).to receive(:prefix).and_return('DN') + allow(barcode).to receive(:number).and_return('123') + allow(plate).to receive(:barcode).and_return(barcode) + + expect(asset.facts.where(predicate: 'contains').count).to eq(0) + asset.update_sequencescape(print_config, user, step).apply(step) + asset.refresh + expect(asset.facts.where(predicate: 'contains').count).to eq(plate.wells.count) end - context '#update_plate' do - let(:step_type) { create :step_type } - let(:step) { create :step, step_type: step_type, state: Step::STATE_RUNNING } - let(:updates) { FactChanges.new } - let(:plate) { build_remote_plate } - let(:asset) { create :asset } - before do - - end - it 'updates all wells uuids at same location' do - well = create :asset - well.facts << Fact.create(predicate: 'location', object: 'A1') - well2 = create :asset - well2.facts << Fact.create(predicate: 'location', object: 'A4') - asset.facts << Fact.create(predicate: 'contains', object_asset_id: well.id) - asset.facts << Fact.create(predicate: 'contains', object_asset_id: well2.id) - - expect(well.uuid).not_to eq(plate.wells.first.uuid) - expect(well2.uuid).not_to eq(plate.wells.last.uuid) - - asset.update_plate(plate, updates) - updates.apply(step) - expect(asset.facts.with_predicate('contains').count).to eq(plate.wells.count) - well.reload - well2.reload - expect(well.uuid).to eq(plate.wells.first.uuid) - expect(well2.uuid).to eq(plate.wells.last.uuid) - end + end + + context '#attributes_to_update' do + it 'can convert location to Sequencescape location format' do + %Q{ + I have a tube rack that contains 4 tubes with names tube1, tube2, + tube3 and tube4. + tube1 is in location A01, tube2 in B01, tube3 in C01 and tube4 in D1. + Each tube has a sample tube inside, with names s1, s2, s3 and s4. + } + facts = %Q{ + :s1 :a :SampleTube . + :s2 :a :SampleTube . + :s3 :a :SampleTube . + :s4 :a :SampleTube . + :rack2 :a :TubeRack ; + :contains :tube1, :tube2, :tube3, :tube4 . + + :tube1 :a :Tube ; + :location "A01" ; + :sample_tube :s1 . + :tube2 :a :Tube ; + :location "B01" ; + :sample_tube :s2 . + :tube3 :a :Tube ; + :location "C01" ; + :sample_tube :s3 . + :tube4 :a :Tube ; + :location "D1" ; + :sample_tube :s4 . + } + @assets = SupportN3::parse_facts(facts) + @rack2 = Asset.find_by(uuid: 'rack2') + expect(@rack2.attributes_to_update).to eq([ + {sample_tube_uuid: "s1", location: "A1"}, + {sample_tube_uuid: "s2", location: "B1"}, + {sample_tube_uuid: "s3", location: "C1"}, + {sample_tube_uuid: "s4", location: "D1"}]) end - context '#update_sequencescape' do - let(:step_type) { create :step_type } - let(:step) { create :step, step_type: step_type, state: Step::STATE_RUNNING } - let(:user) { create :user, username: 'test' } - let(:print_config) { {"Plate"=>'Pum', "Tube"=>'Pim'} } - let(:plate) { build_remote_plate } - let(:asset) { create :asset } - - it 'updates a plate in sequencescape' do - allow(SequencescapeClient).to receive(:version_1_find_by_uuid).with(asset.uuid).and_return(nil) - allow(SequencescapeClient).to receive(:version_1_find_by_uuid).with(plate.uuid).and_return(plate) - allow(SequencescapeClient).to receive(:find_by_uuid).with(asset.uuid).and_return(nil) - allow(SequencescapeClient).to receive(:find_by_uuid).with(plate.uuid).and_return(plate) - allow(SequencescapeClient).to receive(:create_plate).and_return(plate) - barcode = double('barcode') - allow(barcode).to receive(:prefix).and_return('DN') - allow(barcode).to receive(:number).and_return('123') - allow(plate).to receive(:barcode).and_return(barcode) - - expect(asset.facts.where(predicate: 'contains').count).to eq(0) - asset.update_sequencescape(print_config, user, step).apply(step) - asset.refresh - expect(asset.facts.where(predicate: 'contains').count).to eq(plate.wells.count) - end + it 'generates the attributes when the locations are not duplicated' do + facts = %Q{ + :s1 :a :SampleTube . + :s2 :a :SampleTube . + :s3 :a :SampleTube . + :s4 :a :SampleTube . + :rack2 :a :TubeRack ; + :contains :tube1, :tube2, :tube3, :tube4 . + + :tube1 :a :Tube ; + :location "A1" ; + :sample_tube :s1 . + :tube2 :a :Tube ; + :location "B1" ; + :sample_tube :s2 . + :tube3 :a :Tube ; + :location "C1" ; + :sample_tube :s3 . + :tube4 :a :Tube ; + :location "D1" ; + :sample_tube :s4 . + } + @assets = SupportN3::parse_facts(facts) + @rack2 = Asset.find_by(uuid: 'rack2') + expect(@rack2.attributes_to_update).to eq([ + {sample_tube_uuid: "s1", location: "A1"}, + {sample_tube_uuid: "s2", location: "B1"}, + {sample_tube_uuid: "s3", location: "C1"}, + {sample_tube_uuid: "s4", location: "D1"}]) + end + it 'fails when trying to generate attributes when the locations are duplicated' do + facts = %Q{ + :s1 :a :SampleTube . + :s2 :a :SampleTube . + :s3 :a :SampleTube . + :s4 :a :SampleTube . + :rack2 :a :TubeRack ; + :contains :tube1, :tube2, :tube3, :tube4 . + :tube1 :a :Tube ; + :location "A1" ; + :sample_tube :s1 . + :tube2 :a :Tube ; + :location "B1" ; + :sample_tube :s2 . + :tube3 :a :Tube ; + :location "A1" ; + :sample_tube :s3 . + :tube4 :a :Tube ; + :location "B1" ; + :sample_tube :s4 . + } + @assets = SupportN3::parse_facts(facts) + @rack2 = Asset.find_by(uuid: 'rack2') + expect{@rack2.attributes_to_update}.to raise_exception Assets::Export::DuplicateLocations end - context '#attributes_to_update' do - it 'can convert location to Sequencescape location format' do - %Q{ - I have a tube rack that contains 4 tubes with names tube1, tube2, - tube3 and tube4. - tube1 is in location A01, tube2 in B01, tube3 in C01 and tube4 in D1. - Each tube has a sample tube inside, with names s1, s2, s3 and s4. - } - facts = %Q{ - :s1 :a :SampleTube . - :s2 :a :SampleTube . - :s3 :a :SampleTube . - :s4 :a :SampleTube . - :rack2 :a :TubeRack ; - :contains :tube1, :tube2, :tube3, :tube4 . - - :tube1 :a :Tube ; - :location "A01" ; - :sample_tube :s1 . - :tube2 :a :Tube ; - :location "B01" ; - :sample_tube :s2 . - :tube3 :a :Tube ; - :location "C01" ; - :sample_tube :s3 . - :tube4 :a :Tube ; - :location "D1" ; - :sample_tube :s4 . - } - @assets = SupportN3::parse_facts(facts) - @rack2 = Asset.find_by(uuid: 'rack2') - expect(@rack2.attributes_to_update).to eq([ - {sample_tube_uuid: "s1", location: "A1"}, - {sample_tube_uuid: "s2", location: "B1"}, - {sample_tube_uuid: "s3", location: "C1"}, - {sample_tube_uuid: "s4", location: "D1"}]) - end - it 'generates the attributes when the locations are not duplicated' do - facts = %Q{ - :s1 :a :SampleTube . - :s2 :a :SampleTube . - :s3 :a :SampleTube . - :s4 :a :SampleTube . - :rack2 :a :TubeRack ; - :contains :tube1, :tube2, :tube3, :tube4 . - - :tube1 :a :Tube ; - :location "A1" ; - :sample_tube :s1 . - :tube2 :a :Tube ; - :location "B1" ; - :sample_tube :s2 . - :tube3 :a :Tube ; - :location "C1" ; - :sample_tube :s3 . - :tube4 :a :Tube ; - :location "D1" ; - :sample_tube :s4 . - } - @assets = SupportN3::parse_facts(facts) - @rack2 = Asset.find_by(uuid: 'rack2') - expect(@rack2.attributes_to_update).to eq([ - {sample_tube_uuid: "s1", location: "A1"}, - {sample_tube_uuid: "s2", location: "B1"}, - {sample_tube_uuid: "s3", location: "C1"}, - {sample_tube_uuid: "s4", location: "D1"}]) - end - - it 'fails when trying to generate attributes when the locations are duplicated' do - facts = %Q{ - :s1 :a :SampleTube . - :s2 :a :SampleTube . - :s3 :a :SampleTube . - :s4 :a :SampleTube . - :rack2 :a :TubeRack ; - :contains :tube1, :tube2, :tube3, :tube4 . - :tube1 :a :Tube ; - :location "A1" ; - :sample_tube :s1 . - :tube2 :a :Tube ; - :location "B1" ; - :sample_tube :s2 . - :tube3 :a :Tube ; - :location "A1" ; - :sample_tube :s3 . - :tube4 :a :Tube ; - :location "B1" ; - :sample_tube :s4 . - } - @assets = SupportN3::parse_facts(facts) - @rack2 = Asset.find_by(uuid: 'rack2') - expect{@rack2.attributes_to_update}.to raise_exception Assets::Export::DuplicateLocations - end - - it 'does not export locations without a sample in it' do - facts = %Q{ - :s1 :a :SampleTube . - :s2 :a :SampleTube . - :s3 :a :SampleTube . - :s4 :a :SampleTube . - :rack2 :a :TubeRack ; - :contains :tube1, :tube2, :tube3, :tube4 . - - :tube1 :a :Tube ; - :location "A1" ; - :sample_tube :s1 . - :tube2 :a :Tube ; - :location "B1" ; - :sample_tube :s2 . - :tube3 :a :Tube ; - :location "C1" ; - :aliquotType "DNA" . - :tube4 :a :Tube ; - :location "D1" ; - :sample_tube :s4 . - } - @assets = SupportN3::parse_facts(facts) - @rack2 = Asset.find_by(uuid: 'rack2') - expect(@rack2.attributes_to_update).to eq([ - {sample_tube_uuid: "s1", location: "A1"}, - {sample_tube_uuid: "s2", location: "B1"}, - {sample_tube_uuid: "s4", location: "D1"}]) - end + it 'does not export locations without a sample in it' do + facts = %Q{ + :s1 :a :SampleTube . + :s2 :a :SampleTube . + :s3 :a :SampleTube . + :s4 :a :SampleTube . + :rack2 :a :TubeRack ; + :contains :tube1, :tube2, :tube3, :tube4 . + + :tube1 :a :Tube ; + :location "A1" ; + :sample_tube :s1 . + :tube2 :a :Tube ; + :location "B1" ; + :sample_tube :s2 . + :tube3 :a :Tube ; + :location "C1" ; + :aliquotType "DNA" . + :tube4 :a :Tube ; + :location "D1" ; + :sample_tube :s4 . + } + @assets = SupportN3::parse_facts(facts) + @rack2 = Asset.find_by(uuid: 'rack2') + expect(@rack2.attributes_to_update).to eq([ + {sample_tube_uuid: "s1", location: "A1"}, + {sample_tube_uuid: "s2", location: "B1"}, + {sample_tube_uuid: "s4", location: "D1"}]) end end end From c65d73537199baaea0d8e26947e2351b05a43486 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Mon, 1 Jun 2020 16:24:39 +0100 Subject: [PATCH 029/303] Adding documenting comments and tidying up a bit --- app/models/assets/export.rb | 45 +++++++++++------------ lib/sequencescape_client.rb | 2 + script/runners/transfer_plate_to_plate.rb | 6 +++ script/runners/update_sequencescape.rb | 6 ++- 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/app/models/assets/export.rb b/app/models/assets/export.rb index a69df557..dda21064 100644 --- a/app/models/assets/export.rb +++ b/app/models/assets/export.rb @@ -1,29 +1,19 @@ module Assets::Export - - class DuplicateLocations < StandardError ; end - def update_sequencescape(print_config, user, step) - _update_sequencescape(print_config, user, step) #.apply(step) - #activities_affected.each{|a| a.touch } - #refresh - end - - def _update_sequencescape(print_config, user, step) + def update_sequencescape(_print_config, user, _step) FactChanges.new.tap do |updates| begin + # remote (Sequencescape) updates instance = SequencescapeClient.version_1_find_by_uuid(uuid) - unless instance - instance = SequencescapeClient.create_plate(class_name, {}) if class_name - end - unless attributes_to_update.empty? - SequencescapeClient.update_extraction_attributes(instance, attributes_to_update, user.username) - end + instance = create_remote_asset unless instance + create_or_update_remote_contained_assets unless attributes_to_send.empty? + # local (Samples Extraction) updates old_barcode = barcode update_attributes(:uuid => instance.uuid, :barcode => code39_barcode(instance)) - update_plate(instance, updates) + update_wells(instance, updates) updates.add(self, 'beforeBarcode', old_barcode) if old_barcode updates.add_remote(self, 'purpose', class_name) if class_name @@ -44,6 +34,15 @@ def _update_sequencescape(print_config, user, step) end end + def create_remote_asset + SequencescapeClient.create_plate(class_name, {}) if class_name + end + + def create_or_update_remote_contained_assets + # create the (remote) aliquots against the wells created above, or rearrange them (re-racking) + SequencescapeClient.update_extraction_attributes(instance, attributes_to_send, user.username) + end + def mark_to_print(updates) updates.add(self, 'is', 'readyForPrint') end @@ -54,7 +53,7 @@ def code39_barcode(instance) SBCF::SangerBarcode.new(prefix:prefix, number:number).human_barcode end - def update_plate(instance, updates) + def update_wells(instance, updates) instance.wells.each do |well| fact = fact_well_at(well.location) if fact @@ -84,7 +83,6 @@ def mark_as_updated(updates) end end - def duplicate_locations_in_plate? locations = facts.with_predicate('contains').map(&:object_asset).map do |a| a.facts.with_predicate('location').map(&:object) @@ -92,21 +90,21 @@ def duplicate_locations_in_plate? (locations.uniq.length != locations.length) end - def attributes_to_update + def attributes_to_send raise DuplicateLocations if duplicate_locations_in_plate? + facts.with_predicate('contains').map(&:object_asset).map do |well| - racking_info(well) + attributes_to_send_for_well(well) end.compact end - def has_sample? has_predicate_with_value?('supplier_sample_name') || has_relation_with_value?('sample_tube') || has_predicate_with_value?('sample_uuid') end - def racking_info(well) + def attributes_to_send_for_well(well) # If it was already in SS, always export it if well.has_literal?('pushedTo', 'Sequencescape') return { @@ -118,6 +116,7 @@ def racking_info(well) # Do not export any well information unless it has a sample defined for it return nil unless well.has_sample? + # extract the 'facts' that we want to send to Sequencescape for creation of wells well.facts.reduce({}) do |memo, fact| if (['sample_tube'].include?(fact.predicate)) memo["#{fact.predicate}_uuid".to_sym] = fact.object_asset.uuid @@ -131,7 +130,5 @@ def racking_info(well) end memo end - end - end diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index d24ec119..539bbe90 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -29,6 +29,8 @@ def self.version_1_find_by_uuid(uuid, type=:plate) return nil end + # below creates a record in the 'extraction_attributes' table in Sequencescape + # this, in turn, triggers creation of aliquots against the plate def self.update_extraction_attributes(instance, attrs, username='test') instance.extraction_attributes.create!(:attributes_update => attrs, :created_by => username) end diff --git a/script/runners/transfer_plate_to_plate.rb b/script/runners/transfer_plate_to_plate.rb index d7a19695..0fc3f9f1 100644 --- a/script/runners/transfer_plate_to_plate.rb +++ b/script/runners/transfer_plate_to_plate.rb @@ -1,5 +1,11 @@ require 'actions/plate_transfer' +# Stamps an Asset (plate or tube rack) to another Asset +# In the step type config, there should be: +# A condition group, with addFacts 'transfer:q', where 'q' is +# A new asset, with addFacts 'transferredFrom:p', where 'p' is above group +# If the new asset is destined for export for Sequencescape... +# ...add fact 'barcodeType:NoBarcode', and Samples Extraction won't create a barcode class TransferPlateToPlate attr_reader :asset_group diff --git a/script/runners/update_sequencescape.rb b/script/runners/update_sequencescape.rb index b1ee3bdb..cdb3246c 100644 --- a/script/runners/update_sequencescape.rb +++ b/script/runners/update_sequencescape.rb @@ -1,3 +1,8 @@ +# Creates or updates a plate in Sequencescape corresponding to the Samples Extraction Asset +# At time of writing, 'update' function is limited to 're-racking' +# Only works if the Asset has a fact 'pushTo:Sequencescape' +# Above fact can be pre-existing on the asset, or created in the same step that calls this class +# Calls the update_sequencescape method in export.rb class UpdateSequencescape attr_reader :asset_group, :step def initialize(params) @@ -25,7 +30,6 @@ def process end end end - end def out(val) From 2a8ccbb4798d0d682afd5744e4d3237e09698f6e Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Tue, 2 Jun 2020 09:58:34 +0100 Subject: [PATCH 030/303] set tube barcodes on import of a tube rack from SS --- app/models/assets/import.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 6a8fb128..339466eb 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -317,6 +317,7 @@ def annotate_tubes(asset, remote_asset, fact_changes) remote_asset.racked_tubes.each do |racked_tube| remote_tube = racked_tube.tube local_tube = Asset.find_or_create_by!(:uuid => remote_tube.uuid) + local_tube.update!(barcode: remote_tube.labware_barcode['human_barcode']) updates.replace_remote(asset, 'contains', local_tube) From 1659bf65f3970ba60dc7dbe9780c7a582a5b350b Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Tue, 2 Jun 2020 10:12:03 +0100 Subject: [PATCH 031/303] fix tests by adding barcode to tube mock --- spec/remote_assets_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index 51776a08..5c10e9c3 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -49,7 +49,8 @@ def build_remote_tube(opts = {}) uuid: SecureRandom.uuid, type: 'tubes', plate_purpose: purpose, - aliquots: [build_remote_aliquot] + aliquots: [build_remote_aliquot], + labware_barcode: { 'human_barcode' => 'test' } }.merge(opts) my_double = double('remote_asset', obj) From 01cf0baa8e4b8db6b7db494c489596e2ddd99689 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Fri, 5 Jun 2020 10:58:24 +0100 Subject: [PATCH 032/303] correct some mistakes with refactoring, and improve comment --- app/models/assets/export.rb | 4 ++-- script/runners/transfer_plate_to_plate.rb | 5 +++-- spec/models/assets/export_spec.rb | 22 +++++++++++----------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/app/models/assets/export.rb b/app/models/assets/export.rb index dda21064..76c4f11e 100644 --- a/app/models/assets/export.rb +++ b/app/models/assets/export.rb @@ -7,7 +7,7 @@ def update_sequencescape(_print_config, user, _step) # remote (Sequencescape) updates instance = SequencescapeClient.version_1_find_by_uuid(uuid) instance = create_remote_asset unless instance - create_or_update_remote_contained_assets unless attributes_to_send.empty? + create_or_update_remote_contained_assets(instance) unless attributes_to_send.empty? # local (Samples Extraction) updates old_barcode = barcode @@ -38,7 +38,7 @@ def create_remote_asset SequencescapeClient.create_plate(class_name, {}) if class_name end - def create_or_update_remote_contained_assets + def create_or_update_remote_contained_assets(instance) # create the (remote) aliquots against the wells created above, or rearrange them (re-racking) SequencescapeClient.update_extraction_attributes(instance, attributes_to_send, user.username) end diff --git a/script/runners/transfer_plate_to_plate.rb b/script/runners/transfer_plate_to_plate.rb index 0fc3f9f1..b4fa5a70 100644 --- a/script/runners/transfer_plate_to_plate.rb +++ b/script/runners/transfer_plate_to_plate.rb @@ -2,8 +2,9 @@ # Stamps an Asset (plate or tube rack) to another Asset # In the step type config, there should be: -# A condition group, with addFacts 'transfer:q', where 'q' is -# A new asset, with addFacts 'transferredFrom:p', where 'p' is above group +# A condition group, with name set (e.g. 'p') +# A new asset, with addFacts 'transferredFrom:p', where 'p' is the name of above group +# The new asset should also have the type specified, by adding fact 'a:Plate' or 'a:TubeRack' # If the new asset is destined for export for Sequencescape... # ...add fact 'barcodeType:NoBarcode', and Samples Extraction won't create a barcode class TransferPlateToPlate diff --git a/spec/models/assets/export_spec.rb b/spec/models/assets/export_spec.rb index 80cac6b6..d5d8b790 100644 --- a/spec/models/assets/export_spec.rb +++ b/spec/models/assets/export_spec.rb @@ -4,7 +4,7 @@ RSpec.describe 'Assets::Export' do include RemoteAssetsHelper - context '#racking_info' do + context '#attributes_to_send_for_well' do it 'unquotes sample_uuid and sample_tube, ignoring unrelated attributes' do uuid = SecureRandom.uuid asset = create(:asset) @@ -27,8 +27,8 @@ create(:fact, predicate: 'contains', object_asset: well2) ] - expect(asset.racking_info(well1)).to eq({sample_uuid: TokenUtil.unquote(uuid)}) - expect(asset.racking_info(well2)).to eq({ + expect(asset.attributes_to_send_for_well(well1)).to eq({sample_uuid: TokenUtil.unquote(uuid)}) + expect(asset.attributes_to_send_for_well(well2)).to eq({ sample_tube_uuid: sample_tube.uuid, sanger_sample_name: 'name1' }) @@ -59,7 +59,7 @@ @assets = SupportN3::parse_facts(facts) @rack1 = Asset.find_by(uuid: 'rack1') - expect(@rack1.attributes_to_update).to eq([ + expect(@rack1.attributes_to_send).to eq([ {sample_tube_uuid: "s1", location: "A1"}, {sample_tube_uuid: "s2", location: "B1"}, {sample_tube_uuid: "s3", location: "C1"}, @@ -67,7 +67,7 @@ end end - context '#update_plate' do + context '#update_wells' do let(:step_type) { create :step_type } let(:step) { create :step, step_type: step_type, state: Step::STATE_RUNNING } let(:updates) { FactChanges.new } @@ -85,7 +85,7 @@ expect(well.uuid).not_to eq(plate.wells.first.uuid) expect(well2.uuid).not_to eq(plate.wells.last.uuid) - asset.update_plate(plate, updates) + asset.update_wells(plate, updates) updates.apply(step) expect(asset.facts.with_predicate('contains').count).to eq(plate.wells.count) well.reload @@ -121,7 +121,7 @@ end end - context '#attributes_to_update' do + context '#attributes_to_send' do it 'can convert location to Sequencescape location format' do %Q{ I have a tube rack that contains 4 tubes with names tube1, tube2, @@ -152,7 +152,7 @@ } @assets = SupportN3::parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') - expect(@rack2.attributes_to_update).to eq([ + expect(@rack2.attributes_to_send).to eq([ {sample_tube_uuid: "s1", location: "A1"}, {sample_tube_uuid: "s2", location: "B1"}, {sample_tube_uuid: "s3", location: "C1"}, @@ -183,7 +183,7 @@ } @assets = SupportN3::parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') - expect(@rack2.attributes_to_update).to eq([ + expect(@rack2.attributes_to_send).to eq([ {sample_tube_uuid: "s1", location: "A1"}, {sample_tube_uuid: "s2", location: "B1"}, {sample_tube_uuid: "s3", location: "C1"}, @@ -213,7 +213,7 @@ } @assets = SupportN3::parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') - expect{@rack2.attributes_to_update}.to raise_exception Assets::Export::DuplicateLocations + expect{@rack2.attributes_to_send}.to raise_exception Assets::Export::DuplicateLocations end it 'does not export locations without a sample in it' do @@ -240,7 +240,7 @@ } @assets = SupportN3::parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') - expect(@rack2.attributes_to_update).to eq([ + expect(@rack2.attributes_to_send).to eq([ {sample_tube_uuid: "s1", location: "A1"}, {sample_tube_uuid: "s2", location: "B1"}, {sample_tube_uuid: "s4", location: "D1"}]) From 63c2ba929d0083b7e96a0fdc46b43d123ca45af1 Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Fri, 5 Jun 2020 11:02:26 +0100 Subject: [PATCH 033/303] another thing missed --- app/models/assets/export.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/assets/export.rb b/app/models/assets/export.rb index 76c4f11e..50dad07e 100644 --- a/app/models/assets/export.rb +++ b/app/models/assets/export.rb @@ -7,7 +7,7 @@ def update_sequencescape(_print_config, user, _step) # remote (Sequencescape) updates instance = SequencescapeClient.version_1_find_by_uuid(uuid) instance = create_remote_asset unless instance - create_or_update_remote_contained_assets(instance) unless attributes_to_send.empty? + create_or_update_remote_contained_assets(instance, user) unless attributes_to_send.empty? # local (Samples Extraction) updates old_barcode = barcode @@ -38,7 +38,7 @@ def create_remote_asset SequencescapeClient.create_plate(class_name, {}) if class_name end - def create_or_update_remote_contained_assets(instance) + def create_or_update_remote_contained_assets(instance, user) # create the (remote) aliquots against the wells created above, or rearrange them (re-racking) SequencescapeClient.update_extraction_attributes(instance, attributes_to_send, user.username) end From 80765bb9d7bb232e04badfd68b72d7b5f43f68bd Mon Sep 17 00:00:00 2001 From: Katy Taylor Date: Fri, 5 Jun 2020 15:44:06 +0100 Subject: [PATCH 034/303] add quotes around the 'object' in a fact when it is added in the edit step type page - this prevents the page from crashing when you add facts with spaces in the 'object', e.g. 'purpose: thing with spaces' --- app/assets/javascripts/condition_groups.js | 2 +- app/views/step_types/_form.html.erb | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/condition_groups.js b/app/assets/javascripts/condition_groups.js index 664747d2..98b42eca 100644 --- a/app/assets/javascripts/condition_groups.js +++ b/app/assets/javascripts/condition_groups.js @@ -59,7 +59,7 @@ }; proto.checkFactToN3 = function(group, fact) { - return ["?"+group.getName(), ":"+fact.predicate, fact.object? ":"+fact.object : fact.literal].join("\t ")+" ."; + return ["?"+group.getName(), ":"+fact.predicate, fact.object?'"""'+fact.object+ '"""': fact.literal].join("\t ")+" ."; }; proto.actionFactToN3 = function(group, fact) { diff --git a/app/views/step_types/_form.html.erb b/app/views/step_types/_form.html.erb index 1a40ddde..09418405 100644 --- a/app/views/step_types/_form.html.erb +++ b/app/views/step_types/_form.html.erb @@ -1,6 +1,3 @@ - - - <%= bootstrap_form_for(step_type, :html => { :"data-psd-component-class" => "ConditionGroups", :"data-psd-component-parameters" => condition_groups_init_for_step_type(@step_type)}) do |f| %> <% if step_type.errors.any? %>
@@ -13,6 +10,7 @@
<% end %> + <% readonly = params[:action] == 'show' %>
<%= f.text_field :name, :readonly => readonly %> @@ -52,7 +50,6 @@ >New Asset
- From fa4aa51ee7d22c45b874c4948743cb5224262e16 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 8 Jul 2020 08:38:10 +0100 Subject: [PATCH 035/303] Fix yarn install Yarn install was failing due to issues compiling dependencies. This updates the affected dependencies. --- Gemfile.lock | 2 +- yarn.lock | 258 ++++++++++++--------------------------------------- 2 files changed, 59 insertions(+), 201 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e92f178c..5adefaf6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -468,4 +468,4 @@ DEPENDENCIES yajl-ruby BUNDLED WITH - 1.16.2 + 2.1.4 diff --git a/yarn.lock b/yarn.lock index e688efbe..31aa084f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1999,6 +1999,13 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.0.tgz#9523e001306a32444b907423f1de2164222f6ab1" integrity sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw== +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" @@ -2254,11 +2261,6 @@ camelcase@^2.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= - camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -2409,7 +2411,7 @@ chokidar@^2.0.4: optionalDependencies: fsevents "^1.2.7" -chownr@^1.0.1, chownr@^1.1.1: +chownr@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== @@ -2988,7 +2990,7 @@ date-now@^0.1.4: resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= -debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -3026,11 +3028,6 @@ deep-equal-ident@^1.1.1: dependencies: lodash.isequal "^3.0" -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -3095,11 +3092,6 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" @@ -3807,6 +3799,11 @@ file-loader@^1.1.11: loader-utils "^1.0.2" schema-utils "^0.4.5" +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -3949,13 +3946,6 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-minipass@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== - dependencies: - minipass "^2.2.1" - fs-readdir-recursive@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" @@ -3977,12 +3967,12 @@ fs.realpath@^1.0.0: integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4" - integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw== + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== dependencies: - nan "^2.9.2" - node-pre-gyp "^0.10.0" + bindings "^1.5.0" + nan "^2.12.1" fstream@^1.0.0, fstream@^1.0.2: version "1.0.11" @@ -4346,7 +4336,7 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -4382,13 +4372,6 @@ iferr@^0.1.5: resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== - dependencies: - minimatch "^3.0.4" - ignore@^3.3.3: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" @@ -4461,11 +4444,6 @@ inherits@2.0.1: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= -ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - inquirer@^3.0.6: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" @@ -5538,21 +5516,11 @@ lodash._reinterpolate@~3.0.0: resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= -lodash.assign@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= - lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= -lodash.clonedeep@^4.3.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= - lodash.escape@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98" @@ -5605,11 +5573,6 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.mergewith@^4.6.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" - integrity sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ== - lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -5645,7 +5608,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== -lodash@^4.15.0, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.6.1: +lodash@^4.15.0, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.6.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -5843,21 +5806,6 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -minipass@^2.2.1, minipass@^2.3.4: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" - integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== - dependencies: - minipass "^2.2.1" - mississippi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f" @@ -5934,10 +5882,10 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@^2.10.0, nan@^2.9.2: - version "2.12.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" - integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== +nan@^2.12.1, nan@^2.13.2: + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" + integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== nanomatch@^1.2.9: version "1.2.13" @@ -5972,15 +5920,6 @@ nearley@^2.7.10: randexp "0.4.6" semver "^5.4.1" -needle@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== - dependencies: - debug "^2.1.2" - iconv-lite "^0.4.4" - sax "^1.2.4" - neo-async@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" @@ -6082,22 +6021,6 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" -node-pre-gyp@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" - integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - node-releases@^1.1.25: version "1.1.28" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.28.tgz#503c3c70d0e4732b84e7aaa2925fbdde10482d4a" @@ -6106,9 +6029,9 @@ node-releases@^1.1.25: semver "^5.3.0" node-sass@^4.9.2: - version "4.11.0" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.11.0.tgz#183faec398e9cbe93ba43362e2768ca988a6369a" - integrity sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA== + version "4.14.1" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5" + integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g== dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -6117,16 +6040,14 @@ node-sass@^4.9.2: get-stdin "^4.0.1" glob "^7.0.3" in-publish "^2.0.0" - lodash.assign "^4.2.0" - lodash.clonedeep "^4.3.2" - lodash.mergewith "^4.6.0" + lodash "^4.17.15" meow "^3.7.0" mkdirp "^0.5.1" - nan "^2.10.0" + nan "^2.13.2" node-gyp "^3.8.0" npmlog "^4.0.0" request "^2.88.0" - sass-graph "^2.2.4" + sass-graph "2.2.5" stdout-stream "^1.4.0" "true-case-path" "^1.0.2" @@ -6144,14 +6065,6 @@ node@^10.0.0: dependencies: abbrev "1" -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -6189,19 +6102,6 @@ normalize-url@^1.4.0: query-string "^4.1.0" sort-keys "^1.0.0" -npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== - -npm-packlist@^1.1.6: - version "1.4.1" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc" - integrity sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -6209,7 +6109,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -6404,13 +6304,6 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= - dependencies: - lcid "^1.0.0" - os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" @@ -6425,7 +6318,7 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@0, osenv@^0.1.4: +osenv@0: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== @@ -7506,16 +7399,6 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - react-dom@^16.4.1: version "16.8.4" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.4.tgz#1061a8e01a2b3b0c8160037441c3bf00a0e3bc48" @@ -8084,7 +7967,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2: +rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -8182,15 +8065,15 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sass-graph@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" - integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k= +sass-graph@2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8" + integrity sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag== dependencies: glob "^7.0.0" lodash "^4.0.0" scss-tokenizer "^0.2.3" - yargs "^7.0.0" + yargs "^13.3.2" sass-loader@^6.0.7: version "6.0.7" @@ -8590,7 +8473,7 @@ string-length@^2.0.0: astral-regex "^1.0.0" strip-ansi "^4.0.0" -string-width@^1.0.1, string-width@^1.0.2: +string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= @@ -8781,19 +8664,6 @@ tar@^2.0.0: fstream "^1.0.2" inherits "2" -tar@^4: - version "4.4.8" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" - integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.3.4" - minizlib "^1.1.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.2" - test-exclude@^5.2.3: version "5.2.3" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" @@ -9334,11 +9204,6 @@ whet.extend@~0.9.9: resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" integrity sha1-+HfVv2SMl+WqVC+twW1qJZucEaE= -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= - which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" @@ -9465,11 +9330,6 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== - yargs-parser@^13.1.1: version "13.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" @@ -9478,12 +9338,13 @@ yargs-parser@^13.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= +yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: - camelcase "^3.0.0" + camelcase "^5.0.0" + decamelize "^1.2.0" yargs-parser@^7.0.0: version "7.0.0" @@ -9508,24 +9369,21 @@ yargs@^13.3.0: y18n "^4.0.0" yargs-parser "^13.1.1" -yargs@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= +yargs@^13.3.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" require-directory "^2.1.1" - require-main-filename "^1.0.1" + require-main-filename "^2.0.0" set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^5.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" yargs@^8.0.2: version "8.0.2" From 11eb3d0478099d4e28566a43f7980c2324eef82c Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 8 Jul 2020 08:49:48 +0100 Subject: [PATCH 036/303] Upgrade caniuse-lite Can i use lite was spitting out deprecation warnings. This change updates it. It also removes the package from the package.json as we're only using it as a depenendency. --- package.json | 1 - yarn.lock | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 892c1293..56199769 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "dependencies": { "@rails/webpacker": "^3.2.2", "ajv": "^6.4.0", - "caniuse-lite": "^1.0.30000830", "classnames": "^2.2.6", "eslint": "^4.19.1", "fine-uploader": "^5.16.2", diff --git a/yarn.lock b/yarn.lock index 31aa084f..c8a9a2b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2296,7 +2296,7 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000942.tgz#e29e4c6afa3558edafe7c190c7f8bdd93fb7c486" integrity sha512-HB+j2/Gywe+0JPtEMw8ioTi4ykIOco9nfSGspMGIBocqi4aMYZYALP992RmhVcUyB0oS5h8nrKGk9fCF9L1VXA== -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000830, caniuse-lite@^1.0.30000844: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000844: version "1.0.30000942" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000942.tgz#454139b28274bce70bfe1d50c30970df7430c6e4" integrity sha512-wLf+IhZUy2rfz48tc40OH7jHjXjnvDFEYqBHluINs/6MgzoNLPf25zhE4NOVzqxLKndf+hau81sAW0RcGHIaBQ== From 138d258186ae4e705a55bb434656e91310a9987a Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 9 Jul 2020 14:30:36 +0100 Subject: [PATCH 037/303] Add heron_activities_view Completes #117 Adds a heron activiteis view --- ...0709123033_create_heron_activities_view.rb | 57 +++++++++ db/schema.rb | 56 ++++----- db/views_schema.rb | 7 ++ dump.rdb | Bin 0 -> 92 bytes lib/tasks/views_schema.rake | 43 +++++++ lib/views_schema.rb | 115 ++++++++++++++++++ spec/views/heron_activities_view_spec.rb | 95 +++++++++++++++ test/factories/activities.rb | 5 + test/factories/assets.rb | 28 +++++ test/factories/facts.rb | 5 +- 10 files changed, 382 insertions(+), 29 deletions(-) create mode 100644 db/migrate/20200709123033_create_heron_activities_view.rb create mode 100644 db/views_schema.rb create mode 100644 dump.rdb create mode 100644 lib/tasks/views_schema.rake create mode 100644 lib/views_schema.rb create mode 100644 spec/views/heron_activities_view_spec.rb diff --git a/db/migrate/20200709123033_create_heron_activities_view.rb b/db/migrate/20200709123033_create_heron_activities_view.rb new file mode 100644 index 00000000..33c41e93 --- /dev/null +++ b/db/migrate/20200709123033_create_heron_activities_view.rb @@ -0,0 +1,57 @@ +class CreateHeronActivitiesView < ActiveRecord::Migration[5.1] + def up + ActiveRecord::Base.connection.execute(<<~SQL + CREATE VIEW heron_activities_view AS + SELECT + IFNULL( + supplier_name_fact.object, + well_supplier_name_fact.object) AS "Supplier sample name", + input_asset.barcode AS "Input barcode", + output_asset.barcode AS "Output barcode", + activity_types.name AS "Activity type", + instruments.name AS "Instrument", + kits.barcode AS "Kit barcode", + kit_types.name AS "Kit type", + ac.completed_at AS "Date", + users.fullname AS "User", + ac.id AS "_activity_id_" + FROM activities AS ac + LEFT OUTER JOIN asset_groups_assets AS aga ON aga.asset_group_id = ac.asset_group_id + LEFT OUTER JOIN assets AS output_asset ON output_asset.id = aga.asset_id + LEFT OUTER JOIN activity_types ON ac.activity_type_id = activity_types.id + LEFT OUTER JOIN kits ON ac.kit_id = kits.id + LEFT OUTER JOIN kit_types ON kits.kit_type_id = kit_types.id + LEFT OUTER JOIN instruments ON ac.instrument_id = instruments.id + LEFT OUTER JOIN facts AS supplier_name_fact ON supplier_name_fact.asset_id = output_asset.id AND supplier_name_fact.predicate = "supplier_sample_name" + LEFT OUTER JOIN facts AS well_fact ON well_fact.asset_id = output_asset.id AND well_fact.predicate = "contains" + LEFT OUTER JOIN facts AS well_supplier_name_fact ON well_supplier_name_fact.asset_id = well_fact.object_asset_id AND well_supplier_name_fact.predicate = "supplier_sample_name" + LEFT OUTER JOIN assets AS input_asset ON input_asset.id = ( + SELECT object_asset_id FROM operations + INNER JOIN steps ON steps.id = operations.step_id + WHERE operations.predicate = 'transferredFrom' AND steps.activity_id = ac.id AND operations.object_asset_id IS NOT NULL + ORDER BY operations.created_at ASC, operations.id ASC + LIMIT 1 + ) + LEFT OUTER JOIN users ON users.id = ( + SELECT user_id FROM steps + WHERE steps.activity_id = ac.id AND steps.user_id IS NOT NULL + ORDER BY steps.created_at, steps.id DESC + LIMIT 1 + ) + WHERE + ac.state = 'finish' + AND (supplier_name_fact.id IS NOT NULL OR well_supplier_name_fact.id IS NOT NULL) + AND activity_types.name IN ('CGAP Heron Extraction 500ul - 16ul', + 'CGAP Heron Extraction 500ul - 24ul', + 'Illumina Extraction', + 'DNAP Heron Extraction 500ul - 24ul', + 'CGAP Heron Extraction 200ul - 24ul', + 'Heron R&D Extraction') + SQL + ) + end + + def down + ActiveRecord::Base.connection.execute('DROP VIEW IF EXISTS heron_activities_view') + end +end diff --git a/db/schema.rb b/db/schema.rb index ce70f7ad..6ae54d84 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,9 +10,9 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20191127154249) do +ActiveRecord::Schema.define(version: 20200709123033) do - create_table "actions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "actions", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "action_type", null: false t.integer "step_type_id" t.integer "subject_condition_group_id" @@ -26,7 +26,7 @@ t.index ["subject_condition_group_id"], name: "index_actions_on_subject_condition_group_id" end - create_table "activities", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "activities", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "activity_type_id" t.integer "instrument_id" t.integer "asset_group_id" @@ -43,7 +43,7 @@ t.index ["kit_id"], name: "index_activities_on_kit_id" end - create_table "activity_type_compatibilities", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "activity_type_compatibilities", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "asset_id" t.integer "activity_type_id" t.datetime "created_at", null: false @@ -52,7 +52,7 @@ t.index ["asset_id"], name: "index_activity_type_compatibilities_on_asset_id" end - create_table "activity_type_step_types", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "activity_type_step_types", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "activity_type_id" t.integer "step_type_id" t.datetime "created_at", null: false @@ -61,7 +61,7 @@ t.index ["step_type_id"], name: "index_activity_type_step_types_on_step_type_id" end - create_table "activity_types", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "activity_types", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "name" t.integer "superceded_by_id" t.datetime "created_at", null: false @@ -69,7 +69,7 @@ t.index ["superceded_by_id"], name: "index_activity_types_on_superceded_by_id" end - create_table "activity_types_instruments", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "activity_types_instruments", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "instrument_id" t.integer "activity_type_id" t.datetime "created_at", null: false @@ -78,7 +78,7 @@ t.index ["instrument_id"], name: "index_activity_types_instruments_on_instrument_id" end - create_table "asset_groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "asset_groups", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "activity_owner_id" @@ -87,7 +87,7 @@ t.string "uuid" end - create_table "asset_groups_assets", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "asset_groups_assets", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "asset_id" t.integer "asset_group_id" t.datetime "created_at", null: false @@ -96,7 +96,7 @@ t.index ["asset_id"], name: "index_asset_groups_assets_on_asset_id" end - create_table "assets", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "assets", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "uuid" t.string "barcode" t.datetime "created_at", null: false @@ -106,7 +106,7 @@ t.index ["barcode"], name: "index_assets_on_barcode" end - create_table "condition_groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "condition_groups", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "name" t.boolean "keep_selected", default: true t.integer "step_type_id" @@ -114,7 +114,7 @@ t.index ["step_type_id"], name: "index_condition_groups_on_step_type_id" end - create_table "conditions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "conditions", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "condition_group_id" t.string "predicate", null: false t.string "object" @@ -125,7 +125,7 @@ t.index ["object_condition_group_id"], name: "index_conditions_on_object_condition_group_id" end - create_table "delayed_jobs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "delayed_jobs", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "priority", default: 0, null: false t.integer "attempts", default: 0, null: false t.text "handler", limit: 4294967295, null: false @@ -140,7 +140,7 @@ t.index ["priority", "run_at"], name: "delayed_jobs_priority" end - create_table "facts", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "facts", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "asset_id" t.string "predicate", null: false t.string "object" @@ -158,14 +158,14 @@ t.index ["object_asset_id"], name: "index_facts_on_object_asset_id" end - create_table "instruments", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "instruments", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "barcode" t.string "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "kit_types", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "kit_types", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "name" t.integer "activity_type_id" t.datetime "created_at", null: false @@ -174,7 +174,7 @@ t.index ["activity_type_id"], name: "index_kit_types_on_activity_type_id" end - create_table "kits", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "kits", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "barcode", null: false t.integer "max_num_reactions" t.integer "num_reactions_performed" @@ -184,7 +184,7 @@ t.index ["kit_type_id"], name: "index_kits_on_kit_type_id" end - create_table "label_templates", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "label_templates", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "name", null: false t.string "template_type" t.integer "external_id", null: false @@ -192,7 +192,7 @@ t.datetime "updated_at", null: false end - create_table "operations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "operations", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "action_id" t.integer "step_id" t.integer "asset_id" @@ -208,7 +208,7 @@ t.index ["step_id"], name: "index_operations_on_step_id" end - create_table "printers", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "printers", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "name", null: false t.string "printer_type" t.boolean "default_printer", default: false, null: false @@ -216,7 +216,7 @@ t.datetime "updated_at", null: false end - create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "sessions", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "session_id", null: false t.text "data" t.datetime "created_at" @@ -225,7 +225,7 @@ t.index ["updated_at"], name: "index_sessions_on_updated_at" end - create_table "step_messages", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "step_messages", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| t.integer "step_id", null: false t.text "content", limit: 4294967295 t.datetime "created_at", null: false @@ -233,7 +233,7 @@ t.index ["step_id"], name: "index_step_messages_on_step_id" end - create_table "step_types", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "step_types", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "name" t.string "step_template" t.binary "n3_definition" @@ -247,7 +247,7 @@ t.index ["superceded_by_id"], name: "index_step_types_on_superceded_by_id" end - create_table "steps", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "steps", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "step_type_id" t.integer "user_id" t.date "completion_date" @@ -274,7 +274,7 @@ t.index ["user_id"], name: "index_steps_on_user_id" end - create_table "uploaded_files", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "uploaded_files", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| t.integer "asset_id" t.binary "data", limit: 16777215 t.string "filename" @@ -284,7 +284,7 @@ t.index ["asset_id"], name: "index_uploaded_files_on_asset_id" end - create_table "uploads", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "uploads", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "step_id" t.integer "activity_id" t.binary "data", limit: 16777215 @@ -296,7 +296,7 @@ t.index ["step_id"], name: "index_uploads_on_step_id" end - create_table "users", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "users", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "login" t.string "password" t.string "barcode" @@ -312,7 +312,7 @@ t.index ["tube_printer_id"], name: "index_users_on_tube_printer_id" end - create_table "work_orders", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "work_orders", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.integer "work_order_id" t.integer "activity_id" t.datetime "created_at", null: false diff --git a/db/views_schema.rb b/db/views_schema.rb new file mode 100644 index 00000000..799bd806 --- /dev/null +++ b/db/views_schema.rb @@ -0,0 +1,7 @@ +# This is an automatically generated file by rake:db:views:dump_schema +require 'views_schema' +ViewsSchema.create_view( +'heron_activities_view', +%Q{select ifnull(`supplier_name_fact`.`object`,`well_supplier_name_fact`.`object`) AS `Supplier sample name`,`input_asset`.`barcode` AS `Input barcode`,`output_asset`.`barcode` AS `Output barcode`,`activity_types`.`name` AS `Activity type`,`instruments`.`name` AS `Instrument`,`kits`.`barcode` AS `Kit barcode`,`kit_types`.`name` AS `Kit type`,`ac`.`completed_at` AS `Date`,`users`.`fullname` AS `User`,`ac`.`id` AS `_activity_id_` from (((((((((((`activities` `ac` left join `asset_groups_assets` `aga` on((`aga`.`asset_group_id` = `ac`.`asset_group_id`))) left join `assets` `output_asset` on((`output_asset`.`id` = `aga`.`asset_id`))) left join `activity_types` on((`ac`.`activity_type_id` = `activity_types`.`id`))) left join `kits` on((`ac`.`kit_id` = `kits`.`id`))) left join `kit_types` on((`kits`.`kit_type_id` = `kit_types`.`id`))) left join `instruments` on((`ac`.`instrument_id` = `instruments`.`id`))) left join `facts` `supplier_name_fact` on(((`supplier_name_fact`.`asset_id` = `output_asset`.`id`) and (`supplier_name_fact`.`predicate` = 'supplier_sample_name')))) left join `facts` `well_fact` on(((`well_fact`.`asset_id` = `output_asset`.`id`) and (`well_fact`.`predicate` = 'contains')))) left join `facts` `well_supplier_name_fact` on(((`well_supplier_name_fact`.`asset_id` = `well_fact`.`object_asset_id`) and (`well_supplier_name_fact`.`predicate` = 'supplier_sample_name')))) left join `assets` `input_asset` on((`input_asset`.`id` = (select `operations`.`object_asset_id` from (`operations` join `steps` on((`steps`.`id` = `operations`.`step_id`))) where ((`operations`.`predicate` = 'transferredFrom') and (`steps`.`activity_id` = `ac`.`id`) and (`operations`.`object_asset_id` is not null)) order by `operations`.`created_at`,`operations`.`id` limit 1)))) left join `users` on((`users`.`id` = (select `steps`.`user_id` from `steps` where ((`steps`.`activity_id` = `ac`.`id`) and (`steps`.`user_id` is not null)) order by `steps`.`created_at`,`steps`.`id` desc limit 1)))) where ((`ac`.`state` = 'finish') and ((`supplier_name_fact`.`id` is not null) or (`well_supplier_name_fact`.`id` is not null)) and (`activity_types`.`name` in ('CGAP Heron Extraction 500ul - 16ul','CGAP Heron Extraction 500ul - 24ul','Illumina Extraction','DNAP Heron Extraction 500ul - 24ul','CGAP Heron Extraction 200ul - 24ul','Heron R&D Extraction')))}, +algorithm: 'UNDEFINED', security: 'DEFINER' +) diff --git a/dump.rdb b/dump.rdb new file mode 100644 index 0000000000000000000000000000000000000000..180779667fa623486b8fc875b7ebff8fbeb55ca0 GIT binary patch literal 92 zcmWG?b@2=~Ffg$E#aWb^l3A=\w*) DEFINER=`[^`]*`@`[^`]*` SQL SECURITY (?\w*) VIEW `[^`]+` AS (?.*)\z/i.freeze + + def self.each_view + all_views.each do |name| + query = ActiveRecord::Base.connection.exec_query("SHOW CREATE TABLE #{name}").first + matched = REGEXP.match(query['Create View']) + yield(name, matched[:statement], matched[:algorithm], matched[:security]) + end + rescue ActiveRecord::StatementInvalid => e + puts Rainbow(WARNING).red.inverse + raise e + end + + def self.all_views + ActiveRecord::Base.connection.execute(" + SELECT TABLE_NAME AS name + FROM INFORMATION_SCHEMA.VIEWS + WHERE TABLE_SCHEMA = '#{ActiveRecord::Base.connection.current_database}';").map do |v| + # Behaviour depends on ruby version, so we need to work out what we have + v.is_a?(Hash) ? v['name'] : v.first + end.flatten + end + + # + # Creates a new view. Will fail if the view already exists. + # @param name [String] The name of the view to create + # @param statement [String,ActiveRecord::Relation] SQL select statement or equivalent rails relation object + # @param algorithm [String] View algorithm to use, either UNDEFINED MERGE TEMPTABLE (default UNDEFINED) + # @param security [String] View security to use, either DEFINER INVOKER (default DEFINER) + # + # @return [Void] + def self.create_view(name, statement, algorithm: ALGORITHMS.first, security: SECURITIES.first) + execute( + action: 'CREATE', + name: name, + statement: statement, + algorithm: algorithm, + security: security + ) + end + + # + # Updates an existing view, or creates a new view if it doesn't exist already. + # @param name [String] The name of the view to create + # @param statement [String,ActiveRecord::Relation] SQL select statement or equivalent rails relation object + # @param algorithm [String] View algorithm to use, either UNDEFINED MERGE TEMPTABLE (default UNDEFINED) + # @param security [String] View security to use, either DEFINER INVOKER (default DEFINER) + # + # @return [Void] + def self.update_view(name, statement, algorithm: ALGORITHMS.first, security: SECURITIES.first) + execute( + action: 'CREATE OR REPLACE', + name: name, + statement: statement, + algorithm: algorithm, + security: security + ) + end + + # + # Drops the view + # @param name [String] The name of the view to drop + # + # @return [Void] + def self.drop_view(name) + raise "Invalid name: `#{args[:name]}`" unless /^[a-z0-9_]*$/.match?(args[:name]) + + ActiveRecord::Base.connection.execute("DROP VIEW IF EXISTS `#{name}`;") + end + + # Generates the SQL for view creation/updating + # @note Use create_view or update_view + # + # @param args [Hash] The options for the new view + # @option args [String] name The name of the view to create + # @option args [String] action Whether to create or update, can be 'CREATE' or 'CREATE OR REPLACE' + # @option args [String,ActiveRecord::Relation] statement SQL select statement or equivalent rails relation object + # @option args [String] algorithm View algorithm to use, either UNDEFINED MERGE TEMPTABLE (default UNDEFINED) + # @option args [String] security View security to use, either DEFINER INVOKER (default DEFINER) + def self.execute(args) + raise "Invalid name: `#{args[:name]}`" unless /^[a-z0-9_]*$/.match?(args[:name]) + + args[:statement] = args[:statement].to_sql if args[:statement].respond_to?(:to_sql) + ActiveRecord::Base.connection.execute(VIEW_STATEMENT % args) + end +end diff --git a/spec/views/heron_activities_view_spec.rb b/spec/views/heron_activities_view_spec.rb new file mode 100644 index 00000000..d29cdd1b --- /dev/null +++ b/spec/views/heron_activities_view_spec.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'heron_activities_view' do + let(:activity_type) { FactoryBot.create :activity_type, name: 'Illumina Extraction' } + let(:instrument) { FactoryBot.create :instrument, name: 'Instument' } + let(:kit_type) { FactoryBot.create :kit_type, name: 'Kit type' } + let(:kit) { FactoryBot.create :kit, kit_type: kit_type } + let(:user) { FactoryBot.create :user, fullname: 'Users name' } + let(:well_attributes) do + [ + { supplier_sample_name: 'Sample A' }, + { supplier_sample_name: 'Sample B' } + ] + end + let(:target_plate) { FactoryBot.create :plate, well_attributes: well_attributes } + let(:source_plate) { FactoryBot.create :plate, well_attributes: well_attributes } + let(:intermediate_plate) { FactoryBot.create :plate, well_attributes: well_attributes } + let(:asset_group) { FactoryBot.create :asset_group, assets: [target_plate] } + let(:step_type) { FactoryBot.create :step_type, step_action: 'transfer_plate_to_plate.rb' } + # Both first and second transfer specifying the same asset group is based + # on the data I'm actually seeing in production + let(:first_transfer) do + FactoryBot.create :step, step_type: step_type, asset_group: asset_group, + user: user + end + let(:second_transfer) do + FactoryBot.create :step, step_type: step_type, asset_group: asset_group, + user: user + end + + let(:activity) do + FactoryBot.create :finished_activity, + activity_type: activity_type, + asset_group: asset_group, + kit: kit, + instrument: instrument, + steps: [first_transfer, second_transfer] + end + + def create_transfer(step:, from:, to:) + FactoryBot.create :fact, predicate: 'transferredFrom', + asset: to, + object_asset: from + FactoryBot.create :operation, predicate: 'transferredFrom', + asset: to, + step: step, + object_asset: from + end + + before do + activity + create_transfer step: first_transfer, + from: source_plate, + to: intermediate_plate + create_transfer step: second_transfer, + from: intermediate_plate, + to: target_plate + end + + let(:results) do + ApplicationRecord.connection.execute('SELECT * FROM heron_activities_view') + end + + it 'lists finished activities at the sample level' do + expect(results.size).to eq 2 + end + + it 'has the expected columns' do + expect(results.fields).to eq [ + 'Supplier sample name', + 'Input barcode', + 'Output barcode', + 'Activity type', + 'Instrument', + 'Kit barcode', + 'Kit type', + 'Date', + 'User', + '_activity_id_' + ] + end + + it 'lists the correct information' do + expect(results.to_a).to include( + ['Example', source_plate.barcode, target_plate.barcode, + 'Illumina Extraction', 'Instument', kit.barcode, + 'Kit type', activity.completed_at, 'Users name', activity.id], + ['Example', source_plate.barcode, target_plate.barcode, + 'Illumina Extraction', 'Instument', kit.barcode, + 'Kit type', activity.completed_at, 'Users name', activity.id] + ) + end +end diff --git a/test/factories/activities.rb b/test/factories/activities.rb index 4c8b66db..362bba6b 100644 --- a/test/factories/activities.rb +++ b/test/factories/activities.rb @@ -2,5 +2,10 @@ factory :activity do activity_type { create :activity_type } asset_group { create :asset_group } + + factory :finished_activity do + state { 'finish' } + completed_at { DateTime.current } + end end end diff --git a/test/factories/assets.rb b/test/factories/assets.rb index b22fc897..de92d7f0 100644 --- a/test/factories/assets.rb +++ b/test/factories/assets.rb @@ -6,5 +6,33 @@ end end + factory :plate do + transient do + well_attributes do + [] + end + end + + barcode + + facts do + well_attributes.map do |attributes| + well = build :well_with_samples, attributes + build :fact, predicate: 'contains', object_asset: well + end + end + end + + factory :well_with_samples do + transient do + supplier_sample_name { 'Sample Name' } + end + + barcode { nil } + + facts do + build_list :fact, 1, predicate: 'supplier_sample_name', object: 'Example' + end + end end end diff --git a/test/factories/facts.rb b/test/factories/facts.rb index 3934f1b4..08042908 100644 --- a/test/factories/facts.rb +++ b/test/factories/facts.rb @@ -1,5 +1,8 @@ FactoryBot.define do factory :fact, class: 'Fact' do - + factory :contained_well_fact do + predicate { 'contains' } + association(:object, factory: :well_with_samples) + end end end From 1c65cb1b19dfd183ad11bf61a9c0cfbef2a9cc5d Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 14 Jul 2020 11:38:34 +0100 Subject: [PATCH 038/303] Enhance db:test:prepare Use db:setup to ensure all tasks are run as expected. --- lib/tasks/views_schema.rake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/tasks/views_schema.rake b/lib/tasks/views_schema.rake index 56ae2791..54e0e7a2 100644 --- a/lib/tasks/views_schema.rake +++ b/lib/tasks/views_schema.rake @@ -41,3 +41,7 @@ end Rake::Task['db:schema:load'].enhance do Rake::Task['db:views:schema_load'].invoke end + +Rake::Task['db:test:prepare'].enhance do + Rake::Task['db:views:schema_load'].invoke +end From a10c635d4509e4531ea44b1c7cb185048cbf3879 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 21 Jul 2020 09:46:24 +0100 Subject: [PATCH 039/303] Install bundler in Gemfile Bundler is already installed, so install alone won't install the correct version. Here we pull the version last used to build the Gemfile.lock and install that. Not 100% Dockerfiles support backticks, but will see. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 095bea65..7f647b2b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ ADD Gemfile /samples_extraction ADD Gemfile.lock /samples_extraction ADD package.json /samples_extraction ADD yarn.lock /samples_extraction -RUN gem install bundler +RUN gem install bundler -v `tail -n 1 Gemfile.lock` RUN bundle install RUN yarn install From ddfd15d8288a75ce9914f778e3ad766bd77a4947 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 21 Jul 2020 10:15:41 +0100 Subject: [PATCH 040/303] Try specifying BUNDLER_VERSION Sadly while the back-ticks installed the correct bundler, the actual install used the wrong version. --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7f647b2b..21c43581 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,5 @@ FROM starefossen/ruby-node +ENV BUNDLER_VERSION=2.1.4 RUN apt-get update -qq && apt-get install -y RUN apt-get -y install git vim WORKDIR /samples_extraction @@ -6,7 +7,7 @@ ADD Gemfile /samples_extraction ADD Gemfile.lock /samples_extraction ADD package.json /samples_extraction ADD yarn.lock /samples_extraction -RUN gem install bundler -v `tail -n 1 Gemfile.lock` +RUN gem install bundler RUN bundle install RUN yarn install From 473b7b238f5d9ef237d93f66f945fdb11154f38d Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 20 Oct 2020 17:03:43 +0100 Subject: [PATCH 041/303] Extend bin/setup Extend bin setup to ease setup of new environments --- bin/setup | 20 ++++++++++++++++++++ bin/webpack | 6 +++++- bin/webpack-dev-server | 6 +++++- bin/yarn | 11 +++++++++++ config/initializers/secret_key_config.rb | 1 - 5 files changed, 41 insertions(+), 3 deletions(-) create mode 100755 bin/yarn delete mode 100644 config/initializers/secret_key_config.rb diff --git a/bin/setup b/bin/setup index acdb2c13..636b9eec 100755 --- a/bin/setup +++ b/bin/setup @@ -12,11 +12,31 @@ Dir.chdir APP_ROOT do system "gem install bundler --conservative" system "bundle check || bundle install" + # Install JavaScript dependencies if using Yarn + system('bin/yarn') + # puts "\n== Copying sample files ==" # unless File.exist?("config/database.yml") # system "cp config/database.yml.sample config/database.yml" # end + unless File.exist?('config/secrets.yml') + puts "\n== Generating secret key ==" + secret = `bundle exec rails secret` + + File.open('config/secrets.yml', 'w') do |file| + content = <<~HTML + development: + secret_key_base: #{secret} + test: + secret_key_base: #{secret} + production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> + HTML + file << content + end + end + puts "\n== Preparing database ==" system "bin/rake db:setup" diff --git a/bin/webpack b/bin/webpack index 46583272..008ecb22 100755 --- a/bin/webpack +++ b/bin/webpack @@ -12,4 +12,8 @@ require "bundler/setup" require "webpacker" require "webpacker/webpack_runner" -Webpacker::WebpackRunner.run(ARGV) + +APP_ROOT = File.expand_path("..", __dir__) +Dir.chdir(APP_ROOT) do + Webpacker::WebpackRunner.run(ARGV) +end diff --git a/bin/webpack-dev-server b/bin/webpack-dev-server index faa69f07..a931a9b7 100755 --- a/bin/webpack-dev-server +++ b/bin/webpack-dev-server @@ -12,4 +12,8 @@ require "bundler/setup" require "webpacker" require "webpacker/dev_server_runner" -Webpacker::DevServerRunner.run(ARGV) + +APP_ROOT = File.expand_path("..", __dir__) +Dir.chdir(APP_ROOT) do + Webpacker::DevServerRunner.run(ARGV) +end diff --git a/bin/yarn b/bin/yarn new file mode 100755 index 00000000..460dd565 --- /dev/null +++ b/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +APP_ROOT = File.expand_path('..', __dir__) +Dir.chdir(APP_ROOT) do + begin + exec "yarnpkg", *ARGV + rescue Errno::ENOENT + $stderr.puts "Yarn executable was not detected in the system." + $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + exit 1 + end +end diff --git a/config/initializers/secret_key_config.rb b/config/initializers/secret_key_config.rb deleted file mode 100644 index ec2ab31c..00000000 --- a/config/initializers/secret_key_config.rb +++ /dev/null @@ -1 +0,0 @@ -Rails.application.config.secret_key_base = ENV["SECRET_KEY_BASE"] From 2f0af137cd26464c062125457a2487ee8f7d2358 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 21 Oct 2020 08:50:46 +0100 Subject: [PATCH 042/303] Update to Ruby-2.6.6 - Update to ruby 2.6.6 - Update mysql2 gem for compatibility Ruby 2.7.2 update blocked by google_hash gem. This doesn't seem to be maintained anymore. It seems to have been introduced for ChangesSupport::DisjointList as a performance optimization. Leaving for the moment, as ChangesSupport::DisjointList is quite a lot to unpick. --- .ruby-version | 2 +- Gemfile.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ruby-version b/.ruby-version index 951d42f2..f6ab44e9 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-2.4.2 +ruby-2.6.6 diff --git a/Gemfile.lock b/Gemfile.lock index 5adefaf6..2bb25e6e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -192,7 +192,7 @@ GEM minitest (5.11.3) multi_json (1.13.1) multipart-post (2.1.1) - mysql2 (0.5.2) + mysql2 (0.5.3) net-http-persistent (3.0.1) connection_pool (~> 2.2) net-http-pipeline (1.0.1) From 2cbec70b88c51871182b6e1216f440ead23a1559 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 21 Oct 2020 09:03:17 +0100 Subject: [PATCH 043/303] Update sanger dependencies --- Gemfile | 2 +- Gemfile.lock | 21 ++++++++------------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Gemfile b/Gemfile index c9c205db..80c69d02 100644 --- a/Gemfile +++ b/Gemfile @@ -57,7 +57,7 @@ gem 'pmb-client', git: 'https://github.com/sanger/pmb-client.git' # Sequencescspae gem 'rest-client' gem 'faraday' -gem 'sequencescape-client-api', git: 'https://github.com/sanger/sequencescape-client-api.git', branch: 'rails_4', require: 'sequencescape' +gem 'sequencescape-client-api', require: 'sequencescape' # #gem 'sequencescape-client-api', require: 'sequencescape' diff --git a/Gemfile.lock b/Gemfile.lock index 2bb25e6e..28906716 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,17 +11,6 @@ GIT specs: sanger_barcode_format (0.0.2) -GIT - remote: https://github.com/sanger/sequencescape-client-api.git - revision: d01a3aeca31a5c8df32996e16f466542bf179609 - branch: rails_4 - specs: - sequencescape-client-api (0.3.9) - activemodel (>= 4.0.0, < 5.2) - activesupport (>= 4.0.0, < 5.2) - i18n - yajl-ruby (>= 1.3.1) - GEM remote: http://rubygems.org/ specs: @@ -208,7 +197,8 @@ GEM coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (3.1.0) - puma (3.12.1) + puma (5.0.2) + nio4r (~> 2.0) pusher-client (0.6.2) json websocket (~> 1.0) @@ -327,6 +317,11 @@ GEM rake sdoc (1.0.0) rdoc (>= 5.0) + sequencescape-client-api (0.4.2) + activemodel (>= 5.0.0) + activesupport (>= 5.0.0) + i18n + yajl-ruby (>= 1.4.1) shoulda-matchers (4.1.0) activesupport (>= 4.2.0) sparql (3.0.2) @@ -452,7 +447,7 @@ DEPENDENCIES sanger_barcode_format! sass-rails sdoc - sequencescape-client-api! + sequencescape-client-api shoulda-matchers spring sprockets-rails From 238f6b2ad7ec729bf192cac354d90d2f0255fbdb Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 21 Oct 2020 09:57:20 +0100 Subject: [PATCH 044/303] Update rubocop gems --- Gemfile.lock | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 28906716..19194c99 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -65,7 +65,7 @@ GEM addressable (2.6.0) public_suffix (>= 2.0.2, < 4.0) arel (8.0.0) - ast (2.4.0) + ast (2.4.1) autoprefixer-rails (9.6.0) execjs babel-source (5.8.35) @@ -138,7 +138,6 @@ GEM domain_name (~> 0.5) i18n (1.6.0) concurrent-ruby (~> 1.0) - jaro_winkler (1.5.3) jbuilder (2.9.1) activesupport (>= 4.2.0) jquery-rails (4.3.5) @@ -190,9 +189,9 @@ GEM nokogiri (1.10.3) mini_portile2 (~> 2.4.0) os (0.9.6) - parallel (1.17.0) - parser (2.6.3.0) - ast (~> 2.4.0) + parallel (1.19.2) + parser (2.7.2.0) + ast (~> 2.4.1) pry (0.12.2) coderay (~> 1.1.0) method_source (~> 0.9.0) @@ -202,7 +201,7 @@ GEM pusher-client (0.6.2) json websocket (~> 1.0) - rack (2.0.7) + rack (2.2.3) rack-proxy (0.6.5) rack rack-test (1.1.0) @@ -263,10 +262,12 @@ GEM railties (>= 3.2) tilt redis (4.1.2) + regexp_parser (1.8.2) rest-client (2.0.2) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) + rexml (3.2.4) rspec-core (3.8.1) rspec-support (~> 3.8.0) rspec-expectations (3.8.4) @@ -284,18 +285,24 @@ GEM rspec-mocks (~> 3.8.0) rspec-support (~> 3.8.0) rspec-support (3.8.2) - rubocop (0.71.0) - jaro_winkler (~> 1.5.1) + rubocop (0.93.1) parallel (~> 1.10) - parser (>= 2.6) + parser (>= 2.7.1.5) rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8) + rexml + rubocop-ast (>= 0.6.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 1.7) - rubocop-performance (1.4.0) - rubocop (>= 0.71.0) - rubocop-rails (2.0.1) + unicode-display_width (>= 1.4.0, < 2.0) + rubocop-ast (0.8.0) + parser (>= 2.7.1.5) + rubocop-performance (1.8.1) + rubocop (>= 0.87.0) + rubocop-ast (>= 0.4.0) + rubocop-rails (2.8.1) + activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.70.0) + rubocop (>= 0.87.0) ruby-growl (4.1) uuid (~> 2.3, >= 2.3.5) ruby-progressbar (1.10.1) @@ -372,7 +379,7 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.7.6) - unicode-display_width (1.6.0) + unicode-display_width (1.7.0) uuid (2.3.9) macaddr (~> 1.0) web-console (3.7.0) From 34e1e13f41fb895ba79646c372e06cb7553a434d Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 21 Oct 2020 11:16:00 +0100 Subject: [PATCH 045/303] Add rubocop_todo and run layout cops - Layout cop auto-correct - Generate todo - Add inline diabling for handful of cops that needed it I ran into failures on using all the safe auto-correctors, so keeping things limited for now. --- .rubocop.yml | 197 +- .rubocop_todo.yml | 3600 +++++++++++++++++ app/channels/activity_channel.rb | 6 +- app/controllers/asset_groups_controller.rb | 6 +- app/controllers/assets_controller.rb | 4 +- app/controllers/samples_status_controller.rb | 6 +- app/helpers/activities_helper.rb | 22 +- app/helpers/application_helper.rb | 16 +- app/helpers/assets_helper.rb | 2 +- app/models/action.rb | 8 +- app/models/activities/background_tasks.rb | 4 +- app/models/activities/json_attributes.rb | 8 +- app/models/activities/state.rb | 4 +- app/models/activities/steps_management.rb | 6 +- app/models/activities/tasks.rb | 2 +- app/models/activities/websocket_events.rb | 6 +- app/models/activity.rb | 2 +- app/models/activity_type.rb | 4 +- app/models/asset.rb | 12 +- app/models/asset_group.rb | 6 +- app/models/assets/facts_management.rb | 12 +- app/models/assets/import.rb | 14 +- app/models/condition.rb | 8 +- app/models/condition_group.rb | 8 +- app/models/fact.rb | 6 +- app/models/label_template.rb | 4 +- app/models/operation.rb | 2 +- app/models/printables/group.rb | 4 +- app/models/printables/instance.rb | 2 +- app/models/printer.rb | 8 +- app/models/step.rb | 6 +- app/models/step_type.rb | 28 +- app/models/steps/cancellable.rb | 10 +- app/models/steps/state.rb | 20 +- app/models/user.rb | 4 +- db/seeds.rb | 2 +- lib/actions/plate_transfer.rb | 6 +- lib/actions/racking.rb | 28 +- lib/changes_support/disjoint_list.rb | 18 +- lib/changes_support/transaction_scope.rb | 4 +- lib/fact_changes.rb | 48 +- lib/inference_engines/cwm/step_execution.rb | 6 +- .../runner/step_execution.rb | 8 +- lib/label_template_setup.rb | 6 +- lib/label_templates/ss_plate.rb | 18 +- lib/label_templates/ss_tube.rb | 26 +- lib/parsers/csv_layout/csv_parser.rb | 4 +- lib/parsers/csv_layout/line_parser.rb | 3 +- lib/parsers/csv_metadata/csv_parser.rb | 2 +- lib/parsers/csv_metadata/data_parser.rb | 1 + lib/parsers/csv_metadata/datum_parser.rb | 1 + lib/parsers/csv_metadata/headers_parser.rb | 3 +- lib/parsers/csv_metadata/line_parser.rb | 1 + lib/sequencescape_client.rb | 12 +- lib/support_n3.rb | 58 +- lib/tasks/setup_templates.rake | 4 +- lib/token_util.rb | 5 +- script/aliquot_type_inference.rb | 6 +- script/claim_uuids.rb | 2 +- script/container_inferences.rb | 3 +- script/fix_duplicated_tubes.rb | 2 +- script/purpose_name_inference.rb | 6 +- script/recreate_steptypes.rb | 2 +- script/runners/create_12_tubes.rb | 24 +- script/runners/create_file.rb | 2 +- script/runners/create_layout.rb | 4 +- script/runners/create_stamped_plate.rb | 3 +- script/runners/full_rack_generator.rb | 6 +- script/runners/load_metadata.rb | 6 +- .../move_barcodes_from_tube_rack_to_plate.rb | 6 +- script/runners/print_barcodes.rb | 3 +- .../put_tubes_into_rack_by_column_order.rb | 6 +- script/runners/rack_layout.rb | 4 +- script/runners/rack_layout_any_barcode.rb | 4 +- script/runners/rack_layout_creating_tubes.rb | 4 +- script/runners/transfer_plate_to_plate.rb | 7 +- ...plate_to_plate_and_update_sequencescape.rb | 2 +- script/runners/transfer_samples.rb | 3 +- ...transfer_tubes_to_tube_rack_by_position.rb | 7 +- script/runners/update_sequencescape.rb | 3 +- script/study_name_inference.rb | 6 +- .../tasks/runners/aliquot_type_inference.rb | 4 + spec/concerns/deprecatable_spec.rb | 2 +- .../controllers/activities_controller_spec.rb | 10 +- .../activity_types_controller_spec.rb | 14 +- .../asset_groups_controller_spec.rb | 66 +- spec/controllers/assets_controller_spec.rb | 16 +- spec/controllers/changes_controller_spec.rb | 2 +- .../instruments_controller_spec.rb | 18 +- spec/controllers/kit_types_controller_spec.rb | 22 +- spec/controllers/kits_controller_spec.rb | 18 +- spec/controllers/printers_controller_spec.rb | 12 +- .../controllers/step_types_controller_spec.rb | 24 +- spec/controllers/steps_controller_spec.rb | 16 +- spec/helpers/application_helper_spec.rb | 8 +- spec/inferences_helper.rb | 4 +- spec/integration/inference_spec.rb | 10 +- spec/lib/actions/plate_transfer_spec.rb | 18 +- spec/lib/actions/racking_spec.rb | 16 +- spec/lib/actions/tube_transfer_spec.rb | 8 +- .../lib/changes_support/disjoint_list_spec.rb | 92 +- .../changes_support/transaction_scope_spec.rb | 10 +- spec/lib/fact_changes_spec.rb | 242 +- .../barcode_creatable_parser_spec.rb | 6 +- .../parsers/csv_layout/barcode_parser_spec.rb | 6 +- .../lib/parsers/csv_layout/csv_parser_spec.rb | 4 +- .../parsers/csv_layout/line_parser_spec.rb | 22 +- .../parsers/csv_layout/line_reader_spec.rb | 2 +- .../csv_layout/location_parser_spec.rb | 6 +- .../validators/any_barcode_validator_spec.rb | 1 + .../fluidx_barcode_validator_spec.rb | 1 + .../validators/location_validator_spec.rb | 1 + .../parsers/csv_metadata/csv_parser_spec.rb | 4 +- .../validators/headers_validator_spec.rb | 1 + spec/lib/support_n3_spec.rb | 260 +- spec/models/action_spec.rb | 24 +- .../activities/background_tasks_spec.rb | 14 +- spec/models/activities/state_spec.rb | 4 +- .../activities/steps_management_spec.rb | 10 +- spec/models/asset_group_spec.rb | 10 +- spec/models/asset_spec.rb | 8 +- spec/models/assets/export_spec.rb | 36 +- spec/models/assets/import_spec.rb | 42 +- spec/models/condition_spec.rb | 26 +- spec/models/step_execution_spec.rb | 22 +- spec/models/step_spec.rb | 154 +- spec/models/step_type_spec.rb | 74 +- .../steps/background_tasks/inference_spec.rb | 14 +- spec/models/steps/cancellable_spec.rb | 14 +- spec/models/steps/deprecatable_spec.rb | 14 +- spec/models/steps/job_spec.rb | 14 +- spec/models/steps/queueable_job_spec.rb | 8 +- spec/models/steps/state_spec.rb | 2 +- spec/models/steps/stoppable_spec.rb | 18 +- spec/models/steps/task_spec.rb | 16 +- spec/remote_assets_helper.rb | 16 +- spec/requests/api/v1/assets_spec.rb | 2 +- spec/script/runners/load_metadata_spec.rb | 12 +- .../runners/transfer_plate_to_plate_spec.rb | 32 +- spec/script/runners/transfer_samples_spec.rb | 26 +- ...fer_tubes_to_tube_rack_by_position_spec.rb | 30 +- spec/shared_examples/background_step.rb | 4 +- 142 files changed, 4928 insertions(+), 1106 deletions(-) create mode 100644 .rubocop_todo.yml diff --git a/.rubocop.yml b/.rubocop.yml index 5c85b271..a94be896 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,2 +1,195 @@ -require: rubocop-performance -require: rubocop-rails +inherit_from: .rubocop_todo.yml + +require: + - rubocop-performance + - rubocop-rails + +# Blocks are used to structure tests and are part of the shoulda dsl. +# The standard BlockLength limits are too stringent for this purpose. +# Block DSL is also used in routes +# We should be careful keeping rake tasks here, as large tasks are still an issue. +# Not sure if we need to split namespaces across several files though. +# We exclude builders, as they are concerned with rendering xml +Metrics/BlockLength: + Exclude: + - Gemfile + - 'db/seeds/**/*' + - '**/*.builder' + ExcludedMethods: + - describe + - context + - background + - scenario + - namespace + - task + - included + - shared_context + - shared_examples + - state_machine + - configure + - draw + - feature + - subject + - let + - let! + - factory + - define + - guard + - transient + - with_nested_has_many_association + - with_association + - it + - class_eval + - has_metadata + - resources + +Layout/BeginEndAlignment: # (new in 0.91) + Enabled: true +Layout/EmptyLinesAroundAttributeAccessor: # (new in 0.83) + Enabled: true +Layout/SpaceAroundMethodCallOperator: # (new in 0.82) + Enabled: true +Lint/BinaryOperatorWithIdenticalOperands: # (new in 0.89) + Enabled: true +Lint/ConstantDefinitionInBlock: # (new in 0.91) + Enabled: true +Lint/DeprecatedOpenSSLConstant: # (new in 0.84) + Enabled: true +Lint/DuplicateElsifCondition: # (new in 0.88) + Enabled: true +Lint/DuplicateRequire: # (new in 0.90) + Enabled: true +Lint/DuplicateRescueException: # (new in 0.89) + Enabled: true +Lint/EmptyConditionalBody: # (new in 0.89) + Enabled: true +Lint/EmptyFile: # (new in 0.90) + Enabled: true +Lint/FloatComparison: # (new in 0.89) + Enabled: true +Lint/HashCompareByIdentity: # (new in 0.93) + Enabled: true +Lint/IdentityComparison: # (new in 0.91) + Enabled: true +Lint/MissingSuper: # (new in 0.89) + Enabled: true +Lint/MixedRegexpCaptureTypes: # (new in 0.85) + Enabled: true +Lint/OutOfRangeRegexpRef: # (new in 0.89) + Enabled: true +Lint/RaiseException: # (new in 0.81) + Enabled: true +Lint/RedundantSafeNavigation: # (new in 0.93) + Enabled: true +Lint/SelfAssignment: # (new in 0.89) + Enabled: true +Lint/StructNewOverride: # (new in 0.81) + Enabled: true +Lint/TopLevelReturnWithArgument: # (new in 0.89) + Enabled: true +Lint/TrailingCommaInAttributeDeclaration: # (new in 0.90) + Enabled: true +Lint/UnreachableLoop: # (new in 0.89) + Enabled: true +Lint/UselessMethodDefinition: # (new in 0.90) + Enabled: true +Lint/UselessTimes: # (new in 0.91) + Enabled: true +Style/AccessorGrouping: # (new in 0.87) + Enabled: true +Style/BisectedAttrAccessor: # (new in 0.87) + Enabled: true +Style/CaseLikeIf: # (new in 0.88) + Enabled: true +Style/ClassEqualityComparison: # (new in 0.93) + Enabled: true +Style/CombinableLoops: # (new in 0.90) + Enabled: true +Style/ExplicitBlockArgument: # (new in 0.89) + Enabled: true +Style/ExponentialNotation: # (new in 0.82) + Enabled: true +Style/GlobalStdStream: # (new in 0.89) + Enabled: true +Style/HashAsLastArrayItem: # (new in 0.88) + Enabled: true +Style/HashEachMethods: # (new in 0.80) + Enabled: true +Style/HashLikeCase: # (new in 0.88) + Enabled: true +Style/HashTransformKeys: # (new in 0.80) + Enabled: true +Style/HashTransformValues: # (new in 0.80) + Enabled: true +Style/KeywordParametersOrder: # (new in 0.90) + Enabled: true +Style/OptionalBooleanParameter: # (new in 0.89) + Enabled: true +Style/RedundantAssignment: # (new in 0.87) + Enabled: true +Style/RedundantFetchBlock: # (new in 0.86) + Enabled: true +Style/RedundantFileExtensionInRequire: # (new in 0.88) + Enabled: true +Style/RedundantRegexpCharacterClass: # (new in 0.85) + Enabled: true +Style/RedundantRegexpEscape: # (new in 0.85) + Enabled: true +Style/RedundantSelfAssignment: # (new in 0.90) + Enabled: true +Style/SingleArgumentDig: # (new in 0.89) + Enabled: true +Style/SlicingWithRange: # (new in 0.83) + Enabled: true +Style/SoleNestedConditional: # (new in 0.89) + Enabled: true +Style/StringConcatenation: # (new in 0.89) + Enabled: true +Rails/ActiveRecordCallbacksOrder: # (new in 2.7) + Enabled: true +Rails/AfterCommitOverride: # (new in 2.8) + Enabled: true +Rails/FindById: # (new in 2.7) + Enabled: true +Rails/Inquiry: # (new in 2.7) + Enabled: true +Rails/MailerName: # (new in 2.7) + Enabled: true +Rails/MatchRoute: # (new in 2.7) + Enabled: true +Rails/NegateInclude: # (new in 2.7) + Enabled: true +Rails/Pluck: # (new in 2.7) + Enabled: true +Rails/PluckInWhere: # (new in 2.7) + Enabled: true +Rails/RenderInline: # (new in 2.7) + Enabled: true +Rails/RenderPlainText: # (new in 2.7) + Enabled: true +Rails/ShortI18n: # (new in 2.7) + Enabled: true +Rails/SquishedSQLHeredocs: # (new in 2.8) + Enabled: true +Rails/WhereExists: # (new in 2.7) + Enabled: true +Rails/WhereNot: # (new in 2.8) + Enabled: true +Performance/AncestorsInclude: # (new in 1.7) + Enabled: true +Performance/BigDecimalWithNumericArgument: # (new in 1.7) + Enabled: true +Performance/RedundantSortBlock: # (new in 1.7) + Enabled: true +Performance/RedundantStringChars: # (new in 1.7) + Enabled: true +Performance/ReverseFirst: # (new in 1.7) + Enabled: true +Performance/SortReverse: # (new in 1.7) + Enabled: true +Performance/Squeeze: # (new in 1.7) + Enabled: true +Performance/StringInclude: # (new in 1.7) + Enabled: true +Performance/Sum: # (new in 1.8) + Enabled: true diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000..e868a180 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,3600 @@ +# This configuration was generated by +# `rubocop --auto-gen-config --exclude-limit 1000` +# on 2020-10-21 10:05:59 UTC using RuboCop version 0.93.1. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 17 +# Cop supports --auto-correct. +# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. +# Include: **/*.gemfile, **/Gemfile, **/gems.rb +Bundler/OrderedGems: + Exclude: + - 'Gemfile' + +# Offense count: 29 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: with_first_argument, with_fixed_indentation +Layout/ArgumentAlignment: + Exclude: + - 'app/controllers/steps_controller.rb' + - 'app/models/condition.rb' + - 'app/resources/api/v1/asset_resource.rb' + - 'lib/actions/tube_transfer.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/support_n3.rb' + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/task_spec.rb' + - 'spec/script/runners/load_metadata_spec.rb' + +# Offense count: 16 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: with_first_element, with_fixed_indentation +Layout/ArrayAlignment: + Exclude: + - 'app/models/assets/export.rb' + - 'lib/fact_changes.rb' + - 'lib/label_templates/ss_tube.rb' + - 'spec/inferences_helper.rb' + - 'spec/integration/inferences_data.rb' + - 'spec/lib/support_n3_spec.rb' + +# Offense count: 21 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleAlignWith. +# SupportedStylesAlignWith: either, start_of_block, start_of_line +Layout/BlockAlignment: + Exclude: + - 'app/controllers/asset_groups_controller.rb' + - 'app/helpers/assets_helper.rb' + - 'app/models/asset.rb' + - 'script/aliquot_type_inference.rb' + - 'script/tasks/runners/aliquot_type_inference.rb' + - 'spec/controllers/activity_types_controller_spec.rb' + - 'spec/controllers/kits_controller_spec.rb' + - 'spec/controllers/printers_controller_spec.rb' + - 'spec/controllers/step_types_controller_spec.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/models/step_spec.rb' + +# Offense count: 30 +# Cop supports --auto-correct. +Layout/BlockEndNewline: + Exclude: + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/models/action_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/script/runners/load_metadata_spec.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + +# Offense count: 7 +# Cop supports --auto-correct. +Layout/ClosingParenthesisIndentation: + Exclude: + - 'app/models/activity_type.rb' + - 'app/models/asset.rb' + - 'db/migrate/20200709123033_create_heron_activities_view.rb' + - 'lib/actions/racking.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Layout/CommentIndentation: + Exclude: + - 'app/controllers/assets_controller.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Layout/ElseAlignment: + Exclude: + - 'spec/models/assets/import_spec.rb' + +# Offense count: 90 +# Cop supports --auto-correct. +Layout/EmptyLineAfterGuardClause: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/controllers/activities_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'app/models/action.rb' + - 'app/models/activities/steps_management.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/import.rb' + - 'app/models/assets/traction_fields.rb' + - 'app/models/condition.rb' + - 'app/models/condition_group.rb' + - 'app/models/label_template.rb' + - 'app/models/printables/group.rb' + - 'app/models/printables/instance.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/cancellable.rb' + - 'app/models/steps/compatible.rb' + - 'app/models/steps/deprecatable.rb' + - 'app/models/steps/job.rb' + - 'app/models/steps/state.rb' + - 'app/models/steps/task.rb' + - 'app/models/uploaded_file.rb' + - 'config/initializers/inference_engine.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/label_template_setup.rb' + - 'lib/step_execution_process.rb' + - 'lib/token_util.rb' + - 'script/aliquot_type_inference.rb' + - 'script/container_inferences.rb' + - 'script/purpose_name_inference.rb' + - 'script/runners/create_12_tubes.rb' + - 'script/runners/load_metadata.rb' + - 'script/study_name_inference.rb' + - 'spec/inferences_helper.rb' + - 'spec/requests/api/v1/assets_spec.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Layout/EmptyLineAfterMagicComment: + Exclude: + - 'db/migrate/20170608101740_remove_unneeded_tables.rb' + +# Offense count: 47 +# Cop supports --auto-correct. +# Configuration parameters: AllowAdjacentOneLineDefs, NumberOfEmptyLines. +Layout/EmptyLineBetweenDefs: + Exclude: + - 'app/controllers/activities_controller.rb' + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/controllers/reracking_controller.rb' + - 'app/controllers/step_types_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/models/activity_type.rb' + - 'app/models/asset.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/import.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/cancellable.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/default/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/support_n3.rb' + - 'script/aliquot_type_inference.rb' + - 'script/container_inferences.rb' + - 'script/runners/load_metadata.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/runners/rack_layout.rb' + - 'script/runners/rack_layout_any_barcode.rb' + - 'script/runners/rack_layout_creating_tubes.rb' + - 'script/tasks/runners/aliquot_type_inference.rb' + - 'spec/models/activities/background_tasks_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/script/runners/transfer_plate_to_plate_spec.rb' + +# Offense count: 114 +# Cop supports --auto-correct. +Layout/EmptyLines: + Exclude: + - 'Gemfile' + - 'app/controllers/activities_controller.rb' + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/controllers/reracking_controller.rb' + - 'app/controllers/step_types_controller.rb' + - 'app/controllers/uploaded_files_controller.rb' + - 'app/controllers/user_sessions_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/models/action.rb' + - 'app/models/activity.rb' + - 'app/models/activity_type.rb' + - 'app/models/asset.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/import.rb' + - 'app/models/step.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/cancellable.rb' + - 'app/models/steps/state.rb' + - 'app/models/user.rb' + - 'config/environments/production.rb' + - 'config/environments/test.rb' + - 'config/routes.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/default/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/label_template_setup.rb' + - 'lib/label_templates/ss_tube.rb' + - 'lib/parsers/csv_metadata/csv_parser.rb' + - 'lib/support_n3.rb' + - 'script/container_inferences.rb' + - 'script/runners/load_metadata.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/runners/put_tubes_into_rack_by_column_order.rb' + - 'script/runners/rack_layout.rb' + - 'script/runners/rack_layout_any_barcode.rb' + - 'script/runners/rack_layout_creating_tubes.rb' + - 'script/runners/transfer_plate_to_plate.rb' + - 'spec/controllers/asset_groups_controller_spec.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/validators/location_validator_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/queueable_job_spec.rb' + - 'spec/models/steps/state_spec.rb' + - 'spec/models/steps/stoppable_spec.rb' + - 'spec/rails_helper.rb' + - 'spec/script/runners/transfer_plate_to_plate_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + - 'test/factories/steps.rb' + +# Offense count: 8 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: around, only_before +Layout/EmptyLinesAroundAccessModifier: + Exclude: + - 'app/controllers/activity_types_controller.rb' + - 'app/controllers/instruments_controller.rb' + - 'app/controllers/kit_types_controller.rb' + - 'app/controllers/kits_controller.rb' + - 'app/controllers/printers_controller.rb' + - 'app/controllers/step_types_controller.rb' + - 'app/controllers/users_controller.rb' + - 'lib/parsers/csv_layout/barcode_parser.rb' + +# Offense count: 99 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, no_empty_lines +Layout/EmptyLinesAroundBlockBody: + Exclude: + - 'app/controllers/assets_controller.rb' + - 'app/models/assets/facts_management.rb' + - 'config/environments/development.rb' + - 'config/environments/production.rb' + - 'config/routes.rb' + - 'db/migrate/20190717130805_change_sti_type.rb' + - 'spec/controllers/activities_controller_spec.rb' + - 'spec/controllers/asset_groups_controller_spec.rb' + - 'spec/controllers/step_types_controller_spec.rb' + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/actions/tube_transfer_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb' + - 'spec/lib/parsers/csv_layout/validators/location_validator_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/action_spec.rb' + - 'spec/models/activities/background_tasks_spec.rb' + - 'spec/models/assets/facts_management_spec.rb' + - 'spec/models/assets/traction_fields_spec.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/fact_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/cancellable_spec.rb' + - 'spec/models/steps/queueable_job_spec.rb' + - 'spec/models/steps/state_spec.rb' + - 'spec/models/steps/task_spec.rb' + - 'spec/rails_helper.rb' + - 'spec/requests/api/v1/assets_spec.rb' + - 'spec/script/runners/transfer_plate_to_plate_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + - 'spec/shared_examples/background_step.rb' + - 'test/factories/activity_types.rb' + - 'test/factories/condition_groups.rb' + - 'test/factories/conditions.rb' + - 'test/factories/kits.rb' + - 'test/factories/steps.rb' + - 'test/factories/users.rb' + +# Offense count: 54 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only +Layout/EmptyLinesAroundClassBody: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/controllers/activities_controller.rb' + - 'app/controllers/application_controller.rb' + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/controllers/changes_controller.rb' + - 'app/controllers/instruments_controller.rb' + - 'app/controllers/reracking_controller.rb' + - 'app/controllers/samples_not_started_controller.rb' + - 'app/controllers/samples_started_controller.rb' + - 'app/controllers/samples_status_controller.rb' + - 'app/controllers/step_types_controller.rb' + - 'app/controllers/steps_controller.rb' + - 'app/models/action.rb' + - 'app/models/activities/background_tasks.rb' + - 'app/models/activity.rb' + - 'app/models/asset_group.rb' + - 'app/models/fact.rb' + - 'app/models/operation.rb' + - 'app/models/step.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/background_tasks/inference.rb' + - 'app/models/steps/background_tasks/runner.rb' + - 'app/models/user.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/default/step_execution.rb' + - 'lib/label_template_setup.rb' + - 'lib/parsers/csv_layout/barcode_parser.rb' + - 'lib/parsers/csv_layout/csv_parser.rb' + - 'lib/parsers/csv_layout/line_reader.rb' + - 'lib/parsers/csv_layout/location_parser.rb' + - 'lib/parsers/csv_metadata/csv_parser.rb' + - 'script/container_inferences.rb' + - 'script/purpose_name_inference.rb' + - 'script/runners/create_stamped_plate.rb' + - 'script/runners/print_barcodes.rb' + - 'script/runners/transfer_plate_to_plate.rb' + - 'script/runners/transfer_samples.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'script/study_name_inference.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Layout/EmptyLinesAroundExceptionHandlingKeywords: + Exclude: + - 'script/runners/rack_layout_any_barcode.rb' + - 'script/runners/rack_layout_creating_tubes.rb' + +# Offense count: 6 +# Cop supports --auto-correct. +Layout/EmptyLinesAroundMethodBody: + Exclude: + - 'app/controllers/activities_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'lib/actions/racking.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'script/runners/transfer_plate_to_plate.rb' + +# Offense count: 40 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines +Layout/EmptyLinesAroundModuleBody: + Exclude: + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/step_types_helper.rb' + - 'app/models/activities/background_tasks.rb' + - 'app/models/activities/state.rb' + - 'app/models/activities/tasks.rb' + - 'app/models/activities/websocket_events.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/import.rb' + - 'app/models/assets/traction_fields.rb' + - 'app/models/concerns/uuidable.rb' + - 'app/models/steps/cancellable.rb' + - 'app/models/steps/compatible.rb' + - 'app/models/steps/deprecatable.rb' + - 'app/models/steps/job.rb' + - 'app/models/steps/queueable_job.rb' + - 'app/models/steps/retryable.rb' + - 'app/models/steps/state.rb' + - 'app/models/steps/stoppable.rb' + - 'app/models/steps/websocket_events.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/label_template_setup.rb' + - 'lib/sequencescape_client_v2.rb' + - 'lib/step_execution_process.rb' + - 'lib/support_n3.rb' + - 'lib/token_util.rb' + - 'script/claim_uuids.rb' + - 'spec/inferences_helper.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleAlignWith, Severity. +# SupportedStylesAlignWith: keyword, variable, start_of_line +Layout/EndAlignment: + Exclude: + - 'spec/models/assets/import_spec.rb' + +# Offense count: 43 +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. +Layout/ExtraSpacing: + Exclude: + - 'app/helpers/application_helper.rb' + - 'app/models/asset.rb' + - 'app/models/fact.rb' + - 'app/models/step.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/state.rb' + - 'app/models/user.rb' + - 'config/environments/development.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'spec/controllers/activities_controller_spec.rb' + - 'spec/controllers/activity_types_controller_spec.rb' + - 'spec/controllers/instruments_controller_spec.rb' + - 'spec/controllers/kit_types_controller_spec.rb' + - 'spec/controllers/kits_controller_spec.rb' + - 'spec/controllers/printers_controller_spec.rb' + - 'spec/controllers/step_types_controller_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/models/action_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/steps/state_spec.rb' + - 'test/factories/instruments.rb' + - 'test/factories/kits.rb' + - 'test/factories/users.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: consistent, consistent_relative_to_receiver, special_for_inner_method_call, special_for_inner_method_call_in_parentheses +Layout/FirstArgumentIndentation: + Exclude: + - 'app/models/printables/group.rb' + - 'db/views_schema.rb' + - 'lib/actions/racking.rb' + +# Offense count: 63 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_brackets +Layout/FirstArrayElementIndentation: + Exclude: + - 'lib/label_templates/ss_tube.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/lib/changes_support/transaction_scope_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/action_spec.rb' + - 'spec/models/activities/steps_management_spec.rb' + - 'spec/models/assets/export_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/script/runners/transfer_plate_to_plate_spec.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + +# Offense count: 134 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_braces +Layout/FirstHashElementIndentation: + Exclude: + - 'app/controllers/steps_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/step_types_helper.rb' + - 'app/models/activities/json_attributes.rb' + - 'app/models/activities/tasks.rb' + - 'app/models/activity_type.rb' + - 'app/models/asset.rb' + - 'lib/actions/racking.rb' + - 'lib/label_types/plate.rb' + - 'lib/label_types/tube.rb' + - 'lib/parsers/csv_layout/csv_parser.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/support_n3.rb' + - 'spec/controllers/asset_groups_controller_spec.rb' + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/integration/inferences_data.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/activities/steps_management_spec.rb' + - 'spec/models/assets/export_spec.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/queueable_job_spec.rb' + - 'spec/remote_assets_helper.rb' + +# Offense count: 195 +# Cop supports --auto-correct. +# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. +# SupportedHashRocketStyles: key, separator, table +# SupportedColonStyles: key, separator, table +# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit +Layout/HashAlignment: + Exclude: + - 'app/helpers/step_types_helper.rb' + - 'app/models/activities/json_attributes.rb' + - 'app/models/activity_type.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/printables/group.rb' + - 'app/models/printables/instance.rb' + - 'app/models/steps/state.rb' + - 'lib/fact_changes.rb' + - 'lib/label_templates/ss_plate.rb' + - 'lib/label_templates/ss_tube.rb' + - 'lib/label_types/tube.rb' + - 'lib/sequencescape_client.rb' + - 'lib/support_n3.rb' + - 'script/plate_to_code39.rb' + - 'script/runners/load_metadata.rb' + - 'spec/controllers/asset_groups_controller_spec.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/action_spec.rb' + - 'spec/models/activities/steps_management_spec.rb' + - 'spec/models/asset_spec.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/steps/task_spec.rb' + +# Offense count: 61 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: normal, indented_internal_methods +Layout/IndentationConsistency: + Exclude: + - 'app/controllers/activities_controller.rb' + - 'app/controllers/activity_types_controller.rb' + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/controllers/changes_controller.rb' + - 'app/controllers/instruments_controller.rb' + - 'app/controllers/kit_types_controller.rb' + - 'app/controllers/kits_controller.rb' + - 'app/controllers/printers_controller.rb' + - 'app/controllers/step_types_controller.rb' + - 'app/controllers/steps_controller.rb' + - 'app/controllers/users_controller.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/background_tasks/inference_spec.rb' + +# Offense count: 124 +# Cop supports --auto-correct. +# Configuration parameters: IndentationWidth, EnforcedStyle. +# SupportedStyles: spaces, tabs +Layout/IndentationStyle: + Exclude: + - 'app/models/condition.rb' + - 'db/migrate/20170917175535_add_from_remote_to_facts.rb' + - 'db/migrate/20171210183629_add_sti_to_step.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/background_tasks/inference_spec.rb' + - 'spec/remote_assets_helper.rb' + +# Offense count: 93 +# Cop supports --auto-correct. +# Configuration parameters: Width, IgnoredPatterns. +Layout/IndentationWidth: + Exclude: + - 'app/controllers/activities_controller.rb' + - 'app/controllers/activity_types_controller.rb' + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/controllers/changes_controller.rb' + - 'app/controllers/instruments_controller.rb' + - 'app/controllers/kit_types_controller.rb' + - 'app/controllers/kits_controller.rb' + - 'app/controllers/printers_controller.rb' + - 'app/controllers/step_types_controller.rb' + - 'app/controllers/steps_controller.rb' + - 'app/controllers/users_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/models/asset.rb' + - 'app/models/step.rb' + - 'db/migrate/20170917175535_add_from_remote_to_facts.rb' + - 'db/migrate/20171210183629_add_sti_to_step.rb' + - 'spec/controllers/activity_types_controller_spec.rb' + - 'spec/controllers/kits_controller_spec.rb' + - 'spec/controllers/printers_controller_spec.rb' + - 'spec/controllers/step_types_controller_spec.rb' + - 'spec/integration/inferences_data.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/steps/background_tasks/inference_spec.rb' + - 'spec/remote_assets_helper.rb' + +# Offense count: 91 +# Cop supports --auto-correct. +# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment. +Layout/LeadingCommentSpace: + Exclude: + - 'Gemfile' + - 'app/channels/activity_channel.rb' + - 'app/channels/application_cable/connection.rb' + - 'app/controllers/activities_controller.rb' + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/models/action.rb' + - 'app/models/activities/websocket_events.rb' + - 'app/models/activity.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/import.rb' + - 'app/models/operation.rb' + - 'app/models/step.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/state.rb' + - 'app/models/steps/websocket_events.rb' + - 'config/application.rb' + - 'config/environments/test.rb' + - 'config/initializers/session_store.rb' + - 'config/routes.rb' + - 'db/migrate/20180428131814_create_uploaded_files.rb' + - 'db/migrate/20190407165921_migrate_reasoning_to_task_type.rb' + - 'db/seeds.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/sequencescape_client.rb' + - 'lib/support_n3.rb' + - 'script/remove_duplicates.rb' + - 'script/runners/transfer_plate_to_plate.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/steps/queueable_job_spec.rb' + - 'spec/models/steps/task_spec.rb' + - 'spec/remote_assets_helper.rb' + - 'test/test_helper.rb' + +# Offense count: 6 +# Cop supports --auto-correct. +Layout/LeadingEmptyLines: + Exclude: + - 'app/models/asset_group.rb' + - 'app/models/step.rb' + - 'config/routes.rb' + - 'lib/tasks/setup_templates.rake' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/test2.rb' + +# Offense count: 16 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineArrayBraceLayout: + Exclude: + - 'app/models/instrument.rb' + - 'app/models/step_type.rb' + - 'lib/label_templates/ss_tube.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/assets/export_spec.rb' + +# Offense count: 31 +# Cop supports --auto-correct. +Layout/MultilineBlockLayout: + Exclude: + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/models/action_spec.rb' + - 'spec/models/activities/steps_management_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/script/runners/load_metadata_spec.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + +# Offense count: 31 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineHashBraceLayout: + Exclude: + - 'app/helpers/application_helper.rb' + - 'app/models/activities/tasks.rb' + - 'app/models/activity_type.rb' + - 'app/models/asset.rb' + - 'lib/label_templates/ss_plate.rb' + - 'lib/support_n3.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + +# Offense count: 6 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineMethodCallBraceLayout: + Exclude: + - 'app/models/asset.rb' + - 'lib/support_n3.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/steps/task_spec.rb' + +# Offense count: 26 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented, indented_relative_to_receiver +Layout/MultilineMethodCallIndentation: + Exclude: + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + +# Offense count: 7 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented +Layout/MultilineOperationIndentation: + Exclude: + - 'app/models/assets/export.rb' + - 'app/models/step_type.rb' + +# Offense count: 129 +# Cop supports --auto-correct. +Layout/SpaceAfterColon: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/models/assets/export.rb' + - 'app/models/printables/group.rb' + - 'app/models/printables/instance.rb' + - 'lib/fact_changes.rb' + - 'lib/label_template_setup.rb' + - 'lib/label_templates/ss_plate.rb' + - 'lib/label_templates/ss_tube.rb' + - 'lib/label_types/tube.rb' + - 'spec/controllers/kits_controller_spec.rb' + - 'spec/controllers/step_types_controller_spec.rb' + - 'test/factories/barcode_creatable.rb' + +# Offense count: 316 +# Cop supports --auto-correct. +Layout/SpaceAfterComma: + Exclude: + - 'app/controllers/activities_controller.rb' + - 'app/controllers/samples_status_controller.rb' + - 'app/controllers/step_types_controller.rb' + - 'app/controllers/uploaded_files_controller.rb' + - 'app/models/action.rb' + - 'app/models/activities/steps_management.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/import.rb' + - 'app/models/condition_group.rb' + - 'app/models/label_template.rb' + - 'app/models/printer.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/state.rb' + - 'config/environments/development.rb' + - 'config/environments/production.rb' + - 'config/environments/test.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/default/step_execution.rb' + - 'lib/label_template_setup.rb' + - 'lib/label_templates/ss_plate.rb' + - 'lib/label_templates/ss_tube.rb' + - 'lib/label_types/tube.rb' + - 'lib/support_n3.rb' + - 'lib/token_util.rb' + - 'script/runners/create_12_tubes.rb' + - 'script/runners/load_metadata.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/lib/actions/plate_transfer_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/line_reader_spec.rb' + - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/action_spec.rb' + - 'spec/models/activities/steps_management_spec.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/script/runners/transfer_plate_to_plate_spec.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + - 'test/factories/barcode_creatable.rb' + +# Offense count: 311 +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator. +# SupportedStylesForExponentOperator: space, no_space +Layout/SpaceAroundOperators: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/controllers/activities_controller.rb' + - 'app/controllers/application_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/controllers/samples_status_controller.rb' + - 'app/controllers/user_sessions_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/assets_helper.rb' + - 'app/helpers/step_types_helper.rb' + - 'app/models/action.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/import.rb' + - 'app/models/assets/traction_fields.rb' + - 'app/models/condition.rb' + - 'app/models/fact.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/compatible.rb' + - 'app/models/steps/deprecatable.rb' + - 'app/models/steps/job.rb' + - 'app/models/uploaded_file.rb' + - 'config/environments/development.rb' + - 'config/environments/production.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/default/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/label_template_setup.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/parsers/csv_layout/line_reader.rb' + - 'lib/parsers/csv_metadata/headers_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'lib/sequencescape_client.rb' + - 'lib/support_n3.rb' + - 'lib/token_util.rb' + - 'script/claim_uuids.rb' + - 'script/recreate_steptypes.rb' + - 'script/runners/create_12_tubes.rb' + - 'script/runners/create_file.rb' + - 'script/runners/create_layout.rb' + - 'script/runners/full_rack_generator.rb' + - 'script/runners/load_metadata.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/runners/rack_layout.rb' + - 'script/runners/rack_layout_any_barcode.rb' + - 'script/runners/rack_layout_creating_tubes.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'spec/concerns/deprecatable_spec.rb' + - 'spec/controllers/assets_controller_spec.rb' + - 'spec/inferences_helper.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/lib/actions/plate_transfer_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/actions/tube_transfer_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/action_spec.rb' + - 'spec/models/activities/background_tasks_spec.rb' + - 'spec/models/assets/export_spec.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/remote_assets_helper.rb' + - 'spec/script/runners/load_metadata_spec.rb' + - 'spec/script/runners/transfer_plate_to_plate_spec.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + +# Offense count: 5 +# Cop supports --auto-correct. +Layout/SpaceBeforeComma: + Exclude: + - 'db/migrate/20160705084036_create_uploads.rb' + - 'db/migrate/20180428131814_create_uploaded_files.rb' + - 'lib/parsers/csv_layout/barcode_creatable_parser.rb' + - 'spec/models/step_type_spec.rb' + +# Offense count: 6 +# Cop supports --auto-correct. +Layout/SpaceBeforeComment: + Exclude: + - 'Gemfile' + - 'app/models/step_type.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Layout/SpaceBeforeSemicolon: + Exclude: + - 'app/models/assets/export.rb' + - 'app/models/assets/import.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: require_no_space, require_space +Layout/SpaceInLambdaLiteral: + Exclude: + - 'app/models/fact.rb' + +# Offense count: 9 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. +# SupportedStyles: space, no_space, compact +# SupportedStylesForEmptyBrackets: space, no_space +Layout/SpaceInsideArrayLiteralBrackets: + Exclude: + - 'lib/inference_engines/cwm/step_execution.rb' + - 'script/runners/create_layout.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/models/steps/task_spec.rb' + +# Offense count: 6 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: space, no_space +Layout/SpaceInsideParens: + Exclude: + - 'app/models/concerns/deprecatable.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/script/runners/load_metadata_spec.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: space, no_space +Layout/SpaceInsideStringInterpolation: + Exclude: + - 'app/helpers/activities_helper.rb' + +# Offense count: 35 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: final_newline, final_blank_line +Layout/TrailingEmptyLines: + Exclude: + - 'app/models/activities/steps_management.rb' + - 'app/models/fact.rb' + - 'app/models/printables/print_asset.rb' + - 'app/views/printers/_printer.json.jbuilder' + - 'app/views/printers/index.json.jbuilder' + - 'app/views/printers/show.json.jbuilder' + - 'app/views/users/index.json.jbuilder' + - 'app/views/users/show.json.jbuilder' + - 'db/migrate/20160626224627_create_condition_groups.rb' + - 'lib/label_templates/ss_plate.rb' + - 'lib/label_templates/ss_tube.rb' + - 'lib/label_types/tube.rb' + - 'lib/sequencescape_client.rb' + - 'lib/step_execution_process.rb' + - 'lib/tasks/setup_templates.rake' + - 'script/aliquot_type_inference.rb' + - 'script/claim_uuids.rb' + - 'script/container_inferences.rb' + - 'script/purpose_name_inference.rb' + - 'script/runners/create_stamped_plate.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/runners/transfer_plate_to_plate.rb' + - 'script/runners/update_sequencescape.rb' + - 'script/study_name_inference.rb' + - 'spec/concerns/deprecatable_spec.rb' + - 'spec/controllers/step_types_controller_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/models/activity_type_spec.rb' + - 'spec/models/asset_group_spec.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/steps/state_spec.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + +# Offense count: 42 +# Cop supports --auto-correct. +# Configuration parameters: AllowInHeredoc. +Layout/TrailingWhitespace: + Exclude: + - 'app/helpers/assets_helper.rb' + - 'app/models/activities/steps_management.rb' + - 'app/models/condition.rb' + - 'app/models/printables/print_asset.rb' + - 'db/migrate/20170122173205_add_state_to_step.rb' + - 'db/migrate/20170128170039_add_namespace_to_fact_predicate.rb' + - 'db/migrate/20170212120729_add_group_owned_to_activity.rb' + - 'db/migrate/20171205163743_add_work_orders_table.rb' + - 'db/migrate/20180428131814_create_uploaded_files.rb' + - 'db/migrate/20190407165821_add_task_type_to_step_type.rb' + - 'lib/label_templates/ss_plate.rb' + - 'lib/label_templates/ss_tube.rb' + - 'spec/concerns/deprecatable_spec.rb' + - 'spec/controllers/kit_types_controller_spec.rb' + - 'spec/models/action_spec.rb' + - 'spec/models/condition_spec.rb' + - 'test/factories/actions.rb' + - 'test/factories/activity_type_step_types.rb' + - 'test/factories/asset_groups.rb' + - 'test/factories/kit_types.rb' + - 'test/factories/label_templates.rb' + - 'test/factories/operations.rb' + - 'test/factories/printers.rb' + - 'test/factories/step_executions.rb' + - 'test/factories/step_types.rb' + +# Offense count: 9 +Lint/AmbiguousBlockAssociation: + Exclude: + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/steps/job_spec.rb' + - 'spec/models/steps/task_spec.rb' + +# Offense count: 5 +Lint/ConstantDefinitionInBlock: + Exclude: + - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' + - 'spec/models/activities/background_tasks_spec.rb' + +# Offense count: 3 +Lint/DuplicateMethods: + Exclude: + - 'lib/parsers/csv_layout/barcode_parser.rb' + - 'lib/support_n3.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +Lint/NonDeterministicRequireOrder: + Exclude: + - 'lib/tasks/setup_templates.rake' + - 'spec/rails_helper.rb' + +# Offense count: 9 +# Cop supports --auto-correct. +Lint/ParenthesesAsGroupedExpression: + Exclude: + - 'script/runners/load_metadata.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/runners/rack_layout.rb' + - 'script/runners/rack_layout_any_barcode.rb' + - 'script/runners/rack_layout_creating_tubes.rb' + +# Offense count: 10 +# Cop supports --auto-correct. +Lint/RedundantStringCoercion: + Exclude: + - 'app/helpers/activities_helper.rb' + - 'app/models/asset.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'script/runners/create_file.rb' + - 'script/runners/create_layout.rb' + - 'script/runners/full_rack_generator.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + +# Offense count: 1 +# Configuration parameters: IgnoreImplicitReferences. +Lint/ShadowedArgument: + Exclude: + - 'lib/sequencescape_client.rb' + +# Offense count: 10 +Lint/ShadowingOuterLocalVariable: + Exclude: + - 'app/models/activities/steps_management.rb' + - 'app/models/printables/group.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/support_n3.rb' + - 'spec/lib/support_n3_spec.rb' + +# Offense count: 2 +# Configuration parameters: AllowComments. +Lint/SuppressedException: + Exclude: + - 'spec/controllers/steps_controller_spec.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Lint/ToJSON: + Exclude: + - 'lib/fact_changes.rb' + +# Offense count: 3 +Lint/UnreachableCode: + Exclude: + - 'app/helpers/activities_helper.rb' + - 'app/models/activity_type.rb' + - 'lib/inference_engines/runner/step_execution.rb' + +# Offense count: 57 +# Cop supports --auto-correct. +# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. +Lint/UnusedBlockArgument: + Exclude: + - 'app/models/action.rb' + - 'app/models/asset.rb' + - 'app/models/label_template.rb' + - 'app/models/printables/print_asset.rb' + - 'app/models/printer.rb' + - 'db/migrate/20161028122148_add_action_type_to_operations.rb' + - 'db/migrate/20161028134840_add_connect_by_to_step_type.rb' + - 'db/migrate/20170122001651_add_active_step_to_activity.rb' + - 'db/migrate/20170122173205_add_state_to_step.rb' + - 'db/migrate/20170128170039_add_namespace_to_fact_predicate.rb' + - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/support_n3.rb' + - 'script/fix_duplicated_tubes.rb' + - 'script/runners/create_12_tubes.rb' + - 'script/runners/load_metadata.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/models/activities/background_tasks_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + +# Offense count: 24 +# Cop supports --auto-correct. +# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. +Lint/UnusedMethodArgument: + Exclude: + - 'app/controllers/application_controller.rb' + - 'app/helpers/application_helper.rb' + - 'app/models/action.rb' + - 'app/models/asset.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/traction_fields.rb' + - 'lib/actions/racking.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/sequencescape_client.rb' + - 'lib/support_n3.rb' + - 'script/remove_duplicates.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/runners/transfer_samples.rb' + - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' + - 'spec/remote_assets_helper.rb' + +# Offense count: 64 +Lint/UselessAssignment: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/controllers/activities_controller.rb' + - 'app/helpers/application_helper.rb' + - 'app/models/activities/json_attributes.rb' + - 'app/models/activities/tasks.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/step_type.rb' + - 'db/seeds.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/parsers/csv_layout/barcode_parser.rb' + - 'lib/parsers/csv_layout/location_parser.rb' + - 'lib/sequencescape_client.rb' + - 'lib/support_n3.rb' + - 'lib/token_util.rb' + - 'script/fix_duplicated_tubes.rb' + - 'script/recreate_steptypes.rb' + - 'script/remove_duplicates.rb' + - 'script/runners/put_tubes_into_rack_by_column_order.rb' + - 'script/runners/transfer_plate_to_plate.rb' + - 'script/runners/update_sequencescape.rb' + - 'spec/controllers/assets_controller_spec.rb' + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/activity_spec.rb' + - 'spec/models/asset_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/steps/queueable_job_spec.rb' + - 'spec/remote_assets_helper.rb' + +# Offense count: 3 +# Configuration parameters: CheckForMethodsWithNoSideEffects. +Lint/Void: + Exclude: + - 'app/models/printables/group.rb' + - 'lib/inference_engines/default/step_execution.rb' + - 'spec/models/assets/export_spec.rb' + +# Offense count: 84 +# Configuration parameters: IgnoredMethods. +Metrics/AbcSize: + Max: 79 + +# Offense count: 12 +# Configuration parameters: CountComments, CountAsOne, ExcludedMethods. +# ExcludedMethods: refine +Metrics/BlockLength: + Max: 75 + +# Offense count: 7 +# Configuration parameters: CountBlocks. +Metrics/BlockNesting: + Max: 5 + +# Offense count: 11 +# Configuration parameters: CountComments, CountAsOne. +Metrics/ClassLength: + Max: 474 + +# Offense count: 37 +# Configuration parameters: IgnoredMethods. +Metrics/CyclomaticComplexity: + Max: 26 + +# Offense count: 106 +# Configuration parameters: CountComments, CountAsOne, ExcludedMethods. +Metrics/MethodLength: + Max: 334 + +# Offense count: 7 +# Configuration parameters: CountComments, CountAsOne. +Metrics/ModuleLength: + Max: 254 + +# Offense count: 32 +# Configuration parameters: IgnoredMethods. +Metrics/PerceivedComplexity: + Max: 26 + +# Offense count: 7 +Naming/AccessorMethodName: + Exclude: + - 'app/models/assets/import.rb' + - 'app/models/fact.rb' + - 'app/models/step.rb' + - 'lib/fact_changes.rb' + - 'lib/sequencescape_client.rb' + +# Offense count: 1 +# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS +Naming/FileName: + Exclude: + - 'config/initializers/pmb_server-setup.rb' + +# Offense count: 10 +# Configuration parameters: IgnoredPatterns. +# SupportedStyles: snake_case, camelCase +Naming/MethodName: + EnforcedStyle: snake_case + +# Offense count: 36 +# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. +# AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to +Naming/MethodParameterName: + Exclude: + - 'app/models/condition.rb' + - 'app/models/fact.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/support_n3.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/queueable_job_spec.rb' + +# Offense count: 27 +# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros. +# NamePrefix: is_, has_, have_ +# ForbiddenPrefixes: is_, has_, have_ +# AllowedMethods: is_a? +# MethodDefinitionMacros: define_method, define_singleton_method +Naming/PredicateName: + Exclude: + - 'spec/**/*' + - 'app/models/activities/websocket_events.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/import.rb' + - 'app/models/condition.rb' + - 'app/models/condition_group.rb' + - 'app/models/steps/queueable_job.rb' + - 'app/models/steps/state.rb' + - 'lib/fact_changes.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'lib/support_n3.rb' + - 'lib/token_util.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: PreferredName. +Naming/RescuedExceptionsVariableName: + Exclude: + - 'app/models/assets/export.rb' + - 'lib/sequencescape_client.rb' + +# Offense count: 40 +# Configuration parameters: EnforcedStyle. +# SupportedStyles: snake_case, camelCase +Naming/VariableName: + Exclude: + - 'app/helpers/application_helper.rb' + - 'app/models/action.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/actions/tube_transfer.rb' + - 'lib/fact_changes.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + +# Offense count: 2 +# Configuration parameters: MinSize. +Performance/CollectionLiteralInLoop: + Exclude: + - 'app/models/assets/export.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Performance/CompareWithBlock: + Exclude: + - 'app/controllers/samples_status_controller.rb' + - 'app/models/activities/steps_management.rb' + +# Offense count: 20 +# Cop supports --auto-correct. +Performance/Count: + Exclude: + - 'app/models/step_type.rb' + - 'lib/support_n3.rb' + - 'spec/lib/actions/plate_transfer_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/steps/cancellable_spec.rb' + - 'spec/models/steps/deprecatable_spec.rb' + +# Offense count: 25 +# Cop supports --auto-correct. +Performance/Detect: + Exclude: + - 'app/helpers/activities_helper.rb' + - 'app/models/asset.rb' + - 'app/models/assets/export.rb' + - 'app/models/label_template.rb' + - 'app/models/printer.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'lib/parsers/csv_metadata/datum_parser.rb' + - 'lib/sequencescape_client.rb' + - 'lib/support_n3.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'spec/lib/actions/plate_transfer_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/actions/tube_transfer_spec.rb' + - 'spec/lib/support_n3_spec.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +Performance/RedundantMatch: + Exclude: + - 'app/models/asset.rb' + - 'lib/inference_engines/runner/step_execution.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +Performance/RegexpMatch: + Exclude: + - 'app/models/asset.rb' + - 'lib/inference_engines/runner/step_execution.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +Performance/StringReplacement: + Exclude: + - 'app/models/assets/import.rb' + - 'lib/token_util.rb' + +# Offense count: 72 +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect. +Performance/TimesMap: + Exclude: + - 'app/models/action.rb' + - 'lib/token_util.rb' + - 'script/runners/create_12_tubes.rb' + - 'script/runners/create_file.rb' + - 'script/runners/create_layout.rb' + - 'script/runners/full_rack_generator.rb' + - 'spec/concerns/deprecatable_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/models/activities/background_tasks_spec.rb' + - 'spec/models/asset_group_spec.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/background_tasks/inference_spec.rb' + - 'spec/models/steps/cancellable_spec.rb' + - 'spec/models/steps/deprecatable_spec.rb' + - 'spec/models/steps/queueable_job_spec.rb' + - 'spec/models/steps/stoppable_spec.rb' + - 'spec/script/runners/load_metadata_spec.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + +# Offense count: 89 +# Cop supports --auto-correct. +Rails/ActiveRecordAliases: + Exclude: + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/changes_controller.rb' + - 'app/models/activities/background_tasks.rb' + - 'app/models/activities/state.rb' + - 'app/models/activity_type.rb' + - 'app/models/asset.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/import.rb' + - 'app/models/concerns/deprecatable.rb' + - 'app/models/fact.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/retryable.rb' + - 'app/models/uploaded_file.rb' + - 'app/models/user.rb' + - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/support_n3.rb' + - 'script/plate_to_code39.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'spec/helpers/application_helper_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/models/activities/background_tasks_spec.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/steps/background_tasks/inference_spec.rb' + - 'spec/models/steps/queueable_job_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + - 'spec/shared_examples/background_step.rb' + - 'test/factories/assets.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/ActiveRecordCallbacksOrder: + Exclude: + - 'app/models/activity_type.rb' + - 'app/models/step_type.rb' + +# Offense count: 20 +# Cop supports --auto-correct. +Rails/ApplicationRecord: + Exclude: + - 'app/models/action.rb' + - 'app/models/activity.rb' + - 'app/models/activity_type.rb' + - 'app/models/activity_type_compatibility.rb' + - 'app/models/activity_type_step_type.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/asset_groups_asset.rb' + - 'app/models/condition.rb' + - 'app/models/condition_group.rb' + - 'app/models/fact.rb' + - 'app/models/instrument.rb' + - 'app/models/kit.rb' + - 'app/models/kit_type.rb' + - 'app/models/label_template.rb' + - 'app/models/printer.rb' + - 'app/models/step.rb' + - 'app/models/step_message.rb' + - 'app/models/step_type.rb' + - 'app/models/user.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: NilOrEmpty, NotPresent, UnlessPresent. +Rails/Blank: + Exclude: + - 'app/models/action.rb' + - 'app/models/steps/task.rb' + +# Offense count: 4 +# Configuration parameters: Database, Include. +# SupportedDatabases: mysql, postgresql +# Include: db/migrate/*.rb +Rails/BulkChangeTable: + Exclude: + - 'db/migrate/20160923094944_add_sessions_table.rb' + - 'db/migrate/20170303142929_set_barcode_index_not_unique.rb' + - 'db/migrate/20171009132757_add_next_step_to_steps.rb' + - 'db/migrate/20180628135208_add_started_at_and_completed_at_to_step.rb' + +# Offense count: 1 +# Configuration parameters: Include. +# Include: db/migrate/*.rb +Rails/CreateTableWithTimestamps: + Exclude: + - 'db/migrate/20160626224627_create_condition_groups.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforceForPrefixed. +Rails/Delegate: + Exclude: + - 'lib/parsers/csv_metadata/csv_parser.rb' + +# Offense count: 28 +# Cop supports --auto-correct. +# Configuration parameters: Whitelist, AllowedMethods, AllowedReceivers. +# Whitelist: find_by_sql +# AllowedMethods: find_by_sql +# AllowedReceivers: Gem::Specification +Rails/DynamicFindBy: + Exclude: + - 'app/controllers/activities_controller.rb' + - 'app/controllers/samples_status_controller.rb' + - 'app/models/assets/import.rb' + - 'spec/lib/support_n3_spec.rb' + +# Offense count: 2 +# Configuration parameters: EnforcedStyle. +# SupportedStyles: slashes, arguments +Rails/FilePath: + Exclude: + - 'script/runners/transfer_plate_to_plate_and_update_sequencescape.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/FindBy: + Exclude: + - 'app/models/asset.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/FindEach: + Exclude: + - 'app/models/asset.rb' + - 'app/models/steps/deprecatable.rb' + +# Offense count: 2 +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/HasAndBelongsToMany: + Exclude: + - 'app/models/activity_type.rb' + - 'app/models/instrument.rb' + +# Offense count: 22 +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/HasManyOrHasOneDependent: + Exclude: + - 'app/models/activity.rb' + - 'app/models/activity_type.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/concerns/deprecatable.rb' + - 'app/models/condition_group.rb' + - 'app/models/instrument.rb' + - 'app/models/kit.rb' + - 'app/models/kit_type.rb' + - 'app/models/step.rb' + - 'app/models/user.rb' + +# Offense count: 8 +# Configuration parameters: Include. +# Include: app/helpers/**/*.rb +Rails/HelperInstanceVariable: + Exclude: + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + +# Offense count: 9 +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/InverseOf: + Exclude: + - 'app/models/activity.rb' + - 'app/models/concerns/deprecatable.rb' + - 'app/models/condition_group.rb' + - 'app/models/step.rb' + - 'app/models/user.rb' + +# Offense count: 1 +# Configuration parameters: Include. +# Include: app/controllers/**/*.rb +Rails/LexicallyScopedActionFilter: + Exclude: + - 'app/controllers/reracking_controller.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Rails/NegateInclude: + Exclude: + - 'lib/changes_support/disjoint_list.rb' + - 'lib/support_n3.rb' + +# Offense count: 8 +# Configuration parameters: Include. +# Include: app/**/*.rb, config/**/*.rb, db/**/*.rb, lib/**/*.rb +Rails/Output: + Exclude: + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/label_template_setup.rb' + - 'lib/views_schema.rb' + +# Offense count: 9 +Rails/OutputSafety: + Exclude: + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/steps_helper.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Rails/Pluck: + Exclude: + - 'lib/actions/racking.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Rails/Presence: + Exclude: + - 'app/models/asset.rb' + +# Offense count: 6 +# Cop supports --auto-correct. +# Configuration parameters: NotNilAndNotEmpty, NotBlank, UnlessBlank. +Rails/Present: + Exclude: + - 'app/helpers/activities_helper.rb' + - 'lib/fact_changes.rb' + - 'lib/support_n3.rb' + +# Offense count: 5 +# Cop supports --auto-correct. +Rails/RedundantForeignKey: + Exclude: + - 'app/models/concerns/deprecatable.rb' + - 'app/models/step.rb' + - 'app/models/user.rb' + +# Offense count: 2 +Rails/ReflectionClassName: + Exclude: + - 'app/models/concerns/deprecatable.rb' + +# Offense count: 9 +# Configuration parameters: Include. +# Include: db/migrate/*.rb +Rails/ReversibleMigration: + Exclude: + - 'db/migrate/20170608101740_remove_unneeded_tables.rb' + - 'db/migrate/20190516153622_remove_task_type.rb' + +# Offense count: 24 +# Configuration parameters: ForbiddenMethods, AllowedMethods. +# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all +Rails/SkipsModelValidations: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/import.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/cancellable.rb' + - 'app/models/steps/state.rb' + - 'app/models/steps/websocket_events.rb' + - 'app/models/uploaded_file.rb' + - 'db/migrate/20190528125756_fix_incorrect_fact_literals.rb' + - 'db/migrate/20190717130805_change_sti_type.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'spec/models/steps/job_spec.rb' + - 'spec/shared_examples/background_step.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Rails/SquishedSQLHeredocs: + Exclude: + - 'db/migrate/20200709123033_create_heron_activities_view.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: strict, flexible +Rails/TimeZone: + Exclude: + - 'app/controllers/assets_controller.rb' + - 'spec/remote_assets_helper.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/Validation: + Exclude: + - 'app/models/label_template.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +Rails/WhereNot: + Exclude: + - 'app/models/activities/state.rb' + - 'app/models/step_type.rb' + - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' + +# Offense count: 1 +# Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols. +# SupportedStyles: inline, group +Style/AccessModifierDeclarations: + Exclude: + - 'app/models/printables/group.rb' + +# Offense count: 16 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: separated, grouped +Style/AccessorGrouping: + Exclude: + - 'lib/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/default/step_execution.rb' + - 'lib/support_n3.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: prefer_alias, prefer_alias_method +Style/Alias: + Exclude: + - 'app/models/asset_group.rb' + +# Offense count: 1 +# Configuration parameters: AllowedChars. +Style/AsciiComments: + Exclude: + - 'script/runners/transfer_plate_to_plate.rb' + +# Offense count: 83 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: percent_q, bare_percent +Style/BarePercentLiterals: + Exclude: + - 'db/seeds.rb' + - 'db/views_schema.rb' + - 'script/aliquot_type_inference.rb' + - 'script/container_inferences.rb' + - 'script/purpose_name_inference.rb' + - 'script/recreate_steptypes.rb' + - 'script/study_name_inference.rb' + - 'script/tasks/runners/aliquot_type_inference.rb' + - 'spec/integration/inferences_data.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/assets/export_spec.rb' + - 'spec/models/steps/cancellable_spec.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/BlockComments: + Exclude: + - 'spec/spec_helper.rb' + +# Offense count: 127 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, IgnoredMethods, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. +# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces +# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object +# FunctionalMethods: let, let!, subject, watch +# IgnoredMethods: lambda, proc, it +Style/BlockDelimiters: + Exclude: + - 'app/controllers/uploaded_files_controller.rb' + - 'script/recreate_steptypes.rb' + - 'spec/controllers/activities_controller_spec.rb' + - 'spec/controllers/activity_types_controller_spec.rb' + - 'spec/controllers/asset_groups_controller_spec.rb' + - 'spec/controllers/changes_controller_spec.rb' + - 'spec/controllers/instruments_controller_spec.rb' + - 'spec/controllers/kit_types_controller_spec.rb' + - 'spec/controllers/kits_controller_spec.rb' + - 'spec/controllers/printers_controller_spec.rb' + - 'spec/controllers/step_types_controller_spec.rb' + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/helpers/application_helper_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/validators/any_barcode_validator_spec.rb' + - 'spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb' + - 'spec/lib/parsers/csv_layout/validators/location_validator_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb' + - 'spec/models/action_spec.rb' + - 'spec/models/activities/steps_management_spec.rb' + - 'spec/models/asset_group_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/background_tasks/inference_spec.rb' + - 'spec/models/steps/stoppable_spec.rb' + - 'spec/models/steps/task_spec.rb' + - 'spec/script/runners/load_metadata_spec.rb' + - 'spec/script/runners/transfer_plate_to_plate_spec.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: AllowOnConstant. +Style/CaseEquality: + Exclude: + - 'lib/sequencescape_client.rb' + - 'lib/support_n3.rb' + +# Offense count: 6 +# Cop supports --auto-correct. +Style/CaseLikeIf: + Exclude: + - 'app/models/action.rb' + - 'app/models/operation.rb' + - 'app/models/step_type.rb' + - 'lib/actions/racking.rb' + +# Offense count: 37 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: nested, compact +Style/ClassAndModuleChildren: + Exclude: + - 'app/models/activities/json_attributes.rb' + - 'app/models/activities/state.rb' + - 'app/models/activities/steps_management.rb' + - 'app/models/activities/websocket_events.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/import.rb' + - 'app/models/assets/traction_fields.rb' + - 'app/models/printables/group.rb' + - 'app/models/printables/instance.rb' + - 'app/models/steps/background_tasks/inference.rb' + - 'app/models/steps/background_tasks/runner.rb' + - 'app/models/steps/cancellable.rb' + - 'app/models/steps/compatible.rb' + - 'app/models/steps/deprecatable.rb' + - 'app/models/steps/job.rb' + - 'app/models/steps/queueable_job.rb' + - 'app/models/steps/retryable.rb' + - 'app/models/steps/state.rb' + - 'app/models/steps/stoppable.rb' + - 'app/models/steps/task.rb' + - 'app/models/steps/websocket_events.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/sequencescape_client_v2.rb' + - 'test/test_helper.rb' + +# Offense count: 39 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: is_a?, kind_of? +Style/ClassCheck: + Exclude: + - 'app/models/asset.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/traction_fields.rb' + - 'app/models/condition.rb' + - 'app/models/condition_group.rb' + - 'app/models/steps/websocket_events.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/fact_changes.rb' + - 'lib/parsers/csv_layout/line_reader.rb' + - 'lib/token_util.rb' + - 'spec/lib/changes_support/transaction_scope_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' + - 'spec/requests/api/v1/assets_spec.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +# Configuration parameters: IgnoredMethods. +# IgnoredMethods: ==, equal?, eql? +Style/ClassEqualityComparison: + Exclude: + - 'app/helpers/application_helper.rb' + - 'lib/support_n3.rb' + - 'spec/remote_assets_helper.rb' + +# Offense count: 3 +Style/ClassVars: + Exclude: + - 'app/models/action.rb' + - 'lib/sequencescape_client.rb' + +# Offense count: 26 +# Cop supports --auto-correct. +Style/ColonMethodCall: + Exclude: + - 'app/models/activity_type.rb' + - 'app/models/assets/import.rb' + - 'app/models/step_type.rb' + - 'db/seeds.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/support_n3.rb' + - 'script/runners/put_tubes_into_rack_by_column_order.rb' + - 'spec/inferences_helper.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/models/assets/export_spec.rb' + +# Offense count: 8 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions. +# SupportedStyles: assign_to_condition, assign_inside_condition +Style/ConditionalAssignment: + Exclude: + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'app/models/asset_group.rb' + - 'app/models/condition.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + +# Offense count: 213 +Style/Documentation: + Exclude: + - 'spec/**/*' + - 'test/**/*' + - 'app/channels/activity_channel.rb' + - 'app/channels/application_cable/connection.rb' + - 'app/controllers/activities_controller.rb' + - 'app/controllers/activity_types_controller.rb' + - 'app/controllers/application_controller.rb' + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/controllers/changes_controller.rb' + - 'app/controllers/history_controller.rb' + - 'app/controllers/instruments_controller.rb' + - 'app/controllers/kit_types_controller.rb' + - 'app/controllers/kits_controller.rb' + - 'app/controllers/printers_controller.rb' + - 'app/controllers/reracking_controller.rb' + - 'app/controllers/samples_not_started_controller.rb' + - 'app/controllers/samples_started_controller.rb' + - 'app/controllers/step_types_controller.rb' + - 'app/controllers/steps_controller.rb' + - 'app/controllers/uploaded_files_controller.rb' + - 'app/controllers/user_sessions_controller.rb' + - 'app/controllers/users_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/assets_helper.rb' + - 'app/helpers/step_types_helper.rb' + - 'app/helpers/steps_helper.rb' + - 'app/models/action.rb' + - 'app/models/activities/background_tasks.rb' + - 'app/models/activities/json_attributes.rb' + - 'app/models/activities/state.rb' + - 'app/models/activities/steps_management.rb' + - 'app/models/activities/tasks.rb' + - 'app/models/activities/websocket_events.rb' + - 'app/models/activity.rb' + - 'app/models/activity_type.rb' + - 'app/models/activity_type_compatibility.rb' + - 'app/models/activity_type_step_type.rb' + - 'app/models/application_record.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/asset_groups_asset.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/import.rb' + - 'app/models/assets/traction_fields.rb' + - 'app/models/concerns/deprecatable.rb' + - 'app/models/concerns/uuidable.rb' + - 'app/models/condition.rb' + - 'app/models/condition_group.rb' + - 'app/models/fact.rb' + - 'app/models/instrument.rb' + - 'app/models/kit.rb' + - 'app/models/kit_type.rb' + - 'app/models/label_template.rb' + - 'app/models/operation.rb' + - 'app/models/printables/group.rb' + - 'app/models/printables/instance.rb' + - 'app/models/printer.rb' + - 'app/models/step.rb' + - 'app/models/step_message.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/background_tasks/inference.rb' + - 'app/models/steps/background_tasks/runner.rb' + - 'app/models/steps/cancellable.rb' + - 'app/models/steps/compatible.rb' + - 'app/models/steps/deprecatable.rb' + - 'app/models/steps/job.rb' + - 'app/models/steps/queueable_job.rb' + - 'app/models/steps/retryable.rb' + - 'app/models/steps/state.rb' + - 'app/models/steps/stoppable.rb' + - 'app/models/steps/task.rb' + - 'app/models/steps/websocket_events.rb' + - 'app/models/uploaded_file.rb' + - 'app/models/user.rb' + - 'app/resources/api/v1/asset_resource.rb' + - 'config/application.rb' + - 'db/migrate/20160622135510_create_activity_types.rb' + - 'db/migrate/20160622144557_create_kit_types.rb' + - 'db/migrate/20160623144123_create_kits.rb' + - 'db/migrate/20160623144133_create_asset_groups.rb' + - 'db/migrate/20160623145500_create_instruments.rb' + - 'db/migrate/20160623145510_create_activities.rb' + - 'db/migrate/20160623160509_create_activity_types_instruments.rb' + - 'db/migrate/20160623160514_create_step_types.rb' + - 'db/migrate/20160623160518_create_users.rb' + - 'db/migrate/20160623160640_create_lab_plates.rb' + - 'db/migrate/20160623160650_create_lab_aliquot_containers.rb' + - 'db/migrate/20160623160656_create_lab_aliquots.rb' + - 'db/migrate/20160623160701_create_lab_samples.rb' + - 'db/migrate/20160626202505_create_assets.rb' + - 'db/migrate/20160626202605_create_steps.rb' + - 'db/migrate/20160626224625_create_facts.rb' + - 'db/migrate/20160626224627_create_condition_groups.rb' + - 'db/migrate/20160626224628_create_conditions.rb' + - 'db/migrate/20160628112845_create_activity_type_step_types.rb' + - 'db/migrate/20160628113258_create_assets_facts.rb' + - 'db/migrate/20160629102636_create_asset_groups_assets.rb' + - 'db/migrate/20160629125357_create_asset_groups_steps.rb' + - 'db/migrate/20160629144842_create_actions.rb' + - 'db/migrate/20160705084036_create_uploads.rb' + - 'db/migrate/20160706142323_create_operations.rb' + - 'db/migrate/20160723210242_asset_to_facts_counter_cache.rb' + - 'db/migrate/20160808151909_create_predicates.rb' + - 'db/migrate/20160808152447_create_asset_relations.rb' + - 'db/migrate/20160903164344_create_delayed_jobs.rb' + - 'db/migrate/20160906104116_create_label_templates.rb' + - 'db/migrate/20160918121032_create_printers.rb' + - 'db/migrate/20160923094944_add_sessions_table.rb' + - 'db/migrate/20161003115051_create_activity_type_compatibilities.rb' + - 'db/migrate/20161028122148_add_action_type_to_operations.rb' + - 'db/migrate/20161028133116_add_position_to_facts.rb' + - 'db/migrate/20161028134840_add_connect_by_to_step_type.rb' + - 'db/migrate/20170122001651_add_active_step_to_activity.rb' + - 'db/migrate/20170122173205_add_state_to_step.rb' + - 'db/migrate/20170128170039_add_namespace_to_fact_predicate.rb' + - 'db/migrate/20170212120729_add_group_owned_to_activity.rb' + - 'db/migrate/20170225191046_add_object_asset_to_operations.rb' + - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' + - 'db/migrate/20170225193214_add_status_to_operations.rb' + - 'db/migrate/20170226142235_add_deprecatable_to_step.rb' + - 'db/migrate/20170302135104_add_index_to_asset_barcode.rb' + - 'db/migrate/20170303142929_set_barcode_index_not_unique.rb' + - 'db/migrate/20170608101740_remove_unneeded_tables.rb' + - 'db/migrate/20170710095951_change_extr_attr_to_long_text.rb' + - 'db/migrate/20170808222124_add_output_to_steps.rb' + - 'db/migrate/20170917175535_add_from_remote_to_facts.rb' + - 'db/migrate/20171009132757_add_next_step_to_steps.rb' + - 'db/migrate/20171205163743_add_work_orders_table.rb' + - 'db/migrate/20171210183629_add_sti_to_step.rb' + - 'db/migrate/20180109120254_add_printer_config_to_step.rb' + - 'db/migrate/20180428131814_create_uploaded_files.rb' + - 'db/migrate/20180623200601_add_activity_running_field.rb' + - 'db/migrate/20180626154634_add_action_to_step_type.rb' + - 'db/migrate/20180628135208_add_started_at_and_completed_at_to_step.rb' + - 'db/migrate/20180703154511_add_job_id_to_step.rb' + - 'db/migrate/20190406171804_add_name_to_asset_group.rb' + - 'db/migrate/20190407165821_add_task_type_to_step_type.rb' + - 'db/migrate/20190407165921_migrate_reasoning_to_task_type.rb' + - 'db/migrate/20190430181432_add_uuid_to_asset_group.rb' + - 'db/migrate/20190516153622_remove_task_type.rb' + - 'db/migrate/20190519195103_add_messages_table.rb' + - 'db/migrate/20190524091452_add_priority_to_step_type.rb' + - 'db/migrate/20190526185059_change_handler_to_long_text.rb' + - 'db/migrate/20190528125756_fix_incorrect_fact_literals.rb' + - 'db/migrate/20190717130805_change_sti_type.rb' + - 'db/migrate/20191127154249_add_kit_type_abbreviation.rb' + - 'db/migrate/20200709123033_create_heron_activities_view.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/actions/tube_transfer.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/deployed_version.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/default/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/label_template_setup.rb' + - 'lib/parsers/csv_layout/barcode_creatable_parser.rb' + - 'lib/parsers/csv_layout/barcode_parser.rb' + - 'lib/parsers/csv_layout/csv_parser.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/parsers/csv_layout/line_reader.rb' + - 'lib/parsers/csv_layout/location_parser.rb' + - 'lib/parsers/csv_layout/validators/any_barcode_validator.rb' + - 'lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb' + - 'lib/parsers/csv_layout/validators/location_validator.rb' + - 'lib/parsers/csv_metadata/csv_parser.rb' + - 'lib/parsers/csv_metadata/data_parser.rb' + - 'lib/parsers/csv_metadata/datum_parser.rb' + - 'lib/parsers/csv_metadata/headers_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'lib/parsers/csv_metadata/validators/headers_validator.rb' + - 'lib/psd_formatter.rb' + - 'lib/sequencescape_client.rb' + - 'lib/sequencescape_client_v2.rb' + - 'lib/step_execution_process.rb' + - 'lib/support_n3.rb' + - 'lib/token_util.rb' + - 'script/aliquot_type_inference.rb' + - 'script/claim_uuids.rb' + - 'script/container_inferences.rb' + - 'script/purpose_name_inference.rb' + - 'script/runners/create_stamped_plate.rb' + - 'script/runners/load_metadata.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/runners/print_barcodes.rb' + - 'script/runners/rack_layout.rb' + - 'script/runners/rack_layout_any_barcode.rb' + - 'script/runners/rack_layout_creating_tubes.rb' + - 'script/runners/transfer_samples.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'script/study_name_inference.rb' + - 'script/tasks/runners/aliquot_type_inference.rb' + +# Offense count: 1 +# Configuration parameters: EnforcedStyle. +# SupportedStyles: allowed_in_returns, forbidden +Style/DoubleNegation: + Exclude: + - 'app/channels/activity_channel.rb' + +# Offense count: 31 +# Cop supports --auto-correct. +Style/EachWithObject: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/step_types_helper.rb' + - 'app/models/activities/background_tasks.rb' + - 'app/models/activities/websocket_events.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/traction_fields.rb' + - 'app/models/printables/group.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/cancellable.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/fact_changes.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/parsers/csv_metadata/data_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'lib/support_n3.rb' + - 'script/fix_duplicated_tubes.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + +# Offense count: 28 +# Cop supports --auto-correct. +Style/EmptyLambdaParameter: + Exclude: + - 'app/models/activities/state.rb' + - 'app/models/asset.rb' + - 'app/models/fact.rb' + - 'app/models/operation.rb' + - 'app/models/printer.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/deprecatable.rb' + - 'app/models/steps/state.rb' + +# Offense count: 14 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: compact, expanded +Style/EmptyMethod: + Exclude: + - 'app/controllers/activity_types_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/controllers/instruments_controller.rb' + - 'app/controllers/kit_types_controller.rb' + - 'app/controllers/kits_controller.rb' + - 'app/controllers/printers_controller.rb' + - 'app/controllers/samples_status_controller.rb' + - 'app/controllers/step_types_controller.rb' + - 'app/controllers/users_controller.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +Style/EvenOdd: + Exclude: + - 'spec/models/condition_spec.rb' + - 'spec/models/step_execution_spec.rb' + +# Offense count: 7 +# Cop supports --auto-correct. +Style/ExpandPathArguments: + Exclude: + - 'Rakefile' + - 'config.ru' + - 'config/application.rb' + - 'config/boot.rb' + - 'config/environment.rb' + - 'spec/rails_helper.rb' + - 'test/test_helper.rb' + +# Offense count: 2 +# Configuration parameters: EnforcedStyle. +# SupportedStyles: annotated, template, unannotated +Style/FormatStringToken: + Exclude: + - 'config/routes.rb' + - 'lib/views_schema.rb' + +# Offense count: 362 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, always_true, never +Style/FrozenStringLiteralComment: + Exclude: + - 'Gemfile' + - 'Rakefile' + - 'app/channels/activity_channel.rb' + - 'app/channels/application_cable/channel.rb' + - 'app/channels/application_cable/connection.rb' + - 'app/controllers/activities_controller.rb' + - 'app/controllers/activity_types_controller.rb' + - 'app/controllers/api/v1/assets_controller.rb' + - 'app/controllers/application_controller.rb' + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/controllers/changes_controller.rb' + - 'app/controllers/history_controller.rb' + - 'app/controllers/instruments_controller.rb' + - 'app/controllers/kit_types_controller.rb' + - 'app/controllers/kits_controller.rb' + - 'app/controllers/printers_controller.rb' + - 'app/controllers/reracking_controller.rb' + - 'app/controllers/samples_not_started_controller.rb' + - 'app/controllers/samples_started_controller.rb' + - 'app/controllers/samples_status_controller.rb' + - 'app/controllers/step_types_controller.rb' + - 'app/controllers/steps_controller.rb' + - 'app/controllers/uploaded_files_controller.rb' + - 'app/controllers/user_sessions_controller.rb' + - 'app/controllers/users_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/assets_helper.rb' + - 'app/helpers/step_types_helper.rb' + - 'app/helpers/steps_helper.rb' + - 'app/models/action.rb' + - 'app/models/activities/background_tasks.rb' + - 'app/models/activities/json_attributes.rb' + - 'app/models/activities/state.rb' + - 'app/models/activities/steps_management.rb' + - 'app/models/activities/tasks.rb' + - 'app/models/activities/websocket_events.rb' + - 'app/models/activity.rb' + - 'app/models/activity_type.rb' + - 'app/models/activity_type_compatibility.rb' + - 'app/models/activity_type_step_type.rb' + - 'app/models/application_record.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/asset_groups_asset.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/import.rb' + - 'app/models/assets/traction_fields.rb' + - 'app/models/concerns/deprecatable.rb' + - 'app/models/concerns/uuidable.rb' + - 'app/models/condition.rb' + - 'app/models/condition_group.rb' + - 'app/models/fact.rb' + - 'app/models/instrument.rb' + - 'app/models/kit.rb' + - 'app/models/kit_type.rb' + - 'app/models/label_template.rb' + - 'app/models/operation.rb' + - 'app/models/printables/group.rb' + - 'app/models/printables/instance.rb' + - 'app/models/printables/print_asset.rb' + - 'app/models/printer.rb' + - 'app/models/step.rb' + - 'app/models/step_message.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/background_tasks/inference.rb' + - 'app/models/steps/background_tasks/runner.rb' + - 'app/models/steps/cancellable.rb' + - 'app/models/steps/compatible.rb' + - 'app/models/steps/deprecatable.rb' + - 'app/models/steps/job.rb' + - 'app/models/steps/queueable_job.rb' + - 'app/models/steps/retryable.rb' + - 'app/models/steps/state.rb' + - 'app/models/steps/stoppable.rb' + - 'app/models/steps/task.rb' + - 'app/models/steps/websocket_events.rb' + - 'app/models/uploaded_file.rb' + - 'app/models/user.rb' + - 'app/resources/api/v1/asset_resource.rb' + - 'app/views/activities/index.json.jbuilder' + - 'app/views/activities/show.json.jbuilder' + - 'app/views/activity_types/index.json.jbuilder' + - 'app/views/activity_types/show.json.jbuilder' + - 'app/views/asset_groups/update.json.jbuilder' + - 'app/views/assets/index.json.jbuilder' + - 'app/views/assets/show.json.jbuilder' + - 'app/views/instruments/index.json.jbuilder' + - 'app/views/instruments/show.json.jbuilder' + - 'app/views/kit_types/index.json.jbuilder' + - 'app/views/kit_types/show.json.jbuilder' + - 'app/views/kits/index.json.jbuilder' + - 'app/views/kits/show.json.jbuilder' + - 'app/views/printers/_printer.json.jbuilder' + - 'app/views/printers/index.json.jbuilder' + - 'app/views/printers/show.json.jbuilder' + - 'app/views/step_types/index.json.jbuilder' + - 'app/views/step_types/show.json.jbuilder' + - 'app/views/steps/index.json.jbuilder' + - 'app/views/steps/show.json.jbuilder' + - 'app/views/user_sessions/create.json.jbuilder' + - 'app/views/users/_user.json.jbuilder' + - 'app/views/users/index.json.jbuilder' + - 'app/views/users/show.json.jbuilder' + - 'config.ru' + - 'config/application.rb' + - 'config/boot.rb' + - 'config/environment.rb' + - 'config/environments/development.rb' + - 'config/environments/production.rb' + - 'config/environments/test.rb' + - 'config/initializers/assets.rb' + - 'config/initializers/backtrace_silencers.rb' + - 'config/initializers/cookies_serializer.rb' + - 'config/initializers/delayed_job_config.rb' + - 'config/initializers/filter_parameter_logging.rb' + - 'config/initializers/inference_engine.rb' + - 'config/initializers/inflections.rb' + - 'config/initializers/jsonapi.rb' + - 'config/initializers/mime_types.rb' + - 'config/initializers/pmb_server-setup.rb' + - 'config/initializers/session_store.rb' + - 'config/initializers/version_string.rb' + - 'config/initializers/wrap_parameters.rb' + - 'config/routes.rb' + - 'db/migrate/20160622135510_create_activity_types.rb' + - 'db/migrate/20160622144557_create_kit_types.rb' + - 'db/migrate/20160623144123_create_kits.rb' + - 'db/migrate/20160623144133_create_asset_groups.rb' + - 'db/migrate/20160623145500_create_instruments.rb' + - 'db/migrate/20160623145510_create_activities.rb' + - 'db/migrate/20160623160509_create_activity_types_instruments.rb' + - 'db/migrate/20160623160514_create_step_types.rb' + - 'db/migrate/20160623160518_create_users.rb' + - 'db/migrate/20160623160640_create_lab_plates.rb' + - 'db/migrate/20160623160650_create_lab_aliquot_containers.rb' + - 'db/migrate/20160623160656_create_lab_aliquots.rb' + - 'db/migrate/20160623160701_create_lab_samples.rb' + - 'db/migrate/20160626202505_create_assets.rb' + - 'db/migrate/20160626202605_create_steps.rb' + - 'db/migrate/20160626224625_create_facts.rb' + - 'db/migrate/20160626224627_create_condition_groups.rb' + - 'db/migrate/20160626224628_create_conditions.rb' + - 'db/migrate/20160628112845_create_activity_type_step_types.rb' + - 'db/migrate/20160628113258_create_assets_facts.rb' + - 'db/migrate/20160629102636_create_asset_groups_assets.rb' + - 'db/migrate/20160629125357_create_asset_groups_steps.rb' + - 'db/migrate/20160629144842_create_actions.rb' + - 'db/migrate/20160705084036_create_uploads.rb' + - 'db/migrate/20160706142323_create_operations.rb' + - 'db/migrate/20160723210242_asset_to_facts_counter_cache.rb' + - 'db/migrate/20160808151909_create_predicates.rb' + - 'db/migrate/20160808152447_create_asset_relations.rb' + - 'db/migrate/20160903164344_create_delayed_jobs.rb' + - 'db/migrate/20160906104116_create_label_templates.rb' + - 'db/migrate/20160918121032_create_printers.rb' + - 'db/migrate/20160923094944_add_sessions_table.rb' + - 'db/migrate/20161003115051_create_activity_type_compatibilities.rb' + - 'db/migrate/20161028122148_add_action_type_to_operations.rb' + - 'db/migrate/20161028133116_add_position_to_facts.rb' + - 'db/migrate/20161028134840_add_connect_by_to_step_type.rb' + - 'db/migrate/20170122001651_add_active_step_to_activity.rb' + - 'db/migrate/20170122173205_add_state_to_step.rb' + - 'db/migrate/20170128170039_add_namespace_to_fact_predicate.rb' + - 'db/migrate/20170212120729_add_group_owned_to_activity.rb' + - 'db/migrate/20170225191046_add_object_asset_to_operations.rb' + - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' + - 'db/migrate/20170225193214_add_status_to_operations.rb' + - 'db/migrate/20170226142235_add_deprecatable_to_step.rb' + - 'db/migrate/20170302135104_add_index_to_asset_barcode.rb' + - 'db/migrate/20170303142929_set_barcode_index_not_unique.rb' + - 'db/migrate/20170710095951_change_extr_attr_to_long_text.rb' + - 'db/migrate/20170808222124_add_output_to_steps.rb' + - 'db/migrate/20170917175535_add_from_remote_to_facts.rb' + - 'db/migrate/20171009132757_add_next_step_to_steps.rb' + - 'db/migrate/20171205163743_add_work_orders_table.rb' + - 'db/migrate/20171210183629_add_sti_to_step.rb' + - 'db/migrate/20180109120254_add_printer_config_to_step.rb' + - 'db/migrate/20180428131814_create_uploaded_files.rb' + - 'db/migrate/20180623200601_add_activity_running_field.rb' + - 'db/migrate/20180626154634_add_action_to_step_type.rb' + - 'db/migrate/20180628135208_add_started_at_and_completed_at_to_step.rb' + - 'db/migrate/20180703154511_add_job_id_to_step.rb' + - 'db/migrate/20190406171804_add_name_to_asset_group.rb' + - 'db/migrate/20190407165821_add_task_type_to_step_type.rb' + - 'db/migrate/20190407165921_migrate_reasoning_to_task_type.rb' + - 'db/migrate/20190430181432_add_uuid_to_asset_group.rb' + - 'db/migrate/20190516153622_remove_task_type.rb' + - 'db/migrate/20190519195103_add_messages_table.rb' + - 'db/migrate/20190524091452_add_priority_to_step_type.rb' + - 'db/migrate/20190526185059_change_handler_to_long_text.rb' + - 'db/migrate/20190528125756_fix_incorrect_fact_literals.rb' + - 'db/migrate/20190717130805_change_sti_type.rb' + - 'db/migrate/20191127154249_add_kit_type_abbreviation.rb' + - 'db/migrate/20200709123033_create_heron_activities_view.rb' + - 'db/seeds.rb' + - 'db/views_schema.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/actions/tube_transfer.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/default/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/label_template_setup.rb' + - 'lib/label_templates/smp3_tube.rb' + - 'lib/label_templates/smpe_8mm.rb' + - 'lib/label_templates/ss_plate.rb' + - 'lib/label_templates/ss_tube.rb' + - 'lib/label_types/plate.rb' + - 'lib/label_types/tube.rb' + - 'lib/parsers/csv_layout/barcode_creatable_parser.rb' + - 'lib/parsers/csv_layout/barcode_parser.rb' + - 'lib/parsers/csv_layout/csv_parser.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/parsers/csv_layout/line_reader.rb' + - 'lib/parsers/csv_layout/location_parser.rb' + - 'lib/parsers/csv_layout/validators/any_barcode_validator.rb' + - 'lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb' + - 'lib/parsers/csv_layout/validators/location_validator.rb' + - 'lib/parsers/csv_metadata/csv_parser.rb' + - 'lib/parsers/csv_metadata/data_parser.rb' + - 'lib/parsers/csv_metadata/datum_parser.rb' + - 'lib/parsers/csv_metadata/headers_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'lib/parsers/csv_metadata/validators/headers_validator.rb' + - 'lib/sequencescape_client.rb' + - 'lib/sequencescape_client_v2.rb' + - 'lib/step_execution_process.rb' + - 'lib/support_n3.rb' + - 'lib/tasks/setup_templates.rake' + - 'lib/tasks/views_schema.rake' + - 'lib/token_util.rb' + - 'lib/views_schema.rb' + - 'script/aliquot_type_inference.rb' + - 'script/claim_uuids.rb' + - 'script/container_inferences.rb' + - 'script/fix_duplicated_tubes.rb' + - 'script/plate_to_code39.rb' + - 'script/purpose_name_inference.rb' + - 'script/recreate_steptypes.rb' + - 'script/remove_duplicates.rb' + - 'script/runners/create_12_tubes.rb' + - 'script/runners/create_file.rb' + - 'script/runners/create_layout.rb' + - 'script/runners/create_stamped_plate.rb' + - 'script/runners/full_rack_generator.rb' + - 'script/runners/load_metadata.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/runners/print_barcodes.rb' + - 'script/runners/put_tubes_into_rack_by_column_order.rb' + - 'script/runners/rack_layout.rb' + - 'script/runners/rack_layout_any_barcode.rb' + - 'script/runners/rack_layout_creating_tubes.rb' + - 'script/runners/transfer_plate_to_plate.rb' + - 'script/runners/transfer_plate_to_plate_and_update_sequencescape.rb' + - 'script/runners/transfer_samples.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'script/runners/update_sequencescape.rb' + - 'script/study_name_inference.rb' + - 'script/tasks/runners/aliquot_type_inference.rb' + - 'script/test2.rb' + - 'spec/concerns/deprecatable_spec.rb' + - 'spec/controllers/activities_controller_spec.rb' + - 'spec/controllers/activity_types_controller_spec.rb' + - 'spec/controllers/asset_groups_controller_spec.rb' + - 'spec/controllers/assets_controller_spec.rb' + - 'spec/controllers/changes_controller_spec.rb' + - 'spec/controllers/instruments_controller_spec.rb' + - 'spec/controllers/kit_types_controller_spec.rb' + - 'spec/controllers/kits_controller_spec.rb' + - 'spec/controllers/printers_controller_spec.rb' + - 'spec/controllers/step_types_controller_spec.rb' + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/controllers/user_sessions_controller_spec.rb' + - 'spec/helpers/application_helper_spec.rb' + - 'spec/inferences_helper.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/integration/inferences_data.rb' + - 'spec/lib/actions/plate_transfer_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/actions/tube_transfer_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/changes_support/transaction_scope_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/line_reader_spec.rb' + - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/validators/any_barcode_validator_spec.rb' + - 'spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb' + - 'spec/lib/parsers/csv_layout/validators/location_validator_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/lib/token_util_spec.rb' + - 'spec/models/action_spec.rb' + - 'spec/models/activities/background_tasks_spec.rb' + - 'spec/models/activities/state_spec.rb' + - 'spec/models/activities/steps_management_spec.rb' + - 'spec/models/activity_spec.rb' + - 'spec/models/activity_type_spec.rb' + - 'spec/models/asset_group_spec.rb' + - 'spec/models/asset_spec.rb' + - 'spec/models/assets/export_spec.rb' + - 'spec/models/assets/facts_management_spec.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/models/assets/traction_fields_spec.rb' + - 'spec/models/condition_group_spec.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/fact_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/background_tasks/inference_spec.rb' + - 'spec/models/steps/cancellable_spec.rb' + - 'spec/models/steps/deprecatable_spec.rb' + - 'spec/models/steps/job_spec.rb' + - 'spec/models/steps/queueable_job_spec.rb' + - 'spec/models/steps/state_spec.rb' + - 'spec/models/steps/stoppable_spec.rb' + - 'spec/models/steps/task_spec.rb' + - 'spec/rails_helper.rb' + - 'spec/remote_assets_helper.rb' + - 'spec/requests/api/v1/assets_spec.rb' + - 'spec/script/runners/load_metadata_spec.rb' + - 'spec/script/runners/transfer_plate_to_plate_spec.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + - 'spec/shared_examples/background_step.rb' + - 'spec/spec_helper.rb' + - 'spec/support/api_schema_matcher.rb' + - 'test/factories/actions.rb' + - 'test/factories/activities.rb' + - 'test/factories/activity_type_step_types.rb' + - 'test/factories/activity_types.rb' + - 'test/factories/asset_groups.rb' + - 'test/factories/assets.rb' + - 'test/factories/barcode_creatable.rb' + - 'test/factories/condition_groups.rb' + - 'test/factories/conditions.rb' + - 'test/factories/facts.rb' + - 'test/factories/inferences.rb' + - 'test/factories/instruments.rb' + - 'test/factories/kit_types.rb' + - 'test/factories/kits.rb' + - 'test/factories/label_templates.rb' + - 'test/factories/operations.rb' + - 'test/factories/printers.rb' + - 'test/factories/step_executions.rb' + - 'test/factories/step_types.rb' + - 'test/factories/steps.rb' + - 'test/factories/uploaded_file.rb' + - 'test/factories/user_sessions.rb' + - 'test/factories/users.rb' + - 'test/test_helper.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Style/GlobalStdStream: + Exclude: + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + +# Offense count: 32 +# Configuration parameters: MinBodyLength. +Style/GuardClause: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/controllers/activities_controller.rb' + - 'app/controllers/application_controller.rb' + - 'app/controllers/asset_groups_controller.rb' + - 'app/models/activities/websocket_events.rb' + - 'app/models/activity_type.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/condition.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/deprecatable.rb' + - 'app/models/steps/retryable.rb' + - 'app/models/steps/task.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/fact_changes.rb' + - 'lib/label_template_setup.rb' + - 'lib/parsers/csv_layout/csv_parser.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/parsers/csv_layout/validators/any_barcode_validator.rb' + - 'lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb' + - 'lib/parsers/csv_layout/validators/location_validator.rb' + - 'lib/parsers/csv_metadata/csv_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'lib/step_execution_process.rb' + - 'lib/support_n3.rb' + +# Offense count: 7 +# Cop supports --auto-correct. +Style/HashEachMethods: + Exclude: + - 'lib/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'lib/support_n3.rb' + - 'script/runners/load_metadata.rb' + - 'spec/requests/api/v1/assets_spec.rb' + +# Offense count: 962 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. +# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys +Style/HashSyntax: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/channels/application_cable/connection.rb' + - 'app/controllers/activity_types_controller.rb' + - 'app/controllers/application_controller.rb' + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/assets_controller.rb' + - 'app/controllers/history_controller.rb' + - 'app/controllers/instruments_controller.rb' + - 'app/controllers/reracking_controller.rb' + - 'app/controllers/samples_status_controller.rb' + - 'app/controllers/step_types_controller.rb' + - 'app/controllers/user_sessions_controller.rb' + - 'app/controllers/users_controller.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/assets_helper.rb' + - 'app/helpers/step_types_helper.rb' + - 'app/models/action.rb' + - 'app/models/activities/background_tasks.rb' + - 'app/models/activities/state.rb' + - 'app/models/activities/steps_management.rb' + - 'app/models/activity.rb' + - 'app/models/activity_type.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/import.rb' + - 'app/models/concerns/deprecatable.rb' + - 'app/models/condition.rb' + - 'app/models/condition_group.rb' + - 'app/models/fact.rb' + - 'app/models/kit.rb' + - 'app/models/label_template.rb' + - 'app/models/printer.rb' + - 'app/models/step.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/background_tasks/inference.rb' + - 'app/models/steps/background_tasks/runner.rb' + - 'app/models/steps/state.rb' + - 'app/models/steps/task.rb' + - 'app/models/user.rb' + - 'config/routes.rb' + - 'db/migrate/20160623160518_create_users.rb' + - 'db/migrate/20160626202605_create_steps.rb' + - 'db/migrate/20160626224625_create_facts.rb' + - 'db/migrate/20160626224627_create_condition_groups.rb' + - 'db/migrate/20160626224628_create_conditions.rb' + - 'db/migrate/20160629144842_create_actions.rb' + - 'db/migrate/20160705084036_create_uploads.rb' + - 'db/migrate/20160923094944_add_sessions_table.rb' + - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' + - 'db/migrate/20170302135104_add_index_to_asset_barcode.rb' + - 'db/migrate/20170710095951_change_extr_attr_to_long_text.rb' + - 'db/migrate/20180428131814_create_uploaded_files.rb' + - 'db/migrate/20190526185059_change_handler_to_long_text.rb' + - 'lib/actions/racking.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/sequencescape_client.rb' + - 'lib/support_n3.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'script/runners/update_sequencescape.rb' + - 'spec/controllers/activities_controller_spec.rb' + - 'spec/controllers/asset_groups_controller_spec.rb' + - 'spec/controllers/kit_types_controller_spec.rb' + - 'spec/controllers/kits_controller_spec.rb' + - 'spec/controllers/printers_controller_spec.rb' + - 'spec/controllers/step_types_controller_spec.rb' + - 'spec/inferences_helper.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/integration/inferences_data.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/activities/steps_management_spec.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/stoppable_spec.rb' + - 'test/factories/assets.rb' + - 'test/factories/steps.rb' + - 'test/factories/users.rb' + +# Offense count: 6 +# Configuration parameters: AllowIfModifier. +Style/IfInsideElse: + Exclude: + - 'app/models/asset.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/support_n3.rb' + +# Offense count: 72 +# Cop supports --auto-correct. +Style/IfUnlessModifier: + Exclude: + - 'app/controllers/asset_groups_controller.rb' + - 'app/controllers/changes_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/models/activity_type.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/import.rb' + - 'app/models/assets/traction_fields.rb' + - 'app/models/condition.rb' + - 'app/models/printables/instance.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/job.rb' + - 'app/models/steps/retryable.rb' + - 'app/models/steps/task.rb' + - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/actions/tube_transfer.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/default/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/label_template_setup.rb' + - 'lib/parsers/csv_layout/csv_parser.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/parsers/csv_layout/validators/any_barcode_validator.rb' + - 'lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb' + - 'lib/parsers/csv_layout/validators/location_validator.rb' + - 'lib/parsers/csv_metadata/csv_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'lib/parsers/csv_metadata/validators/headers_validator.rb' + - 'lib/support_n3.rb' + - 'script/aliquot_type_inference.rb' + - 'script/claim_uuids.rb' + - 'script/runners/rack_layout.rb' + - 'script/tasks/runners/aliquot_type_inference.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/models/activities/background_tasks_spec.rb' + - 'test/factories/assets.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Style/IfUnlessModifierOfIfUnless: + Exclude: + - 'lib/actions/plate_transfer.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: InverseMethods, InverseBlocks. +Style/InverseMethods: + Exclude: + - 'app/helpers/activities_helper.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + +# Offense count: 11 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: line_count_dependent, lambda, literal +Style/Lambda: + Exclude: + - 'app/models/activity.rb' + - 'app/models/asset.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/steps/state.rb' + +# Offense count: 2 +Style/MixinUsage: + Exclude: + - 'script/runners/put_tubes_into_rack_by_column_order.rb' + - 'spec/inferences_helper.rb' + +# Offense count: 16 +Style/MultilineBlockChain: + Exclude: + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'lib/actions/racking.rb' + - 'lib/fact_changes.rb' + - 'lib/support_n3.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + +# Offense count: 5 +# Cop supports --auto-correct. +Style/MultilineIfModifier: + Exclude: + - 'app/helpers/application_helper.rb' + - 'app/helpers/step_types_helper.rb' + - 'app/models/user.rb' + +# Offense count: 1 +Style/MultipleComparison: + Exclude: + - 'script/runners/load_metadata.rb' + +# Offense count: 19 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: literals, strict +Style/MutableConstant: + Exclude: + - 'app/controllers/assets_controller.rb' + - 'app/models/steps/state.rb' + - 'config/initializers/version_string.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/parsers/csv_layout/barcode_parser.rb' + - 'lib/parsers/csv_layout/csv_parser.rb' + - 'lib/parsers/csv_layout/line_reader.rb' + - 'lib/parsers/csv_metadata/csv_parser.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: both, prefix, postfix +Style/NegatedIf: + Exclude: + - 'app/models/printables/instance.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Style/NestedModifier: + Exclude: + - 'lib/actions/plate_transfer.rb' + +# Offense count: 11 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, MinBodyLength. +# SupportedStyles: skip_modifier_ifs, always +Style/Next: + Exclude: + - 'app/models/asset_group.rb' + - 'app/models/assets/export.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/inference_engines/default/step_execution.rb' + - 'lib/support_n3.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/support_n3_spec.rb' + +# Offense count: 13 +# Cop supports --auto-correct. +# Configuration parameters: Strict. +Style/NumericLiterals: + MinDigits: 14 + +# Offense count: 73 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IgnoredMethods. +# SupportedStyles: predicate, comparison +Style/NumericPredicate: + Exclude: + - 'spec/**/*' + - 'app/helpers/application_helper.rb' + - 'app/models/action.rb' + - 'app/models/activities/state.rb' + - 'app/models/activities/steps_management.rb' + - 'app/models/activities/websocket_events.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/import.rb' + - 'app/models/assets/traction_fields.rb' + - 'app/models/condition.rb' + - 'app/models/condition_group.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/task.rb' + - 'lib/actions/racking.rb' + - 'lib/actions/tube_transfer.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/deployed_version.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'lib/support_n3.rb' + - 'lib/token_util.rb' + - 'script/aliquot_type_inference.rb' + - 'script/container_inferences.rb' + - 'script/purpose_name_inference.rb' + - 'script/runners/load_metadata.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/runners/print_barcodes.rb' + - 'script/runners/rack_layout.rb' + - 'script/runners/rack_layout_any_barcode.rb' + - 'script/runners/rack_layout_creating_tubes.rb' + - 'script/runners/transfer_plate_to_plate.rb' + - 'script/runners/transfer_samples.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'script/runners/update_sequencescape.rb' + - 'script/study_name_inference.rb' + - 'script/tasks/runners/aliquot_type_inference.rb' + +# Offense count: 15 +# Configuration parameters: AllowedMethods. +# AllowedMethods: respond_to_missing? +Style/OptionalBooleanParameter: + Exclude: + - 'app/helpers/application_helper.rb' + - 'app/models/steps/cancellable.rb' + - 'lib/fact_changes.rb' + - 'lib/support_n3.rb' + +# Offense count: 7 +# Cop supports --auto-correct. +Style/OrAssignment: + Exclude: + - 'app/controllers/asset_groups_controller.rb' + - 'app/helpers/application_helper.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/import.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/ParallelAssignment: + Exclude: + - 'spec/models/step_spec.rb' + +# Offense count: 89 +# Cop supports --auto-correct. +# Configuration parameters: AllowSafeAssignment, AllowInMultilineConditions. +Style/ParenthesesAroundCondition: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'app/models/action.rb' + - 'app/models/activities/websocket_events.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/import.rb' + - 'app/models/condition.rb' + - 'app/models/condition_group.rb' + - 'app/models/operation.rb' + - 'app/models/steps/job.rb' + - 'app/models/steps/retryable.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/actions/tube_transfer.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/fact_changes.rb' + - 'lib/support_n3.rb' + - 'script/runners/create_file.rb' + - 'script/runners/create_layout.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'spec/models/activities/background_tasks_spec.rb' + - 'spec/models/step_spec.rb' + - 'test/factories/assets.rb' + +# Offense count: 81 +# Cop supports --auto-correct. +# Configuration parameters: PreferredDelimiters. +Style/PercentLiteralDelimiters: + Exclude: + - 'db/seeds.rb' + - 'script/aliquot_type_inference.rb' + - 'script/purpose_name_inference.rb' + - 'script/recreate_steptypes.rb' + - 'script/study_name_inference.rb' + - 'script/tasks/runners/aliquot_type_inference.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/integration/inferences_data.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/models/assets/export_spec.rb' + - 'spec/models/steps/cancellable_spec.rb' + +# Offense count: 21 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: lower_case_q, upper_case_q +Style/PercentQLiterals: + Exclude: + - 'db/views_schema.rb' + - 'spec/integration/inferences_data.rb' + - 'spec/models/steps/cancellable_spec.rb' + +# Offense count: 8 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: short, verbose +Style/PreferredHashMethods: + Exclude: + - 'lib/changes_support/disjoint_list.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'spec/models/asset_spec.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/RedundantAssignment: + Exclude: + - 'app/models/asset.rb' + +# Offense count: 9 +# Cop supports --auto-correct. +Style/RedundantBegin: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/models/assets/export.rb' + - 'app/models/step_type.rb' + - 'lib/parsers/csv_layout/barcode_parser.rb' + - 'lib/parsers/csv_layout/location_parser.rb' + - 'lib/sequencescape_client.rb' + - 'spec/controllers/steps_controller_spec.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/RedundantCondition: + Exclude: + - 'spec/integration/inference_spec.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/RedundantFreeze: + Exclude: + - 'lib/psd_formatter.rb' + +# Offense count: 7 +# Cop supports --auto-correct. +Style/RedundantInterpolation: + Exclude: + - 'app/helpers/application_helper.rb' + - 'app/models/asset.rb' + +# Offense count: 32 +# Cop supports --auto-correct. +Style/RedundantParentheses: + Exclude: + - 'app/helpers/activities_helper.rb' + - 'app/models/action.rb' + - 'app/models/asset.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/import.rb' + - 'app/models/condition_group.rb' + - 'app/models/step_type.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/actions/tube_transfer.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/fact_changes.rb' + - 'lib/parsers/csv_layout/csv_parser.rb' + - 'lib/support_n3.rb' + - 'script/runners/create_stamped_plate.rb' + +# Offense count: 82 +# Cop supports --auto-correct. +Style/RedundantPercentQ: + Exclude: + - 'db/seeds.rb' + - 'db/views_schema.rb' + - 'script/aliquot_type_inference.rb' + - 'script/container_inferences.rb' + - 'script/purpose_name_inference.rb' + - 'script/recreate_steptypes.rb' + - 'script/study_name_inference.rb' + - 'script/tasks/runners/aliquot_type_inference.rb' + - 'spec/integration/inferences_data.rb' + - 'spec/models/assets/export_spec.rb' + - 'spec/models/steps/cancellable_spec.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/RedundantRegexpEscape: + Exclude: + - 'lib/token_util.rb' + +# Offense count: 47 +# Cop supports --auto-correct. +# Configuration parameters: AllowMultipleReturnValues. +Style/RedundantReturn: + Exclude: + - 'app/helpers/steps_helper.rb' + - 'app/models/action.rb' + - 'app/models/activities/background_tasks.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/import.rb' + - 'app/models/condition.rb' + - 'app/models/label_template.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/compatible.rb' + - 'app/models/uploaded_file.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/label_template_setup.rb' + - 'lib/sequencescape_client.rb' + - 'lib/step_execution_process.rb' + - 'lib/token_util.rb' + - 'script/aliquot_type_inference.rb' + - 'script/container_inferences.rb' + - 'script/purpose_name_inference.rb' + - 'script/runners/load_metadata.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'script/runners/update_sequencescape.rb' + - 'script/study_name_inference.rb' + - 'spec/requests/api/v1/assets_spec.rb' + +# Offense count: 22 +# Cop supports --auto-correct. +Style/RedundantSelf: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/channels/application_cable/connection.rb' + - 'app/models/activities/json_attributes.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/concerns/deprecatable.rb' + - 'app/models/operation.rb' + - 'app/models/step.rb' + - 'app/models/steps/stoppable.rb' + - 'app/models/steps/websocket_events.rb' + - 'lib/sequencescape_client.rb' + +# Offense count: 17 +# Cop supports --auto-correct. +# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods. +# AllowedMethods: present?, blank?, presence, try, try! +Style/SafeNavigation: + Exclude: + - 'app/controllers/steps_controller.rb' + - 'app/controllers/user_sessions_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/models/activities/json_attributes.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/import.rb' + - 'app/models/condition.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/queueable_job.rb' + - 'app/models/user.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'lib/support_n3.rb' + - 'spec/models/steps/background_tasks/inference_spec.rb' + +# Offense count: 7 +# Cop supports --auto-correct. +Style/SelfAssignment: + Exclude: + - 'app/models/assets/import.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'script/runners/create_file.rb' + - 'script/runners/create_layout.rb' + - 'spec/models/action_spec.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: AllowAsExpressionSeparator. +Style/Semicolon: + Exclude: + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: only_raise, only_fail, semantic +Style/SignalException: + Exclude: + - 'spec/inferences_helper.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +Style/SlicingWithRange: + Exclude: + - 'app/models/asset.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + +# Offense count: 14 +# Configuration parameters: AllowModifier. +Style/SoleNestedConditional: + Exclude: + - 'app/models/action.rb' + - 'app/models/asset.rb' + - 'app/models/assets/import.rb' + - 'app/models/condition_group.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/parsers/csv_layout/csv_parser.rb' + - 'lib/support_n3.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'spec/integration/inference_spec.rb' + +# Offense count: 22 +# Cop supports --auto-correct. +Style/StringConcatenation: + Exclude: + - 'app/controllers/assets_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/models/asset.rb' + - 'app/models/assets/export.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'script/runners/load_metadata.rb' + - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' + - 'script/runners/rack_layout.rb' + - 'script/runners/rack_layout_any_barcode.rb' + - 'script/runners/rack_layout_creating_tubes.rb' + - 'spec/inferences_helper.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/script/runners/load_metadata_spec.rb' + - 'spec/script/runners/transfer_plate_to_plate_spec.rb' + - 'spec/script/runners/transfer_samples_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + +# Offense count: 737 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiterals: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/controllers/assets_controller.rb' + - 'app/controllers/steps_controller.rb' + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'app/helpers/steps_helper.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/import.rb' + - 'app/models/fact.rb' + - 'app/models/step_type.rb' + - 'app/views/printers/show.json.jbuilder' + - 'app/views/users/show.json.jbuilder' + - 'config/initializers/mime_types.rb' + - 'db/migrate/20160903164344_create_delayed_jobs.rb' + - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' + - 'db/migrate/20190717130805_change_sti_type.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/disjoint_list.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/label_template_setup.rb' + - 'lib/label_templates/ss_plate.rb' + - 'lib/label_templates/ss_tube.rb' + - 'lib/label_types/plate.rb' + - 'lib/label_types/tube.rb' + - 'lib/parsers/csv_layout/barcode_parser.rb' + - 'lib/parsers/csv_layout/csv_parser.rb' + - 'lib/parsers/csv_layout/validators/any_barcode_validator.rb' + - 'lib/parsers/csv_layout/validators/location_validator.rb' + - 'lib/parsers/csv_metadata/csv_parser.rb' + - 'lib/sequencescape_client_v2.rb' + - 'lib/support_n3.rb' + - 'lib/tasks/setup_templates.rake' + - 'lib/token_util.rb' + - 'script/aliquot_type_inference.rb' + - 'script/claim_uuids.rb' + - 'script/container_inferences.rb' + - 'script/plate_to_code39.rb' + - 'script/purpose_name_inference.rb' + - 'script/runners/create_12_tubes.rb' + - 'script/runners/create_file.rb' + - 'script/runners/create_layout.rb' + - 'script/runners/create_stamped_plate.rb' + - 'script/runners/full_rack_generator.rb' + - 'script/runners/load_metadata.rb' + - 'script/runners/print_barcodes.rb' + - 'script/runners/put_tubes_into_rack_by_column_order.rb' + - 'script/runners/rack_layout.rb' + - 'script/runners/rack_layout_any_barcode.rb' + - 'script/runners/rack_layout_creating_tubes.rb' + - 'script/runners/transfer_plate_to_plate.rb' + - 'script/runners/transfer_plate_to_plate_and_update_sequencescape.rb' + - 'script/runners/transfer_samples.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'script/runners/update_sequencescape.rb' + - 'script/study_name_inference.rb' + - 'script/test2.rb' + - 'spec/concerns/deprecatable_spec.rb' + - 'spec/controllers/activities_controller_spec.rb' + - 'spec/controllers/activity_types_controller_spec.rb' + - 'spec/controllers/asset_groups_controller_spec.rb' + - 'spec/controllers/assets_controller_spec.rb' + - 'spec/controllers/changes_controller_spec.rb' + - 'spec/controllers/instruments_controller_spec.rb' + - 'spec/controllers/kit_types_controller_spec.rb' + - 'spec/controllers/kits_controller_spec.rb' + - 'spec/controllers/printers_controller_spec.rb' + - 'spec/controllers/step_types_controller_spec.rb' + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/controllers/user_sessions_controller_spec.rb' + - 'spec/helpers/application_helper_spec.rb' + - 'spec/integration/inference_spec.rb' + - 'spec/lib/actions/plate_transfer_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/changes_support/transaction_scope_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/line_reader_spec.rb' + - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb' + - 'spec/lib/support_n3_spec.rb' + - 'spec/lib/token_util_spec.rb' + - 'spec/models/activities/steps_management_spec.rb' + - 'spec/models/activity_type_spec.rb' + - 'spec/models/asset_spec.rb' + - 'spec/models/assets/export_spec.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/fact_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + - 'spec/models/step_type_spec.rb' + - 'spec/models/steps/queueable_job_spec.rb' + - 'spec/models/steps/task_spec.rb' + - 'spec/rails_helper.rb' + - 'spec/remote_assets_helper.rb' + - 'spec/requests/api/v1/assets_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + - 'spec/shared_examples/background_step.rb' + +# Offense count: 72 +# Cop supports --auto-correct. +# Configuration parameters: MinSize. +# SupportedStyles: percent, brackets +Style/SymbolArray: + EnforcedStyle: brackets + +# Offense count: 2 +# Cop supports --auto-correct. +Style/SymbolLiteral: + Exclude: + - 'spec/lib/fact_changes_spec.rb' + +# Offense count: 16 +# Cop supports --auto-correct. +# Configuration parameters: IgnoredMethods. +# IgnoredMethods: respond_to, define_method +Style/SymbolProc: + Exclude: + - 'app/models/assets/import.rb' + - 'app/models/condition_group.rb' + - 'lib/label_template_setup.rb' + - 'lib/parsers/csv_metadata/headers_parser.rb' + - 'lib/support_n3.rb' + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/models/steps/cancellable_spec.rb' + +# Offense count: 8 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, AllowSafeAssignment. +# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex +Style/TernaryParentheses: + Exclude: + - 'app/helpers/activities_helper.rb' + - 'app/helpers/application_helper.rb' + - 'lib/fact_changes.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/remote_assets_helper.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInArguments: + Exclude: + - 'app/models/user.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInArrayLiteral: + Exclude: + - 'spec/models/step_type_spec.rb' + +# Offense count: 5 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleForMultiline. +# SupportedStylesForMultiline: comma, consistent_comma, no_comma +Style/TrailingCommaInHashLiteral: + Exclude: + - 'lib/label_templates/ss_plate.rb' + - 'lib/support_n3.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, AllowedMethods. +# AllowedMethods: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym +Style/TrivialAccessors: + Exclude: + - 'lib/support_n3.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Style/UnlessElse: + Exclude: + - 'lib/fact_changes.rb' + - 'spec/inferences_helper.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Style/WhileUntilDo: + Exclude: + - 'script/runners/create_file.rb' + - 'script/runners/create_layout.rb' + +# Offense count: 75 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, MinSize, WordRegex. +# SupportedStyles: percent, brackets +Style/WordArray: + Exclude: + - 'app/channels/activity_channel.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/import.rb' + - 'app/models/label_template.rb' + - 'app/models/printer.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/tube_transfer.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'spec/lib/actions/plate_transfer_spec.rb' + - 'spec/lib/actions/racking_spec.rb' + - 'spec/lib/changes_support/disjoint_list_spec.rb' + - 'spec/lib/fact_changes_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' + - 'spec/lib/parsers/csv_layout/line_reader_spec.rb' + - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' + - 'spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb' + - 'spec/lib/token_util_spec.rb' + - 'spec/models/activities/steps_management_spec.rb' + - 'spec/models/assets/import_spec.rb' + - 'spec/script/runners/load_metadata_spec.rb' + +# Offense count: 27 +# Cop supports --auto-correct. +Style/ZeroLengthPredicate: + Exclude: + - 'app/models/action.rb' + - 'app/models/asset.rb' + - 'app/models/asset_group.rb' + - 'app/models/assets/traction_fields.rb' + - 'app/models/steps/task.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/fact_changes.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'lib/token_util.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + - 'spec/controllers/steps_controller_spec.rb' + - 'spec/lib/actions/plate_transfer_spec.rb' + - 'spec/models/step_spec.rb' + +# Offense count: 96 +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. +# URISchemes: http, https +Layout/LineLength: + Max: 2354 diff --git a/app/channels/activity_channel.rb b/app/channels/activity_channel.rb index 09b1f1a4..091a9688 100644 --- a/app/channels/activity_channel.rb +++ b/app/channels/activity_channel.rb @@ -43,9 +43,9 @@ def process_asset_group(strong_params) #asset_group.update_attributes(assets: received_list) #asset_group.touch rescue Errno::ECONNREFUSED => e - asset_group.activity.send_wss_event({error: {type: 'danger', msg: 'Cannot connect with sequencescape'} }) + asset_group.activity.send_wss_event({ error: { type: 'danger', msg: 'Cannot connect with sequencescape' } }) rescue StandardError => e - asset_group.activity.send_wss_event({error: {type: 'danger', msg: e.message} }) + asset_group.activity.send_wss_event({ error: { type: 'danger', msg: e.message } }) end end end @@ -104,7 +104,7 @@ def subscribed def unsubscribed previous_value = subscribed_ids - connection_for_redis.set('SUBSCRIBED_IDS', previous_value.reject{|v| v== stream_id }) + connection_for_redis.set('SUBSCRIBED_IDS', previous_value.reject { |v| v== stream_id }) stop_all_streams end diff --git a/app/controllers/asset_groups_controller.rb b/app/controllers/asset_groups_controller.rb index 8985b956..38d6ad3d 100644 --- a/app/controllers/asset_groups_controller.rb +++ b/app/controllers/asset_groups_controller.rb @@ -15,7 +15,7 @@ def show respond_to do |format| format.html { render @asset_group } format.n3 { render :show } - format.json { head :ok} + format.json { head :ok } end end @@ -33,7 +33,7 @@ def upload @asset_group.update_with_assets([].concat(@asset_group.assets).concat([asset])) @asset_group.touch - render json: {success: true} + render json: { success: true } end def print @@ -48,7 +48,7 @@ def update_barcodes perform_assets_update if @alerts - render json: {errors: @alerts} + render json: { errors: @alerts } end end diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index 94be11af..26215008 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -131,12 +131,12 @@ def get_search_results(queries) end def valid_indexes - params.keys.map{|k| k.match(/^[pq](\d*)$/)}.compact.map{|k| k[1]} + params.keys.map { |k| k.match(/^[pq](\d*)$/) }.compact.map { |k| k[1] } end def set_queries @queries = valid_indexes.map do |val| - OpenStruct.new({:predicate => params["p"+val], :object => params["o"+val]}) + OpenStruct.new({ :predicate => params["p"+val], :object => params["o"+val] }) end end diff --git a/app/controllers/samples_status_controller.rb b/app/controllers/samples_status_controller.rb index aeb0cbd0..572f5c13 100644 --- a/app/controllers/samples_status_controller.rb +++ b/app/controllers/samples_status_controller.rb @@ -12,9 +12,9 @@ def index def pagination_params_for_activity_type(activity_type) if samples_started_params[:activity_type_id].to_i==activity_type.id - {:page => samples_started_params[:page], :per_page => 5} + { :page => samples_started_params[:page], :per_page => 5 } else - {:page => 1, :per_page => 5} + { :page => 1, :per_page => 5 } end end @@ -27,7 +27,7 @@ def set_activity_type_selected end def set_activity_types - @activity_types = ActivityType.all.visible.sort{|a,b| a.name <=> b.name}.uniq + @activity_types = ActivityType.all.visible.sort { |a,b| a.name <=> b.name }.uniq end def set_assets_for_activity_types diff --git a/app/helpers/activities_helper.rb b/app/helpers/activities_helper.rb index 48830ce1..89d928c5 100644 --- a/app/helpers/activities_helper.rb +++ b/app/helpers/activities_helper.rb @@ -9,7 +9,7 @@ def ontology_json end def step_types_data_for_step_types(activity, step_types) - step_types.select{|st| st.step_template.blank? }.map do |st| + step_types.select { |st| st.step_template.blank? }.map do |st| { createStepUrl: Rails.application.routes.url_helpers.activity_steps_path(activity), stepType: st, @@ -66,18 +66,18 @@ def operations_data(operations) occured_predicates = [] operations.reduce([]) do |memo, fact| if occured_predicates.include?(fact.predicate) - obj = memo.select{|f| f["predicate"] == fact.predicate}.first + obj = memo.select { |f| f["predicate"] == fact.predicate }.first obj["repeats"] = obj["repeats"] ? obj["repeats"]+1 : 0 next memo end elem = fact.object_asset if elem - obj = {"object_asset" => { + obj = { "object_asset" => { uuid: elem.uuid, barcode: elem.barcode, id: elem.id, info_line: elem.info_line - }}.merge(fact.attributes) + } }.merge(fact.attributes) else obj = fact.attributes end @@ -92,18 +92,18 @@ def facts_data(facts) occured_predicates = [] facts.reduce([]) do |memo, fact| if occured_predicates.include?(fact.predicate) - obj = memo.select{|f| f["predicate"] == fact.predicate}.first + obj = memo.select { |f| f["predicate"] == fact.predicate }.first obj["repeats"] = obj["repeats"] ? obj["repeats"]+1 : 0 next memo end elem = fact.object_asset if elem - obj = {"object_asset" => { + obj = { "object_asset" => { uuid: elem.uuid, barcode: elem.barcode, id: elem.id, info_line: elem.info_line - }}.merge(fact.attributes) + } }.merge(fact.attributes) else obj = fact.attributes end @@ -115,7 +115,7 @@ def facts_data(facts) def asset_data(asset) asset.facts.reload - {barcode: asset.barcode, uuid: asset.uuid, facts: facts_data(asset.facts)} + { barcode: asset.barcode, uuid: asset.uuid, facts: facts_data(asset.facts) } end def asset_group_data(activity, asset_group) @@ -127,7 +127,7 @@ def asset_group_data(activity, asset_group) condition_group_name: asset_group.condition_group_name, name: asset_group.display_name, assets_running: activity.steps.running.joins(asset_group: :assets).map(&:assets).flatten.map(&:uuid).uniq, - assets: asset_group.assets.map{|asset| asset_data(asset)} + assets: asset_group.assets.map { |asset| asset_data(asset) } } end @@ -142,7 +142,7 @@ def asset_groups_data(activity) def step_type_templates_data_for_step_types(activity, step_types, asset_group) - step_types.select{|s| !s.step_template.blank? }.map do |st| + step_types.select { |s| !s.step_template.blank? }.map do |st| { assetGroup: asset_group, createStepUrl: Rails.application.routes.url_helpers.activity_steps_path(activity), @@ -172,7 +172,7 @@ def data_asset_display_for_activity(activity) def messages_for_activity(activity) activity.steps.failed.map(&:step_messages).flatten.map do |m| - {type: 'danger', msg: m.content.to_s.html_safe} + { type: 'danger', msg: m.content.to_s.html_safe } end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 2f92faff..c281134d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -8,7 +8,7 @@ def empty_well_aliquot_type end def bootstrap_link_to(name = nil, options = nil, html_options = nil, &block) - modified_options = {:class => 'btn btn-default'} + modified_options = { :class => 'btn btn-default' } modified_options.merge!(html_options) if html_options link_to(name, options, modified_options) end @@ -55,16 +55,16 @@ def object_for(fact) end def render_react_display_for_asset(asset) - data_asset_display = {}.tap {|o| o[asset.uuid]=data_asset_display(asset.facts) } + data_asset_display = {}.tap { |o| o[asset.uuid]=data_asset_display(asset.facts) } react_component('FactsSvg', { asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display }) end def render_react_tooltip - react_component('ReactTooltip', {multiline: true, effect: 'solid'}) + react_component('ReactTooltip', { multiline: true, effect: 'solid' }) end def facts_with_object_asset(facts) - facts.left_outer_joins(:object_asset).to_a.map {|f| f.attributes.merge({object_asset: object_with_facts(f.object_asset)})} + facts.left_outer_joins(:object_asset).to_a.map { |f| f.attributes.merge({ object_asset: object_with_facts(f.object_asset) }) } end def object_with_facts(object) @@ -73,12 +73,12 @@ def object_with_facts(object) end def render_react_display_and_facts_for_asset(asset) - data_asset_display = {}.tap {|o| o[asset.uuid]=data_asset_display(asset.facts) } + data_asset_display = {}.tap { |o| o[asset.uuid]=data_asset_display(asset.facts) } react_component('Facts', { asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display }) end - def render_react_edit_asset(asset, readonly=false) - data_asset_display = {}.tap {|o| o[asset.uuid]=data_asset_display(asset.facts) } + def render_react_edit_asset(asset, readonly = false) + data_asset_display = {}.tap { |o| o[asset.uuid]=data_asset_display(asset.facts) } react_component('FactsEditor', { changesUrl: readonly ? nil : changes_url, asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display }) @@ -135,7 +135,7 @@ def svg(name) end def svg_for_facts(facts) - svg(facts.select{|f| f.predicate == 'a'}.pluck(:object).first) + svg(facts.select { |f| f.predicate == 'a' }.pluck(:object).first) end def show_alert(data) diff --git a/app/helpers/assets_helper.rb b/app/helpers/assets_helper.rb index 8b9be361..12f64acb 100644 --- a/app/helpers/assets_helper.rb +++ b/app/helpers/assets_helper.rb @@ -1,7 +1,7 @@ module AssetsHelper def condition_groups_init_for_asset(asset) obj = {} - obj[asset.barcode] = { :template => 'templates/asset_facts'} + obj[asset.barcode] = { :template => 'templates/asset_facts' } obj[asset.barcode][:facts]=asset.facts.map do |fact| { :cssClasses => '', diff --git a/app/models/action.rb b/app/models/action.rb index f30385fb..b26c73f8 100644 --- a/app/models/action.rb +++ b/app/models/action.rb @@ -13,7 +13,7 @@ def self.types # Given the current action (that defines a relation between 2 conditional groups) # and the list of assets classified into 2 groups: sources or destinations, this method # will generate a list of pairs [source, destination] that can be connected. - def each_connected_asset(sources, destinations, wildcard_values={}, &block) + def each_connected_asset(sources, destinations, wildcard_values = {}, &block) unless (wildcard_values.nil? || wildcard_values.empty?) if (object_condition_group) if (wildcard_values[object_condition_group.id]) @@ -44,7 +44,7 @@ def each_connected_asset(sources, destinations, wildcard_values={}, &block) end end if step_type.connect_by == 'position' - sources.zip(destinations).each {|s,d| yield s,d if d} + sources.zip(destinations).each { |s,d| yield s,d if d } else sources.each do |s| destinations.each do |d| @@ -66,13 +66,13 @@ def destinations(asset_group) end end - def run(asset_group, wildcard_values={}) + def run(asset_group, wildcard_values = {}) FactChanges.new.tap do |updates| if action_type == 'createAsset' if (asset_group.classified_by_condition_group(subject_condition_group).length > 0) assets = asset_group.classified_by_condition_group(subject_condition_group) else - assets = num_assets_to_create(asset_group).times.map{ Asset.new } + assets = num_assets_to_create(asset_group).times.map { Asset.new } updates.create_assets(assets) updates.add_assets([[asset_group, assets]]) #asset_group.assets << assets diff --git a/app/models/activities/background_tasks.rb b/app/models/activities/background_tasks.rb index 56673410..4238397e 100644 --- a/app/models/activities/background_tasks.rb +++ b/app/models/activities/background_tasks.rb @@ -14,7 +14,7 @@ def create!(params) end def background_tasks - return step_types.for_reasoning.map{|type| BackgroundTask.new(type)} + return step_types.for_reasoning.map { |type| BackgroundTask.new(type) } end def create_background_steps(ordered_tasks, reasoning_params) @@ -28,7 +28,7 @@ def create_background_steps(ordered_tasks, reasoning_params) end end - def create_connected_tasks(step, asset_group, printer_config=nil, user=nil) + def create_connected_tasks(step, asset_group, printer_config = nil, user = nil) reasoning_params = { :asset_group => asset_group, :activity => self, diff --git a/app/models/activities/json_attributes.rb b/app/models/activities/json_attributes.rb index e13bb337..a641cce0 100644 --- a/app/models/activities/json_attributes.rb +++ b/app/models/activities/json_attributes.rb @@ -1,5 +1,5 @@ module Activities::JsonAttributes - def initial_json_attributes(current_user=nil) + def initial_json_attributes(current_user = nil) { activity: { id: id, @@ -10,11 +10,11 @@ def initial_json_attributes(current_user=nil) selectedAssetGroup: owned_asset_groups.first.id }, tubePrinter: { - optionsData: Printer.for_tube.map{|a| [a.name, a.id]}, + optionsData: Printer.for_tube.map { |a| [a.name, a.id] }, defaultValue: current_user && current_user.tube_printer ? current_user.tube_printer.id : nil }, platePrinter: { - optionsData: Printer.for_plate.map{|a| [a.name, a.id]}, + optionsData: Printer.for_plate.map { |a| [a.name, a.id] }, defaultValue: current_user && current_user.plate_printer ? current_user.plate_printer.id : nil } }.merge(websockets_attributes(json_attributes)) @@ -31,7 +31,7 @@ def json_attributes stepTypes: -> { ApplicationController.helpers.step_types_control_data(self) }, stepsPending: -> { ApplicationController.helpers.steps_data_for_steps(self.steps.running) }, stepsRunning: -> { ApplicationController.helpers.steps_data_for_steps(self.steps.processing) }, - stepsFailed: -> { ApplicationController.helpers.steps_data_for_steps(self.steps.finished.select{|s| s.state == 'failed'}) }, + stepsFailed: -> { ApplicationController.helpers.steps_data_for_steps(self.steps.finished.select { |s| s.state == 'failed' }) }, stepsFinished: -> { ApplicationController.helpers.steps_data_for_steps(self.steps.reload.finished.reverse) } } end diff --git a/app/models/activities/state.rb b/app/models/activities/state.rb index 5157bc64..a2b57de7 100644 --- a/app/models/activities/state.rb +++ b/app/models/activities/state.rb @@ -1,8 +1,8 @@ module Activities::State def self.included(klass) klass.instance_eval do - scope :in_progress, ->() { where('completed_at is null')} - scope :finished, ->() { where('completed_at is not null')} + scope :in_progress, ->() { where('completed_at is null') } + scope :finished, ->() { where('completed_at is not null') } end end diff --git a/app/models/activities/steps_management.rb b/app/models/activities/steps_management.rb index 308b3cbc..9974ba5f 100644 --- a/app/models/activities/steps_management.rb +++ b/app/models/activities/steps_management.rb @@ -5,7 +5,7 @@ def active_step end def previous_steps - asset_group.assets.includes(:steps).map(&:steps).concat(steps).flatten.sort{|a,b| a.id <=> b.id}.uniq + asset_group.assets.includes(:steps).map(&:steps).concat(steps).flatten.sort { |a,b| a.id <=> b.id }.uniq end def assets @@ -16,11 +16,11 @@ def steps_for(assets) assets.includes(:steps).map(&:steps).concat(steps).flatten.compact.uniq end - def step_types_for(assets, required_assets=nil) + def step_types_for(assets, required_assets = nil) stypes = step_types.not_for_reasoning.includes(:condition_groups => :conditions).select do |step_type| step_type.compatible_with?(assets, required_assets) end.uniq - stype = stypes.detect{|stype| steps.in_progress.for_step_type(stype).count > 0} + stype = stypes.detect { |stype| steps.in_progress.for_step_type(stype).count > 0 } stype.nil? ? stypes : [stype] end diff --git a/app/models/activities/tasks.rb b/app/models/activities/tasks.rb index 835f9605..ee776a46 100644 --- a/app/models/activities/tasks.rb +++ b/app/models/activities/tasks.rb @@ -7,7 +7,7 @@ def create_step(params) printer_config: params[:printer_config], step_type: params[:step_type], asset_group: params[:asset_group], - user: params[:user]}) + user: params[:user] }) connected_tasks = create_connected_tasks(step, params[:asset_group], params[:printer_config], params[:user]) step.run! diff --git a/app/models/activities/websocket_events.rb b/app/models/activities/websocket_events.rb index f02da628..ead73a5c 100644 --- a/app/models/activities/websocket_events.rb +++ b/app/models/activities/websocket_events.rb @@ -22,7 +22,7 @@ def stream_id end def websockets_attributes(attrs) - attrs.keys.reduce({shownComponents: {}}) do |memo, key| + attrs.keys.reduce({ shownComponents: {} }) do |memo, key| memo[key] = attrs[key].call unless (ActivityChannel.activity_attributes(id)[key.to_s] == false) memo end @@ -35,12 +35,12 @@ def initial_websockets_attributes(attrs) end end - def wss_event(opts={}) + def wss_event(opts = {}) _wss_event(opts) #delay(queue: 'websockets')._wss_event(opts) end - def _wss_event(opts={}) + def _wss_event(opts = {}) if Rails.configuration.redis_enabled && is_being_listened? data = websockets_attributes(json_attributes).merge(opts) #debugger if data[:stepsFinished][0]['state']=='error' diff --git a/app/models/activity.rb b/app/models/activity.rb index 0d7f7e1e..1dd2ad77 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -19,7 +19,7 @@ class Activity < ActiveRecord::Base where(activity_type: activity_type) } - scope :for_user, ->(user) { joins(:steps).where({:steps => {:user_id => user.id}}).distinct } + scope :for_user, ->(user) { joins(:steps).where({ :steps => { :user_id => user.id } }).distinct } include Activities::StepsManagement include Activities::Tasks diff --git a/app/models/activity_type.rb b/app/models/activity_type.rb index 98c7752f..f04bc47a 100644 --- a/app/models/activity_type.rb +++ b/app/models/activity_type.rb @@ -30,7 +30,7 @@ def create_activity(params) group = AssetGroup.create activity = Activity.create({ kit: params[:kit], instrument: params[:instrument], - activity_type: self, asset_group: group}) + activity_type: self, asset_group: group }) activities << activity group.update_attributes!(activity_owner: activity) end @@ -59,7 +59,7 @@ def after_deprecate def compatible_with?(assets) - condition_groups.any?{|c| c.compatible_with?(assets)} + condition_groups.any? { |c| c.compatible_with?(assets) } end def to_n3 diff --git a/app/models/asset.rb b/app/models/asset.rb index 20c36afd..f4d83ee0 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -38,11 +38,11 @@ def update_compatible_activity_type has_many :activities, -> { distinct }, :through => :steps scope :currently_changing, ->() { - joins(:asset_groups, :steps).where(:steps => {:state => 'running'}) + joins(:asset_groups, :steps).where(:steps => { :state => 'running' }) } scope :for_activity_type, ->(activity_type) { - joins(:activities).where(:activities => { :activity_type_id => activity_type.id}) + joins(:activities).where(:activities => { :activity_type_id => activity_type.id }) } scope :not_started, ->() { @@ -199,7 +199,7 @@ def printable_object(username = 'unknown') } } end - return {:label => { + return { :label => { :barcode => barcode_formatted_for_printing, :barcode2d => barcode_formatted_for_printing, :top_line => TokenUtil.human_barcode(barcode), @@ -257,12 +257,12 @@ def asset_description end def self.class_type(facts) - class_types = facts.select{|f| f[:predicate] == 'a'}.map(&:object) + class_types = facts.select { |f| f[:predicate] == 'a' }.map(&:object) return 'TubeRack' if class_types.include?('TubeRack') return 'Plate' if class_types.include?('Plate') return 'Tube' if class_types.include?('Tube') return 'SampleTube' if class_types.include?('SampleTube') - return facts.select{|f| f[:predicate] == 'a'}.first.object if facts.select{|f| f[:predicate] == 'a'}.first + return facts.select { |f| f[:predicate] == 'a' }.first.object if facts.select { |f| f[:predicate] == 'a' }.first return "" end @@ -292,7 +292,7 @@ def assets_at_location(location) end def remove_from_parent(parent) - facts.with_predicate('parent').select{|f| f.object_asset==parent}.each(&:destroy) + facts.with_predicate('parent').select { |f| f.object_asset==parent }.each(&:destroy) facts.with_predicate('location').each(&:destroy) end diff --git a/app/models/asset_group.rb b/app/models/asset_group.rb index 5d7693b3..c127fdcd 100644 --- a/app/models/asset_group.rb +++ b/app/models/asset_group.rb @@ -47,7 +47,7 @@ def step_type_for_import end def position_for_asset(asset) - assets.each_with_index{|a, pos| return pos if (asset.id == a.id)} + assets.each_with_index { |a, pos| return pos if (asset.id == a.id) } return -1 end @@ -101,7 +101,7 @@ def has_asset?(asset) def select_barcodes(barcodes) barcodes.each do |barcode| - if assets.select{|a| a.barcode == barcode}.empty? + if assets.select { |a| a.barcode == barcode }.empty? asset = Asset.find_or_import_asset_with_barcode(barcode) return false if asset.nil? add_assets(asset) @@ -112,7 +112,7 @@ def select_barcodes(barcodes) def unselect_barcodes(barcodes) barcodes.each do |barcode| - selection = assets.select{|a| (a.barcode == barcode) || (a.uuid == barcode)} + selection = assets.select { |a| (a.barcode == barcode) || (a.uuid == barcode) } assets.delete(selection) end end diff --git a/app/models/assets/facts_management.rb b/app/models/assets/facts_management.rb index 84e211bd..1b2d3b1a 100644 --- a/app/models/assets/facts_management.rb +++ b/app/models/assets/facts_management.rb @@ -2,14 +2,14 @@ module Assets::FactsManagement def self.included(klass) klass.instance_eval do scope :with_fact, ->(predicate, object) { - joins(:facts).where(:facts => {:predicate => predicate, :object => object}) + joins(:facts).where(:facts => { :predicate => predicate, :object => object }) } scope :with_field, ->(predicate, object) { where(predicate => object) } scope :with_predicate, ->(predicate) { - joins(:facts).where(:facts => {:predicate => predicate}) + joins(:facts).where(:facts => { :predicate => predicate }) } @@ -17,19 +17,19 @@ def self.included(klass) end def has_literal?(predicate, object) - facts.any?{|f| f.predicate == predicate && f.object == object} + facts.any? { |f| f.predicate == predicate && f.object == object } end def has_predicate?(predicate) - facts.any?{|f| f.predicate == predicate} + facts.any? { |f| f.predicate == predicate } end def has_predicate_with_value?(predicate) - facts.any?{|f| (f.predicate == predicate) && !f.object.nil?} + facts.any? { |f| (f.predicate == predicate) && !f.object.nil? } end def has_relation_with_value?(predicate) - facts.any?{|f| (f.predicate == predicate) && !f.object_asset_id.nil?} + facts.any? { |f| (f.predicate == predicate) && !f.object_asset_id.nil? } end def has_fact?(fact) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 339466eb..44a67cbc 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -25,7 +25,7 @@ def json_for_remote(remote_asset) # aliquots.to_a, same reason listal = listw.compact.map(&:aliquots).map(&:to_a) if listal - listsa = listal.flatten.compact.map{|al| al.sample } + listsa = listal.flatten.compact.map { |al| al.sample } if listsa distinct+=listsa.compact.map(&:attributes).to_json end @@ -38,7 +38,7 @@ def json_for_remote(remote_asset) # aliquots.to_a, same reason listal = remote_asset.aliquots.to_a if listal - listsa = listal.flatten.compact.map{|al| al.sample } + listsa = listal.flatten.compact.map { |al| al.sample } if listsa distinct+=listsa.compact.map(&:attributes).to_json end @@ -56,7 +56,7 @@ def json_for_remote(remote_asset) # aliquots.to_a, same reason listal = list_tubes.compact.map(&:aliquots).map(&:to_a) if listal - listsa = listal.flatten.compact.map{|al| al.sample } + listsa = listal.flatten.compact.map { |al| al.sample } if listsa distinct+=listsa.compact.map(&:attributes).to_json end @@ -86,7 +86,7 @@ def get_import_step @import_step end - def _process_refresh(remote_asset, fact_changes=nil) + def _process_refresh(remote_asset, fact_changes = nil) fact_changes ||= FactChanges.new asset_group = AssetGroup.new @import_step.update_attributes(asset_group: asset_group) @@ -123,7 +123,7 @@ def type_of_asset_for_sequencescape end end - def refresh(fact_changes=nil) + def refresh(fact_changes = nil) if is_remote_asset? remote_asset = SequencescapeClient::find_by_uuid(uuid) raise RefreshSourceNotFoundAnymore unless remote_asset @@ -137,7 +137,7 @@ def refresh(fact_changes=nil) self end - def refresh!(fact_changes=nil) + def refresh!(fact_changes = nil) if is_remote_asset? @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Refresh!!'), state: 'running') remote_asset = SequencescapeClient::find_by_uuid(uuid) @@ -151,7 +151,7 @@ def is_remote_asset? facts.from_remote_asset.count > 0 end - def update_facts_from_remote(list, step=nil) + def update_facts_from_remote(list, step = nil) step = step || @import_step list = [list].flatten added = list.map do |f| diff --git a/app/models/condition.rb b/app/models/condition.rb index 6dadaa08..c440be64 100644 --- a/app/models/condition.rb +++ b/app/models/condition.rb @@ -3,14 +3,14 @@ class Condition < ActiveRecord::Base has_many :activity_types, :through => :condition_group belongs_to :object_condition_group, :class_name => 'ConditionGroup' - def check_wildcard_condition(asset, wildcard_values={}) + def check_wildcard_condition(asset, wildcard_values = {}) cg = object_condition_group # If the condition group is a wildcard, we'll cache all the possible # values and check compatibility with other definitions of the same # wildcard. if asset.facts.kind_of? Array - facts = asset.facts.select{|f| f.predicate == predicate} + facts = asset.facts.select { |f| f.predicate == predicate } else facts = asset.facts.with_predicate(predicate) end @@ -34,7 +34,7 @@ def store_wildcard_values(wildcard_values, cg, asset, actual_values) end end - def check_related_condition_group(cg, fact, related_assets = [], checked_condition_groups=[], wildcard_values={}) + def check_related_condition_group(cg, fact, related_assets = [], checked_condition_groups = [], wildcard_values = {}) related_asset = Asset.find(fact.object_asset_id) # This condition does not support evaluating relations like: @@ -76,7 +76,7 @@ def is_runtime_evaluable_condition? (predicate == 'equalTo') || (predicate == 'notEqualTo') || (predicate == 'hasNotPredicate') || (predicate == 'sum') end - def compatible_with?(asset, related_assets = [], checked_condition_groups=[], wildcard_values = {}) + def compatible_with?(asset, related_assets = [], checked_condition_groups = [], wildcard_values = {}) return true if is_runtime_evaluable_condition? return false if asset.nil? return check_wildcard_condition(asset, wildcard_values) if is_wildcard_condition? diff --git a/app/models/condition_group.rb b/app/models/condition_group.rb index a1f94a46..26b3e05b 100644 --- a/app/models/condition_group.rb +++ b/app/models/condition_group.rb @@ -10,12 +10,12 @@ def is_wildcard? conditions.empty? end - def select_compatible_assets(assets, position=nil) - compatibles = assets.select{|a| compatible_with?(a) } + def select_compatible_assets(assets, position = nil) + compatibles = assets.select { |a| compatible_with?(a) } (position.nil? ? compatibles : [compatibles[position]]) end - def compatible_with?(assets, related_assets = [], checked_condition_groups=[], wildcard_values={}) + def compatible_with?(assets, related_assets = [], checked_condition_groups = [], wildcard_values = {}) assets = [assets].flatten return true if is_wildcard? if ((cardinality) && (cardinality > 0)) @@ -33,7 +33,7 @@ def has_runtime_conditions? end def runtime_conditions - conditions.select{|c| c.is_runtime_evaluable_condition?} + conditions.select { |c| c.is_runtime_evaluable_condition? } end def runtime_conditions_compatible_with?(asset, related_asset) diff --git a/app/models/fact.rb b/app/models/fact.rb index 465b34cd..679d94b0 100644 --- a/app/models/fact.rb +++ b/app/models/fact.rb @@ -3,9 +3,9 @@ class Fact < ActiveRecord::Base belongs_to :object_asset, :class_name => 'Asset' scope :not_to_remove, ->() { where(:to_remove_by => nil) } - scope :with_predicate, ->(predicate) { where(:predicate => predicate)} - scope :with_ns_predicate, ->(namespace) { where(:ns_predicate => namespace)} - scope :with_fact, -> (predicate, object) { where(:predicate => predicate, :object => object)} + scope :with_predicate, ->(predicate) { where(:predicate => predicate) } + scope :with_ns_predicate, ->(namespace) { where(:ns_predicate => namespace) } + scope :with_fact, -> (predicate, object) { where(:predicate => predicate, :object => object) } scope :from_remote_asset, ->() { where(:is_remote? => true) } validates :object_asset_id, presence: true, unless: :literal? diff --git a/app/models/label_template.rb b/app/models/label_template.rb index 86b98940..eed63192 100644 --- a/app/models/label_template.rb +++ b/app/models/label_template.rb @@ -6,11 +6,11 @@ def self.for_type(type, barcodetype = 'ean13') type = { 'Plate' => ['TubeRack', 'Plate'], 'Tube' => ['Tube', 'SampleTube'] - }.select{|k,v| v.include?(type)}.first[0] + }.select { |k,v| v.include?(type) }.first[0] templates = where(:template_type => type) - templates_by_barcodetype = templates.select{|t| t.name.include?(barcodetype)} + templates_by_barcodetype = templates.select { |t| t.name.include?(barcodetype) } return templates if templates_by_barcodetype.empty? return templates_by_barcodetype end diff --git a/app/models/operation.rb b/app/models/operation.rb index 1609e0f1..84ecf876 100644 --- a/app/models/operation.rb +++ b/app/models/operation.rb @@ -33,7 +33,7 @@ def action_type_for_option(option) end end - def generate_changes_for(option_name, updates=nil) + def generate_changes_for(option_name, updates = nil) updates ||= FactChanges.new type = action_type_for_option(option_name) if (type == :add_facts) diff --git a/app/models/printables/group.rb b/app/models/printables/group.rb index 47630b33..08c0cd29 100644 --- a/app/models/printables/group.rb +++ b/app/models/printables/group.rb @@ -21,12 +21,12 @@ def print_assets(assets, printer_config, user) classify_for_printing(assets, printer_config).each do |printer_name, info_for_template| info_for_template.each do |label_template, assets| - body_print = assets.map{|a| a.printable_object(user)}.compact.reverse + body_print = assets.map { |a| a.printable_object(user) }.compact.reverse next if body_print.empty? PMB::PrintJob.new( printer_name:printer_name, label_template_id: label_template.external_id, - labels:{body: body_print} + labels:{ body: body_print } ).save end end diff --git a/app/models/printables/instance.rb b/app/models/printables/instance.rb index f22c4c80..fb0b2cc3 100644 --- a/app/models/printables/instance.rb +++ b/app/models/printables/instance.rb @@ -10,7 +10,7 @@ def print(printer_config, user) PMB::PrintJob.new( printer_name:printer_name, label_template_id: label_template.external_id, - labels:{body: body_print} + labels:{ body: body_print } ).save end end diff --git a/app/models/printer.rb b/app/models/printer.rb index d7f95516..49b4a531 100644 --- a/app/models/printer.rb +++ b/app/models/printer.rb @@ -1,7 +1,7 @@ class Printer < ActiveRecord::Base - scope :for_tube, ->() { where(:printer_type => 'Tube')} - scope :for_plate, ->() { where(:printer_type => 'Plate')} - scope :for_default, ->() { where(:default_printer => true)} + scope :for_tube, ->() { where(:printer_type => 'Tube') } + scope :for_plate, ->() { where(:printer_type => 'Plate') } + scope :for_default, ->() { where(:default_printer => true) } def self.for_type(type) type = printer_type_for(type) @@ -13,6 +13,6 @@ def self.printer_type_for(type) { 'Plate' => ['TubeRack', 'Plate'], 'Tube' => ['Tube', 'SampleTube'] - }.select{|k,v| v.include?(type)}.first[0] + }.select { |k,v| v.include?(type) }.first[0] end end diff --git a/app/models/step.rb b/app/models/step.rb index f438526a..39adb627 100644 --- a/app/models/step.rb +++ b/app/models/step.rb @@ -21,9 +21,9 @@ class Step < ActiveRecord::Base serialize :printer_config - scope :running_with_asset, ->(asset) { includes(:assets).where(asset_groups_assets: { asset_id: asset.id}, state: 'running') } - scope :for_assets, ->(assets) { joins(:asset_group => :assets).where(:asset_groups_assets => {:asset_id => assets })} - scope :for_step_type, ->(step_type) { where(:step_type => step_type)} + scope :running_with_asset, ->(asset) { includes(:assets).where(asset_groups_assets: { asset_id: asset.id }, state: 'running') } + scope :for_assets, ->(assets) { joins(:asset_group => :assets).where(:asset_groups_assets => { :asset_id => assets }) } + scope :for_step_type, ->(step_type) { where(:step_type => step_type) } include Deprecatable include Steps::QueueableJob diff --git a/app/models/step_type.rb b/app/models/step_type.rb index eb460ee0..7beb2aa8 100644 --- a/app/models/step_type.rb +++ b/app/models/step_type.rb @@ -9,25 +9,25 @@ class StepType < ActiveRecord::Base has_many :activity_type_step_types, dependent: :destroy has_many :activity_types, :through => :activity_type_step_types - has_many :activities, ->{distinct}, through: :activity_types + has_many :activities, -> { distinct }, through: :activity_types has_many :condition_groups, dependent: :destroy has_many :actions, dependent: :destroy - has_many :action_subject_condition_groups, ->{distinct}, :through => :actions, :source => :subject_condition_group - has_many :action_object_condition_groups, ->{distinct}, :through => :actions, :source => :object_condition_group + has_many :action_subject_condition_groups, -> { distinct }, :through => :actions, :source => :subject_condition_group + has_many :action_object_condition_groups, -> { distinct }, :through => :actions, :source => :object_condition_group def action_condition_groups [action_subject_condition_groups, action_object_condition_groups].flatten.uniq - condition_groups end include Deprecatable - scope :with_template, ->() { where('step_template is not null')} + scope :with_template, ->() { where('step_template is not null') } def self.for_task_type(task_type) - select{|stype| stype.task_type == task_type } + select { |stype| stype.task_type == task_type } end - scope :for_reasoning, ->() { not_deprecated.where(:for_reasoning => true).order(priority: :desc)} + scope :for_reasoning, ->() { not_deprecated.where(:for_reasoning => true).order(priority: :desc) } scope :not_for_reasoning, ->() { not_deprecated.where(:for_reasoning => false) } @@ -48,7 +48,7 @@ def all_step_templates def valid_name_file(names) - names.select{|l| l.match(/^[A-Za-z]/)} + names.select { |l| l.match(/^[A-Za-z]/) } end def all_background_steps_files @@ -129,9 +129,9 @@ def position_for_assets_by_condition_group(assets) end] end - def condition_group_classification_for(assets, checked_condition_groups=[], wildcard_values={}) + def condition_group_classification_for(assets, checked_condition_groups = [], wildcard_values = {}) related_assets = [] - h = Hash[assets.map{|asset| [asset, condition_groups_for(asset, related_assets, [], wildcard_values)]}] + h = Hash[assets.map { |asset| [asset, condition_groups_for(asset, related_assets, [], wildcard_values)] }] related_assets.each do |a| h[a]= condition_groups_for(a, [], checked_condition_groups, wildcard_values) end @@ -164,10 +164,10 @@ def every_asset_has_at_least_one_condition_group?(classification) def every_required_asset_is_in_classification?(classification, required_assets) return true if required_assets.nil? - required_assets.all?{|asset| !classification[asset].empty?} + required_assets.all? { |asset| !classification[asset].empty? } end - def compatible_with?(assets, required_assets=nil, checked_condition_groups=[], wildcard_values={}) + def compatible_with?(assets, required_assets = nil, checked_condition_groups = [], wildcard_values = {}) assets = Array(assets).flatten # Every asset has at least one condition group satisfied classification = condition_group_classification_for(assets, checked_condition_groups, wildcard_values) @@ -179,7 +179,7 @@ def compatible_with?(assets, required_assets=nil, checked_condition_groups=[], w return false end - def condition_groups_for(asset, related_assets = [], checked_condition_groups=[], wildcard_values={}) + def condition_groups_for(asset, related_assets = [], checked_condition_groups = [], wildcard_values = {}) condition_groups.select do |condition_group| condition_group.compatible_with?([asset].flatten, related_assets, checked_condition_groups, wildcard_values) #condition_group.conditions_compatible_with?(asset, related_assets) @@ -197,10 +197,10 @@ def classification_for(assets, cgroups) def check_dependency_compatibility_for(asset, condition_group, assets) check_cgs = condition_groups.select do |cg| - cg.conditions.select{|c| c.object_condition_group == condition_group}.count > 0 + cg.conditions.select { |c| c.object_condition_group == condition_group }.count > 0 end return true if check_cgs.empty? - ancestors = assets.select{|a| a.facts.any?{|f| f.object_asset == asset}}.uniq + ancestors = assets.select { |a| a.facts.any? { |f| f.object_asset == asset } }.uniq return true if ancestors.empty? classification = classification_for(ancestors, check_cgs) diff --git a/app/models/steps/cancellable.rb b/app/models/steps/cancellable.rb index 1361ac78..c4b42ba8 100644 --- a/app/models/steps/cancellable.rb +++ b/app/models/steps/cancellable.rb @@ -1,8 +1,8 @@ module Steps::Cancellable def self.included(klass) klass.instance_eval do - scope :newer_than, ->(step) { where("id > #{step.id}").includes(:operations, :step_type)} - scope :older_than, ->(step) { where("id < #{step.id}").includes(:operations, :step_type)} + scope :newer_than, ->(step) { where("id > #{step.id}").includes(:operations, :step_type) } + scope :older_than, ->(step) { where("id < #{step.id}").includes(:operations, :step_type) } end end @@ -51,10 +51,10 @@ def _remake_me end - def _cancel_me_and_any_newer_completed_steps(change_state=true) + def _cancel_me_and_any_newer_completed_steps(change_state = true) changes = [ fact_changes_for_option(:cancel), - steps_newer_than_me.completed.map{|s| s.fact_changes_for_option(:cancel)} + steps_newer_than_me.completed.map { |s| s.fact_changes_for_option(:cancel) } ].flatten.compact.reduce(FactChanges.new) do |memo, updates| memo.merge(updates) end @@ -69,7 +69,7 @@ def _cancel_me_and_any_newer_completed_steps(change_state=true) def _remake_me_and_any_older_cancelled_steps changes = [ - steps_older_than_me.cancelled.map{|s| s.fact_changes_for_option(:remake)}, + steps_older_than_me.cancelled.map { |s| s.fact_changes_for_option(:remake) }, fact_changes_for_option(:remake) ].flatten.compact.reduce(FactChanges.new) do |memo, updates| memo.merge(updates) diff --git a/app/models/steps/state.rb b/app/models/steps/state.rb index 467628f5..aa4e0412 100644 --- a/app/models/steps/state.rb +++ b/app/models/steps/state.rb @@ -8,20 +8,20 @@ module Steps::State def self.included(klass) klass.instance_eval do - scope :in_progress, ->() { where(:in_progress? => true)} - scope :cancelled, ->() {where(:state => 'cancelled')} - scope :deprecated, ->() {where(:state => 'ignored')} + scope :in_progress, ->() { where(:in_progress? => true) } + scope :cancelled, ->() { where(:state => 'cancelled') } + scope :deprecated, ->() { where(:state => 'ignored') } scope :processing, ->() { where("state = 'running' OR state = 'cancelling' OR state = 'remaking' OR state = 'retrying'").includes(:operations, :step_type) } - scope :running, ->() { where(state: 'running').includes(:operations, :step_type)} - scope :pending, ->() { where(state: 'pending')} - scope :failed, ->() { where(state: 'failed')} - scope :completed, ->() { where(state: 'complete')} - scope :stopped, ->() { where(state: 'stopped')} + scope :running, ->() { where(state: 'running').includes(:operations, :step_type) } + scope :pending, ->() { where(state: 'pending') } + scope :failed, ->() { where(state: 'failed') } + scope :completed, ->() { where(state: 'complete') } + scope :stopped, ->() { where(state: 'stopped') } scope :active, ->() { where("state = 'running' OR state = 'pending' OR state IS NULL") } - scope :finished, ->() { includes(:operations, :step_type)} - scope :in_activity, ->() { where.not(activity_id: nil)} + scope :finished, ->() { includes(:operations, :step_type) } + scope :in_activity, ->() { where.not(activity_id: nil) } include AASM diff --git a/app/models/user.rb b/app/models/user.rb index 5566b95a..d9a8c73e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -33,8 +33,8 @@ def clean_session end def session_info - {:username => username, :fullname => fullname, :barcode => barcode, :role => role, - :tube_printer_name => tube_printer_name, :plate_printer_name => plate_printer_name} + { :username => username, :fullname => fullname, :barcode => barcode, :role => role, + :tube_printer_name => tube_printer_name, :plate_printer_name => plate_printer_name } end def printer_config diff --git a/db/seeds.rb b/db/seeds.rb index cff98140..89b85b19 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -87,6 +87,6 @@ ['Update Sequencescape', 'update_sequencescape.rb', %Q{ { ?p :a :TubeRack .}=>{}. }] -].map{|l| StepType.create(name: l[0], step_action: l[1], n3_definition: l[2]) } +].map { |l| StepType.create(name: l[0], step_action: l[1], n3_definition: l[2]) } #reracking_activity_type.step_types << runners diff --git a/lib/actions/plate_transfer.rb b/lib/actions/plate_transfer.rb index e76eb45e..4704140a 100644 --- a/lib/actions/plate_transfer.rb +++ b/lib/actions/plate_transfer.rb @@ -38,7 +38,7 @@ def self.validate_tube_is_compatible_with_aliquot(updates, tube, aliquotType) true end - def self.transfer_by_location(plate, destination, updates=nil) + def self.transfer_by_location(plate, destination, updates = nil) aliquot = plate.facts.where(predicate: 'aliquotType').first updates ||= FactChanges.new updates.tap do |updates| @@ -71,7 +71,7 @@ def self.transfer_by_location(plate, destination, updates=nil) end end - def self.transfer_with_asset_creation(plate, destination, updates=nil) + def self.transfer_with_asset_creation(plate, destination, updates = nil) aliquot_value = updates.values_for_predicate(destination, 'aliquotType').first updates ||= FactChanges.new updates.tap do |updates| @@ -96,7 +96,7 @@ def self.transfer_with_asset_creation(plate, destination, updates=nil) # # plate: Asset # destimation: Asset or String representing a uuid or a wildcard - def self.transfer_plates(plate, destination, updates=nil) + def self.transfer_plates(plate, destination, updates = nil) updates ||= FactChanges.new updates.tap do |updates| if destination.kind_of?(Asset) && (destination.has_wells?) diff --git a/lib/actions/racking.rb b/lib/actions/racking.rb index 7fcba2e9..c1a0d130 100644 --- a/lib/actions/racking.rb +++ b/lib/actions/racking.rb @@ -66,12 +66,12 @@ def reracking_tubes(rack, list_layout) fact_changes_unrack.merge(fact_changes_rack) end - def fact_changes_for_unrack_tubes(list_layout, destination_rack=nil) + def fact_changes_for_unrack_tubes(list_layout, destination_rack = nil) FactChanges.new.tap do |updates| rerackGroup=nil previous_racks = [] - tubes = list_layout.map{|obj| obj[:asset]}.compact + tubes = list_layout.map { |obj| obj[:asset] }.compact return updates if tubes.empty? tubes_ids = tubes.map(&:id) tubes_list = Asset.where(id: tubes_ids).includes(:facts) @@ -150,11 +150,11 @@ def fact_changes_for_rack_when_unracking_tubes(rack, unracked_tubes) actual_tubes = (tubes_from_previous_rack - unracked_tubes) TUBE_TO_PLATE_TRANSFERRABLE_PROPERTIES.each do |transferrable_property| - unracked_tubes.map{|tube| tube.facts.with_predicate(transferrable_property).map(&:object)}.flatten.compact.each do |value| + unracked_tubes.map { |tube| tube.facts.with_predicate(transferrable_property).map(&:object) }.flatten.compact.each do |value| updates.remove_where(rack, transferrable_property.to_s, value) updates.merge(fact_changes_for_remove_purpose(rack, value)) if transferrable_property.to_s == 'aliquotType' end - actual_tubes.map{|tube| tube.facts.with_predicate(transferrable_property).map(&:object).flatten.compact}.each do |value| + actual_tubes.map { |tube| tube.facts.with_predicate(transferrable_property).map(&:object).flatten.compact }.each do |value| updates.add(rack, transferrable_property.to_s, value) updates.merge(fact_changes_for_add_purpose(rack, value)) if transferrable_property.to_s == 'aliquotType' end @@ -165,7 +165,7 @@ def fact_changes_for_rack_when_unracking_tubes(rack, unracked_tubes) def fact_changes_for_rack_when_racking_tubes(rack, racked_tubes) FactChanges.new.tap do |updates| TUBE_TO_PLATE_TRANSFERRABLE_PROPERTIES.map do |prop| - racked_tubes.map{|tube| tube.facts.with_predicate(prop)} + racked_tubes.map { |tube| tube.facts.with_predicate(prop) } end.flatten.compact.each do |fact| updates.add(rack, fact.predicate.to_s, fact.object_value) updates.merge(fact_changes_for_add_purpose(rack, fact.object_value)) if fact.predicate.to_s == 'aliquotType' @@ -219,12 +219,12 @@ def get_duplicates(list) memo[element] = 0 unless memo[element] memo[element]+=1 memo - end.each_pair.select{|key, count| count > 1} + end.each_pair.select { |key, count| count > 1 } end def check_duplicates(params, error_messages, error_locations) - duplicated_locations = get_duplicates(params.map{|location, barcode| location}) - duplicated_assets = get_duplicates(params.map{|location, barcode| barcode}) + duplicated_locations = get_duplicates(params.map { |location, barcode| location }) + duplicated_assets = get_duplicates(params.map { |location, barcode| barcode }) duplicated_locations.each do |location, count| error_locations.push(location) @@ -269,7 +269,7 @@ def check_collisions(rack, list_layout, error_messages, error_locations) end end end - unless (list_layout.map{|obj| obj[:asset]}.include?(tube)) + unless (list_layout.map { |obj| obj[:asset] }.include?(tube)) # Remember that the tubes needs to be always in a rack. They cannot be interchanged # in between racks error_messages.push( @@ -294,7 +294,7 @@ def csv_parsing(asset_group, parser) if asset_group.assets.with_fact('a', 'TubeRack').count > 1 error_messages.push("Too many TubeRacks found to perform the layout process") end - raise InvalidDataParams.new(error_messages) if error_messages.count > 0 + raise InvalidDataParams, error_messages if error_messages.count > 0 asset = asset_group.assets.with_fact('a', 'TubeRack').first @@ -308,16 +308,16 @@ def csv_parsing(asset_group, parser) end unless error_messages.empty? - raise InvalidDataParams.new(error_messages) + raise InvalidDataParams, error_messages end if parser.valid? updates = parser.parsed_changes.merge(reracking_tubes(asset, parser.layout)) error_messages.push(asset.validate_rack_content) - raise InvalidDataParams.new(error_messages) if error_messages.flatten.compact.count > 0 + raise InvalidDataParams, error_messages if error_messages.flatten.compact.count > 0 return updates else - raise InvalidDataParams.new(parser.error_list) + raise InvalidDataParams, parser.error_list end end @@ -325,7 +325,7 @@ def csv_parsing(asset_group, parser) def samples_symphony(step_type, params) rack = asset_group.assets.with_fact('a', 'TubeRack').first msgs = Parsers::Symphony.parse(params[:file].read, rack) - raise InvalidDataParams.new(msgs) if msgs.length > 0 + raise InvalidDataParams, msgs if msgs.length > 0 end end diff --git a/lib/changes_support/disjoint_list.rb b/lib/changes_support/disjoint_list.rb index 61d54a7c..b5bf632e 100644 --- a/lib/changes_support/disjoint_list.rb +++ b/lib/changes_support/disjoint_list.rb @@ -24,7 +24,7 @@ def initialize(list) @list = [] @disjoint_lists = [self] - list.each {|o| add(o)} + list.each { |o| add(o) } end def add_disjoint_list(disjoint_list) @@ -46,7 +46,7 @@ def store_for(element) def _store_for(unique_id) store_name = location_for_unique_id[unique_id] return nil if store_name.nil? || store_name == DISABLED_NAME - @disjoint_lists.select{|l| l.name == store_name}.first + @disjoint_lists.select { |l| l.name == store_name }.first end @@ -108,7 +108,7 @@ def uniq! def <<(element) if element.kind_of?(Array) - element.each{|e| add(e)} + element.each { |e| add(e) } else add(element) end @@ -116,7 +116,7 @@ def <<(element) def concat(element) if element.kind_of?(Array) - element.each{|e| add(e)} + element.each { |e| add(e) } else add(element) end @@ -155,7 +155,7 @@ def concat_disjoint_list(disjoint_list) _disable(key) end end - disjoint_list.to_a.each {|val| add(val)} + disjoint_list.to_a.each { |val| add(val) } self end @@ -165,7 +165,7 @@ def merge(disjoint_list) _disable(key) end end - disjoint_list.to_a.each {|val| add(val)} + disjoint_list.to_a.each { |val| add(val) } self end @@ -212,7 +212,7 @@ def _disable(unique_id) location_for_unique_id[unique_id]=DISABLED_NAME end - def _unique_id_for_element(element, deep=0) + def _unique_id_for_element(element, deep = 0) return sum_function_for(SecureRandom.uuid) if deep==MAX_DEEP_UNIQUE_ID if element.kind_of?(String) sum_function_for(element) @@ -226,10 +226,10 @@ def _unique_id_for_element(element, deep=0) elsif (element.has_key?(:predicate)) _unique_id_for_fact(element) else - sum_function_for(element.keys.dup.concat(element.values.map{|val| _unique_id_for_element(val, deep+1)}).join("")) + sum_function_for(element.keys.dup.concat(element.values.map { |val| _unique_id_for_element(val, deep+1) }).join("")) end elsif element.kind_of?(Enumerable) - sum_function_for(element.map{|o| _unique_id_for_element(o, deep+1)}.join("")) + sum_function_for(element.map { |o| _unique_id_for_element(o, deep+1) }.join("")) else sum_function_for(element.to_s) end diff --git a/lib/changes_support/transaction_scope.rb b/lib/changes_support/transaction_scope.rb index 03c629b1..1b519979 100644 --- a/lib/changes_support/transaction_scope.rb +++ b/lib/changes_support/transaction_scope.rb @@ -48,7 +48,7 @@ def _result_set_from_database(opts) def _filter_removed_entries(opts) if (@klass==Asset) if @updates.to_h[:delete_assets] - selected_elements=result_set.to_a.select{|a| @updates.to_h[:delete_assets].include?(a.uuid)} + selected_elements=result_set.to_a.select { |a| @updates.to_h[:delete_assets].include?(a.uuid) } @result_set=result_set.to_a - selected_elements end if @updates.to_h[:remove_facts] @@ -104,7 +104,7 @@ def _disjoint_list_for(type) _disjoint_lists[model][type] end - def _join_condition(elem, default_fkey_name=nil) + def _join_condition(elem, default_fkey_name = nil) default_fkey_name ||= @klass.to_s.downcase.to_sym rel={} rel[default_fkey_name] = elem diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index 83e878e8..8feb0bc2 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -15,7 +15,7 @@ class FactChanges attr_accessor :operations - def initialize(json=nil) + def initialize(json = nil) @assets_updated=[] reset parse_json(json) if json @@ -89,7 +89,7 @@ def to_h end, 'add_assets': asset_group_asset_to_h(@assets_to_add), 'remove_assets': asset_group_asset_to_h(@assets_to_remove) - }.reject {|k,v| v.length == 0 } + }.reject { |k,v| v.length == 0 } end def to_json @@ -118,15 +118,15 @@ def values_for_predicate(asset, predicate) (actual_values + values_to_add - values_to_destroy) end - def _build_fact_attributes(s, p, o, options={}) + def _build_fact_attributes(s, p, o, options = {}) t = [s,p,o, options] - params = {asset: t[0], predicate: t[1], literal: !(t[2].kind_of?(Asset))} + params = { asset: t[0], predicate: t[1], literal: !(t[2].kind_of?(Asset)) } params[:literal] ? params[:object] = t[2] : params[:object_asset] = t[2] params = params.merge(t[3]) if t[3] params end - def add(s,p,o, options={}) + def add(s,p,o, options = {}) s = find_asset(s) o = (options[:literal]==true) ? o : find_asset(o) @@ -137,20 +137,20 @@ def add(s,p,o, options={}) end def add_facts(listOfLists) - listOfLists.each{|list| add(list[0], list[1], list[2])} + listOfLists.each { |list| add(list[0], list[1], list[2]) } self end def remove_facts(listOfLists) - listOfLists.each{|list| remove_where(list[0], list[1], list[2])} + listOfLists.each { |list| remove_where(list[0], list[1], list[2]) } self end - def add_remote(s,p,o, options={}) - add(s,p,o, options.merge({is_remote?: true})) if (s && p && o) + def add_remote(s,p,o, options = {}) + add(s,p,o, options.merge({ is_remote?: true })) if (s && p && o) end - def replace_remote(asset, p, o, options={}) + def replace_remote(asset, p, o, options = {}) if (asset && p && o) asset.facts.with_predicate(p).each do |fact| remove(fact) @@ -164,7 +164,7 @@ def replace_remote(asset, p, o, options={}) def remove(f) return if f.nil? if f.kind_of?(Enumerable) - facts_to_destroy << f.map{|o| o.attributes.symbolize_keys} + facts_to_destroy << f.map { |o| o.attributes.symbolize_keys } elsif f.kind_of?(Fact) facts_to_destroy << f.attributes.symbolize_keys if f end @@ -205,7 +205,7 @@ def merge(fact_changes) self end - def apply(step, with_operations=true) + def apply(step, with_operations = true) _handle_errors(step) if errors_added.length > 0 ActiveRecord::Base.transaction do |t| _set_remote_facts(facts_to_set_to_remote) @@ -277,7 +277,7 @@ def is_new_record?(uuid) !!(instances_from_uuid[uuid] && instances_from_uuid[uuid].new_record?) end - def find_instance_of_class_by_uuid(klass, instance_or_uuid_or_id, create=false) + def find_instance_of_class_by_uuid(klass, instance_or_uuid_or_id, create = false) if TokenUtil.is_wildcard?(instance_or_uuid_or_id) uuid = uuid_for_wildcard(instance_or_uuid_or_id) # Do not try to find it if it is a new wildcard created @@ -302,7 +302,7 @@ def uuid_for_wildcard(wildcard) end def wildcard_for_uuid(uuid) - wildcards.keys.select{|key| wildcards[key] == uuid}.first + wildcards.keys.select { |key| wildcards[key] == uuid }.first end def find_instance_from_uuid(klass, uuid) @@ -314,9 +314,9 @@ def find_instance_from_uuid(klass, uuid) def validate_instances(instances) if instances.kind_of?(Array) - instances.each{|a| raise StandardError.new(a) if a.nil? } + instances.each { |a| raise StandardError, a if a.nil? } else - raise StandardError.new(a) if instances.nil? + raise StandardError, a if instances.nil? end instances end @@ -360,7 +360,7 @@ def add_assets(list) asset_ids = elem end assets = validate_instances(find_assets(asset_ids)) - assets_to_add << assets.map{|asset| { asset_group: asset_group, asset: asset} } + assets_to_add << assets.map { |asset| { asset_group: asset_group, asset: asset } } #add_to_list_keep_unique(assets.map{|asset| { asset_group: asset_group, asset: asset} }, :assets_to_add, :assets_to_remove) #assets_to_add.concat(assets.map{|asset| { asset_group: asset_group, asset: asset} }) end @@ -377,7 +377,7 @@ def remove_assets(list) asset_ids = elem end assets = validate_instances(find_assets(asset_ids)) - assets_to_remove << assets.map{|asset| { asset_group: asset_group, asset: asset} } + assets_to_remove << assets.map { |asset| { asset_group: asset_group, asset: asset } } #add_to_list_keep_unique(assets.map{|asset| { asset_group: asset_group, asset: asset} }, :assets_to_remove, :assets_to_add) #assets_to_remove.concat(assets.map{|asset| { asset_group: asset_group, asset: asset} }) end @@ -422,7 +422,7 @@ def _remove_assets(step, assets_to_remove, with_operations = true) end end - def _create_assets(step, assets, with_operations=true) + def _create_assets(step, assets, with_operations = true) return unless assets count = Asset.count + 1 assets = assets.each_with_index.map do |asset, barcode_index| @@ -450,14 +450,14 @@ def _build_barcode(asset, i) end end - def _detach_assets(step, assets, with_operations=true) + def _detach_assets(step, assets, with_operations = true) operations = _asset_operations('deleteAssets', step, assets) if with_operations _instances_deletion(Fact, assets.map(&:facts).flatten.compact) _instances_deletion(AssetGroupsAsset, assets.map(&:asset_groups_assets).flatten.compact) operations end - def _create_asset_groups(step, asset_groups, with_operations=true) + def _create_asset_groups(step, asset_groups, with_operations = true) return unless asset_groups asset_groups.each_with_index do |asset_group, index| asset_group.update_attributes( @@ -469,7 +469,7 @@ def _create_asset_groups(step, asset_groups, with_operations=true) _asset_group_building_operations('createAssetGroups', step, asset_groups) if with_operations end - def _detach_asset_groups(step, asset_groups, with_operations=true) + def _detach_asset_groups(step, asset_groups, with_operations = true) operations = _asset_group_building_operations('deleteAssetGroups', step, asset_groups) if with_operations instances = asset_groups.flatten ids_to_remove = instances.map(&:id).compact.uniq @@ -478,14 +478,14 @@ def _detach_asset_groups(step, asset_groups, with_operations=true) operations end - def _create_facts(step, params_for_facts, with_operations=true) + def _create_facts(step, params_for_facts, with_operations = true) _instance_builder_for_import(Fact, params_for_facts) do |facts| _fact_operations('addFacts', step, facts) if with_operations end end - def _remove_facts(step, facts_to_remove, with_operations=true) + def _remove_facts(step, facts_to_remove, with_operations = true) ids = [] modified_list = facts_to_remove.reduce([]) do |memo, data| if data[:id] diff --git a/lib/inference_engines/cwm/step_execution.rb b/lib/inference_engines/cwm/step_execution.rb index 6f012f5f..fb2d3a35 100644 --- a/lib/inference_engines/cwm/step_execution.rb +++ b/lib/inference_engines/cwm/step_execution.rb @@ -53,7 +53,7 @@ def generate_plan line = "# EXECUTING: #{call_str}" proxy = Rails.configuration.cwm_proxy - env_vars = {'http_proxy' => proxy, 'https_proxy' => proxy} + env_vars = { 'http_proxy' => proxy, 'https_proxy' => proxy } Open3.popen3(*[env_vars, call_list].flatten) do |stdin, stdout, stderror, thr| content = stdout.read @@ -116,12 +116,12 @@ def remove_facts(graphs) graphs.each do |quads| quads.map do |quad| asset = Asset.find_by!(:uuid => TokenUtil.uuid(fragment(quad[0]))) - updates.remove(asset.facts.select {|f| equal_quad_and_fact?(quad, f) }) + updates.remove(asset.facts.select { |f| equal_quad_and_fact?(quad, f) }) end end end - def add_quad_to_asset(quad, asset, action_type="addFacts") + def add_quad_to_asset(quad, asset, action_type = "addFacts") object = fragment(quad[2]) object_asset = nil literal = true diff --git a/lib/inference_engines/runner/step_execution.rb b/lib/inference_engines/runner/step_execution.rb index 04b51959..f0e673ee 100644 --- a/lib/inference_engines/runner/step_execution.rb +++ b/lib/inference_engines/runner/step_execution.rb @@ -104,13 +104,13 @@ def compatible? def add_facts(list) FactChanges.new.tap do |updates| - list.each {|l| updates.add(l[0], l[1], l[2])} + list.each { |l| updates.add(l[0], l[1], l[2]) } end end def remove_facts(list) FactChanges.new.tap do |updates| - list.each {|l| updates.remove_where(l[0], l[1], l[2]) } + list.each { |l| updates.remove_where(l[0], l[1], l[2]) } end end @@ -128,7 +128,7 @@ def create_asset(list) def select_asset(uuids) FactChanges.new.tap do |updates| - assets = uuids.map{|uuid| Asset.find_by(uuid: uuid)} + assets = uuids.map { |uuid| Asset.find_by(uuid: uuid) } updates.add_assets(@step.asset_group.id, uuids) #@step.asset_group.add_assets(assets) end @@ -136,7 +136,7 @@ def select_asset(uuids) def unselect_asset(uuids) FactChanges.new.tap do |updates| - assets = uuids.map{|uuid| Asset.find_by(uuid: uuid)} + assets = uuids.map { |uuid| Asset.find_by(uuid: uuid) } updates.remove_assets(@step.asset_group.id, uuids) #@step.asset_group.remove_assets(assets) end diff --git a/lib/label_template_setup.rb b/lib/label_template_setup.rb index 2cd08ab2..586874fa 100644 --- a/lib/label_template_setup.rb +++ b/lib/label_template_setup.rb @@ -11,11 +11,11 @@ def label_templates end def find_label_template_by_name(name) - label_templates.detect {|t| t.name == name } + label_templates.detect { |t| t.name == name } end def label_type_id_for(type_name) - label_types.detect {|lt| lt.name == type_name }.id + label_types.detect { |lt| lt.name == type_name }.id end def templates @@ -23,7 +23,7 @@ def templates end def register_label_type(name, data) - ltype = PMB::LabelType.all.detect {|lt| lt.name == name } + ltype = PMB::LabelType.all.detect { |lt| lt.name == name } if ltype.nil? PMB::LabelType.new(data).save end diff --git a/lib/label_templates/ss_plate.rb b/lib/label_templates/ss_plate.rb index 64e67272..cbd36594 100644 --- a/lib/label_templates/ss_plate.rb +++ b/lib/label_templates/ss_plate.rb @@ -3,7 +3,7 @@ # Label template currently defined for sqsc_96plate_label_template (20/Jan/2017) def bitmap_definition(attrs) - {"horizontal_magnification":"05", + { "horizontal_magnification":"05", "vertical_magnification":"1", "font":"G", "space_adjustment":"00", @@ -18,16 +18,16 @@ def plate_barcode_definition(name, type_id, barcode_type) labels_attributes:[{ name: 'label', bitmaps_attributes:[ - bitmap_definition({"field_name":"top_left","x_origin":"0030","y_origin":"0035"}), - bitmap_definition({"field_name":"bottom_left","x_origin":"0030","y_origin":"0065"}), - bitmap_definition({"field_name":"top_right","x_origin":"0550","y_origin":"0035"}), - bitmap_definition({"field_name":"bottom_right","x_origin":"0550","y_origin":"0065"}), - bitmap_definition({"field_name":"top_far_right","x_origin":"0750","y_origin":"0035"}), - bitmap_definition({"field_name":"bottom_far_right","x_origin":"0750","y_origin":"0065"}), - bitmap_definition({"field_name":"label_counter_right","x_origin":"0890","y_origin":"0065","rotational_angles":"33"}) + bitmap_definition({ "field_name":"top_left","x_origin":"0030","y_origin":"0035" }), + bitmap_definition({ "field_name":"bottom_left","x_origin":"0030","y_origin":"0065" }), + bitmap_definition({ "field_name":"top_right","x_origin":"0550","y_origin":"0035" }), + bitmap_definition({ "field_name":"bottom_right","x_origin":"0550","y_origin":"0065" }), + bitmap_definition({ "field_name":"top_far_right","x_origin":"0750","y_origin":"0035" }), + bitmap_definition({ "field_name":"bottom_far_right","x_origin":"0750","y_origin":"0065" }), + bitmap_definition({ "field_name":"label_counter_right","x_origin":"0890","y_origin":"0065","rotational_angles":"33" }) ], barcodes_attributes:[ - {"field_name":"barcode", "barcode_type": barcode_type,"one_module_width":"02","height":"0070","rotational_angle":nil,"one_cell_width":nil, + { "field_name":"barcode", "barcode_type": barcode_type,"one_module_width":"02","height":"0070","rotational_angle":nil,"one_cell_width":nil, "type_of_check_digit":"2","no_of_columns":nil,"bar_height":nil,"x_origin":"0200","y_origin":"0000", } ] diff --git a/lib/label_templates/ss_tube.rb b/lib/label_templates/ss_tube.rb index 92c21df8..0685fc01 100644 --- a/lib/label_templates/ss_tube.rb +++ b/lib/label_templates/ss_tube.rb @@ -9,24 +9,24 @@ def tube_barcode_definition(name, type_id, barcode_type) labels_attributes:[{ name: 'label', bitmaps_attributes:[ - {"horizontal_magnification":"05","vertical_magnification":"05","font":"H","space_adjustment":"03","rotational_angles":"11", - "x_origin":"0038","y_origin":"0210","field_name":"bottom_line"}, - {"horizontal_magnification":"05","vertical_magnification":"05","font":"H","space_adjustment":"02","rotational_angles":"11", - "x_origin":"0070","y_origin":"0210","field_name":"middle_line"}, - {"horizontal_magnification":"05","vertical_magnification":"05","font":"H","space_adjustment":"02","rotational_angles":"11", - "x_origin":"0120","y_origin":"0210","field_name":"top_line"}, - {"horizontal_magnification":"05","vertical_magnification":"1","font":"G","space_adjustment":"00","rotational_angles":"00", - "x_origin":"0240","y_origin":"0165","field_name":"round_label_top_line"}, - {"horizontal_magnification":"05","vertical_magnification":"1","font":"G","space_adjustment":"00","rotational_angles":"00", - "x_origin":"0220","y_origin":"0193","field_name":"round_label_bottom_line"} + { "horizontal_magnification":"05","vertical_magnification":"05","font":"H","space_adjustment":"03","rotational_angles":"11", + "x_origin":"0038","y_origin":"0210","field_name":"bottom_line" }, + { "horizontal_magnification":"05","vertical_magnification":"05","font":"H","space_adjustment":"02","rotational_angles":"11", + "x_origin":"0070","y_origin":"0210","field_name":"middle_line" }, + { "horizontal_magnification":"05","vertical_magnification":"05","font":"H","space_adjustment":"02","rotational_angles":"11", + "x_origin":"0120","y_origin":"0210","field_name":"top_line" }, + { "horizontal_magnification":"05","vertical_magnification":"1","font":"G","space_adjustment":"00","rotational_angles":"00", + "x_origin":"0240","y_origin":"0165","field_name":"round_label_top_line" }, + { "horizontal_magnification":"05","vertical_magnification":"1","font":"G","space_adjustment":"00","rotational_angles":"00", + "x_origin":"0220","y_origin":"0193","field_name":"round_label_bottom_line" } ], barcodes_attributes:[ - {"barcode_type":"Q","one_module_width":"03","height":"0080","rotational_angle":"1","one_cell_width":"03", + { "barcode_type":"Q","one_module_width":"03","height":"0080","rotational_angle":"1","one_cell_width":"03", "type_of_check_digit":nil, "no_of_columns":nil,"bar_height":nil,"x_origin":"0300","y_origin":"0145","field_name":"barcode2d" }, - {"barcode_type": barcode_type,"one_module_width":"01","height":"0100","rotational_angle":nil, + { "barcode_type": barcode_type,"one_module_width":"01","height":"0100","rotational_angle":nil, "one_cell_width":nil,"type_of_check_digit":"2", - "no_of_columns":nil,"bar_height":nil,"x_origin":"0043","y_origin":"0100","field_name":"barcode"} + "no_of_columns":nil,"bar_height":nil,"x_origin":"0043","y_origin":"0100","field_name":"barcode" } ] } ] diff --git a/lib/parsers/csv_layout/csv_parser.rb b/lib/parsers/csv_layout/csv_parser.rb index e54dbacc..8fcf9eba 100644 --- a/lib/parsers/csv_layout/csv_parser.rb +++ b/lib/parsers/csv_layout/csv_parser.rb @@ -25,7 +25,7 @@ class CsvParser line_reader: Parsers::CsvLayout::LineReader } - def initialize(str, component_defs={}) + def initialize(str, component_defs = {}) @parsed = false @input = str @components = self.class::DEFAULT_COMPONENTS.merge(component_defs) @@ -90,7 +90,7 @@ def validate_location_duplication end def duplicated(sym) - all_elems = layout.map{|obj| obj[sym]} + all_elems = layout.map { |obj| obj[sym] } all_elems.select do |element| (!element.nil?) && (all_elems.count(element) > 1) end.uniq.compact diff --git a/lib/parsers/csv_layout/line_parser.rb b/lib/parsers/csv_layout/line_parser.rb index 37166b3c..23c83490 100644 --- a/lib/parsers/csv_layout/line_parser.rb +++ b/lib/parsers/csv_layout/line_parser.rb @@ -3,6 +3,7 @@ module CsvLayout class LineParser include ActiveModel::Validations attr_reader :parsed_content + validate :validate_parsed_content def initialize(input_reader, parser) @@ -15,7 +16,7 @@ def initialize(input_reader, parser) def parsed_data if valid? - @parsed_content.select{|e| !e[:barcode_parser].no_read_barcode? }.map do |entry| + @parsed_content.select { |e| !e[:barcode_parser].no_read_barcode? }.map do |entry| { location: entry[:location_parser].location, asset: entry[:barcode_parser].asset diff --git a/lib/parsers/csv_metadata/csv_parser.rb b/lib/parsers/csv_metadata/csv_parser.rb index 4dba15b5..48feef96 100644 --- a/lib/parsers/csv_metadata/csv_parser.rb +++ b/lib/parsers/csv_metadata/csv_parser.rb @@ -23,7 +23,7 @@ class CsvParser headers_validator: Parsers::CsvMetadata::Validators::HeadersValidator } - def initialize(str, component_defs={}) + def initialize(str, component_defs = {}) @parsed = false @input = str @components = self.class::DEFAULT_COMPONENTS.merge(component_defs) diff --git a/lib/parsers/csv_metadata/data_parser.rb b/lib/parsers/csv_metadata/data_parser.rb index c6b9629f..40757ae8 100644 --- a/lib/parsers/csv_metadata/data_parser.rb +++ b/lib/parsers/csv_metadata/data_parser.rb @@ -2,6 +2,7 @@ module Parsers module CsvMetadata class DataParser attr_reader :data + include ActiveModel::Validations def initialize(line, parser) diff --git a/lib/parsers/csv_metadata/datum_parser.rb b/lib/parsers/csv_metadata/datum_parser.rb index 684f8182..2e6fd69b 100644 --- a/lib/parsers/csv_metadata/datum_parser.rb +++ b/lib/parsers/csv_metadata/datum_parser.rb @@ -2,6 +2,7 @@ module Parsers module CsvMetadata class DatumParser attr_reader :datum + include ActiveModel::Validations validate :validations diff --git a/lib/parsers/csv_metadata/headers_parser.rb b/lib/parsers/csv_metadata/headers_parser.rb index 1db62ee3..9ee53444 100644 --- a/lib/parsers/csv_metadata/headers_parser.rb +++ b/lib/parsers/csv_metadata/headers_parser.rb @@ -2,6 +2,7 @@ module Parsers module CsvMetadata class HeadersParser attr_reader :headers + include ActiveModel::Validations validate :validations @@ -18,7 +19,7 @@ def initialize(line, parser) end def _parse(line) - @headers=line.map{|header| header.strip } + @headers=line.map { |header| header.strip } end end end diff --git a/lib/parsers/csv_metadata/line_parser.rb b/lib/parsers/csv_metadata/line_parser.rb index 0e065e42..bc1dedba 100644 --- a/lib/parsers/csv_metadata/line_parser.rb +++ b/lib/parsers/csv_metadata/line_parser.rb @@ -3,6 +3,7 @@ module CsvMetadata class LineParser include ActiveModel::Validations attr_reader :parsed_content, :headers_parser + validate :validate_parsed_content def initialize(input_reader, parser) diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 539bbe90..83d522fe 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -23,7 +23,7 @@ def self.client @client ||= Sequencescape::Api.new(self.api_connection_options) end - def self.version_1_find_by_uuid(uuid, type=:plate) + def self.version_1_find_by_uuid(uuid, type = :plate) client.send(type).find(uuid) rescue Sequencescape::Api::ResourceNotFound => exception return nil @@ -31,12 +31,12 @@ def self.version_1_find_by_uuid(uuid, type=:plate) # below creates a record in the 'extraction_attributes' table in Sequencescape # this, in turn, triggers creation of aliquots against the plate - def self.update_extraction_attributes(instance, attrs, username='test') + def self.update_extraction_attributes(instance, attrs, username = 'test') instance.extraction_attributes.create!(:attributes_update => attrs, :created_by => username) end def self.purpose_by_name(name) - client.plate_purpose.all.select{|p| p.name===name}.first + client.plate_purpose.all.select { |p| p.name===name }.first end def self.create_plate(purpose_name, attrs) @@ -52,18 +52,18 @@ def self.get_study_by_name(name) end def self.get_study_searcher_by_name - @@study_searcher ||= client.search.all.select{|s| s.name == Rails.configuration.searcher_study_by_name}.first + @@study_searcher ||= client.search.all.select { |s| s.name == Rails.configuration.searcher_study_by_name }.first end def self.get_searcher_by_barcode - @@searcher ||= client.search.all.select{|s| s.name == Rails.configuration.searcher_name_by_barcode}.first + @@searcher ||= client.search.all.select { |s| s.name == Rails.configuration.searcher_name_by_barcode }.first end def self.get_remote_asset(barcode) find_by(barcode: barcode) end - def self.find_by_uuid(uuid, opts=nil) + def self.find_by_uuid(uuid, opts = nil) find_by(uuid: uuid) end diff --git a/lib/support_n3.rb b/lib/support_n3.rb index 260d6d7e..03cc466f 100644 --- a/lib/support_n3.rb +++ b/lib/support_n3.rb @@ -60,7 +60,7 @@ def self.ontology_to_json(ontology_file) end - def self.parse_string(input, options = {}, step_type=nil) + def self.parse_string(input, options = {}, step_type = nil) options = { validate: false, canonicalize: false, @@ -79,11 +79,11 @@ def self.fragment(k) k.try(:fragment) || (k.try(:name) || k).to_s.gsub(/.*#/,'') end - def self.build_asset(name, create_assets=true, created_assets=[]) + def self.build_asset(name, create_assets = true, created_assets = []) if create_assets asset = Asset.find_or_create_by(:name => name) else - asset = created_assets.select{|a| a.name == name}.first + asset = created_assets.select { |a| a.name == name }.first unless asset asset = Asset.create(:name => name) created_assets.push(asset) @@ -93,11 +93,11 @@ def self.build_asset(name, create_assets=true, created_assets=[]) end def self.is_literal?(element, quads) - element.literal? || quads.select {|q| q[0] == element}.count == 0 + element.literal? || quads.select { |q| q[0] == element }.count == 0 end - def self.load_step_actions(content, options={}) + def self.load_step_actions(content, options = {}) options = { validate: false, canonicalize: false, @@ -118,11 +118,11 @@ def self.load_step_actions(content, options={}) def self.subgraph(node, quads) - quads.select{|q| q[3]==node} + quads.select { |q| q[3]==node } end - def self.create_fact(quad, quads, create_assets=true, created_assets=[]) + def self.create_fact(quad, quads, create_assets = true, created_assets = []) asset = build_asset(SupportN3::fragment(quad[0]), create_assets, created_assets) if is_literal?(quad[2], quads) asset.facts << Fact.create( @@ -136,7 +136,7 @@ def self.create_fact(quad, quads, create_assets=true, created_assets=[]) asset end - def self.parse_facts(input, options = {}, create_assets=true) + def self.parse_facts(input, options = {}, create_assets = true) options = { validate: false, canonicalize: false, @@ -147,7 +147,7 @@ def self.parse_facts(input, options = {}, create_assets=true) quads = RDF::N3::Reader.new(input, options).quads.clone quads.map do |quad| create_fact(quad, quads, create_assets, created_assets) - end.sort_by{|a| a.name }.uniq + end.sort_by { |a| a.name }.uniq end class RuleGraphAccessor @@ -163,10 +163,10 @@ class RuleGraphAccessor attr_reader :step_type def self.rules(quads) - quads.select{|quad| fragment(quad[1])=='implies'} + quads.select { |quad| fragment(quad[1])=='implies' } end - def self.parse_rules(quads, enforce_step_type=nil) + def self.parse_rules(quads, enforce_step_type = nil) self.activity_type = nil deprecate_class_by_name(ActivityType, activity_type_name(quads), activity_type(quads)) do |old_instances| RuleGraphAccessor.rules(quads).each do |k,p,v,g| @@ -209,7 +209,7 @@ def initialize(step_type, quads, graph_conditions, graph_consequences) end def conditions - @conditions ||= @quads.select{|quad| quad.last === @graph_conditions} + @conditions ||= @quads.select { |quad| quad.last === @graph_conditions } end def actions @@ -258,9 +258,9 @@ def find_or_create_condition_group_for(node, params) end def keep_selected_list - actions.select{|quad| fragment(quad[1]) == 'unselectAsset'}.map do |q| + actions.select { |quad| fragment(quad[1]) == 'unselectAsset' }.map do |q| if q[2].class == RDF::Node - fragment(@quads.select{|k,p,v,g| g==q[2]}.flatten[0]) + fragment(@quads.select { |k,p,v,g| g==q[2] }.flatten[0]) else fragment(q[2]) end @@ -284,7 +284,7 @@ def update_condition_group(condition_group, p, v) # object_condition_group = nil #end Condition.create({ :predicate => fragment(p), :object => fragment(v), - :condition_group_id => condition_group.id, :object_condition_group => object_condition_group}) + :condition_group_id => condition_group.id, :object_condition_group => object_condition_group }) end end @@ -297,15 +297,15 @@ def build_condition_groups conditions.each do |k,p,v,g| # Finds the condition group (or creates it) condition_group = find_or_create_condition_group_for(k, - {:step_type => @step_type, - :keep_selected => check_keep_selected_asset(k)}) + { :step_type => @step_type, + :keep_selected => check_keep_selected_asset(k) }) end cgr = [] conditions.each do |k,p,v,g| if is_wildcard?(v) vcgroup = find_or_create_condition_group_for(v, - {:step_type => @step_type, - :keep_selected => check_keep_selected_asset(v)}) + { :step_type => @step_type, + :keep_selected => check_keep_selected_asset(v) }) cgr.push(condition_group_for(v)) end # After reading all condition groups we will be able to recognize @@ -323,7 +323,7 @@ def build_condition_groups end def self.activity_type_name(quads) - quads.select{|quad| fragment(quad[1]) == 'activityTypeName'}.flatten[2].to_s + quads.select { |quad| fragment(quad[1]) == 'activityTypeName' }.flatten[2].to_s end def activity_type_name @@ -353,22 +353,22 @@ def config_for_step_type end def name_for_step_type - value = actions.select{|quad| fragment(quad[1]) == 'stepTypeName'}.flatten[2] + value = actions.select { |quad| fragment(quad[1]) == 'stepTypeName' }.flatten[2] fragment(value) unless value.nil? end def connect_by - value = actions.select{|quad| fragment(quad[1]) == 'connectBy'}.flatten[2] + value = actions.select { |quad| fragment(quad[1]) == 'connectBy' }.flatten[2] fragment(value) unless value.nil? end def step_template - value = actions.select{|quad| fragment(quad[1]) == 'stepTemplate'}.flatten[2] + value = actions.select { |quad| fragment(quad[1]) == 'stepTemplate' }.flatten[2] fragment(value) unless value.nil? end def step_action - value = actions.select{|quad| fragment(quad[1]) == 'stepAction'}.flatten[2] + value = actions.select { |quad| fragment(quad[1]) == 'stepAction' }.flatten[2] fragment(value) unless value.nil? end @@ -383,7 +383,7 @@ def build_actions actions.each do |k,p,v,g| action = fragment(p) unless v.literal? - @quads.select{|quad| quad.last == v}.each do |k,p,v,g| + @quads.select { |quad| quad.last == v }.each do |k,p,v,g| # Updates cardinality for the condition group if fragment(p) == 'maxCardinality' @c_groups_cardinalities[fragment(k)] = fragment(v) @@ -396,8 +396,8 @@ def build_actions # Creates condition groups from the subjects of the actions # side of the rules if @c_groups[fragment(k)].nil? - @c_groups[fragment(k)] = ConditionGroup.create({:cardinality => @c_groups_cardinalities[fragment(k)], - :name => fragment(k), :keep_selected => check_keep_selected_asset(fragment(k))}) + @c_groups[fragment(k)] = ConditionGroup.create({ :cardinality => @c_groups_cardinalities[fragment(k)], + :name => fragment(k), :keep_selected => check_keep_selected_asset(fragment(k)) }) end # Creates condition groups from the objects of the actions side object_condition_group_id = nil @@ -412,7 +412,7 @@ def build_actions object_condition_group_id = c_groups[fragment(v)].id end end - Action.create({:action_type => action, :predicate => fragment(p), + Action.create({ :action_type => action, :predicate => fragment(p), :object => fragment(v), :step_type_id => @step_type.id, :subject_condition_group_id => @c_groups[fragment(k)].id, @@ -421,7 +421,7 @@ def build_actions if (action=='unselectAsset') Condition.create({ :predicate => fragment(p), :object => fragment(v), - :condition_group_id => @c_groups[fragment(k)].id}) + :condition_group_id => @c_groups[fragment(k)].id }) end end end diff --git a/lib/tasks/setup_templates.rake b/lib/tasks/setup_templates.rake index 0d6eb667..4afc27d9 100644 --- a/lib/tasks/setup_templates.rake +++ b/lib/tasks/setup_templates.rake @@ -3,9 +3,9 @@ namespace :label_templates do desc "Find or register label templates in print-my-barcode" task setup: :environment do # Find the possible label templates and trigger their registration - Dir['./lib/label_types/*'].each {|f| require f } + Dir['./lib/label_types/*'].each { |f| require f } puts "Label types loaded..." - Dir['./lib/label_templates/*'].each {|f| require f } + Dir['./lib/label_templates/*'].each { |f| require f } puts "Templates loaded..." LabelTemplateSetup.find_or_register_each_template! end diff --git a/lib/token_util.rb b/lib/token_util.rb index 982e2763..8f30f2ae 100644 --- a/lib/token_util.rb +++ b/lib/token_util.rb @@ -1,4 +1,5 @@ module TokenUtil + # rubocop:todo Naming/MethodName def self.UUID_REGEXP /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ end @@ -86,7 +87,7 @@ def self.generate_positions(letters, columns) end def self.pad(str,chr,size) - "#{(size-str.size).times.map{chr}.join('')}#{str}" + "#{(size-str.size).times.map { chr }.join('')}#{str}" end def self.unpad_location(location) @@ -114,5 +115,5 @@ def self.unquote(str) return str unless str str.gsub(/\"/,"") end - + # rubocop:enable Naming/MethodName end diff --git a/script/aliquot_type_inference.rb b/script/aliquot_type_inference.rb index 1eb19895..98c4d974 100644 --- a/script/aliquot_type_inference.rb +++ b/script/aliquot_type_inference.rb @@ -1,8 +1,10 @@ class AliquotTypeInference attr_reader :asset_group + def initialize(params) @asset_group = params[:asset_group] end + # rubocop:todo Naming/MethodName def _CODE %Q{ { @@ -47,7 +49,7 @@ def out(val) return end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] out({}) unless args @@ -57,4 +59,4 @@ def out(val) asset_group = AssetGroup.find(asset_group_id) out(AliquotTypeInference.new(asset_group: asset_group).process) - +# rubocop:enable Naming/MethodName diff --git a/script/claim_uuids.rb b/script/claim_uuids.rb index 693c052b..b2db7869 100644 --- a/script/claim_uuids.rb +++ b/script/claim_uuids.rb @@ -5,7 +5,7 @@ module ClaimUuids def orphan_receptacles(stock_plate_ss) stock_plate_ss.wells.map do |well| - list = well.aliquots.first.sample.receptacles.select{|w| w.plate.nil?} + list = well.aliquots.first.sample.receptacles.select { |w| w.plate.nil? } if list.length>1 puts "The plate #{stock_plate_ss.barcode} has more than one orphan for the well #{well.id}" end diff --git a/script/container_inferences.rb b/script/container_inferences.rb index 715d4c23..0985b13a 100644 --- a/script/container_inferences.rb +++ b/script/container_inferences.rb @@ -1,5 +1,6 @@ class ContainerInferences attr_reader :asset_group + def initialize(params) @asset_group = params[:asset_group] end @@ -53,7 +54,7 @@ def out(val) return end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] out({}) unless args diff --git a/script/fix_duplicated_tubes.rb b/script/fix_duplicated_tubes.rb index 93aded6c..1a06fab7 100644 --- a/script/fix_duplicated_tubes.rb +++ b/script/fix_duplicated_tubes.rb @@ -1,6 +1,6 @@ group = AssetGroup.find(26968) -rack = group.assets.joins(:facts).where(facts: {predicate: 'a', object: 'TubeRack'}).first +rack = group.assets.joins(:facts).where(facts: { predicate: 'a', object: 'TubeRack' }).first facts = rack.facts.with_predicate('contains') diff --git a/script/purpose_name_inference.rb b/script/purpose_name_inference.rb index 99aba4e8..88b429de 100644 --- a/script/purpose_name_inference.rb +++ b/script/purpose_name_inference.rb @@ -1,9 +1,11 @@ class PurposeNameInference attr_reader :asset_group + def initialize(params) @asset_group = params[:asset_group] end + # rubocop:todo Naming/MethodName def _CODE %Q{ { @@ -29,6 +31,7 @@ def _CODE } } end + # rubocop:enable Naming/MethodName def containers2 asset_group.assets.with_predicate('contains') @@ -73,7 +76,7 @@ def out(val) return end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] out({}) unless args @@ -82,4 +85,3 @@ def out(val) asset_group_id = matches[1] asset_group = AssetGroup.find(asset_group_id) out(PurposeNameInference.new(asset_group: asset_group).process) - diff --git a/script/recreate_steptypes.rb b/script/recreate_steptypes.rb index c10277b9..5c59c3e4 100755 --- a/script/recreate_steptypes.rb +++ b/script/recreate_steptypes.rb @@ -52,7 +52,7 @@ ['Update Sequencescape', 'update_sequencescape.rb', %Q{ { ?p :a :TubeRack .}=>{}. }] -].map{|l| +].map { |l| s=StepType.find_by(name: l[0]) s2=StepType.create(name: l[0], step_action: l[1], for_reasoning: true, n3_definition: l[2]) s.deprecate_with(s) diff --git a/script/runners/create_12_tubes.rb b/script/runners/create_12_tubes.rb index 3a35977c..f2913acf 100755 --- a/script/runners/create_12_tubes.rb +++ b/script/runners/create_12_tubes.rb @@ -1,23 +1,23 @@ -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } TOTAL_NUMBER=12 -tubes = TOTAL_NUMBER.times.map{|i| "?p#{i}"} -samples = TOTAL_NUMBER.times.map{|i| "?q#{i}" } -sanger_sample_id = TOTAL_NUMBER.times.map{|i| "SAMPLE#{i}"} +tubes = TOTAL_NUMBER.times.map { |i| "?p#{i}" } +samples = TOTAL_NUMBER.times.map { |i| "?q#{i}" } +sanger_sample_id = TOTAL_NUMBER.times.map { |i| "SAMPLE#{i}" } study_name = "STDY1" -f1 = tubes.each_with_index.map{|t, i| [t, 'a', 'SampleTube']} -f2 = tubes.each_with_index.map{|t, i| [t, 'is', 'NotStarted']} -f3 = tubes.each_with_index.map{|t, i| [t, 'sample_tube', samples[i]]} -f4 = tubes.each_with_index.map{|t, i| [t, 'sanger_sample_id', sanger_sample_id[i]]} -f5 = tubes.each_with_index.map{|t, i| [t, 'study_name', study_name]} -f6 = tubes.each_with_index.map{|t, i| [t, 'transferVolume', 20]} -f7 = tubes.each_with_index.map{|t, i| [t, 'volume', 100]} +f1 = tubes.each_with_index.map { |t, i| [t, 'a', 'SampleTube'] } +f2 = tubes.each_with_index.map { |t, i| [t, 'is', 'NotStarted'] } +f3 = tubes.each_with_index.map { |t, i| [t, 'sample_tube', samples[i]] } +f4 = tubes.each_with_index.map { |t, i| [t, 'sanger_sample_id', sanger_sample_id[i]] } +f5 = tubes.each_with_index.map { |t, i| [t, 'study_name', study_name] } +f6 = tubes.each_with_index.map { |t, i| [t, 'transferVolume', 20] } +f7 = tubes.each_with_index.map { |t, i| [t, 'volume', 100] } all_assets = tubes + samples obj= { create_assets: all_assets, - add_facts: [f1,f2,f3,f4,f5,f6,f7].reduce([]){|memo, facts| memo.concat(facts)}, + add_facts: [f1,f2,f3,f4,f5,f6,f7].reduce([]) { |memo, facts| memo.concat(facts) }, add_assets: [tubes] }.to_json diff --git a/script/runners/create_file.rb b/script/runners/create_file.rb index 2787e95f..a3ffe13f 100755 --- a/script/runners/create_file.rb +++ b/script/runners/create_file.rb @@ -7,7 +7,7 @@ barcodes = [] while (num < NUM_BARCODES) do number=(rand*999999).floor.to_s - barcode = ["FR"].concat((6-number.length).times.map{ "0" }).concat([number]).join("") + barcode = ["FR"].concat((6-number.length).times.map { "0" }).concat([number]).join("") found = Asset.find_by(barcode: barcode) unless found barcodes.push(barcode) diff --git a/script/runners/create_layout.rb b/script/runners/create_layout.rb index a8c61880..21f980cc 100755 --- a/script/runners/create_layout.rb +++ b/script/runners/create_layout.rb @@ -7,7 +7,7 @@ barcodes = [] while (num < NUM_BARCODES) do number=(rand*999999).floor.to_s - barcode = ["FR"].concat((6-number.length).times.map{ "0" }).concat([number]).join("") + barcode = ["FR"].concat((6-number.length).times.map { "0" }).concat([number]).join("") found = Asset.find_by(barcode: barcode) unless found barcodes.push(barcode) @@ -32,6 +32,6 @@ file = UploadedFile.create(filename: "_temp.csv", data: temp_file.read) asset = file.build_asset(content_type: "csv") -data= { add_assets: [[nil, [asset.uuid] ]]} +data= { add_assets: [[nil, [asset.uuid] ]] } puts data.to_json diff --git a/script/runners/create_stamped_plate.rb b/script/runners/create_stamped_plate.rb index 8f470f23..0fb475cc 100644 --- a/script/runners/create_stamped_plate.rb +++ b/script/runners/create_stamped_plate.rb @@ -2,6 +2,7 @@ class CreateStampedPlate attr_reader :asset_group + def initialize(params) @asset_group = params[:asset_group] end @@ -28,7 +29,7 @@ def process end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] diff --git a/script/runners/full_rack_generator.rb b/script/runners/full_rack_generator.rb index 8ab66a5a..aa8add61 100644 --- a/script/runners/full_rack_generator.rb +++ b/script/runners/full_rack_generator.rb @@ -1,4 +1,4 @@ -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] out({}) unless args @@ -6,13 +6,13 @@ out({}) unless matches asset_group_id = matches[1] asset_group = AssetGroup.find(asset_group_id) -rack = asset_group.assets.joins(:facts).where(facts: { predicate: 'a', object: 'TubeRack'}).first +rack = asset_group.assets.joins(:facts).where(facts: { predicate: 'a', object: 'TubeRack' }).first current_tubes = rack.facts.where(predicate: 'contains').map(&:object_asset) facts_from_tubes = current_tubes.pluck(:facts) locations_with_tube = facts_from_tubes.empty? ? [] : facts_from_tubes.where(predicate: 'location').pluck(:object) -tubes = 96.times.map{|i| "?tube#{i}"} +tubes = 96.times.map { |i| "?tube#{i}" } letters = ("A".."H").to_a columns = (1..12).to_a location_for_position = 96.times.map do |i| diff --git a/script/runners/load_metadata.rb b/script/runners/load_metadata.rb index 76bad43d..89c2cc95 100644 --- a/script/runners/load_metadata.rb +++ b/script/runners/load_metadata.rb @@ -25,7 +25,7 @@ def find_asset(line_parsed) end def filter_unneeded_data(line_parsed) - line_parsed.reject{|k,v| k=='location' || k=='barcode'} + line_parsed.reject { |k,v| k=='location' || k=='barcode' } end def metadata_updates(asset_group) @@ -56,7 +56,7 @@ def process end end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] @@ -70,5 +70,5 @@ def process rescue InvalidDataParams => e puts ({ set_errors: e.errors }.to_json) rescue StandardError => e - puts ({ set_errors: ['Unknown error while parsing file'+e.backtrace.to_s]}.to_json) + puts ({ set_errors: ['Unknown error while parsing file'+e.backtrace.to_s] }.to_json) end diff --git a/script/runners/move_barcodes_from_tube_rack_to_plate.rb b/script/runners/move_barcodes_from_tube_rack_to_plate.rb index 47948f70..e61d55ae 100644 --- a/script/runners/move_barcodes_from_tube_rack_to_plate.rb +++ b/script/runners/move_barcodes_from_tube_rack_to_plate.rb @@ -33,11 +33,11 @@ def assets_compatible_with_step_type def plate - asset_group.assets.select{|a| a.facts.where(predicate: 'a', object: 'Plate').count > 0 }.first + asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'Plate').count > 0 }.first end def tube_rack - asset_group.assets.select{|a| a.facts.where(predicate: 'a', object: 'TubeRack').count > 0}.first + asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'TubeRack').count > 0 }.first end def wells_for(asset) @@ -95,6 +95,6 @@ def process JSON.parse(json) puts json rescue StandardError => e - puts ({ set_errors: ['Unknown error while applying barcodes'+e.backtrace.to_s]}.to_json) + puts ({ set_errors: ['Unknown error while applying barcodes'+e.backtrace.to_s] }.to_json) end diff --git a/script/runners/print_barcodes.rb b/script/runners/print_barcodes.rb index 9a7b762d..6e754222 100644 --- a/script/runners/print_barcodes.rb +++ b/script/runners/print_barcodes.rb @@ -1,5 +1,6 @@ class PrintBarcodes attr_reader :asset_group, :step + def initialize(params) @asset_group = params[:asset_group] @step = params[:step] @@ -36,7 +37,7 @@ def process end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] diff --git a/script/runners/put_tubes_into_rack_by_column_order.rb b/script/runners/put_tubes_into_rack_by_column_order.rb index 6acaba77..840a3977 100644 --- a/script/runners/put_tubes_into_rack_by_column_order.rb +++ b/script/runners/put_tubes_into_rack_by_column_order.rb @@ -2,7 +2,7 @@ require 'token_util' include Actions::Racking -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } updates = FactChanges.new @@ -14,11 +14,11 @@ out({}) unless matches asset_group_id = matches[1] asset_group = AssetGroup.find(asset_group_id) -rack = asset_group.assets.joins(:facts).where(facts: { predicate: 'a', object: 'TubeRack'}).first +rack = asset_group.assets.joins(:facts).where(facts: { predicate: 'a', object: 'TubeRack' }).first tube_ids_in_rack = rack.facts.with_predicate('contains').map(&:object_asset_id) locations_with_tube = Fact.where(predicate: 'location', asset_id: tube_ids_in_rack).map(&:object) -tubes = asset_group.assets.joins(:facts).where(facts: { predicate: 'a', object: 'Tube'}) +tubes = asset_group.assets.joins(:facts).where(facts: { predicate: 'a', object: 'Tube' }) LETTERS = ("A".."H").to_a COLUMNS = (1..12).to_a diff --git a/script/runners/rack_layout.rb b/script/runners/rack_layout.rb index 88638c2c..6bebf87b 100644 --- a/script/runners/rack_layout.rb +++ b/script/runners/rack_layout.rb @@ -23,7 +23,7 @@ def process end end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] @@ -37,5 +37,5 @@ def process rescue InvalidDataParams => e puts ({ set_errors: e.errors }.to_json) rescue StandardError => e - puts ({ set_errors: ['Unknown error while parsing file'+e]}.to_json) + puts ({ set_errors: ['Unknown error while parsing file'+e] }.to_json) end diff --git a/script/runners/rack_layout_any_barcode.rb b/script/runners/rack_layout_any_barcode.rb index 31169d66..1ad5e2fc 100644 --- a/script/runners/rack_layout_any_barcode.rb +++ b/script/runners/rack_layout_any_barcode.rb @@ -24,7 +24,7 @@ def process end end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] @@ -39,5 +39,5 @@ def process puts ({ set_errors: e.errors }.to_json) rescue StandardError => e - puts ({ set_errors: ['Unknown error while parsing file'+e.to_json+e.backtrace.join('')]}.to_json) + puts ({ set_errors: ['Unknown error while parsing file'+e.to_json+e.backtrace.join('')] }.to_json) end diff --git a/script/runners/rack_layout_creating_tubes.rb b/script/runners/rack_layout_creating_tubes.rb index 9a3cfd10..6a5429fc 100644 --- a/script/runners/rack_layout_creating_tubes.rb +++ b/script/runners/rack_layout_creating_tubes.rb @@ -24,7 +24,7 @@ def process end end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] @@ -39,5 +39,5 @@ def process puts ({ set_errors: e.errors }.to_json) rescue StandardError => e - puts ({ set_errors: ['Unknown error while parsing file'+e.to_json+e.backtrace.join('')]}.to_json) + puts ({ set_errors: ['Unknown error while parsing file'+e.to_json+e.backtrace.join('')] }.to_json) end diff --git a/script/runners/transfer_plate_to_plate.rb b/script/runners/transfer_plate_to_plate.rb index b4fa5a70..67589421 100644 --- a/script/runners/transfer_plate_to_plate.rb +++ b/script/runners/transfer_plate_to_plate.rb @@ -10,13 +10,17 @@ class TransferPlateToPlate attr_reader :asset_group + def initialize(params) @asset_group = params[:asset_group] end + # rubocop:todo Naming/MethodName def _CODE end + # rubocop:enable Naming/MethodName + # # { # ?p :a :Plate . @@ -49,10 +53,9 @@ def process end end end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] asset_group = AssetGroup.find(asset_group_id) puts TransferPlateToPlate.new(asset_group: asset_group).process.to_json - diff --git a/script/runners/transfer_plate_to_plate_and_update_sequencescape.rb b/script/runners/transfer_plate_to_plate_and_update_sequencescape.rb index ca9f300c..a8e471f3 100644 --- a/script/runners/transfer_plate_to_plate_and_update_sequencescape.rb +++ b/script/runners/transfer_plate_to_plate_and_update_sequencescape.rb @@ -1,4 +1,4 @@ -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] matches = args.match(/(\d*)\.json/) diff --git a/script/runners/transfer_samples.rb b/script/runners/transfer_samples.rb index d470525f..a45b4f52 100644 --- a/script/runners/transfer_samples.rb +++ b/script/runners/transfer_samples.rb @@ -4,6 +4,7 @@ class TransferSamples include Actions::TubeTransfer attr_reader :asset_group + def initialize(params) @asset_group = params[:asset_group] end @@ -46,7 +47,7 @@ def process end end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] diff --git a/script/runners/transfer_tubes_to_tube_rack_by_position.rb b/script/runners/transfer_tubes_to_tube_rack_by_position.rb index 4f0667c0..a6857636 100644 --- a/script/runners/transfer_tubes_to_tube_rack_by_position.rb +++ b/script/runners/transfer_tubes_to_tube_rack_by_position.rb @@ -2,6 +2,7 @@ class TransferTubesToTubeRackByPosition attr_reader :asset_group + include Actions::TubeTransfer def initialize(params) @asset_group = params[:asset_group] @@ -95,7 +96,7 @@ def process FactChanges.new.tap do |updates| aliquot_types = [] if assets_compatible_with_step_type - tubes = asset_group.assets.joins(:facts).where(facts: {predicate: 'transferToTubeRackByPosition'}).uniq + tubes = asset_group.assets.joins(:facts).where(facts: { predicate: 'transferToTubeRackByPosition' }).uniq rack = tubes.first.facts.with_predicate('transferToTubeRackByPosition').first.object_asset return updates unless validate_tube_are_not_in_rack(rack, tubes, updates) @@ -103,7 +104,7 @@ def process wells = rack.facts.with_predicate('contains').map(&:object_asset).sort_by do |elem| location = elem.facts.with_predicate('location').first.object location_to_pos(location) - end.reject{|w| w.has_predicate?('transferredFrom')}.uniq + end.reject { |w| w.has_predicate?('transferredFrom') }.uniq return updates unless validate_enough_tubes_for_all_wells(tubes, wells, updates) @@ -139,7 +140,7 @@ def process end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] diff --git a/script/runners/update_sequencescape.rb b/script/runners/update_sequencescape.rb index cdb3246c..844e1efd 100644 --- a/script/runners/update_sequencescape.rb +++ b/script/runners/update_sequencescape.rb @@ -5,6 +5,7 @@ # Calls the update_sequencescape method in export.rb class UpdateSequencescape attr_reader :asset_group, :step + def initialize(params) @asset_group = params[:asset_group] @step = params[:step] @@ -37,7 +38,7 @@ def out(val) return end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] out({}) unless args diff --git a/script/study_name_inference.rb b/script/study_name_inference.rb index 0642ef20..c0baffb1 100644 --- a/script/study_name_inference.rb +++ b/script/study_name_inference.rb @@ -1,9 +1,11 @@ class StudyNameInference attr_reader :asset_group + def initialize(params) @asset_group = params[:asset_group] end + # rubocop:todo Naming/MethodName def _CODE %Q{ { @@ -14,6 +16,7 @@ def _CODE }. } end + # rubocop:enable Naming/MethodName def assets_compatible_with_step_type asset_group.assets.with_predicate('contains').select do |a| @@ -42,10 +45,9 @@ def process end end -return unless ARGV.any?{|s| s.match(".json")} +return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] asset_group = AssetGroup.find(asset_group_id) puts StudyNameInference.new(asset_group: asset_group).process.to_json - diff --git a/script/tasks/runners/aliquot_type_inference.rb b/script/tasks/runners/aliquot_type_inference.rb index 9dc64c8a..0cb51349 100755 --- a/script/tasks/runners/aliquot_type_inference.rb +++ b/script/tasks/runners/aliquot_type_inference.rb @@ -1,8 +1,10 @@ class AliquotTypeInference attr_reader :asset_group + def initialize(params) @asset_group = params[:asset_group] end + # rubocop:todo Naming/MethodName def _CODE %Q{ { @@ -14,6 +16,8 @@ def _CODE } } end + # rubocop:enable Naming/MethodName + def assets_compatible_with_step_type asset_group.assets.with_predicate('aliquotType').select { |a| a.has_predicate?('contains') } end diff --git a/spec/concerns/deprecatable_spec.rb b/spec/concerns/deprecatable_spec.rb index 176e6108..fa5c045d 100644 --- a/spec/concerns/deprecatable_spec.rb +++ b/spec/concerns/deprecatable_spec.rb @@ -16,7 +16,7 @@ def build_instance active_instance = build_instance - deprecatable_list.each{|old| old.deprecate_with(active_instance)} + deprecatable_list.each { |old| old.deprecate_with(active_instance) } expect(model.visible.count).to eq(1) expect(model.all.count).to eq(deprecatable_list.count+1) diff --git a/spec/controllers/activities_controller_spec.rb b/spec/controllers/activities_controller_spec.rb index f3d73774..dd7c2c1c 100644 --- a/spec/controllers/activities_controller_spec.rb +++ b/spec/controllers/activities_controller_spec.rb @@ -11,14 +11,14 @@ setup do @activity_type = FactoryBot.create :activity_type @kit_type = FactoryBot.create :kit_type, :activity_type => @activity_type - @kit = FactoryBot.create :kit, {:kit_type => @kit_type} + @kit = FactoryBot.create :kit, { :kit_type => @kit_type } @instrument = FactoryBot.create :instrument end context "when updating an activity" do before do - @activity = @kit.kit_type.activity_type.create_activity({kit: @kit, instrument: @instrument}) + @activity = @kit.kit_type.activity_type.create_activity({ kit: @kit, instrument: @instrument }) end it 'can finish the activity' do post :update, params: { id: @activity.id, activity: { state: 'finish' } } @@ -29,7 +29,7 @@ context "when scanning a new kit" do context 'when the kit does not exist' do let(:subject) { - post :create, params: { activity: { :kit_barcode => '11850', :instrument_barcode => @instrument.barcode} } + post :create, params: { activity: { :kit_barcode => '11850', :instrument_barcode => @instrument.barcode } } } it 'fails creating the activity' do count = @kit.kit_type.activity_type.activities.count @@ -45,7 +45,7 @@ context 'when the kit exists' do context 'when the instrument does not support the activity type' do let(:subject) { - post :create, params: { activity: { :kit_barcode => @kit.barcode, :instrument_barcode => @instrument.barcode} } + post :create, params: { activity: { :kit_barcode => @kit.barcode, :instrument_barcode => @instrument.barcode } } } it 'fails creating the activity' do count = @kit.kit_type.activity_type.activities.count @@ -64,7 +64,7 @@ end it "creates a new activity" do count = @kit.kit_type.activity_type.activities.count - post :create, params: { activity: { :kit_barcode => @kit.barcode, :instrument_barcode => @instrument.barcode} } + post :create, params: { activity: { :kit_barcode => @kit.barcode, :instrument_barcode => @instrument.barcode } } @kit.kit_type.activity_type.activities.reload assert_equal @kit.kit_type.activity_type.activities.count, count + 1 assert_equal @activity_type.activities.count, count + 1 diff --git a/spec/controllers/activity_types_controller_spec.rb b/spec/controllers/activity_types_controller_spec.rb index c6cdf6ee..003a83e2 100644 --- a/spec/controllers/activity_types_controller_spec.rb +++ b/spec/controllers/activity_types_controller_spec.rb @@ -16,9 +16,9 @@ end it "should create activity_type" do - expect{ - post :create, params: { activity_type: @activity_type.attributes} - }.to change{ActivityType.count}.by(1) + expect { + post :create, params: { activity_type: @activity_type.attributes } + }.to change { ActivityType.count }.by(1) assert_redirected_to activity_type_path(assigns(:activity_type)) end @@ -34,14 +34,14 @@ end it "should update activity_type" do - patch :update, params: { id: @activity_type, activity_type: @activity_type.attributes} + patch :update, params: { id: @activity_type, activity_type: @activity_type.attributes } assert_redirected_to activity_type_path(assigns(:activity_type)) end it "should destroy activity_type" do - expect{ - delete :destroy, params: { id: @activity_type} - }.to change{ActivityType.count}.by(-1) + expect { + delete :destroy, params: { id: @activity_type } + }.to change { ActivityType.count }.by(-1) assert_redirected_to activity_types_path end diff --git a/spec/controllers/asset_groups_controller_spec.rb b/spec/controllers/asset_groups_controller_spec.rb index abb6f625..64c51aa6 100644 --- a/spec/controllers/asset_groups_controller_spec.rb +++ b/spec/controllers/asset_groups_controller_spec.rb @@ -6,7 +6,7 @@ let(:asset_group) { create :asset_group } let(:activity_type) { create :activity_type } - let(:activity) { create :activity, {activity_type: activity_type, asset_group: asset_group } } + let(:activity) { create :activity, { activity_type: activity_type, asset_group: asset_group } } @@ -14,19 +14,19 @@ let(:file) { fixture_file_upload('test/data/layout.csv', 'text/csv') } it 'creates a new uploaded file' do - expect{ - post :upload, params: { id: asset_group.id, qqfilename: 'myfile.csv', qqfile: file} - }.to change{UploadedFile.all.count}.by(1) + expect { + post :upload, params: { id: asset_group.id, qqfilename: 'myfile.csv', qqfile: file } + }.to change { UploadedFile.all.count }.by(1) end it 'adds the file to the asset group' do - expect{ - post :upload, params: { id: asset_group.id, qqfilename: 'myfile.csv', qqfile: file} - }.to change{asset_group.assets.count}.by(1) + expect { + post :upload, params: { id: asset_group.id, qqfilename: 'myfile.csv', qqfile: file } + }.to change { asset_group.assets.count }.by(1) end it 'creates a new step to track the change in the asset group' do - expect{ - post :upload, params: { id: asset_group.id, qqfilename: 'myfile.csv', qqfile: file} - }.to change{Step.all.count}.by(1) + expect { + post :upload, params: { id: asset_group.id, qqfilename: 'myfile.csv', qqfile: file } + }.to change { Step.all.count }.by(1) end end @@ -38,18 +38,18 @@ context "when the asset is in the database" do context 'finding by uuid' do it "add the new asset to the group" do - expect{ - post :update, params: {:asset_group => {:assets => [asset.uuid]}, - :id => asset_group.id, :activity_id => activity.id} - }.to change{asset_group.assets.count}.by(1) + expect { + post :update, params: { :asset_group => { :assets => [asset.uuid] }, + :id => asset_group.id, :activity_id => activity.id } + }.to change { asset_group.assets.count }.by(1) end end context 'finding by barcode' do it "add the new asset to the group" do - expect{ - post :update, params: {:asset_group => {:assets => [asset.barcode]}, - :id => asset_group.id, :activity_id => activity.id} - }.to change{asset_group.assets.count}.by(1) + expect { + post :update, params: { :asset_group => { :assets => [asset.barcode] }, + :id => asset_group.id, :activity_id => activity.id } + }.to change { asset_group.assets.count }.by(1) end end end @@ -57,7 +57,7 @@ context "when the asset is not in the database" do let(:barcode) { generate :barcode } let(:uuid) { SecureRandom.uuid } - let(:SequencescapeClient) { double('sequencescape_client')} + let(:SequencescapeClient) { double('sequencescape_client') } let(:remote_asset) { build_remote_tube(barcode: barcode, uuid: uuid) } before do @@ -68,19 +68,19 @@ context 'finding by uuid' do it "retrieves the asset from Sequencescape" do - expect{ - post :update, params: {:asset_group => {:assets => [uuid]}, - :id => asset_group.id, :activity_id => activity.id} - }.to change{asset_group.assets.count}.by(1) + expect { + post :update, params: { :asset_group => { :assets => [uuid] }, + :id => asset_group.id, :activity_id => activity.id } + }.to change { asset_group.assets.count }.by(1) end end context 'finding by barcode' do it "retrieves the asset from Sequencescape" do - expect{ - post :update, params: {:asset_group => {:assets => [barcode]}, - :id => asset_group.id, :activity_id => activity.id} - }.to change{asset_group.assets.count}.by(1) + expect { + post :update, params: { :asset_group => { :assets => [barcode] }, + :id => asset_group.id, :activity_id => activity.id } + }.to change { asset_group.assets.count }.by(1) end end end @@ -88,8 +88,8 @@ context "when it is not in Sequencescape" do it 'does not retrieve anything' do - post :update, params: {:asset_group => {:assets => [SecureRandom.uuid]}, - :id => asset_group.id, :activity_id => activity.id} + post :update, params: { :asset_group => { :assets => [SecureRandom.uuid] }, + :id => asset_group.id, :activity_id => activity.id } expect(asset_group.assets.count).to eq(0) end end @@ -98,12 +98,12 @@ let(:creatable_barcode) { generate :barcode_creatable } it "creates a new asset" do - expect{ - post :update, params: {:asset_group => { + expect { + post :update, params: { :asset_group => { :assets => [creatable_barcode] }, - :id => asset_group.id, :activity_id => activity.id} - }.to change{asset_group.assets.count}.by(1) + :id => asset_group.id, :activity_id => activity.id } + }.to change { asset_group.assets.count }.by(1) end end end diff --git a/spec/controllers/assets_controller_spec.rb b/spec/controllers/assets_controller_spec.rb index 75ddbd74..804e527a 100644 --- a/spec/controllers/assets_controller_spec.rb +++ b/spec/controllers/assets_controller_spec.rb @@ -9,31 +9,31 @@ shared_examples_for 'a search action from a controller' do it 'renders a search' do - send(method, action_name, params: { q: 'S1234'}, xhr: true) + send(method, action_name, params: { q: 'S1234' }, xhr: true) assert_response :success expect(response).to render_template :search end it 'searches by barcode' do asset = create :asset, barcode: 'S1234' search = Asset.where(barcode: 'S1234') - send(method, action_name, params: { p0: 'barcode', o0: 'S1234'}) + send(method, action_name, params: { p0: 'barcode', o0: 'S1234' }) expect(assigns(:assets)[0]).to eq(search[0]) end it 'searches by properties' do asset = create :asset, barcode: 'S1234' asset.facts << create(:fact, predicate: 'a', object: 'Tube') - search = Asset.joins(:facts).where(facts: { predicate: 'a', object: 'Tube'}).first - send(method, action_name, params: { p0: 'a', o0: 'Tube'}) + search = Asset.joins(:facts).where(facts: { predicate: 'a', object: 'Tube' }).first + send(method, action_name, params: { p0: 'a', o0: 'Tube' }) expect(assigns(:assets)[0]).to eq(search) end end context '#search' do - let(:method) {:get} + let(:method) { :get } let(:action_name) { :search } it_behaves_like 'a search action from a controller' end context '#print_search' do - let(:method) {:post} + let(:method) { :post } let(:action_name) { :print_search } it_behaves_like 'a search action from a controller' @@ -49,10 +49,10 @@ allow(mocked_group).to receive(:assets).and_return([]) allow(mocked_group).to receive(:print) - post :print_search, params: { p0: 'barcode', o0: 'S1234'}, xhr: true + post :print_search, params: { p0: 'barcode', o0: 'S1234' }, xhr: true expect(assigns(:assets).to_a).to eq(search.to_a) - expect(mocked_group).to have_received(:print).with({"Plate"=>'Pum', "Tube"=>'Pim'}, 'test') + expect(mocked_group).to have_received(:print).with({ "Plate"=>'Pum', "Tube"=>'Pim' }, 'test') end end end diff --git a/spec/controllers/changes_controller_spec.rb b/spec/controllers/changes_controller_spec.rb index fdc61e13..fcb0e1a9 100644 --- a/spec/controllers/changes_controller_spec.rb +++ b/spec/controllers/changes_controller_spec.rb @@ -10,7 +10,7 @@ add_facts: [["?p", "a", "Tube"]] } }, as: :json - }.to change{Step.all.count}.and change{Asset.all.count}.by(1) + }.to change { Step.all.count }.and change { Asset.all.count }.by(1) change = JSON.parse(response.body) expect(change['assets'].count).to eq(1) expect(change['assets'][0]['uuid']).not_to eq(nil) diff --git a/spec/controllers/instruments_controller_spec.rb b/spec/controllers/instruments_controller_spec.rb index 64019806..9eb51eca 100644 --- a/spec/controllers/instruments_controller_spec.rb +++ b/spec/controllers/instruments_controller_spec.rb @@ -21,32 +21,32 @@ end it "should create instrument" do - expect{ - post :create, params: { instrument: @instrument.attributes} - }.to change{ Instrument.count }.by(1) + expect { + post :create, params: { instrument: @instrument.attributes } + }.to change { Instrument.count }.by(1) assert_redirected_to instrument_path(assigns(:instrument)) end it "should show instrument" do - get :show, params: { id: @instrument} + get :show, params: { id: @instrument } assert_response :success end it "should get edit" do - get :edit, params: { id: @instrument} + get :edit, params: { id: @instrument } assert_response :success end it "should update instrument" do - patch :update, params: { id: @instrument, instrument: @instrument.attributes} + patch :update, params: { id: @instrument, instrument: @instrument.attributes } assert_redirected_to instrument_path(assigns(:instrument)) end it "should destroy instrument" do - expect{ - delete :destroy, params: { id: @instrument} - }.to change{ Instrument.count }.by(-1) + expect { + delete :destroy, params: { id: @instrument } + }.to change { Instrument.count }.by(-1) assert_redirected_to instruments_path end diff --git a/spec/controllers/kit_types_controller_spec.rb b/spec/controllers/kit_types_controller_spec.rb index 68ba1880..f833d66e 100644 --- a/spec/controllers/kit_types_controller_spec.rb +++ b/spec/controllers/kit_types_controller_spec.rb @@ -2,8 +2,8 @@ RSpec.describe KitTypesController, type: :controller do setup do - @activity_type = FactoryBot.create :activity_type, {:name => 'Testing activity type'} - @kit_type = FactoryBot.create :kit_type, {:name => 'My Kit Type', :activity_type => @activity_type} + @activity_type = FactoryBot.create :activity_type, { :name => 'Testing activity type' } + @kit_type = FactoryBot.create :kit_type, { :name => 'My Kit Type', :activity_type => @activity_type } end it "should get index" do @@ -17,32 +17,32 @@ end it "should create kit_type" do - expect{ - post :create, params: { kit_type: @kit_type.attributes} - }.to change{KitType.count}.by(1) + expect { + post :create, params: { kit_type: @kit_type.attributes } + }.to change { KitType.count }.by(1) assert_redirected_to kit_type_path(assigns(:kit_type)) end it "should show kit_type" do - get :show, params: { id: @kit_type} + get :show, params: { id: @kit_type } assert_response :success end it "should get edit" do - get :edit, params: { id: @kit_type} + get :edit, params: { id: @kit_type } assert_response :success end it "should update kit_type" do - patch :update, params: { id: @kit_type, kit_type: @kit_type.attributes} + patch :update, params: { id: @kit_type, kit_type: @kit_type.attributes } assert_redirected_to kit_type_path(assigns(:kit_type)) end it "should destroy kit_type" do - expect{ - delete :destroy, params: { id: @kit_type} - }.to change{KitType.count}.by(-1) + expect { + delete :destroy, params: { id: @kit_type } + }.to change { KitType.count }.by(-1) assert_redirected_to kit_types_path end diff --git a/spec/controllers/kits_controller_spec.rb b/spec/controllers/kits_controller_spec.rb index a8c99f94..34a120d9 100644 --- a/spec/controllers/kits_controller_spec.rb +++ b/spec/controllers/kits_controller_spec.rb @@ -17,32 +17,32 @@ end it "should create kit" do - expect{ - post :create, params: { kit: @kit.attributes} - }.to change{Kit.count}.by(1) + expect { + post :create, params: { kit: @kit.attributes } + }.to change { Kit.count }.by(1) assert_redirected_to kit_path(assigns(:kit)) end it "should show kit" do - get :show, params:{ id: @kit} + get :show, params:{ id: @kit } assert_response :success end it "should get edit" do - get :edit, params:{ id: @kit} + get :edit, params:{ id: @kit } assert_response :success end it "should update kit" do - patch :update, params:{ id: @kit, kit: @kit.attributes} + patch :update, params:{ id: @kit, kit: @kit.attributes } assert_redirected_to kit_path(assigns(:kit)) end it "should destroy kit" do - expect{ - delete :destroy, params: { id: @kit} - }.to change{Kit.count}.by(-1) + expect { + delete :destroy, params: { id: @kit } + }.to change { Kit.count }.by(-1) assert_redirected_to kits_path end diff --git a/spec/controllers/printers_controller_spec.rb b/spec/controllers/printers_controller_spec.rb index e4de3b49..cea6884e 100644 --- a/spec/controllers/printers_controller_spec.rb +++ b/spec/controllers/printers_controller_spec.rb @@ -2,7 +2,7 @@ RSpec.describe PrintersController, type: :controller do setup do - @printer = FactoryBot.create :printer, {:name => 'one'} + @printer = FactoryBot.create :printer, { :name => 'one' } end it "should get index" do @@ -16,9 +16,9 @@ end it "should create printer" do - expect{ + expect { post :create, params: { printer: @printer.attributes } - }.to change{ + }.to change { Printer.count }.by(1) @@ -31,7 +31,7 @@ end it "should get edit" do - get :edit, params: {id: @printer} + get :edit, params: { id: @printer } assert_response :success end @@ -41,9 +41,9 @@ end it "should destroy printer" do - expect{ + expect { delete :destroy, params: { id: @printer } - }.to change{Printer.count}.by(-1) + }.to change { Printer.count }.by(-1) assert_redirected_to printers_path end diff --git a/spec/controllers/step_types_controller_spec.rb b/spec/controllers/step_types_controller_spec.rb index d4a59b9f..7c7e999e 100644 --- a/spec/controllers/step_types_controller_spec.rb +++ b/spec/controllers/step_types_controller_spec.rb @@ -16,9 +16,9 @@ end it "should create step_type" do - expect{ - post :create, params: { step_type: {:name => 'Test'} } - }.to change{ + expect { + post :create, params: { step_type: { :name => 'Test' } } + }.to change { StepType.count }.by(1) @@ -26,7 +26,7 @@ end it "should show step_type" do - get :show, params:{ id: @step_type} + get :show, params:{ id: @step_type } assert_response :success end @@ -42,18 +42,18 @@ it "should update priority for step_type" do step_type = create :step_type - expect{ - post :update, params: { id: step_type.id, step_type: step_type.attributes.merge({priority: 10}.as_json)} - }.to change{ + expect { + post :update, params: { id: step_type.id, step_type: step_type.attributes.merge({ priority: 10 }.as_json) } + }.to change { step_type.reload step_type.priority }.to(10) end it "should destroy step_type" do - expect{ + expect { delete :destroy, params: { id: @step_type } - }.to change{ + }.to change { StepType.count }.by(-1) @@ -61,11 +61,11 @@ end context '#create' do - let(:params) { {step_type: { name: 'My task' } } } + let(:params) { { step_type: { name: 'My task' } } } it 'creates a new step type' do - expect{ + expect { post :create, params: params - }.to change{ StepType.all.count }.by(1) + }.to change { StepType.all.count }.by(1) end it 'redirects to the step type url' do post :create, params: params diff --git a/spec/controllers/steps_controller_spec.rb b/spec/controllers/steps_controller_spec.rb index 5c180174..c5d43992 100644 --- a/spec/controllers/steps_controller_spec.rb +++ b/spec/controllers/steps_controller_spec.rb @@ -1,9 +1,9 @@ require 'rails_helper' RSpec.describe StepsController, type: :controller do - let(:activity) { create(:activity)} + let(:activity) { create(:activity) } let(:asset_group) { create(:asset_group) } - let(:step_type) {create(:step_type)} + let(:step_type) { create(:step_type) } before do session[:token] = 'mytoken' @@ -18,12 +18,12 @@ asset_group_id: asset_group.id, step_type_id: step_type.id } } - }.to change{Step.all.count} + }.to change { Step.all.count } end context 'when receiving a specific printer config' do - let(:tube_printer) { create :printer, name: 'tubes'} - let(:plate_printer) { create :printer, name: 'plates'} + let(:tube_printer) { create :printer, name: 'tubes' } + let(:plate_printer) { create :printer, name: 'plates' } it 'stores the printer_config provided as parameter' do post :create, params: { activity_id: activity.id, step: { @@ -47,7 +47,7 @@ let(:event_name) { Step::EVENT_RUN } it 'changes the state for the step' do - post :update, params: { id: step.id, step: {event_name: event_name} } + post :update, params: { id: step.id, step: { event_name: event_name } } step.reload expect(step.state).to eq('complete') expect(response.status).to eq(200) @@ -92,12 +92,12 @@ expect(step.operations.length > 0).to eq(true) post :update, params: { id: step_id, step: { event_name: 'stop' } } end - expect(step.operations.all?{|op| !op.cancelled?}).to eq(true) + expect(step.operations.all? { |op| !op.cancelled? }).to eq(true) run_step step.reload - expect(step.operations.all?{|op| op.cancelled?}).to eq(true) + expect(step.operations.all? { |op| op.cancelled? }).to eq(true) expect(step.stopped?).to eq(true) end end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 95d64e3c..62103c74 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -22,9 +22,9 @@ def create_well(location, sample, aliquot) let(:barcode) { nil } let(:facts) { [create(:fact, predicate: 'contains', object_asset: well)] } - let(:asset) { create :asset, facts: facts} + let(:asset) { create :asset, facts: facts } context 'when the well has no location' do - let(:location) { nil} + let(:location) { nil } it 'does not display the well' do obj = {} val = helper.data_asset_display_for_plate(asset.facts) @@ -33,7 +33,7 @@ def create_well(location, sample, aliquot) end end context 'when the well has a location' do - let(:location){"A1"} + let(:location) { "A1" } context 'when the well does not have a barcode or a sample' do let(:barcode) { nil } let(:sample) { nil } @@ -45,7 +45,7 @@ def create_well(location, sample, aliquot) end end context 'when the well has a barcode or a sample' do - let(:barcode) { "S1234"} + let(:barcode) { "S1234" } context 'when the well does not have a sample' do let(:sample) { nil } it 'displays an empty well' do diff --git a/spec/inferences_helper.rb b/spec/inferences_helper.rb index 8c004e37..ffb9bf65 100644 --- a/spec/inferences_helper.rb +++ b/spec/inferences_helper.rb @@ -44,7 +44,7 @@ def build_step(rule, input_facts, options = {}) input_assets = SupportN3::parse_facts(input_facts, {}, false) reload_assets(input_assets) fail if input_assets.nil? - asset_group = FactoryBot.create(:asset_group, {:assets => input_assets}) + asset_group = FactoryBot.create(:asset_group, { :assets => input_assets }) user = FactoryBot.create :user, username: 'test' @@ -81,7 +81,7 @@ def check_inference(rule, input_facts, output_facts) asset_group.assets.reload reload_assets(asset_group.assets) obtained_n3 = assets_to_n3(asset_group.assets) - asset_group.assets.each{|a| a.facts.each(&:destroy)} + asset_group.assets.each { |a| a.facts.each(&:destroy) } expected_output_assets = SupportN3::parse_facts(output_facts, {}, false) fail if expected_output_assets.nil? diff --git a/spec/integration/inference_spec.rb b/spec/integration/inference_spec.rb index a05acf46..f9d69712 100644 --- a/spec/integration/inference_spec.rb +++ b/spec/integration/inference_spec.rb @@ -20,21 +20,21 @@ def cwm_engine? obtained_assets = SupportN3::parse_facts(code) f1 = [ - FactoryBot.create(:fact, {:predicate => 'name', :object => 'a name'}), - FactoryBot.create(:fact, {:predicate => 'volume', :object => '17'})] + FactoryBot.create(:fact, { :predicate => 'name', :object => 'a name' }), + FactoryBot.create(:fact, { :predicate => 'volume', :object => '17' })] tube2 = FactoryBot.create(:asset, :name => 'tube2', :facts => f1) f2 = [ - FactoryBot.create(:fact, {:predicate => 'relates', :object_asset => tube2}) + FactoryBot.create(:fact, { :predicate => 'relates', :object_asset => tube2 }) ] tube1 = FactoryBot.create(:asset, :name => 'tube1', :facts=> f2) tube3 = FactoryBot.create(:asset) f3 = [ - FactoryBot.create(:fact, {:predicate => 'relates', :object_asset => tube2}) + FactoryBot.create(:fact, { :predicate => 'relates', :object_asset => tube2 }) ] tube4 = FactoryBot.create(:asset, :name => 'tube4', :facts => f3 ) - f4 = [FactoryBot.create(:fact, {:predicate => 'volume', :object => '17'})] + f4 = [FactoryBot.create(:fact, { :predicate => 'volume', :object => '17' })] tube5 = FactoryBot.create(:asset, :name => 'tube2', :facts => f4) diff --git a/spec/lib/actions/plate_transfer_spec.rb b/spec/lib/actions/plate_transfer_spec.rb index 922a5917..26196b8b 100644 --- a/spec/lib/actions/plate_transfer_spec.rb +++ b/spec/lib/actions/plate_transfer_spec.rb @@ -10,7 +10,7 @@ source.facts << create(:fact, predicate: 'contains', object_asset: tube) destination = create :asset updates = Actions::PlateTransfer.transfer_plates(source,destination) - expect(updates.to_h[:add_facts].select{|t| t[1] == 'barcode'}.length).to eq(0) + expect(updates.to_h[:add_facts].select { |t| t[1] == 'barcode' }.length).to eq(0) end it 'copies facts from source wells to destination wells' do source = create :asset @@ -30,10 +30,10 @@ destination = create :asset updates = Actions::PlateTransfer.transfer_plates(source,destination) - expect(updates.to_h[:add_facts].select{|t| t[1]=='location'}.map{|t| t[2]}).to eq(["A01", "B01"]) - expect(updates.to_h[:add_facts].select{|t| t[1]=='concentration'}.map{|t| t[2]}).to eq(["1.3"]) - expect(updates.to_h[:add_facts].select{|t| t[1]=='sample_common_name'}.map{|t| t[2]}).to eq(["species"]) - expect(updates.to_h[:add_facts].select{|t| t[1]=='a'}.map{|t| t[2]}).to eq(["Well", "Well"]) + expect(updates.to_h[:add_facts].select { |t| t[1]=='location' }.map { |t| t[2] }).to eq(["A01", "B01"]) + expect(updates.to_h[:add_facts].select { |t| t[1]=='concentration' }.map { |t| t[2] }).to eq(["1.3"]) + expect(updates.to_h[:add_facts].select { |t| t[1]=='sample_common_name' }.map { |t| t[2] }).to eq(["species"]) + expect(updates.to_h[:add_facts].select { |t| t[1]=='a' }.map { |t| t[2] }).to eq(["Well", "Well"]) end it 'can copy facts with uuid values' do source = create :asset @@ -58,8 +58,8 @@ updates.add(destination, 'aliquotType', 'DNA') updates = Actions::PlateTransfer.transfer_plates(source, destination, updates) - created_well = updates.to_h[:add_facts].select{|t| (t[1] == 'location')}.first[0] - expect(updates.to_h[:add_facts].select{|t| (t[0]==created_well) && (t[1]=='aliquotType')}.first[2]).to eq('DNA') + created_well = updates.to_h[:add_facts].select { |t| (t[1] == 'location') }.first[0] + expect(updates.to_h[:add_facts].select { |t| (t[0]==created_well) && (t[1]=='aliquotType') }.first[2]).to eq('DNA') end it 'does not copy ignored predicates' do source = create :asset @@ -75,8 +75,8 @@ updates = Actions::PlateTransfer.transfer_plates(source, destination, FactChanges.new) - expect(updates.to_h[:add_facts].select{|t| (t[1] == 'pushedTo')}.length).to eq(0) - expect(updates.to_h[:add_facts].select{|t| (t[1] == 'location')}.length>0).to eq(true) + expect(updates.to_h[:add_facts].select { |t| (t[1] == 'pushedTo') }.length).to eq(0) + expect(updates.to_h[:add_facts].select { |t| (t[1] == 'location') }.length>0).to eq(true) end end end diff --git a/spec/lib/actions/racking_spec.rb b/spec/lib/actions/racking_spec.rb index b2bd9760..29d2f686 100644 --- a/spec/lib/actions/racking_spec.rb +++ b/spec/lib/actions/racking_spec.rb @@ -3,12 +3,12 @@ RSpec.describe Actions::Racking do let(:content) { File.open('test/data/layout.csv').read } - let(:file) { create(:uploaded_file, data: content )} + let(:file) { create(:uploaded_file, data: content ) } let(:activity) { create(:activity) } let(:asset_group) { create(:asset_group, assets: [asset]) } - let(:fact) { create(:fact, predicate: 'a', object: 'TubeRack')} + let(:fact) { create(:fact, predicate: 'a', object: 'TubeRack') } let(:asset) { create :asset, uploaded_file: file, facts: [fact] } - let(:step_type) {create(:step_type, condition_groups: [condition_group]) } + let(:step_type) { create(:step_type, condition_groups: [condition_group]) } let(:step) { create :step, activity: activity, state: Step::STATE_RUNNING, @@ -82,7 +82,7 @@ let(:content) { add_empty_slots(File.open('test/data/layout.csv').read, num_empty, start_pos) } - def add_empty_slots(content, num_empty, start_pos=0) + def add_empty_slots(content, num_empty, start_pos = 0) csv = CSV.new(content).to_a num_empty.times do |i| csv[start_pos + i][1] = 'No Read' @@ -131,7 +131,7 @@ def add_empty_slots(content, num_empty, start_pos=0) updates = fact_changes_for_rack_when_unracking_tubes(asset, @tubes) expect(updates.to_h[:remove_facts].select do |triple| triple[1]=='study_name' - end.map{|triple| triple[2]}.sort).to eq(['STDY1', 'STDY2']) + end.map { |triple| triple[2] }.sort).to eq(['STDY1', 'STDY2']) end it 'removes the purpose when all tubes go out' do @@ -140,7 +140,7 @@ def add_empty_slots(content, num_empty, start_pos=0) updates = fact_changes_for_rack_when_unracking_tubes(asset, @tubes) expect(updates.to_h[:remove_facts].select do |triple| triple[1]=='purpose' - end.map{|triple| triple[2]}.sort).to eq(['DNA Stock Plate']) + end.map { |triple| triple[2] }.sort).to eq(['DNA Stock Plate']) end it 'only returns the studies of the tubes that are going to be removed' do @@ -155,7 +155,7 @@ def add_empty_slots(content, num_empty, start_pos=0) updates = fact_changes_for_rack_when_unracking_tubes(asset, tubes2) expect(updates.to_h[:remove_facts].select do |triple| triple[1]=='study_name' - end.map{|triple| triple[2]}.sort).to eq(['STDY1']) + end.map { |triple| triple[2] }.sort).to eq(['STDY1']) end end @@ -175,7 +175,7 @@ def add_empty_slots(content, num_empty, start_pos=0) updates = fact_changes_for_rack_when_racking_tubes(asset, @tubes) expect(updates.to_h[:add_facts].select do |triple| triple[1]=='study_name' - end.map{|triple| triple[2]}.sort).to eq(['STDY1', 'STDY2']) + end.map { |triple| triple[2] }.sort).to eq(['STDY1', 'STDY2']) end it 'generates the DNA stock plate purpose' do @tubes.each_with_index do |tube, idx| diff --git a/spec/lib/actions/tube_transfer_spec.rb b/spec/lib/actions/tube_transfer_spec.rb index ad210f74..86671f86 100644 --- a/spec/lib/actions/tube_transfer_spec.rb +++ b/spec/lib/actions/tube_transfer_spec.rb @@ -7,19 +7,19 @@ context '#transfer_tubes' do let(:source) { create :asset } let(:destination) { create :asset } - let(:quoted_study_uuid) { TokenUtil.quote(SecureRandom.uuid)} - let(:common_name){ 'common name' } + let(:quoted_study_uuid) { TokenUtil.quote(SecureRandom.uuid) } + let(:common_name) { 'common name' } before do source.facts << create(:fact, predicate: 'study_uuid', object: quoted_study_uuid) source.facts << create(:fact, predicate: 'sample_common_name', object: common_name) end it 'transfers study_uuid' do updates = transfer_tubes(source, destination) - expect(updates.to_h[:add_facts].select{|t| t[1]=='study_uuid'}.first[2]).to eq(quoted_study_uuid) + expect(updates.to_h[:add_facts].select { |t| t[1]=='study_uuid' }.first[2]).to eq(quoted_study_uuid) end it 'transfers common name' do updates = transfer_tubes(source, destination) - expect(updates.to_h[:add_facts].select{|t| t[1]=='sample_common_name'}.first[2]).to eq(common_name) + expect(updates.to_h[:add_facts].select { |t| t[1]=='sample_common_name' }.first[2]).to eq(common_name) end end diff --git a/spec/lib/changes_support/disjoint_list_spec.rb b/spec/lib/changes_support/disjoint_list_spec.rb index 7162b64f..5fa570f4 100644 --- a/spec/lib/changes_support/disjoint_list_spec.rb +++ b/spec/lib/changes_support/disjoint_list_spec.rb @@ -36,7 +36,7 @@ expect(list.unique_id_for_element(["1","2","3"])).to eq(list.unique_id_for_element([1,2,3])) end it 'can generate an id for hash' do - expect(list.unique_id_for_element({a: 1, b: 2, c: 3})).to eq(list.unique_id_for_element({a: "1", b: "2", c: "3"})) + expect(list.unique_id_for_element({ a: 1, b: 2, c: 3 })).to eq(list.unique_id_for_element({ a: "1", b: "2", c: "3" })) end it 'can generate an id for ActiveRecord' do fact1 = create(:fact, predicate: 'p', object: 'v') @@ -71,16 +71,16 @@ expect(list.unique_id_for_element(true)).not_to eq(list.unique_id_for_element(false)) end it 'does not enter in infinite loop' do - obj = {a: 1, b: { c: nil } } + obj = { a: 1, b: { c: nil } } obj[:b][:c] = obj - expect{list.unique_id_for_element(obj)}.not_to raise_error + expect { list.unique_id_for_element(obj) }.not_to raise_error end it 'generates same id for facts when using id or object reference' do asset=create :asset asset2 = create :asset somepredicate='relation' - ob1={asset: asset, predicate: somepredicate, object_asset: asset2} - ob2={id: 123, asset_id: asset.id, predicate: somepredicate, object_asset_id: asset2.id} + ob1={ asset: asset, predicate: somepredicate, object_asset: asset2 } + ob2={ id: 123, asset_id: asset.id, predicate: somepredicate, object_asset_id: asset2.id } expect(list.unique_id_for_element(ob1)).to eq(list.unique_id_for_element(ob2)) end it 'generates different ids for facts using instances not in database' do @@ -89,10 +89,10 @@ asset3 = build :asset somepredicate='relation' - ob1={asset: asset, predicate: somepredicate, object_asset: asset2} - ob2={asset: asset2, predicate: somepredicate, object_asset: asset} - ob3={asset: asset, predicate: somepredicate, object_asset: asset3} - ob4={asset: asset, predicate: somepredicate, object_asset: asset} + ob1={ asset: asset, predicate: somepredicate, object_asset: asset2 } + ob2={ asset: asset2, predicate: somepredicate, object_asset: asset } + ob3={ asset: asset, predicate: somepredicate, object_asset: asset3 } + ob4={ asset: asset, predicate: somepredicate, object_asset: asset } expect(list.unique_id_for_element(ob1)).not_to eq(list.unique_id_for_element(ob2)) expect(list.unique_id_for_element(ob1)).not_to eq(list.unique_id_for_element(ob3)) @@ -108,9 +108,9 @@ describe '#add' do let(:elem) { 'a value' } - let(:raw_list) {[]} - let(:raw_list2) {[]} - let(:list) { ChangesSupport::DisjointList.new(raw_list)} + let(:raw_list) { [] } + let(:raw_list2) { [] } + let(:list) { ChangesSupport::DisjointList.new(raw_list) } let(:list2) { ChangesSupport::DisjointList.new(raw_list2) } before do @@ -121,25 +121,25 @@ expect(list.add(elem)).to eq(list) end it 'adds the element when is not present in any of the lists' do - expect{ + expect { list.add(elem) - }.to change{list.to_a.length}.by(1) - .and change{list.length}.by(1) + }.to change { list.to_a.length }.by(1) + .and change { list.length }.by(1) expect(list.to_a).to eq([elem]) end it 'stores the position in the common hash' do - expect{ + expect { list.add(elem) - }.to change{list.store_for(elem)}.from(nil).to(list) - .and change{list2.store_for(elem)}.from(nil).to(list) + }.to change { list.store_for(elem) }.from(nil).to(list) + .and change { list2.store_for(elem) }.from(nil).to(list) end it 'does not add the element again if it is already present' do list.add(elem) expect(list.to_a).to eq([elem]) - expect{ + expect { list.add(elem) - }.to change{list.to_a.length}.by(0) - .and change{list.length}.by(0) + }.to change { list.to_a.length }.by(0) + .and change { list.length }.by(0) expect(list.to_a).to eq([elem]) end it 'disables the element from the list if is added to another disjoint list' do @@ -154,7 +154,7 @@ context 'with a group of disjoint lists' do let(:lists) { - l=5.times.map{ChangesSupport::DisjointList.new([])} + l=5.times.map { ChangesSupport::DisjointList.new([]) } l[0].add_disjoint_list(l[1]) l[0].add_disjoint_list(l[2]) l[0].add_disjoint_list(l[3]) @@ -192,10 +192,10 @@ end describe '#concat' do - let(:disjoint1) { ChangesSupport::DisjointList.new([])} - let(:disjoint2) { ChangesSupport::DisjointList.new([])} - let(:disjoint3) { ChangesSupport::DisjointList.new([])} - let(:disjoint4) { ChangesSupport::DisjointList.new([])} + let(:disjoint1) { ChangesSupport::DisjointList.new([]) } + let(:disjoint2) { ChangesSupport::DisjointList.new([]) } + let(:disjoint3) { ChangesSupport::DisjointList.new([]) } + let(:disjoint4) { ChangesSupport::DisjointList.new([]) } context 'when concatenating disjoint lists' do before do @@ -224,8 +224,8 @@ it 'removes the element with id from the list' do list.add(elem) expect(list.length).to eq(1) - expect{list.remove(elem)}.to change{list.length}.by(-1) - .and change{list.store_for(elem)}.from(list).to(nil) + expect { list.remove(elem) }.to change { list.length }.by(-1) + .and change { list.store_for(elem) }.from(list).to(nil) expect(list.to_a).to eq([]) end end @@ -237,8 +237,8 @@ let(:list3) { ChangesSupport::DisjointList.new([]) } it 'adds the list to the disjoint lists' do - expect{list.add_disjoint_list(list2)}.to change{list.disjoint_lists}.from([list]).to([list,list2]) - .and change{list2.disjoint_lists}.from([list2]).to([list,list2]) + expect { list.add_disjoint_list(list2) }.to change { list.disjoint_lists }.from([list]).to([list,list2]) + .and change { list2.disjoint_lists }.from([list2]).to([list,list2]) end it 'sets up a shared list of disjoint lists for all added instances' do @@ -246,7 +246,7 @@ expect(list.disjoint_lists).to be(list2.disjoint_lists) list3 = ChangesSupport::DisjointList.new([]) - expect{list3.add_disjoint_list(list2)}.to change{list.disjoint_lists}.from([list,list2]).to([list3,list,list2]) + expect { list3.add_disjoint_list(list2) }.to change { list.disjoint_lists }.from([list,list2]).to([list3,list,list2]) end it 'sets up a common list of locations for all added instances' do @@ -254,7 +254,7 @@ list3.add_disjoint_list(list2) expect(list.location_for_unique_id).to be(list2.location_for_unique_id) expect(list3.location_for_unique_id).to be(list.location_for_unique_id) - expect{list.add(elem)}.to change{list3.location_for_unique_id.keys.length}.by(1) + expect { list.add(elem) }.to change { list3.location_for_unique_id.keys.length }.by(1) end it 'disables all elements already disabled in the added list' do @@ -264,7 +264,7 @@ list3.add(elem) expect(list2.disabled?(elem)).to eq(true) expect(list.disabled?(elem)).to eq(false) - expect{list.add_disjoint_list(list2)}.to change{list.disabled?(elem)}.from(false).to(true) + expect { list.add_disjoint_list(list2) }.to change { list.disabled?(elem) }.from(false).to(true) end it 'removes the element if already present in my opposite list' do @@ -283,20 +283,20 @@ let(:list) { ChangesSupport::DisjointList.new([]) } let(:elem) { 'a value' } it 'returns true if the element was already added' do - expect{list.add(elem)}.to change{list.include?(elem)}.from(false).to(true) + expect { list.add(elem) }.to change { list.include?(elem) }.from(false).to(true) end it 'returns false if the element is not on the list' do expect(list.include?(elem)).to eq(false) list.add(elem) - expect{list.remove(elem)}.to change{list.include?(elem)}.from(true).to(false) + expect { list.remove(elem) }.to change { list.include?(elem) }.from(true).to(false) end end describe '#merge' do - let(:disjoint1) { ChangesSupport::DisjointList.new([])} - let(:disjoint2) { ChangesSupport::DisjointList.new([])} - let(:disjoint3) { ChangesSupport::DisjointList.new([])} - let(:disjoint4) { ChangesSupport::DisjointList.new([])} + let(:disjoint1) { ChangesSupport::DisjointList.new([]) } + let(:disjoint2) { ChangesSupport::DisjointList.new([]) } + let(:disjoint3) { ChangesSupport::DisjointList.new([]) } + let(:disjoint4) { ChangesSupport::DisjointList.new([]) } let(:list2) { ChangesSupport::DisjointList.new(facts_to_destroy) } @@ -311,7 +311,7 @@ disjoint1 << 'green' disjoint4 << 'green' - expect{disjoint1.merge(disjoint3)}.to change{disjoint1.length}.by(-1) + expect { disjoint1.merge(disjoint3) }.to change { disjoint1.length }.by(-1) end it 'merges from different objects' do @@ -392,11 +392,11 @@ end context 'when merging a chain of objects' do - let(:winners) { 6.times.map{ChangesSupport::DisjointList.new([])} } - let(:losers) { 6.times.map{ChangesSupport::DisjointList.new([])} } - let(:list) { winners.zip(losers).map{|l| + let(:winners) { 6.times.map { ChangesSupport::DisjointList.new([]) } } + let(:losers) { 6.times.map { ChangesSupport::DisjointList.new([]) } } + let(:list) { winners.zip(losers).map { |l| l[0].add_disjoint_list(l[1]) - {winner: l[0], loser: l[1]}} + { winner: l[0], loser: l[1] }} } it 'keeps track of all restrictions until the final list' do @@ -432,13 +432,13 @@ it 'adds all elements in both lists if no restrictions are found' do disjoint1 << 'green' disjoint3 << 'blue' - expect{disjoint1.merge(disjoint3)}.to change{disjoint1.to_a}.from(['green']).to(['green', 'blue']) + expect { disjoint1.merge(disjoint3) }.to change { disjoint1.to_a }.from(['green']).to(['green', 'blue']) end it 'adds new elements keeping duplicates unique' do disjoint1 << ['green', 'red', 'white'] disjoint3 << ['blue', 'red', 'white'] - expect{disjoint1.merge(disjoint3)}.to change{ + expect { disjoint1.merge(disjoint3) }.to change { disjoint1.to_a.sort}.from(['green', 'red', 'white']).to(["blue", "green", "red", "white"]) end diff --git a/spec/lib/changes_support/transaction_scope_spec.rb b/spec/lib/changes_support/transaction_scope_spec.rb index c2e14b5d..f0297059 100644 --- a/spec/lib/changes_support/transaction_scope_spec.rb +++ b/spec/lib/changes_support/transaction_scope_spec.rb @@ -12,7 +12,7 @@ end describe 'TransactionScope::ModelAccessor' do - let(:accessor) { updates.transaction_scope(Asset)} + let(:accessor) { updates.transaction_scope(Asset) } context '#where' do it 'returns data from the database' do asset = create :asset @@ -47,7 +47,7 @@ updates.add(uuid, 'is', 'Full') updates.add(uuid2, 'is', 'Empty') updates.add(uuid3, 'a', 'Tube') - expect(accessor.joins(:facts).where(facts: {predicate: 'a', object: 'Tube'}).map(&:uuid)).to eq([uuid, uuid3]) + expect(accessor.joins(:facts).where(facts: { predicate: 'a', object: 'Tube' }).map(&:uuid)).to eq([uuid, uuid3]) end end context 'when the condition is met in the database' do @@ -59,7 +59,7 @@ asset2.facts << create(:fact, predicate: 'is', object: 'Full') asset3.facts << create(:fact, predicate: 'is', object: 'Empty') asset3.facts << create(:fact, predicate: 'a', object: 'Tube') - expect(accessor.joins(:facts).where(facts: {predicate: 'a', object: 'Tube'}).map(&:uuid)).to eq([ + expect(accessor.joins(:facts).where(facts: { predicate: 'a', object: 'Tube' }).map(&:uuid)).to eq([ asset1.uuid, asset3.uuid ]) end @@ -75,7 +75,7 @@ updates.add(uuid2, 'is', 'Empty') asset3.facts << create(:fact, predicate: 'is', object: 'Empty') asset3.facts << create(:fact, predicate: 'a', object: 'Tube') - expect(accessor.joins(:facts).where(facts: {predicate: 'a', object: 'Tube'}).map(&:uuid).sort).to eq([uuid, asset3.uuid].sort) + expect(accessor.joins(:facts).where(facts: { predicate: 'a', object: 'Tube' }).map(&:uuid).sort).to eq([uuid, asset3.uuid].sort) end it 'can join with different models with removed data' do uuid = "fdd84c08-2aa3-4e3f-a39c-06ad35228d00" @@ -88,7 +88,7 @@ asset3.facts << create(:fact, predicate: 'is', object: 'Empty') asset3.facts << create(:fact, predicate: 'a', object: 'Tube') updates.remove_where(asset3.uuid, 'a', 'Tube') - expect(accessor.joins(:facts).where(facts: {predicate: 'a', object: 'Tube'}).map(&:uuid)).to eq([uuid]) + expect(accessor.joins(:facts).where(facts: { predicate: 'a', object: 'Tube' }).map(&:uuid)).to eq([uuid]) end end end diff --git a/spec/lib/fact_changes_spec.rb b/spec/lib/fact_changes_spec.rb index 265dbcda..0a527f98 100644 --- a/spec/lib/fact_changes_spec.rb +++ b/spec/lib/fact_changes_spec.rb @@ -15,7 +15,7 @@ let(:fact1) { create :fact, asset: asset1, predicate: property, object: value } let(:fact2) { create :fact, asset: asset1, predicate: relation, object_asset: asset2 } let(:step) { create :step, activity: activity, state: Step::STATE_RUNNING } - let(:json) { {:"create_assets" => ["?p", "?q"], :"add_facts" => [["?p", "a", "Plate"]]}.to_json } + let(:json) { { :"create_assets" => ["?p", "?q"], :"add_facts" => [["?p", "a", "Plate"]] }.to_json } describe '#new' do it 'parses a json and loads the config from it' do @@ -58,7 +58,7 @@ describe '#parse_json' do let(:updates) { FactChanges.new } it 'raises exception when the parsed object is not right' do - expect{ + expect { updates.parse_json("something went wrong!") }.to raise_error(StandardError) end @@ -86,7 +86,7 @@ end context 'when loading different json' do - let(:updates) {FactChanges.new} + let(:updates) { FactChanges.new } it 'loads created assets' do uuid = SecureRandom.uuid json = { create_assets: [uuid] }.to_json @@ -127,13 +127,13 @@ end it 'loads facts to add' do asset = Asset.create - json = {add_facts: [[asset.uuid, 'is', 'Cool']]}.to_json + json = { add_facts: [[asset.uuid, 'is', 'Cool']] }.to_json expect(updates.parse_json(json)).to eq(true) expect(updates.facts_to_add.length).to eq(1) end it 'loads removed facts' do asset = Asset.create - json = {remove_facts: [[asset.uuid, 'is', 'Cool']]}.to_json + json = { remove_facts: [[asset.uuid, 'is', 'Cool']] }.to_json expect(updates.parse_json(json)).to eq(true) expect(updates.facts_to_destroy.length).to eq(1) end @@ -149,9 +149,9 @@ end describe '#to_h' do - let(:updates) {FactChanges.new} + let(:updates) { FactChanges.new } it 'generates a hash' do - expect{updates.to_h}.not_to raise_error + expect { updates.to_h }.not_to raise_error end it 'creates assets and adds them to the hash' do uuid = SecureRandom.uuid @@ -211,38 +211,38 @@ context 'when the object contains errors' do it 'stores the messages and throws an exception' do updates1.set_errors(["hi"]) - expect{updates1.apply(step)}.to raise_error(StandardError) + expect { updates1.apply(step) }.to raise_error(StandardError) end end context 'with add' do it 'applies a new added property' do updates1.add(asset1, property, value) - expect{ + expect { updates1.apply(step) - }.to change{asset1.facts.count}.by(1) - .and change{Operation.count}.by(1) + }.to change { asset1.facts.count }.by(1) + .and change { Operation.count }.by(1) end it 'applies a new added relation' do updates1.add(asset1, relation, asset2) - expect{ + expect { updates1.apply(step) - }.to change{asset1.facts.count}.by(1) - .and change{Operation.count}.by(1) + }.to change { asset1.facts.count }.by(1) + .and change { Operation.count }.by(1) end it 'is able to add facts to assets created before' do updates1.create_assets(['?p']) updates1.add('?p', property, value) - expect{updates1.apply(step)}.to change{Asset.count}.by(1) - .and change{Fact.count}.by(1) + expect { updates1.apply(step) }.to change { Asset.count }.by(1) + .and change { Fact.count }.by(1) end end context 'with add_remote' do it 'adds a new remote fact' do updates1.add_remote(asset1, relation, asset2) - expect{ + expect { updates1.apply(step) - }.to change{asset1.facts.count}.by(1) - .and change{Operation.count}.by(1) + }.to change { asset1.facts.count }.by(1) + .and change { Operation.count }.by(1) expect(asset1.facts.first.is_remote?).to eq(true) end @@ -250,10 +250,10 @@ context 'with replace_remote' do it 'adds a new remote fact if it does not exist' do updates1.replace_remote(asset1, relation, asset2) - expect{ + expect { updates1.apply(step) - }.to change{asset1.facts.count}.by(1) - .and change{Operation.count}.by(1) + }.to change { asset1.facts.count }.by(1) + .and change { Operation.count }.by(1) expect(asset1.facts.count).to eq(1) expect(asset1.facts.first.is_remote?).to eq(true) end @@ -264,10 +264,10 @@ updates1.replace_remote(asset1, relation, asset2) asset1.facts.reload - expect{ + expect { updates1.apply(step) - }.to change{asset1.facts.count}.by(0) - .and change{Operation.count}.by(2) + }.to change { asset1.facts.count }.by(0) + .and change { Operation.count }.by(2) asset1.facts.reload expect(asset1.facts.count).to eq(1) @@ -278,39 +278,39 @@ it 'removes an already existing fact' do asset1.facts << fact1 updates1.remove(fact1) - expect{ + expect { updates1.apply(step) - }.to change{asset1.facts.count}.by(-1) - .and change{Operation.count}.by(1) + }.to change { asset1.facts.count }.by(-1) + .and change { Operation.count }.by(1) end end context 'with remove_where' do - let(:fact2) { create(:fact, predicate: 'cond1', object: 'val')} - let(:fact3) { create(:fact, predicate: 'cond2', object: 'val')} - let(:fact4) { create(:fact, predicate: 'cond1', object: 'val')} + let(:fact2) { create(:fact, predicate: 'cond1', object: 'val') } + let(:fact3) { create(:fact, predicate: 'cond2', object: 'val') } + let(:fact4) { create(:fact, predicate: 'cond1', object: 'val') } it 'removes facts with a condition' do asset1.facts << [fact1, fact2, fact3, fact4] updates1.remove_where(asset1, 'cond1', 'val') - expect{ + expect { updates1.apply(step) - }.to change{asset1.facts.count}.by(-2) - .and change{Operation.count}.by(2) + }.to change { asset1.facts.count }.by(-2) + .and change { Operation.count }.by(2) end end context 'with create_assets' do it 'creates the assets provided' do updates1.create_assets(["?p", "?q", "?r"]) - expect{updates1.apply(step)}.to change{Asset.count}.by(3) - .and change{Operation.count}.by(3) + expect { updates1.apply(step) }.to change { Asset.count }.by(3) + .and change { Operation.count }.by(3) end end context 'with delete_assets' do - let(:facts1) { create :fact, predicate: 'color', object: 'red'} - let(:facts2) { create :fact, predicate: 'color', object: 'blue'} + let(:facts1) { create :fact, predicate: 'color', object: 'red' } + let(:facts2) { create :fact, predicate: 'color', object: 'blue' } let(:asset3) { create(:asset, facts: [facts1]) } let(:asset4) { create(:asset, facts: [facts2]) } let(:asset_group) { create :asset_group, assets: [asset3, asset4] } @@ -318,45 +318,45 @@ updates1.delete_assets(asset_group.assets) end it 'does not really remove the assets' do - expect{updates1.apply(step)}.to change{Asset.count}.by(0).and change{Operation.count}.by(2) + expect { updates1.apply(step) }.to change { Asset.count }.by(0).and change { Operation.count }.by(2) end it 'removes the facts for the assets' do - expect{updates1.apply(step)}.to change{asset3.facts.count}.by(-1) - .and change{asset4.facts.count}.by(-1) + expect { updates1.apply(step) }.to change { asset3.facts.count }.by(-1) + .and change { asset4.facts.count }.by(-1) end it 'detaches the assets from any groups' do - expect{updates1.apply(step)}.to change{asset3.asset_groups.count}.by(-1) - .and change{asset4.asset_groups.count}.by(-1) + expect { updates1.apply(step) }.to change { asset3.asset_groups.count }.by(-1) + .and change { asset4.asset_groups.count }.by(-1) end end context 'with add_assets' do - let(:asset1) { Asset.create(uuid: SecureRandom.uuid)} - let(:asset2) { Asset.create(uuid: SecureRandom.uuid)} - let(:asset_group) { AssetGroup.create(uuid: SecureRandom.uuid)} + let(:asset1) { Asset.create(uuid: SecureRandom.uuid) } + let(:asset2) { Asset.create(uuid: SecureRandom.uuid) } + let(:asset_group) { AssetGroup.create(uuid: SecureRandom.uuid) } it 'adds the assets to the asset group' do updates1.add_assets([[asset_group, [asset1.uuid, asset2.uuid]]]) - expect{updates1.apply(step)}.to change{asset_group.assets.count}.by(2) - .and change{Operation.count}.by(2) + expect { updates1.apply(step) }.to change { asset_group.assets.count }.by(2) + .and change { Operation.count }.by(2) end end context 'with remove_assets' do - let(:asset1) { Asset.create(uuid: SecureRandom.uuid)} - let(:asset2) { Asset.create(uuid: SecureRandom.uuid)} - let(:asset_group) { AssetGroup.create(uuid: SecureRandom.uuid)} + let(:asset1) { Asset.create(uuid: SecureRandom.uuid) } + let(:asset2) { Asset.create(uuid: SecureRandom.uuid) } + let(:asset_group) { AssetGroup.create(uuid: SecureRandom.uuid) } it 'removes the assets to the asset group' do asset_group.assets << [asset1, asset2] updates1.remove_assets([[asset_group, [asset1.uuid, asset2.uuid]]]) - expect{updates1.apply(step)}.to change{asset_group.assets.count}.by(-2) - .and change{Operation.count}.by(2) + expect { updates1.apply(step) }.to change { asset_group.assets.count }.by(-2) + .and change { Operation.count }.by(2) end end end describe '#add' do it 'raises error if we use a wildcard not created before' do - expect{updates1.add("?p", property, value)}.to raise_error(StandardError) + expect { updates1.add("?p", property, value) }.to raise_error(StandardError) end it 'adds a new property' do expect(updates1.facts_to_add.length).to eq(0) @@ -381,7 +381,7 @@ let(:uuid) { SecureRandom.uuid } it 'does not add the property if the uuid is not quoted because it tries to find it in local' do expect(updates1.facts_to_add.length).to eq(0) - expect{updates1.add(asset1, property, uuid)}.to raise_error(StandardError) + expect { updates1.add(asset1, property, uuid) }.to raise_error(StandardError) end it 'adds the property when quoted' do expect(updates1.facts_to_add.length).to eq(0) @@ -461,7 +461,7 @@ end it 'does not add the property to remove if the uuid is not quoted because it tries to find it' do expect(updates1.facts_to_destroy.length).to eq(0) - expect{updates1.remove_where(fact1.asset, fact1.predicate, uuid)}.to raise_error(StandardError) + expect { updates1.remove_where(fact1.asset, fact1.predicate, uuid) }.to raise_error(StandardError) end end end @@ -530,7 +530,7 @@ expect(updates1.assets_to_create.length).to eq(2) end it 'does not raise error when referring to an asset not referred before' do - expect{updates1.create_assets([SecureRandom.uuid])}.not_to raise_error + expect { updates1.create_assets([SecureRandom.uuid]) }.not_to raise_error end end @@ -545,16 +545,16 @@ expect(updates1.asset_groups_to_create.length).to eq(2) end it 'does not raise error when referring to an asset not referred before' do - expect{updates1.create_asset_groups([SecureRandom.uuid])}.not_to raise_error + expect { updates1.create_asset_groups([SecureRandom.uuid]) }.not_to raise_error end end describe '#delete_assets' do - let(:asset1) { Asset.create(uuid: SecureRandom.uuid)} - let(:asset2) { Asset.create(uuid: SecureRandom.uuid)} - let(:asset3) { Asset.create(uuid: SecureRandom.uuid)} + let(:asset1) { Asset.create(uuid: SecureRandom.uuid) } + let(:asset2) { Asset.create(uuid: SecureRandom.uuid) } + let(:asset3) { Asset.create(uuid: SecureRandom.uuid) } it 'adds the list to the assets to destroy' do updates1.delete_assets([asset1.uuid, asset2.uuid, asset3.uuid]) expect(updates1.assets_to_destroy.length).to eq(3) @@ -564,14 +564,14 @@ expect(updates1.assets_to_destroy.length).to eq(2) end it 'raises error when referring to an asset not referred before ' do - expect{updates1.delete_assets([SecureRandom.uuid])}.to raise_error(StandardError) + expect { updates1.delete_assets([SecureRandom.uuid]) }.to raise_error(StandardError) end end describe '#delete_asset_groups' do - let(:asset_group1) { AssetGroup.create(uuid: SecureRandom.uuid)} - let(:asset_group2) { AssetGroup.create(uuid: SecureRandom.uuid)} - let(:asset_group3) { AssetGroup.create(uuid: SecureRandom.uuid)} + let(:asset_group1) { AssetGroup.create(uuid: SecureRandom.uuid) } + let(:asset_group2) { AssetGroup.create(uuid: SecureRandom.uuid) } + let(:asset_group3) { AssetGroup.create(uuid: SecureRandom.uuid) } it 'adds the list to the asset groups to destroy' do updates1.delete_asset_groups([asset_group1.uuid, asset_group2.uuid, asset_group3.uuid]) expect(updates1.asset_groups_to_destroy.length).to eq(3) @@ -581,14 +581,14 @@ expect(updates1.asset_groups_to_destroy.length).to eq(2) end it 'raises error when referring to an asset not referred before ' do - expect{updates1.delete_asset_groups([SecureRandom.uuid])}.to raise_error(StandardError) + expect { updates1.delete_asset_groups([SecureRandom.uuid]) }.to raise_error(StandardError) end end describe '#add_assets' do - let(:asset1) { Asset.create(uuid: SecureRandom.uuid)} - let(:asset2) { Asset.create(uuid: SecureRandom.uuid)} - let(:asset_group) { AssetGroup.create(uuid: SecureRandom.uuid)} + let(:asset1) { Asset.create(uuid: SecureRandom.uuid) } + let(:asset2) { Asset.create(uuid: SecureRandom.uuid) } + let(:asset_group) { AssetGroup.create(uuid: SecureRandom.uuid) } it 'adds the changes to the list of assets to add one for each asset' do updates1.add_assets([[asset_group, [asset1.uuid, asset2.uuid]]]) expect(updates1.assets_to_add.length).to eq(2) @@ -598,15 +598,15 @@ expect(updates1.assets_to_add.length).to eq(1) end it 'raises error when referring to an asset group not referred before ' do - expect{updates1.add_assets([[SecureRandom.uuid, [asset1.uuid, asset2.uuid]]])}.to raise_error(StandardError) + expect { updates1.add_assets([[SecureRandom.uuid, [asset1.uuid, asset2.uuid]]]) }.to raise_error(StandardError) end end describe '#remove_assets' do - let(:asset1) { Asset.create(uuid: SecureRandom.uuid)} - let(:asset2) { Asset.create(uuid: SecureRandom.uuid)} - let(:asset_group) { AssetGroup.create(uuid: SecureRandom.uuid)} + let(:asset1) { Asset.create(uuid: SecureRandom.uuid) } + let(:asset2) { Asset.create(uuid: SecureRandom.uuid) } + let(:asset_group) { AssetGroup.create(uuid: SecureRandom.uuid) } it 'adds the changes to the list of assets to add one for each asset' do updates1.remove_assets([[asset_group, [asset1.uuid, asset2.uuid]]]) expect(updates1.assets_to_remove.length).to eq(2) @@ -616,7 +616,7 @@ expect(updates1.assets_to_remove.length).to eq(1) end it 'raises error when referring to an asset group not referred before ' do - expect{updates1.remove_assets([[SecureRandom.uuid, [asset1.uuid, asset2.uuid]]])}.to raise_error(StandardError) + expect { updates1.remove_assets([[SecureRandom.uuid, [asset1.uuid, asset2.uuid]]]) }.to raise_error(StandardError) end end @@ -666,7 +666,7 @@ updates1.merge(updates2) - expect(updates1.to_h).to eq({add_facts: [[p.uuid, 'anotherRel', q.uuid]]}) + expect(updates1.to_h).to eq({ add_facts: [[p.uuid, 'anotherRel', q.uuid]] }) end it 'keeps track of disabled changes after merging an object' do p = create :asset @@ -683,10 +683,10 @@ updates1.add(q, 'anotherRel', p) - expect(updates1.to_h).to eq({add_facts: [ + expect(updates1.to_h).to eq({ add_facts: [ [p.uuid, 'anotherRel', q.uuid], [q.uuid, 'anotherRel', p.uuid] - ]}) + ] }) end it 'disables an element because of changes merged' do p = create :asset @@ -749,14 +749,14 @@ }) end context 'when using wildcards' do - let(:obj) {FactChanges.new} - let(:obj2) { FactChanges.new} + let(:obj) { FactChanges.new } + let(:obj2) { FactChanges.new } before do obj.create_assets(["?p"]) obj2.merge(obj) end it 'merges wildcards used in other objects' do - expect{ + expect { obj2.add("?p", "a", "Tube") }.not_to raise_error end @@ -828,13 +828,13 @@ end let(:updates) { FactChanges.new } it 'creates new asset groups' do - expect{updates.apply(step)}.to change{AssetGroup.count}.by(2) + expect { updates.apply(step) }.to change { AssetGroup.count }.by(2) end it 'adds the asset group to the activity this step belongs to' do - expect{updates.apply(step)}.to change{activity.owned_asset_groups.count}.by(2) + expect { updates.apply(step) }.to change { activity.owned_asset_groups.count }.by(2) end it 'creates as many operations as asset groups created' do - expect{updates.apply(step)}.to change{Operation.all.count}.by(2) + expect { updates.apply(step) }.to change { Operation.all.count }.by(2) end context 'when the group is created with wildcard' do it 'adds the wildcard as the name of the asset group' do @@ -849,14 +849,14 @@ let(:updates2) { FactChanges.new } it 'uses that uuid and does not create any group' do updates2.create_asset_groups([asset_group.uuid]) - expect{updates2.apply(step)}.to change{AssetGroup.count}.by(0) + expect { updates2.apply(step) }.to change { AssetGroup.count }.by(0) end end context 'when the uuid does not refer anything already in database' do let(:updates2) { FactChanges.new } it 'uses that uuid and does not create any group' do updates2.create_asset_groups([SecureRandom.uuid]) - expect{updates2.apply(step)}.to change{AssetGroup.count}.by(1) + expect { updates2.apply(step) }.to change { AssetGroup.count }.by(1) end end end @@ -865,14 +865,14 @@ let(:asset_group) { create :asset_group } it 'uses that group' do updates2.create_asset_groups([asset_group]) - expect{updates2.apply(step)}.to change{AssetGroup.count}.by(0) + expect { updates2.apply(step) }.to change { AssetGroup.count }.by(0) end end end context 'with delete_asset_groups' do - let(:asset_group1){ create :asset_group, activity_owner: activity } - let(:asset_group2){ create :asset_group, activity_owner: activity} + let(:asset_group1) { create :asset_group, activity_owner: activity } + let(:asset_group2) { create :asset_group, activity_owner: activity } let(:json) { { create_asset_groups: ['?p'] }.to_json } let(:updates) { FactChanges.new } before do @@ -880,13 +880,13 @@ activity.asset_group end it 'DOES NOT remove the specified asset groups' do - expect{updates.apply(step)}.to change{AssetGroup.count}.by(0) + expect { updates.apply(step) }.to change { AssetGroup.count }.by(0) end it 'removes the asset group from the activity' do - expect{updates.apply(step)}.to change{activity.owned_asset_groups.count}.by(-2) + expect { updates.apply(step) }.to change { activity.owned_asset_groups.count }.by(-2) end it 'creates as many operations as asset groups deleted' do - expect{updates.apply(step)}.to change{Operation.all.count}.by(2) + expect { updates.apply(step) }.to change { Operation.all.count }.by(2) end end @@ -896,35 +896,35 @@ end let(:updates) { FactChanges.new } it 'creates new assets' do - expect{updates.apply(step)}.to change{Asset.count}.by(2) + expect { updates.apply(step) }.to change { Asset.count }.by(2) end it 'creates as many operations as assets created' do - expect{updates.apply(step)}.to change{Operation.all.count}.by(2) + expect { updates.apply(step) }.to change { Operation.all.count }.by(2) end end context 'with delete_assets' do - let(:asset1){ create :asset } - let(:asset2){ create :asset} - let(:asset_group) { create :asset_group, assets: [asset1, asset2]} + let(:asset1) { create :asset } + let(:asset2) { create :asset } + let(:asset_group) { create :asset_group, assets: [asset1, asset2] } let(:updates) { FactChanges.new } before do updates.delete_assets(asset_group.assets.map(&:uuid)) end it 'does not remove the specified assets' do - expect{updates.apply(step)}.to change{Asset.count}.by(0) + expect { updates.apply(step) }.to change { Asset.count }.by(0) end it 'does remove the assets from the asset groups' do - expect{updates.apply(step)}.to change{asset1.asset_groups.count}.by(-1) - .and change{asset2.asset_groups.count}.by(-1) + expect { updates.apply(step) }.to change { asset1.asset_groups.count }.by(-1) + .and change { asset2.asset_groups.count }.by(-1) end it 'creates as many operations as assets deleted' do - expect{updates.apply(step)}.to change{Operation.all.count}.by(2) + expect { updates.apply(step) }.to change { Operation.all.count }.by(2) end end context 'with add_assets' do let(:asset_group) { create :asset_group } - let(:assets){ 2.times.map{ create :asset } } + let(:assets) { 2.times.map { create :asset } } let(:updates) { FactChanges.new } before do step.update_attributes(asset_group: create(:asset_group)) @@ -935,10 +935,10 @@ updates.add_assets([[asset_group, assets]]) end it 'adds the asset to the asset group' do - expect{ updates.apply(step) }.to change{asset_group.assets.count}.by(2) + expect { updates.apply(step) }.to change { asset_group.assets.count }.by(2) end it 'adds one operation for each asset added' do - expect{ updates.apply(step) }.to change{Operation.count}.by(2) + expect { updates.apply(step) }.to change { Operation.count }.by(2) end end context 'when only one list of assets is provided' do @@ -946,17 +946,17 @@ updates.add_assets([assets]) end it 'adds the asset to the asset group of the step' do - expect{ updates.apply(step) }.to change{step.asset_group.assets.count}.by(2) + expect { updates.apply(step) }.to change { step.asset_group.assets.count }.by(2) end it 'adds one operation for each asset added' do - expect{ updates.apply(step) }.to change{Operation.count}.by(2) + expect { updates.apply(step) }.to change { Operation.count }.by(2) end end end context 'with remove_assets' do let(:asset_group) { create :asset_group } - let(:assets){ 2.times.map{ create :asset } } + let(:assets) { 2.times.map { create :asset } } let(:updates) { FactChanges.new } before do step.update_attributes(asset_group: create(:asset_group)) @@ -968,10 +968,10 @@ updates.remove_assets([[asset_group, assets]]) end it 'removes the assets from the asset group' do - expect{ updates.apply(step) }.to change{asset_group.assets.count}.by(-2) + expect { updates.apply(step) }.to change { asset_group.assets.count }.by(-2) end it 'adds one operation for each asset removed' do - expect{ updates.apply(step) }.to change{Operation.count}.by(2) + expect { updates.apply(step) }.to change { Operation.count }.by(2) end end context 'when an asset group and a list of assets is provided' do @@ -980,10 +980,10 @@ updates.remove_assets([assets]) end it 'removes the assets from the asset group of the step' do - expect{ updates.apply(step) }.to change{step.asset_group.assets.count}.by(-2) + expect { updates.apply(step) }.to change { step.asset_group.assets.count }.by(-2) end it 'adds one operation for each asset removed' do - expect{ updates.apply(step) }.to change{Operation.count}.by(2) + expect { updates.apply(step) }.to change { Operation.count }.by(2) end end end @@ -996,8 +996,8 @@ updates.add(asset1, "related", asset2) updates.add(asset1, "transfer", asset2) updates.remove_where(asset1, "transfer", asset2) - expect{updates.apply(step)}.to change{Fact.with_predicate('related').count}.by(1) - .and change{Fact.with_predicate('transfer').count}.by(0) + expect { updates.apply(step) }.to change { Fact.with_predicate('related').count }.by(1) + .and change { Fact.with_predicate('transfer').count }.by(0) end end context 'when you add a fact and remove an specific fact that complies the added one' do @@ -1008,7 +1008,7 @@ updates.add(asset1, "related", asset2) updates.remove(fact) - expect{updates.apply(step)}.to change{Fact.with_predicate('related').count}.by(0) + expect { updates.apply(step) }.to change { Fact.with_predicate('related').count }.by(0) end end end @@ -1023,10 +1023,10 @@ updates.add("?p", "related", "?q") updates.add("?p", "transfer", "?q") updates.remove_where("?p", "transfer", "?q") - expect{updates.apply(step)}.to change{Asset.count}.by(2) - .and change{Fact.count}.by(1) - .and change{Fact.with_predicate('related').count}.by(1) - .and change{Fact.with_predicate('transfer').count}.by(0) + expect { updates.apply(step) }.to change { Asset.count }.by(2) + .and change { Fact.count }.by(1) + .and change { Fact.with_predicate('related').count }.by(1) + .and change { Fact.with_predicate('transfer').count }.by(0) end end it 'performs all the changes specified' do @@ -1036,10 +1036,10 @@ updates.create_asset_groups(["?group1"]) updates.add_assets([["?group1", ["?p", "?q"]]]) - expect{updates.apply(step)}.to change{Asset.count}.by(2) - .and change{AssetGroup.count}.by(1) - .and change{AssetGroupsAsset.count}.by(2) - .and change{activity.owned_asset_groups.count}.by(1) + expect { updates.apply(step) }.to change { Asset.count }.by(2) + .and change { AssetGroup.count }.by(1) + .and change { AssetGroupsAsset.count }.by(2) + .and change { activity.owned_asset_groups.count }.by(1) expect(activity.owned_asset_groups.last.assets.first.facts.first.object).to eq("Plate") end end diff --git a/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb b/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb index b45b477a..21eda023 100644 --- a/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb @@ -26,12 +26,12 @@ def validate(record) end let(:barcode) { '1234' } - let(:location) { 'A10'} - let(:input) {[location, barcode]} + let(:location) { 'A10' } + let(:input) { [location, barcode] } context '#initialize' do let(:parser) { Parsers::CsvLayout::BarcodeCreatableParser.new(input, main_parser) } it 'can be initialized' do - expect{parser.barcode}.not_to raise_error + expect { parser.barcode }.not_to raise_error end it 'returns the barcode' do expect(parser.barcode).to eq(barcode) diff --git a/spec/lib/parsers/csv_layout/barcode_parser_spec.rb b/spec/lib/parsers/csv_layout/barcode_parser_spec.rb index 762dcb5d..12946088 100644 --- a/spec/lib/parsers/csv_layout/barcode_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/barcode_parser_spec.rb @@ -25,12 +25,12 @@ def validate(record) end let(:barcode) { '1234' } - let(:location) { 'A10'} - let(:input) {[location, barcode]} + let(:location) { 'A10' } + let(:input) { [location, barcode] } context '#initialize' do let(:parser) { Parsers::CsvLayout::BarcodeParser.new(input, main_parser) } it 'can be initialized' do - expect{parser.barcode}.not_to raise_error + expect { parser.barcode }.not_to raise_error end it 'returns the barcode' do expect(parser.barcode).to eq(barcode) diff --git a/spec/lib/parsers/csv_layout/csv_parser_spec.rb b/spec/lib/parsers/csv_layout/csv_parser_spec.rb index df78b933..e2c42704 100644 --- a/spec/lib/parsers/csv_layout/csv_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/csv_parser_spec.rb @@ -9,9 +9,9 @@ RSpec.describe Parsers::CsvLayout::CsvParser do describe "parses a layout" do - let(:activity) { create(:activity)} + let(:activity) { create(:activity) } let(:asset_group) { create(:asset_group) } - let(:step_type) {create(:step_type)} + let(:step_type) { create(:step_type) } let(:step) { create :step, activity: activity, state: Step::STATE_RUNNING, diff --git a/spec/lib/parsers/csv_layout/line_parser_spec.rb b/spec/lib/parsers/csv_layout/line_parser_spec.rb index a9cd3d14..1df5913a 100644 --- a/spec/lib/parsers/csv_layout/line_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/line_parser_spec.rb @@ -35,7 +35,7 @@ context '#initialize' do it 'can be initialized' do @input = [["A1", @asset1.barcode]] - expect{parser}.not_to raise_error + expect { parser }.not_to raise_error end end @@ -49,40 +49,40 @@ @input = [["A1","F1234"],["A2","F5678"]] expect(parser).to be_valid expect(parser.parsed_data).to eq([ - {location: "A01", asset: @asset1}, - {location: "A02", asset: @asset2} + { location: "A01", asset: @asset1 }, + { location: "A02", asset: @asset2 } ]) end it 'filters empty lines' do @input = [["A1","F1234"],[],["A2","F5678"]] expect(parser).to be_valid expect(parser.parsed_data).to eq([ - {location: "A01", asset: @asset1}, - {location: "A02", asset: @asset2} + { location: "A01", asset: @asset1 }, + { location: "A02", asset: @asset2 } ]) end it 'filters nil lines' do @input = [["A1","F1234"],nil,["A2","F5678"]] expect(parser).to be_valid expect(parser.parsed_data).to eq([ - {location: "A01", asset: @asset1}, - {location: "A02", asset: @asset2} + { location: "A01", asset: @asset1 }, + { location: "A02", asset: @asset2 } ]) end it 'filters nil empty lines' do @input = [["A1","F1234"],[nil, nil],["A2","F5678"]] expect(parser).to be_valid expect(parser.parsed_data).to eq([ - {location: "A01", asset: @asset1}, - {location: "A02", asset: @asset2} + { location: "A01", asset: @asset1 }, + { location: "A02", asset: @asset2 } ]) end it 'filters no read barcodes' do @input = [["A1","F1234"],["B01", "No read"],["A2","F5678"]] expect(parser).to be_valid expect(parser.parsed_data).to eq([ - {location: "A01", asset: @asset1}, - {location: "A02", asset: @asset2} + { location: "A01", asset: @asset1 }, + { location: "A02", asset: @asset2 } ]) end end diff --git a/spec/lib/parsers/csv_layout/line_reader_spec.rb b/spec/lib/parsers/csv_layout/line_reader_spec.rb index da3b139d..26ed4250 100644 --- a/spec/lib/parsers/csv_layout/line_reader_spec.rb +++ b/spec/lib/parsers/csv_layout/line_reader_spec.rb @@ -2,7 +2,7 @@ require 'parsers/csv_layout/line_reader' RSpec.describe Parsers::CsvLayout::LineReader do - let(:parserClass) { Parsers::CsvLayout::LineReader} + let(:parserClass) { Parsers::CsvLayout::LineReader } let(:result) { [["A01","1234"],["B01", "4567"],["C01","8901"]] } it 'recognises line feed for new line' do expect(parserClass.new("A01,1234\nB01,4567\nC01,8901").lines).to eq(result) diff --git a/spec/lib/parsers/csv_layout/location_parser_spec.rb b/spec/lib/parsers/csv_layout/location_parser_spec.rb index 2974940c..14a24c2e 100644 --- a/spec/lib/parsers/csv_layout/location_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/location_parser_spec.rb @@ -13,12 +13,12 @@ main } let(:barcode) { '1234' } - let(:location) { 'A10'} - let(:input) {[location, barcode]} + let(:location) { 'A10' } + let(:input) { [location, barcode] } context '#initialize' do let(:parser) { Parsers::CsvLayout::LocationParser.new(input, main_parser) } it 'can be initialized' do - expect{parser.location}.not_to raise_error + expect { parser.location }.not_to raise_error end it 'returns the location' do expect(parser.location).to eq(location) diff --git a/spec/lib/parsers/csv_layout/validators/any_barcode_validator_spec.rb b/spec/lib/parsers/csv_layout/validators/any_barcode_validator_spec.rb index f25b51c3..1d3b5e50 100644 --- a/spec/lib/parsers/csv_layout/validators/any_barcode_validator_spec.rb +++ b/spec/lib/parsers/csv_layout/validators/any_barcode_validator_spec.rb @@ -5,6 +5,7 @@ let(:klass) { Class.new { attr_accessor :barcode + include ActiveModel::Validations validates_with Parsers::CsvLayout::Validators::AnyBarcodeValidator } diff --git a/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb b/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb index 0aef942e..4b6a3db7 100644 --- a/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb +++ b/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb @@ -6,6 +6,7 @@ let(:klass) { Class.new { attr_accessor :barcode + include ActiveModel::Validations validates_with Parsers::CsvLayout::Validators::FluidxBarcodeValidator } diff --git a/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb b/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb index e7574ebd..7ffb005b 100644 --- a/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb +++ b/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb @@ -6,6 +6,7 @@ let(:klass) { Class.new { attr_accessor :location + include ActiveModel::Validations validates_with Parsers::CsvLayout::Validators::LocationValidator } diff --git a/spec/lib/parsers/csv_metadata/csv_parser_spec.rb b/spec/lib/parsers/csv_metadata/csv_parser_spec.rb index 954363d4..b1268166 100644 --- a/spec/lib/parsers/csv_metadata/csv_parser_spec.rb +++ b/spec/lib/parsers/csv_metadata/csv_parser_spec.rb @@ -9,9 +9,9 @@ RSpec.describe Parsers::CsvMetadata::CsvParser do describe "parses a metadata file" do - let(:activity) { create(:activity)} + let(:activity) { create(:activity) } let(:asset_group) { create(:asset_group) } - let(:step_type) {create(:step_type)} + let(:step_type) { create(:step_type) } let(:step) { create :step, activity: activity, state: Step::STATE_RUNNING, diff --git a/spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb b/spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb index 1dd1c500..6685be67 100644 --- a/spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb +++ b/spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb @@ -5,6 +5,7 @@ let(:klass) { Class.new { attr_accessor :headers + include ActiveModel::Validations validates_with Parsers::CsvMetadata::Validators::HeadersValidator } diff --git a/spec/lib/support_n3_spec.rb b/spec/lib/support_n3_spec.rb index 35e45668..2290c80a 100644 --- a/spec/lib/support_n3_spec.rb +++ b/spec/lib/support_n3_spec.rb @@ -41,7 +41,7 @@ def validates_rule_with(parsed_obj) it "does not create multiple activitytypes" do testing_name = 'testing_name' - @activity_type = FactoryBot.create :activity_type, {:name => testing_name} + @activity_type = FactoryBot.create :activity_type, { :name => testing_name } @activity_type.reload expect(@activity_type.deprecated?).to eq(false) SupportN3.parse_string(%Q{ @@ -57,7 +57,7 @@ def validates_rule_with(parsed_obj) it "deprecates old activity_types" do testing_name = 'testing_name' - @activity_type = FactoryBot.create :activity_type, {:name => testing_name} + @activity_type = FactoryBot.create :activity_type, { :name => testing_name } @activity_type.reload expect(@activity_type.deprecated?).to eq(false) SupportN3.parse_string(":activity :activityTypeName \"\"\"#{testing_name}\"\"\" .") @@ -68,7 +68,7 @@ def validates_rule_with(parsed_obj) it "deprecates old step_types" do testing_name = 'testing_name' - @step_type = FactoryBot.create :step_type, {:name => testing_name} + @step_type = FactoryBot.create :step_type, { :name => testing_name } @step_type.reload expect(@step_type.deprecated?).to eq(false) SupportN3.parse_string("{} => {:step :stepTypeName \"\"\"#{testing_name}\"\"\" .}.") @@ -85,13 +85,13 @@ def validates_rule_with(parsed_obj) describe "with rules that remove facts" do it '{?x :a :Tube .} => { :step :removeFacts {?x :has :RNA .}.}.' do validates_rule_with({ - ConditionGroup => [{:name => 'x', + ConditionGroup => [{ :name => 'x', :step_type => @step_type, :cardinality => nil, - :keep_selected => true}], - Condition => [{:predicate => 'a', :object => 'Tube'}], - Action => [{:action_type => 'removeFacts', + :keep_selected => true }], + Condition => [{ :predicate => 'a', :object => 'Tube' }], + Action => [{ :action_type => 'removeFacts', :predicate => 'has', :object => 'RNA', - :object_condition_group_id => nil, :step_type_id => @step_type.id}]}) + :object_condition_group_id => nil, :step_type_id => @step_type.id }] }) assert_equal ConditionGroup.first, Condition.first.condition_group assert_equal ConditionGroup.first, Action.first.subject_condition_group end @@ -101,15 +101,15 @@ def validates_rule_with(parsed_obj) it '{?z :has :Content .} => {:step :createAsset {?y :a :Rack .}.}.' do validates_rule_with({ ConditionGroup => [ - {:name => 'z',:step_type => @step_type, :cardinality => nil, - :keep_selected => true}, - {:name => 'y',:step_type => nil, :cardinality => nil, - :keep_selected => true}], - Condition => [{:predicate => 'has', :object => 'Content'}], - Action => [{:action_type => 'createAsset', + { :name => 'z',:step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'y',:step_type => nil, :cardinality => nil, + :keep_selected => true }], + Condition => [{ :predicate => 'has', :object => 'Content' }], + Action => [{ :action_type => 'createAsset', :predicate => 'a', :object => 'Rack', :object_condition_group => nil, - :step_type_id => @step_type.id}]}) + :step_type_id => @step_type.id }] }) z = ConditionGroup.find_by_name('z') y = ConditionGroup.find_by_name('y') @@ -122,13 +122,13 @@ def validates_rule_with(parsed_obj) it '{?a :maxCardinality """96""" . ?a :is :Tube . }=>{ :step :addFacts {?a :has :Capacity .}.}.' do validates_rule_with({ ConditionGroup => [ - {:name => 'a',:step_type => @step_type, :cardinality => 96, - :keep_selected => true}], - Condition => [{:predicate => 'is', :object => 'Tube'}], - Action => [{:action_type => 'addFacts', + { :name => 'a',:step_type => @step_type, :cardinality => 96, + :keep_selected => true }], + Condition => [{ :predicate => 'is', :object => 'Tube' }], + Action => [{ :action_type => 'addFacts', :predicate => 'has', :object => 'Capacity', :object_condition_group => nil, - :step_type_id => @step_type.id}]}) + :step_type_id => @step_type.id }] }) a = ConditionGroup.find_by_name('a') assert_equal a, Action.first.subject_condition_group assert_equal a, Condition.first.condition_group @@ -139,14 +139,14 @@ def validates_rule_with(parsed_obj) it '{?a :is :Tube . }=>{ :step :unselectAsset ?a . :step :addFacts {?a :is :Full.}.}.' do validates_rule_with({ ConditionGroup => [ - {:name => 'a',:step_type => @step_type, :cardinality => nil, - :keep_selected => false}], - Condition => [{:predicate => 'is', :object => 'Tube'}], - Action => [{:action_type => 'addFacts', + { :name => 'a',:step_type => @step_type, :cardinality => nil, + :keep_selected => false }], + Condition => [{ :predicate => 'is', :object => 'Tube' }], + Action => [{ :action_type => 'addFacts', :predicate => 'is', :object => 'Full', :object_condition_group => nil, - :step_type_id => @step_type.id} - ]}) + :step_type_id => @step_type.id } + ] }) a = ConditionGroup.find_by_name('a') assert_equal a, Action.first.subject_condition_group end @@ -154,17 +154,17 @@ def validates_rule_with(parsed_obj) it '{?a :is :Tube . }=>{ :step :unselectAsset {?b :is :Tube.}.}.' do validates_rule_with({ ConditionGroup => [ - {:name => 'a',:step_type => @step_type, :cardinality => nil, - :keep_selected => true}, - {:name => 'b',:step_type => nil, :cardinality => nil, - :keep_selected => false}], - Condition => [{:predicate => 'is', :object => 'Tube'}, - {:predicate => 'is', :object => 'Tube'}], - Action => [{:action_type => 'unselectAsset', + { :name => 'a',:step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'b',:step_type => nil, :cardinality => nil, + :keep_selected => false }], + Condition => [{ :predicate => 'is', :object => 'Tube' }, + { :predicate => 'is', :object => 'Tube' }], + Action => [{ :action_type => 'unselectAsset', :predicate => 'is', :object => 'Tube', :object_condition_group => nil, - :step_type_id => @step_type.id} - ]}) + :step_type_id => @step_type.id } + ] }) assert_equal Action.first.subject_condition_group, ConditionGroup.last end end @@ -173,15 +173,15 @@ def validates_rule_with(parsed_obj) it '{?p :is :Tube . ?q :maxCardinality """1""".} => {:step :createAsset {?q :a :Plate.}.}.' do validates_rule_with({ - ConditionGroup => [{:name => 'p',:step_type => @step_type, - :cardinality => nil, :keep_selected => true}, - {:name => 'q', :step_type => nil, - :cardinality => 1, :keep_selected => true}], - Condition => [{:predicate => 'is', :object=> 'Tube'}], - Action => [{:action_type => 'createAsset', + ConditionGroup => [{ :name => 'p',:step_type => @step_type, + :cardinality => nil, :keep_selected => true }, + { :name => 'q', :step_type => nil, + :cardinality => 1, :keep_selected => true }], + Condition => [{ :predicate => 'is', :object=> 'Tube' }], + Action => [{ :action_type => 'createAsset', :predicate => 'a', :step_type_id => @step_type.id, - :object => 'Plate'}] + :object => 'Plate' }] }) p= ConditionGroup.find_by_name('p') q= ConditionGroup.find_by_name('q') @@ -190,16 +190,16 @@ def validates_rule_with(parsed_obj) it '{?p :is :Tube . ?q :is :TubeRack.} => {:step :addFacts {?p :transferTo ?q.}.}.' do validates_rule_with({ - ConditionGroup => [{:name => 'p',:step_type => @step_type, - :cardinality => nil, :keep_selected => true}, - {:name => 'q', :step_type => @step_type, - :cardinality => nil, :keep_selected => true}], - Condition => [{:predicate => 'is', :object=> 'Tube'}, - {:predicate => 'is', :object => 'TubeRack'}], - Action => [{:action_type => 'addFacts', + ConditionGroup => [{ :name => 'p',:step_type => @step_type, + :cardinality => nil, :keep_selected => true }, + { :name => 'q', :step_type => @step_type, + :cardinality => nil, :keep_selected => true }], + Condition => [{ :predicate => 'is', :object=> 'Tube' }, + { :predicate => 'is', :object => 'TubeRack' }], + Action => [{ :action_type => 'addFacts', :predicate => 'transferTo', :step_type_id => @step_type.id, - :object => 'q'}] + :object => 'q' }] }) p= ConditionGroup.find_by_name('p') q= ConditionGroup.find_by_name('q') @@ -213,21 +213,21 @@ def validates_rule_with(parsed_obj) } .}.' do validates_rule_with({ ConditionGroup => [ - {:name => 'p',:step_type => @step_type, :cardinality => nil, - :keep_selected => true}, - {:name => 'rack',:step_type => nil, :cardinality => 1, - :keep_selected => true}], + { :name => 'p',:step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'rack',:step_type => nil, :cardinality => 1, + :keep_selected => true }], Condition => [ - {:predicate => 'is', :object => 'Tube2D'} + { :predicate => 'is', :object => 'Tube2D' } ], - Action => [{:action_type => 'createAsset', + Action => [{ :action_type => 'createAsset', :predicate => 'is', :object => 'TubeRack', :object_condition_group => nil, - :step_type_id => @step_type.id}, - {:action_type => 'addFacts', + :step_type_id => @step_type.id }, + { :action_type => 'addFacts', :predicate => 'inRack', :object => 'rack', - :step_type_id => @step_type.id} - ]}) + :step_type_id => @step_type.id } + ] }) p = ConditionGroup.find_by_name('p') q = ConditionGroup.find_by_name('rack') @@ -243,16 +243,16 @@ def validates_rule_with(parsed_obj) it '{?q :is :Tube . ?q :has :DNA. ?p :is :Rack . ?p :contains ?q . } => {:step :addFacts { ?p :has :DNA . }}.' do validates_rule_with({ ConditionGroup => [ - {:name => 'q', :step_type => @step_type, :cardinality => nil, - :keep_selected => true}, - {:name => 'p', :step_type => @step_type, :cardinality => nil, - :keep_selected => true} + { :name => 'q', :step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'p', :step_type => @step_type, :cardinality => nil, + :keep_selected => true } ], Condition => [ - {:predicate => 'is', :object => 'Tube'}, - {:predicate => 'has', :object => 'DNA'}, - {:predicate => 'is', :object => 'Rack'}, - {:predicate => 'contains', :object => 'q'} + { :predicate => 'is', :object => 'Tube' }, + { :predicate => 'has', :object => 'DNA' }, + { :predicate => 'is', :object => 'Rack' }, + { :predicate => 'contains', :object => 'q' } ], Action => [ { :action_type => 'addFacts', :predicate => 'has', :object => 'DNA' } @@ -282,24 +282,24 @@ def validates_rule_with(parsed_obj) '} .' do validates_rule_with({ ConditionGroup => [ - {:name => 'a', :step_type => @step_type, :cardinality => nil, - :keep_selected => true}, - {:name => 'b', :step_type => @step_type, :cardinality => nil, - :keep_selected => true}, - {:name => 'c', :step_type => @step_type, :cardinality => nil, - :keep_selected => true}, - {:name => 'd', :step_type => @step_type, :cardinality => nil, - :keep_selected => true} + { :name => 'a', :step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'b', :step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'c', :step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'd', :step_type => @step_type, :cardinality => nil, + :keep_selected => true } ], Condition => [ - {:predicate => 'is', :object => 'A'}, - {:predicate => 'transfer'}, - {:predicate => 'is', :object => 'B'}, - {:predicate => 'transfer'}, - {:predicate => 'is', :object => 'C'}, - {:predicate => 'transfer'}, - {:predicate => 'is', :object => 'D'}, - {:predicate => 'transfer'} + { :predicate => 'is', :object => 'A' }, + { :predicate => 'transfer' }, + { :predicate => 'is', :object => 'B' }, + { :predicate => 'transfer' }, + { :predicate => 'is', :object => 'C' }, + { :predicate => 'transfer' }, + { :predicate => 'is', :object => 'D' }, + { :predicate => 'transfer' } ], Action => [ { :action_type => 'addFacts', :predicate => 'is', :object => 'Processed' }, @@ -331,15 +331,15 @@ def validates_rule_with(parsed_obj) { ?a :location ?_l . ?a :status :Done . ?a :name """My name""". ?b :location ?_l . ?b :status :Done .} => {:step :addFacts { ?a :repeatedLocation ?_l .}}.',{ - ConditionGroup =>[{:name => 'a'}, {:name => 'b'}, {:name => '_l'}], + ConditionGroup =>[{ :name => 'a' }, { :name => 'b' }, { :name => '_l' }], Condition => [ - {:predicate => 'location'}, - {:predicate => 'status', :object => 'Done', :object_condition_group_id => nil}, - {:predicate => 'name', :object_condition_group_id => nil}, - {:predicate => 'location'}, - {:predicate => 'status', :object => 'Done', :object_condition_group_id => nil} + { :predicate => 'location' }, + { :predicate => 'status', :object => 'Done', :object_condition_group_id => nil }, + { :predicate => 'name', :object_condition_group_id => nil }, + { :predicate => 'location' }, + { :predicate => 'status', :object => 'Done', :object_condition_group_id => nil } ], - Action => [{:action_type => 'addFacts', :predicate => 'repeatedLocation'}] }) + Action => [{ :action_type => 'addFacts', :predicate => 'repeatedLocation' }] }) l = ConditionGroup.find_by_name('_l') a = ConditionGroup.find_by_name('a') b = ConditionGroup.find_by_name('b') @@ -358,20 +358,20 @@ def validates_rule_with(parsed_obj) {?p :is :M .}=>{:step :addFacts {?p :is :G.}. :step :stepTypeName """A"""}. {?p :is :G .}=>{:step :addFacts {?p :is :M.}.}.',{ ConditionGroup => [ - {:name => 'p', - :cardinality => nil, :keep_selected => true}, - {:name => 'p', - :cardinality => nil, :keep_selected => true} + { :name => 'p', + :cardinality => nil, :keep_selected => true }, + { :name => 'p', + :cardinality => nil, :keep_selected => true } ], - StepType => [{:name => 'A'}, {}], - Condition => [{:predicate => 'is', :object=> 'M'}, - {:predicate => 'is', :object => 'G'}], - Action => [{:action_type => 'addFacts', + StepType => [{ :name => 'A' }, {}], + Condition => [{ :predicate => 'is', :object=> 'M' }, + { :predicate => 'is', :object => 'G' }], + Action => [{ :action_type => 'addFacts', :predicate => 'is', - :object => 'G'}, - {:action_type => 'addFacts', + :object => 'G' }, + { :action_type => 'addFacts', :predicate => 'is', - :object => 'M'}] + :object => 'M' }] }) expect(ConditionGroup.first.step_type).to eq(StepType.first) expect(ConditionGroup.last.step_type).to eq(StepType.last) @@ -382,23 +382,23 @@ def validates_rule_with(parsed_obj) {?p :is :M . ?p :maxCardinality """1""".}=>{:step :createAsset {?q :is :M.}.}. {?p :is :G . ?p :maxCardinality """2""".}=>{:step :createAsset {?q :is :G.}.}.',{ ConditionGroup => [ - {:name => 'p', - :cardinality => 1, :keep_selected => true}, - {:name => 'q', - :cardinality => nil, :keep_selected => true}, - {:name => 'p', - :cardinality => 2, :keep_selected => true}, - {:name => 'q', - :cardinality => nil, :keep_selected => true} + { :name => 'p', + :cardinality => 1, :keep_selected => true }, + { :name => 'q', + :cardinality => nil, :keep_selected => true }, + { :name => 'p', + :cardinality => 2, :keep_selected => true }, + { :name => 'q', + :cardinality => nil, :keep_selected => true } ], - Condition => [{:predicate => 'is', :object=> 'M'}, - {:predicate => 'is', :object => 'G'}], - Action => [{:action_type => 'createAsset', + Condition => [{ :predicate => 'is', :object=> 'M' }, + { :predicate => 'is', :object => 'G' }], + Action => [{ :action_type => 'createAsset', :predicate => 'is', - :object => 'M'}, - {:action_type => 'createAsset', + :object => 'M' }, + { :action_type => 'createAsset', :predicate => 'is', - :object => 'G'}] + :object => 'G' }] }) expect(StepType.all.count).to eq(2) expect(StepType.first.condition_groups.count).to eq(1) @@ -415,23 +415,23 @@ def validates_rule_with(parsed_obj) {?p :is :M .}=>{:step :createAsset {?q :is :M.}. :step :unselectAsset ?q .}. {?p :is :G .}=>{:step :createAsset {?q :is :G.}. :step :unselectAsset ?p .}.',{ ConditionGroup => [ - {:name => 'p', - :cardinality => nil, :keep_selected => true}, - {:name => 'q', - :cardinality => nil, :keep_selected => false}, - {:name => 'p', - :cardinality => nil, :keep_selected => false}, - {:name => 'q', - :cardinality => nil, :keep_selected => true} + { :name => 'p', + :cardinality => nil, :keep_selected => true }, + { :name => 'q', + :cardinality => nil, :keep_selected => false }, + { :name => 'p', + :cardinality => nil, :keep_selected => false }, + { :name => 'q', + :cardinality => nil, :keep_selected => true } ], - Condition => [{:predicate => 'is', :object=> 'M'}, - {:predicate => 'is', :object => 'G'}], - Action => [{:action_type => 'createAsset', + Condition => [{ :predicate => 'is', :object=> 'M' }, + { :predicate => 'is', :object => 'G' }], + Action => [{ :action_type => 'createAsset', :predicate => 'is', - :object => 'M'}, - {:action_type => 'createAsset', + :object => 'M' }, + { :action_type => 'createAsset', :predicate => 'is', - :object => 'G'}] + :object => 'G' }] }) expect(StepType.all.count).to eq(2) expect(StepType.first.condition_groups.count).to eq(1) diff --git a/spec/models/action_spec.rb b/spec/models/action_spec.rb index ef3fdc7e..85fffff7 100644 --- a/spec/models/action_spec.rb +++ b/spec/models/action_spec.rb @@ -28,10 +28,10 @@ end context 'when there are equal number of sources and destinations' do - let(:sources) {[:a, :b, :c]} - let(:destinations){[:alpha, :beta, :gamma]} - let(:pairs_by_position){[[:a, :alpha], [:b, :beta], [:c, :gamma]]} - let(:pairs){[ + let(:sources) { [:a, :b, :c] } + let(:destinations) { [:alpha, :beta, :gamma] } + let(:pairs_by_position) { [[:a, :alpha], [:b, :beta], [:c, :gamma]] } + let(:pairs) { [ [:a, :alpha], [:a, :beta], [:a, :gamma], [:b, :alpha], [:b, :beta], [:b, :gamma], [:c, :alpha], [:c, :beta], [:c, :gamma] @@ -41,10 +41,10 @@ it_behaves_like 'a connector of all to all' end context 'when there are less sources than destinations' do - let(:sources) {[:a, :b]} - let(:destinations){[:alpha, :beta, :gamma]} - let(:pairs_by_position){[[:a, :alpha], [:b, :beta]]} - let(:pairs){[ + let(:sources) { [:a, :b] } + let(:destinations) { [:alpha, :beta, :gamma] } + let(:pairs_by_position) { [[:a, :alpha], [:b, :beta]] } + let(:pairs) { [ [:a, :alpha], [:a, :beta], [:a, :gamma], [:b, :alpha], [:b, :beta], [:b, :gamma] ]} @@ -52,10 +52,10 @@ it_behaves_like 'a connector of all to all' end context 'when there are less destinations than sources' do - let(:sources) {[:a, :b, :c]} - let(:destinations){[:alpha, :beta]} - let(:pairs_by_position){[[:a, :alpha], [:b, :beta]]} - let(:pairs){[ + let(:sources) { [:a, :b, :c] } + let(:destinations) { [:alpha, :beta] } + let(:pairs_by_position) { [[:a, :alpha], [:b, :beta]] } + let(:pairs) { [ [:a, :alpha], [:a, :beta], [:b, :alpha], [:b, :beta], [:c, :alpha], [:c, :beta] diff --git a/spec/models/activities/background_tasks_spec.rb b/spec/models/activities/background_tasks_spec.rb index 8e1c7ec1..4e57b9b8 100644 --- a/spec/models/activities/background_tasks_spec.rb +++ b/spec/models/activities/background_tasks_spec.rb @@ -11,12 +11,12 @@ def self.update_attributes!(params) end let(:activity) { create :activity } - let(:step_type) { create :step_type} - let(:asset_group) { create :asset_group} + let(:step_type) { create :step_type } + let(:asset_group) { create :asset_group } let(:step) { create :step, step_type: step_type } context '#create_background_steps' do - let(:list_of_tasks) { 5.times.map{ DummyBackgroundStep }} + let(:list_of_tasks) { 5.times.map { DummyBackgroundStep } } it 'creates the list of steps' do activity.create_background_steps(list_of_tasks, {}) expect(Step.all.count).to eq(5) @@ -33,13 +33,13 @@ def self.update_attributes!(params) end context '#create_connected_tasks' do - let(:list_of_tasks) { 5.times.map{ DummyBackgroundStep }} + let(:list_of_tasks) { 5.times.map { DummyBackgroundStep } } let(:other_step) { create :step, step_type: step_type } context 'when it does not have any background task defined' do it 'does not raise an error' do allow(activity).to receive(:background_tasks).and_return([]) - expect{ activity.create_connected_tasks(step, asset_group) }.not_to raise_exception + expect { activity.create_connected_tasks(step, asset_group) }.not_to raise_exception end end context 'when it has background tasks' do @@ -53,8 +53,8 @@ def self.update_attributes!(params) context '#background_tasks' do it 'returns the list of inference tasks sorted by priority' do - step_types = 5.times.each_with_index.map {|i| create :step_type} - reasoning_step_types = 4.times.each_with_index.map {|i| create :step_type, { for_reasoning: true, priority: i } } + step_types = 5.times.each_with_index.map { |i| create :step_type } + reasoning_step_types = 4.times.each_with_index.map { |i| create :step_type, { for_reasoning: true, priority: i } } activity.activity_type.update_attributes(step_types: step_types.concat(reasoning_step_types)) expect(activity.background_tasks.count).to eq(reasoning_step_types.count) diff --git a/spec/models/activities/state_spec.rb b/spec/models/activities/state_spec.rb index acc94de6..914c2ce2 100644 --- a/spec/models/activities/state_spec.rb +++ b/spec/models/activities/state_spec.rb @@ -4,10 +4,10 @@ let(:activity) { create :activity } context 'when finishing an activity' do it 'changes the state to finish' do - expect{activity.finish}.to change{activity.state}.to('finish') + expect { activity.finish }.to change { activity.state }.to('finish') end it 'sets up a completion date' do - expect{activity.finish}.to change{activity.completed_at}.from(nil) + expect { activity.finish }.to change { activity.completed_at }.from(nil) end end end diff --git a/spec/models/activities/steps_management_spec.rb b/spec/models/activities/steps_management_spec.rb index 34eab085..961a0e88 100644 --- a/spec/models/activities/steps_management_spec.rb +++ b/spec/models/activities/steps_management_spec.rb @@ -8,21 +8,21 @@ ['is_a', 'ReceptionTube'], ['aliquotType', 'DNA'] ].map do |a,b| - create :fact, { :predicate => a, :object => b} + create :fact, { :predicate => a, :object => b } end } } let(:step_type) { create :step_type, name: 'Step B', condition_groups: [ create(:condition_group, conditions: [ - create(:condition, { predicate: 'is_a', object: 'ReceptionTube'}), - create(:condition, { predicate: 'aliquotType', object: 'DNA'}) + create(:condition, { predicate: 'is_a', object: 'ReceptionTube' }), + create(:condition, { predicate: 'aliquotType', object: 'DNA' }) ]) ] } - let(:step_type2) { create :step_type, name: 'Step A'} + let(:step_type2) { create :step_type, name: 'Step A' } let(:activity_type) { create :activity_type, step_types: [step_type, step_type2] } - let(:activity) {create :activity, activity_type: activity_type} + let(:activity) { create :activity, activity_type: activity_type } let(:asset_group) { create :asset_group, assets: [asset] } diff --git a/spec/models/asset_group_spec.rb b/spec/models/asset_group_spec.rb index 8164ca73..96cd0ddf 100644 --- a/spec/models/asset_group_spec.rb +++ b/spec/models/asset_group_spec.rb @@ -1,21 +1,21 @@ require 'rails_helper' RSpec.describe AssetGroup, type: :model do context '#update_with_assets' do - let(:existing_assets) { 3.times.map{ create :asset }} - let(:new_assets) { 2.times.map { create :asset }} - let(:group) { create(:asset_group, assets: existing_assets)} + let(:existing_assets) { 3.times.map { create :asset } } + let(:new_assets) { 2.times.map { create :asset } } + let(:group) { create(:asset_group, assets: existing_assets) } before do allow(group).to receive(:refresh!).and_return(true) end it 'adds new assets to the group' do expect { group.update_with_assets(existing_assets.concat(new_assets)) - }.to change{Operation.count}.by(2).and change{group.assets.count}.by(2) + }.to change { Operation.count }.by(2).and change { group.assets.count }.by(2) end it 'removes assets not present anymore in the group' do expect { group.update_with_assets(new_assets) - }.to change{Operation.count}.by(5).and change{group.assets.count}.by(-1) + }.to change { Operation.count }.by(5).and change { group.assets.count }.by(-1) end it 'refreshes the new added assets' do diff --git a/spec/models/asset_spec.rb b/spec/models/asset_spec.rb index b21e19a0..a4532e91 100644 --- a/spec/models/asset_spec.rb +++ b/spec/models/asset_spec.rb @@ -27,7 +27,7 @@ end context '#print_machine_barcode?' do - let(:asset) { create(:asset)} + let(:asset) { create(:asset) } it 'returns true when the asset has a barcode format of machine barcode' do asset.facts << create(:fact, predicate: 'barcodeFormat', object: 'machine_barcode', literal: true) @@ -41,7 +41,7 @@ context '#barcode_formatted_for_printing' do let(:human_barcode) { "EG1234E" } let(:machine_barcode) { 1420001234690 } - let(:asset) { create(:asset, barcode: human_barcode)} + let(:asset) { create(:asset, barcode: human_barcode) } context 'when no specific barcode format has been selected' do it 'returns the human barcode' do @@ -64,7 +64,7 @@ context '#printable_object' do let(:human_barcode) { "EG1234E" } let(:machine_barcode) { 1420001234690 } - let(:asset) { create(:asset, barcode: human_barcode)} + let(:asset) { create(:asset, barcode: human_barcode) } context 'when is a plate' do before do @@ -105,7 +105,7 @@ end context '#study_name' do - let(:study) { 'A STUDY'} + let(:study) { 'A STUDY' } context 'if it is a tube' do it 'returns the study name of the tube' do tube = create :asset diff --git a/spec/models/assets/export_spec.rb b/spec/models/assets/export_spec.rb index d5d8b790..7952b1c7 100644 --- a/spec/models/assets/export_spec.rb +++ b/spec/models/assets/export_spec.rb @@ -27,7 +27,7 @@ create(:fact, predicate: 'contains', object_asset: well2) ] - expect(asset.attributes_to_send_for_well(well1)).to eq({sample_uuid: TokenUtil.unquote(uuid)}) + expect(asset.attributes_to_send_for_well(well1)).to eq({ sample_uuid: TokenUtil.unquote(uuid) }) expect(asset.attributes_to_send_for_well(well2)).to eq({ sample_tube_uuid: sample_tube.uuid, sanger_sample_name: 'name1' @@ -60,10 +60,10 @@ @rack1 = Asset.find_by(uuid: 'rack1') expect(@rack1.attributes_to_send).to eq([ - {sample_tube_uuid: "s1", location: "A1"}, - {sample_tube_uuid: "s2", location: "B1"}, - {sample_tube_uuid: "s3", location: "C1"}, - {sample_tube_uuid: "s4", location: "D1"}]) + { sample_tube_uuid: "s1", location: "A1" }, + { sample_tube_uuid: "s2", location: "B1" }, + { sample_tube_uuid: "s3", location: "C1" }, + { sample_tube_uuid: "s4", location: "D1" }]) end end @@ -99,7 +99,7 @@ let(:step_type) { create :step_type } let(:step) { create :step, step_type: step_type, state: Step::STATE_RUNNING } let(:user) { create :user, username: 'test' } - let(:print_config) { {"Plate"=>'Pum', "Tube"=>'Pim'} } + let(:print_config) { { "Plate"=>'Pum', "Tube"=>'Pim' } } let(:plate) { build_remote_plate } let(:asset) { create :asset } @@ -153,10 +153,10 @@ @assets = SupportN3::parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') expect(@rack2.attributes_to_send).to eq([ - {sample_tube_uuid: "s1", location: "A1"}, - {sample_tube_uuid: "s2", location: "B1"}, - {sample_tube_uuid: "s3", location: "C1"}, - {sample_tube_uuid: "s4", location: "D1"}]) + { sample_tube_uuid: "s1", location: "A1" }, + { sample_tube_uuid: "s2", location: "B1" }, + { sample_tube_uuid: "s3", location: "C1" }, + { sample_tube_uuid: "s4", location: "D1" }]) end it 'generates the attributes when the locations are not duplicated' do @@ -184,10 +184,10 @@ @assets = SupportN3::parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') expect(@rack2.attributes_to_send).to eq([ - {sample_tube_uuid: "s1", location: "A1"}, - {sample_tube_uuid: "s2", location: "B1"}, - {sample_tube_uuid: "s3", location: "C1"}, - {sample_tube_uuid: "s4", location: "D1"}]) + { sample_tube_uuid: "s1", location: "A1" }, + { sample_tube_uuid: "s2", location: "B1" }, + { sample_tube_uuid: "s3", location: "C1" }, + { sample_tube_uuid: "s4", location: "D1" }]) end it 'fails when trying to generate attributes when the locations are duplicated' do @@ -213,7 +213,7 @@ } @assets = SupportN3::parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') - expect{@rack2.attributes_to_send}.to raise_exception Assets::Export::DuplicateLocations + expect { @rack2.attributes_to_send }.to raise_exception Assets::Export::DuplicateLocations end it 'does not export locations without a sample in it' do @@ -241,9 +241,9 @@ @assets = SupportN3::parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') expect(@rack2.attributes_to_send).to eq([ - {sample_tube_uuid: "s1", location: "A1"}, - {sample_tube_uuid: "s2", location: "B1"}, - {sample_tube_uuid: "s4", location: "D1"}]) + { sample_tube_uuid: "s1", location: "A1" }, + { sample_tube_uuid: "s2", location: "B1" }, + { sample_tube_uuid: "s4", location: "D1" }]) end end end diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 8b69123f..9ab1b045 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -84,7 +84,7 @@ fact = create(:fact, predicate: 'a', object: 'Plate', is_remote?: true) asset.facts << fact asset.refresh - expect{fact.reload}.not_to raise_error + expect { fact.reload }.not_to raise_error expect(asset.facts.with_predicate('a').first.object).to eq('Plate') end @@ -92,7 +92,7 @@ fact = create(:fact, predicate: 'a', object: 'Tube', is_remote?: true) asset.facts << fact asset.refresh - expect{fact.reload}.to raise_error(ActiveRecord::RecordNotFound) + expect { fact.reload }.to raise_error(ActiveRecord::RecordNotFound) expect(asset.facts.with_predicate('a').first.object).to eq('Plate') end @@ -100,7 +100,7 @@ fact = create(:fact, predicate: 'is', object: 'Red', is_remote?: false) asset.facts << fact asset.refresh - expect{fact.reload}.not_to raise_error + expect { fact.reload }.not_to raise_error expect(asset.facts.with_predicate('is').first.object).to eq('Red') end @@ -109,9 +109,9 @@ fact = create(:fact, predicate: 'contains', object_asset_id: asset2.id, is_remote?: true) asset.facts << fact asset.refresh - expect{fact.reload}.to raise_error(ActiveRecord::RecordNotFound) - expect{asset.reload}.not_to raise_error - expect{asset2.reload}.not_to raise_error + expect { fact.reload }.to raise_error(ActiveRecord::RecordNotFound) + expect { asset.reload }.not_to raise_error + expect { asset2.reload }.not_to raise_error end it 'replaces the local facts of the assets linked with remote facts that are changing' do @@ -121,8 +121,8 @@ fact = create(:fact, predicate: 'contains', object_asset_id: asset2.id, is_remote?: true) asset.facts << fact asset.refresh - expect{fact_well.reload}.to raise_error(ActiveRecord::RecordNotFound) - expect{asset2.reload}.not_to raise_error + expect { fact_well.reload }.to raise_error(ActiveRecord::RecordNotFound) + expect { asset2.reload }.not_to raise_error end it 'replaces the remote facts of the assets linked with remote facts that are changing' do @@ -132,8 +132,8 @@ fact = create(:fact, predicate: 'contains', object_asset_id: asset2.id, is_remote?: true) asset.facts << fact asset.refresh - expect{fact_well.reload}.to raise_error(ActiveRecord::RecordNotFound) - expect{asset2.reload}.not_to raise_error + expect { fact_well.reload }.to raise_error(ActiveRecord::RecordNotFound) + expect { asset2.reload }.not_to raise_error end end end @@ -187,7 +187,7 @@ end it 'should raise an exception' do - expect{Asset.find_or_import_asset_with_barcode(@barcode_asset)}.to raise_exception Assets::Import::RefreshSourceNotFoundAnymore + expect { Asset.find_or_import_asset_with_barcode(@barcode_asset) }.to raise_exception Assets::Import::RefreshSourceNotFoundAnymore end end @@ -207,7 +207,7 @@ remote_facts = @asset.facts.from_remote_asset remote_facts.each(&:reload) Asset.find_or_import_asset_with_barcode(@barcode_asset) - expect{remote_facts.each(&:reload)}.not_to raise_error + expect { remote_facts.each(&:reload) }.not_to raise_error end end @@ -224,18 +224,18 @@ it 'should destroy any remote facts that has changed' do Asset.find_or_import_asset_with_barcode(@barcode_asset) - expect{@fact_changed.reload}.to raise_exception ActiveRecord::RecordNotFound + expect { @fact_changed.reload }.to raise_exception ActiveRecord::RecordNotFound end it 'should destroy any contains dependant remote facts' do Asset.find_or_import_asset_with_barcode(@barcode_asset) - expect{@dependant_fact.reload}.to raise_exception ActiveRecord::RecordNotFound + expect { @dependant_fact.reload }.to raise_exception ActiveRecord::RecordNotFound end it 'should re-create new remote facts' do @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) @asset.facts.reload - expect(@asset.facts.from_remote_asset.all?{|f| f.object_asset != @well_changed}) + expect(@asset.facts.from_remote_asset.all? { |f| f.object_asset != @well_changed }) end end end @@ -246,8 +246,8 @@ it 'imports the information of the tubes that have a supplier name' do @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_supplier.barcode) tubes = @asset.facts.with_predicate('contains').map(&:object_asset) - tubes_with_info = tubes.select{|t| t.facts.where(predicate: 'supplier_sample_name').count > 0} - locations_with_info = tubes_with_info.map{|t| t.facts.with_predicate('location').first.object} + tubes_with_info = tubes.select { |t| t.facts.where(predicate: 'supplier_sample_name').count > 0 } + locations_with_info = tubes_with_info.map { |t| t.facts.with_predicate('location').first.object } expect(locations_with_info).to eq(['C1','D1']) end @@ -366,7 +366,7 @@ context 'when the plate does not have aliquots in its wells' do setup do - wells = ['A1','B1'].map {|l| build_remote_well(l, aliquots: []) } + wells = ['A1','B1'].map { |l| build_remote_well(l, aliquots: []) } @remote_asset_without_aliquots = build_remote_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_asset_without_aliquots) end @@ -374,13 +374,13 @@ it 'creates the wells with the same uuid as in the remote asset' do @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_aliquots.barcode) wells = @asset.facts.with_predicate('contains').map(&:object_asset) - expect(wells.zip(@remote_asset_without_aliquots.wells).all?{|w,w2| w.uuid == w2.uuid}).to eq(true) + expect(wells.zip(@remote_asset_without_aliquots.wells).all? { |w,w2| w.uuid == w2.uuid }).to eq(true) end end context 'when the plate does not have samples in its wells' do setup do - wells = ['A1','B1'].map {|l| build_remote_well(l, aliquots: [build_remote_aliquot(sample: nil)]) } + wells = ['A1','B1'].map { |l| build_remote_well(l, aliquots: [build_remote_aliquot(sample: nil)]) } @remote_asset_without_samples = build_remote_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_asset_without_samples) end @@ -388,7 +388,7 @@ it 'creates the wells with the same uuid as in the remote asset' do @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_samples.barcode) wells = @asset.facts.with_predicate('contains').map(&:object_asset) - expect(wells.zip(@remote_asset_without_samples.wells).all?{|w,w2| w.uuid == w2.uuid}).to eq(true) + expect(wells.zip(@remote_asset_without_samples.wells).all? { |w,w2| w.uuid == w2.uuid }).to eq(true) end end end diff --git a/spec/models/condition_spec.rb b/spec/models/condition_spec.rb index 642c87c8..7a786433 100644 --- a/spec/models/condition_spec.rb +++ b/spec/models/condition_spec.rb @@ -6,11 +6,11 @@ setup do @wildcard = FactoryBot.create(:condition_group) @cond = FactoryBot.create(:condition, { - :predicate => 'aliquotType', :object_condition_group => @wildcard}) + :predicate => 'aliquotType', :object_condition_group => @wildcard }) @fact = FactoryBot.create(:fact, { :predicate => 'aliquotType', :object => 'DNA' }) - @asset = FactoryBot.create(:asset, {:facts => [@fact]}) + @asset = FactoryBot.create(:asset, { :facts => [@fact] }) end it 'is compatible with a wildcard' do @@ -23,24 +23,24 @@ setup do @assets = 5.times.map do |i| facts = [ - FactoryBot.create(:fact, {:predicate => 'a', :object => 'Tube'}) + FactoryBot.create(:fact, { :predicate => 'a', :object => 'Tube' }) ] aliquot = ((i % 2) == 0) ? 'DNA' : 'RNA' - facts.push(FactoryBot.create(:fact, {:predicate => 'aliquotType', :object => aliquot})) + facts.push(FactoryBot.create(:fact, { :predicate => 'aliquotType', :object => aliquot })) FactoryBot.create(:asset, :facts => facts) end @wells = 5.times.map do |i| facts = [ - FactoryBot.create(:fact, {:predicate => 'a', :object => 'Well'}) + FactoryBot.create(:fact, { :predicate => 'a', :object => 'Well' }) ] aliquot = ((i % 2) == 0) ? 'DNA' : 'RNA' - facts.push(FactoryBot.create(:fact, {:predicate => 'aliquotType', :object => aliquot})) + facts.push(FactoryBot.create(:fact, { :predicate => 'aliquotType', :object => aliquot })) FactoryBot.create(:asset, :facts => facts) end @rack = FactoryBot.create :asset - @rack.facts << (FactoryBot.create(:fact, {:predicate => 'a', :object => 'Rack'})) - @rack.facts << (@wells.map {|well| FactoryBot.create(:fact, {:predicate => 'contains', :object_asset => well})}) + @rack.facts << (FactoryBot.create(:fact, { :predicate => 'a', :object => 'Rack' })) + @rack.facts << (@wells.map { |well| FactoryBot.create(:fact, { :predicate => 'contains', :object_asset => well }) }) @assets = @assets.concat([@wells, @rack]).flatten @@ -67,16 +67,16 @@ expect(@step_type.compatible_with?(@assets, nil, checked, wildcards)).to eq(true) @asset_group = FactoryBot.create(:asset_group, :assets => @assets) - @step = FactoryBot.create(:step, {:step_type => @step_type, :asset_group => @asset_group}) + @step = FactoryBot.create(:step, { :step_type => @step_type, :asset_group => @asset_group }) - {210=>{1737=>["DNA"], 1738=>["RNA"], + { 210=>{ 1737=>["DNA"], 1738=>["RNA"], 1739=>["DNA"], 1740=>["RNA"], 1741=>["DNA"], 1742=>["DNA"], 1743=>["RNA"], 1744=>["DNA"], - 1745=>["RNA"], 1746=>["DNA"]}, - 211=>{1737=>["DNA"], + 1745=>["RNA"], 1746=>["DNA"] }, + 211=>{ 1737=>["DNA"], 1738=>["RNA"], 1739=>["DNA"], 1740=>["RNA"], 1741=>["DNA"], 1742=>["DNA"], 1743=>["RNA"], - 1744=>["DNA"], 1745=>["RNA"], 1746=>["DNA"]}} + 1744=>["DNA"], 1745=>["RNA"], 1746=>["DNA"] } } end diff --git a/spec/models/step_execution_spec.rb b/spec/models/step_execution_spec.rb index 07f9ad09..0cfa33fc 100644 --- a/spec/models/step_execution_spec.rb +++ b/spec/models/step_execution_spec.rb @@ -8,25 +8,25 @@ setup do @assets = 5.times.map do |i| facts = [ - FactoryBot.create(:fact, {:predicate => 'a', :object => 'Tube'}) + FactoryBot.create(:fact, { :predicate => 'a', :object => 'Tube' }) ] aliquot = ((i % 2) == 0) ? 'DNA' : 'RNA' - facts.push(FactoryBot.create(:fact, {:predicate => 'aliquotType', :object => aliquot})) + facts.push(FactoryBot.create(:fact, { :predicate => 'aliquotType', :object => aliquot })) FactoryBot.create(:asset, :facts => facts) end @wells = 5.times.map do |i| facts = [ - FactoryBot.create(:fact, {:predicate => 'a', :object => 'Well'}) + FactoryBot.create(:fact, { :predicate => 'a', :object => 'Well' }) ] aliquot = ((i % 2) == 0) ? 'DNA' : 'RNA' aliquot = 'RNA' - facts.push(FactoryBot.create(:fact, {:predicate => 'aliquotType', :object => aliquot})) + facts.push(FactoryBot.create(:fact, { :predicate => 'aliquotType', :object => aliquot })) FactoryBot.create(:asset, :facts => facts) end @rack = FactoryBot.create :asset - @rack.facts << (FactoryBot.create(:fact, {:predicate => 'a', :object => 'Rack'})) - @rack.facts << (@wells.map {|well| FactoryBot.create(:fact, {:predicate => 'contains', :object_asset => well})}) + @rack.facts << (FactoryBot.create(:fact, { :predicate => 'a', :object => 'Rack' })) + @rack.facts << (@wells.map { |well| FactoryBot.create(:fact, { :predicate => 'contains', :object_asset => well }) }) @assets = @assets.concat([@wells, @rack]).flatten @@ -59,17 +59,17 @@ wildcard_values: wildcards, state: Step::STATE_RUNNING) @step_execution = StepExecution.new({ :step => @step, - :asset_group => @asset_group, :created_assets => created_assets}) + :asset_group => @asset_group, :created_assets => created_assets }) @step_execution.run - {210=>{1737=>["DNA"], 1738=>["RNA"], + { 210=>{ 1737=>["DNA"], 1738=>["RNA"], 1739=>["DNA"], 1740=>["RNA"], 1741=>["DNA"], 1742=>["DNA"], 1743=>["RNA"], 1744=>["DNA"], - 1745=>["RNA"], 1746=>["DNA"]}, - 211=>{1737=>["DNA"], + 1745=>["RNA"], 1746=>["DNA"] }, + 211=>{ 1737=>["DNA"], 1738=>["RNA"], 1739=>["DNA"], 1740=>["RNA"], 1741=>["DNA"], 1742=>["DNA"], 1743=>["RNA"], - 1744=>["DNA"], 1745=>["RNA"], 1746=>["DNA"]}} + 1744=>["DNA"], 1745=>["RNA"], 1746=>["DNA"] } } end diff --git a/spec/models/step_spec.rb b/spec/models/step_spec.rb index f2fae640..3825696e 100644 --- a/spec/models/step_spec.rb +++ b/spec/models/step_spec.rb @@ -11,7 +11,7 @@ def cwm_engine? RSpec.describe Step, type: :model do let(:activity) { create :activity } - let(:user) { create :user, username: 'test'} + let(:user) { create :user, username: 'test' } before do Delayed::Worker.delay_jobs = false end @@ -63,7 +63,7 @@ def create_condition_to_select_asset_type(asset_type) create(:condition, predicate: 'a', object: asset_type) end - def create_condition_group_to_select_asset_type(asset_type, name=nil) + def create_condition_group_to_select_asset_type(asset_type, name = nil) create(:condition_group, name: name, conditions: [create_condition_to_select_asset_type(asset_type)]) end @@ -75,7 +75,7 @@ def create_assets(num, type) describe '#create' do context 'when creating a step with a specific printer config' do - let(:printer_data_config) { {"Tube"=>"1234", "Plate"=>"6789"} } + let(:printer_data_config) { { "Tube"=>"1234", "Plate"=>"6789" } } it 'stores the printer config in the database' do s = create(:step, printer_config: printer_data_config) s2 = Step.find_by(id: s.id) @@ -88,30 +88,30 @@ def create_assets(num, type) setup do @step_type = FactoryBot.create :step_type - @cg1 = FactoryBot.create(:condition_group,{:name => 'p'}) + @cg1 = FactoryBot.create(:condition_group,{ :name => 'p' }) @cg1.conditions << FactoryBot.create(:condition,{ - :predicate => 'is', :object => 'Tube'}) - @cg2 = FactoryBot.create(:condition_group,{:name => 'q'}) + :predicate => 'is', :object => 'Tube' }) + @cg2 = FactoryBot.create(:condition_group,{ :name => 'q' }) @cg2.conditions << FactoryBot.create(:condition,{ - :predicate => 'is', :object => 'Rack'}) + :predicate => 'is', :object => 'Rack' }) @step_type.condition_groups << @cg1 @step_type.condition_groups << @cg2 - @tubes = 7.times.map{|i| FactoryBot.create(:asset, {:facts =>[ + @tubes = 7.times.map { |i| FactoryBot.create(:asset, { :facts =>[ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ]})} - @racks = 5.times.map{|i| FactoryBot.create(:asset, {:facts =>[ + ] })} + @racks = 5.times.map { |i| FactoryBot.create(:asset, { :facts =>[ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ]})} + ] })} @assets = [@tubes, @racks].flatten - @asset_group = FactoryBot.create(:asset_group, {:assets => @assets}) + @asset_group = FactoryBot.create(:asset_group, { :assets => @assets }) end describe 'when creating a new step' do it 'raises an exception if assets are not compatible with step_type' do @cg1.update_attributes(:cardinality => 1) - expect{ + expect { @step = create_step }.to raise_error(AASM::InvalidTransition) end @@ -120,10 +120,10 @@ def create_assets(num, type) describe 'with related assets in conditions' do setup do @cg2.conditions << FactoryBot.create(:condition, { - :predicate => 'contains', :object_condition_group_id => @cg1.id}) + :predicate => 'contains', :object_condition_group_id => @cg1.id }) - @action = FactoryBot.create(:action, {:action_type => 'addFacts', - :predicate => 'is', :object => 'TubeRack', :subject_condition_group => @cg2}) + @action = FactoryBot.create(:action, { :action_type => 'addFacts', + :predicate => 'is', :object => 'TubeRack', :subject_condition_group => @cg2 }) @step_type.actions << @action @racks.each_with_index do |r, i| @@ -146,8 +146,8 @@ def create_assets(num, type) describe 'with wildcards' do setup do @wildcard = FactoryBot.create :condition_group - condition = FactoryBot.create :condition, {:predicate => 'position', - :object_condition_group => @wildcard} + condition = FactoryBot.create :condition, { :predicate => 'position', + :object_condition_group => @wildcard } @cg2.conditions << condition end @@ -155,7 +155,7 @@ def create_assets(num, type) it 'does not execute the rule when the wildcard condition is not met' do previous_num = @asset_group.assets.count - expect{ + expect { @step = create_step }.to raise_error(StandardError) @@ -195,7 +195,7 @@ def create_assets(num, type) it 'uses the value of the condition group evaluated for the same cg' do previous_num = @asset_group.assets.count - @action = FactoryBot.create(:action, {:action_type => 'addFacts', + @action = FactoryBot.create(:action, { :action_type => 'addFacts', :predicate => 'value', :object_condition_group => @wildcard, :subject_condition_group => @cg2 }) @@ -216,11 +216,11 @@ def create_assets(num, type) previous_num = @asset_group.assets.count - @cg1.conditions << FactoryBot.create(:condition, {:predicate => 'location', - :object_condition_group => @wildcard}) - @cg2.conditions << FactoryBot.create(:condition, {:predicate => 'location', - :object_condition_group => @wildcard}) - @action = FactoryBot.create(:action, {:action_type => 'addFacts', + @cg1.conditions << FactoryBot.create(:condition, { :predicate => 'location', + :object_condition_group => @wildcard }) + @cg2.conditions << FactoryBot.create(:condition, { :predicate => 'location', + :object_condition_group => @wildcard }) + @action = FactoryBot.create(:action, { :action_type => 'addFacts', :predicate => 'relates', :object_condition_group => @cg1, :subject_condition_group => @cg2 }) @@ -264,17 +264,17 @@ def create_assets(num, type) describe 'with createAsset action type' do setup do - @cg3 = FactoryBot.create(:condition_group, {:name => 'r'}) + @cg3 = FactoryBot.create(:condition_group, { :name => 'r' }) @cg3.conditions << FactoryBot.create(:condition, { :predicate => 'is', :object => 'NewTube' }) - @action = FactoryBot.create(:action, {:action_type => 'createAsset', - :predicate => 'is', :object => 'NewTube', :subject_condition_group => @cg3}) + @action = FactoryBot.create(:action, { :action_type => 'createAsset', + :predicate => 'is', :object => 'NewTube', :subject_condition_group => @cg3 }) if cwm_engine? - @action2 = FactoryBot.create(:action, {:action_type => 'createAsset', - :predicate => 'createdBy', :object_condition_group => @cg1, :subject_condition_group => @cg3}) - @action3 = FactoryBot.create(:action, {:action_type => 'createAsset', - :predicate => 'createdBy', :object_condition_group => @cg2, :subject_condition_group => @cg3}) + @action2 = FactoryBot.create(:action, { :action_type => 'createAsset', + :predicate => 'createdBy', :object_condition_group => @cg1, :subject_condition_group => @cg3 }) + @action3 = FactoryBot.create(:action, { :action_type => 'createAsset', + :predicate => 'createdBy', :object_condition_group => @cg2, :subject_condition_group => @cg3 }) @step_type.actions << [@action, @action2, @action3] else @@ -295,7 +295,7 @@ def create_assets(num, type) expect(Operation.all.count).to eq(assets_created.count*3) else expect(assets_created.length).to eq(previous_num) - expect(Operation.all.select{|o| o.action_type=='createAssets'}.count).to eq(assets_created.count) + expect(Operation.all.select { |o| o.action_type=='createAssets' }.count).to eq(assets_created.count) end expect(assets_created.length+previous_num).to eq(@asset_group.assets.count) end @@ -312,7 +312,7 @@ def create_assets(num, type) expect(assets_created.length).to eq(6) expect(assets_created.length+previous_num).to eq(@asset_group.assets.count) - expect(Operation.all.select{|o| o.action_type=='createAssets'}.count).to eq(assets_created.count) + expect(Operation.all.select { |o| o.action_type=='createAssets' }.count).to eq(assets_created.count) end it 'cardinality does not restrict the number of assets created when it is over the number of inputs' do @@ -327,14 +327,14 @@ def create_assets(num, type) expect(assets_created.length).to eq(cardinality) #expect(assets_created.length+previous_num).to eq(@asset_group.assets.count) - expect(Operation.all.select{|o| o.action_type=='createAssets'}.count).to eq(assets_created.count) + expect(Operation.all.select { |o| o.action_type=='createAssets' }.count).to eq(assets_created.count) end end it 'adds facts to all the assets created' do previous_num = @asset_group.assets.count action = FactoryBot.create(:action, { :action_type => 'createAsset', - :predicate => 'has', :object => "MoreData", :subject_condition_group => @cg3}) + :predicate => 'has', :object => "MoreData", :subject_condition_group => @cg3 }) @step_type.actions << action @step = create_step @@ -355,12 +355,12 @@ def create_assets(num, type) it 'is able to execute addFacts and createFacts referring to the same condition group' do previous_num = @asset_group.assets.count - action = FactoryBot.create(:action, {:action_type => 'addFacts', - :predicate => 'has', :object => 'MoreData', :subject_condition_group => @cg3}) + action = FactoryBot.create(:action, { :action_type => 'addFacts', + :predicate => 'has', :object => 'MoreData', :subject_condition_group => @cg3 }) @step_type.actions << action @step = create_step expect(@asset_group.assets.count).to eq(previous_num*2) - expect(Operation.all.select{|o| o.action_type == 'addFacts'}.count).to eq(2*previous_num) + expect(Operation.all.select { |o| o.action_type == 'addFacts' }.count).to eq(2*previous_num) end describe 'with overlapping assets' do @@ -369,7 +369,7 @@ def create_assets(num, type) FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') - ]}) + ] }) end @asset_group.assets << @tubes_and_racks end @@ -403,8 +403,8 @@ def create_assets(num, type) describe 'with unselectAsset action type' do setup do - @action = FactoryBot.create(:action, {:action_type => 'addFacts', - :predicate => 'is', :object => 'Empty', :subject_condition_group => @cg1}) + @action = FactoryBot.create(:action, { :action_type => 'addFacts', + :predicate => 'is', :object => 'Empty', :subject_condition_group => @cg1 }) @step_type.actions << @action end @@ -412,14 +412,14 @@ def create_assets(num, type) @cg1.update_attributes(:keep_selected => false) @asset_group.assets.reload - assert_equal true, @tubes.all?{|tube| @asset_group.assets.include?(tube)} + assert_equal true, @tubes.all? { |tube| @asset_group.assets.include?(tube) } @step = create_step @asset_group.reload @asset_group.assets.reload @asset_group.assets.each(&:reload) - assert_equal false, @tubes.any?{|tube| @asset_group.assets.include?(tube)} + assert_equal false, @tubes.any? { |tube| @asset_group.assets.include?(tube) } #expect(Operation.all.count).to eq(@tubes.length) end @@ -430,7 +430,7 @@ def create_assets(num, type) FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') - ]}) + ] }) end @asset_group.assets << @tubes_and_racks end @@ -439,7 +439,7 @@ def create_assets(num, type) @cg1.update_attributes(:keep_selected => false) @asset_group.assets.reload - assert_equal true, [@tubes, @tubes_and_racks].flatten.all?{|tube| @asset_group.assets.include?(tube)} + assert_equal true, [@tubes, @tubes_and_racks].flatten.all? { |tube| @asset_group.assets.include?(tube) } @step = create_step @@ -447,7 +447,7 @@ def create_assets(num, type) @asset_group.assets.reload @asset_group.assets.each(&:reload) - assert_equal false, [@tubes, @tubes_and_racks].flatten.all?{|tube| @asset_group.assets.include?(tube)} + assert_equal false, [@tubes, @tubes_and_racks].flatten.all? { |tube| @asset_group.assets.include?(tube) } end end @@ -455,7 +455,7 @@ def create_assets(num, type) end describe 'when using different values of connect_by' do - let(:asset_group) {create(:asset_group, assets: [origins, targets].flatten)} + let(:asset_group) { create(:asset_group, assets: [origins, targets].flatten) } shared_examples 'a step type that can connect by position' do let(:step_type) { @@ -481,7 +481,7 @@ def create_assets(num, type) s = run_step_type(step_type, asset_group) origins.each(&:reload) destinations.each(&:reload) - transfers = origins.map(&:facts).map{|facts| facts.with_predicate('transfer')}.flatten.sort do |a,b| + transfers = origins.map(&:facts).map { |facts| facts.with_predicate('transfer') }.flatten.sort do |a,b| if (a.asset.id == b.asset.id) (a.object_asset.id <=> b.object_asset.id) else @@ -546,7 +546,7 @@ def create_assets(num, type) let(:origins) { create_assets(5, 'Tube') } let(:targets) { [] } - let(:destinations) { []} + let(:destinations) { [] } let(:num_destinations) { 5 } it_should_behave_like 'a step type that can connect by position' @@ -557,8 +557,8 @@ def create_assets(num, type) describe 'with addFacts action_type' do describe 'with one action' do setup do - @action = FactoryBot.create(:action, {:action_type => 'addFacts', - :predicate => 'is', :object => 'Empty', :subject_condition_group => @cg1}) + @action = FactoryBot.create(:action, { :action_type => 'addFacts', + :predicate => 'is', :object => 'Empty', :subject_condition_group => @cg1 }) @step_type.actions << @action end @@ -657,7 +657,7 @@ def create_assets(num, type) FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') - ]}) + ] }) end @asset_group.assets << @tubes_and_racks end @@ -687,10 +687,10 @@ def create_assets(num, type) describe 'with several actions' do setup do - @action = FactoryBot.create(:action, {:action_type => 'addFacts', - :predicate => 'is', :object => 'Empty'}) - @action2 = FactoryBot.create(:action, {:action_type => 'addFacts', - :predicate => 'is', :object => 'Red'}) + @action = FactoryBot.create(:action, { :action_type => 'addFacts', + :predicate => 'is', :object => 'Empty' }) + @action2 = FactoryBot.create(:action, { :action_type => 'addFacts', + :predicate => 'is', :object => 'Red' }) @step_type.actions << @action @step_type.actions << @action2 @@ -747,8 +747,8 @@ def create_assets(num, type) describe 'with removeFacts action_type' do describe 'with one action' do setup do - @action = FactoryBot.create(:action, {:action_type => 'removeFacts', - :predicate => 'is', :object => 'Tube', :subject_condition_group => @cg1}) + @action = FactoryBot.create(:action, { :action_type => 'removeFacts', + :predicate => 'is', :object => 'Tube', :subject_condition_group => @cg1 }) @step_type.actions << @action end @@ -772,9 +772,9 @@ def create_assets(num, type) describe 'relating different condition groups' do setup do # Something like removeFact(?tube :relatesTo ?rack) - @action = FactoryBot.create(:action, {:action_type => 'removeFacts', + @action = FactoryBot.create(:action, { :action_type => 'removeFacts', :predicate => 'relatesTo', :subject_condition_group => @cg1, - :object_condition_group => @cg2}) + :object_condition_group => @cg2 }) @step_type.actions << @action end @@ -782,16 +782,16 @@ def create_assets(num, type) @tubes.first.facts << FactoryBot.create(:fact, { :predicate => 'relatesTo', :object => @racks.first.relation_id, :object_asset => @racks.first, - :literal => false}) + :literal => false }) - assert_equal 1, @tubes.first.facts.select{|f| f.predicate == 'relatesTo'}.length + assert_equal 1, @tubes.first.facts.select { |f| f.predicate == 'relatesTo' }.length @asset_group.update_attributes(:assets => [@tubes.first, @racks.first].flatten) create_step @tubes.each(&:reload) @racks.each(&:reload) - assert_equal 0, @tubes.first.facts.select{|f| f.predicate == 'relatesTo'}.length + assert_equal 0, @tubes.first.facts.select { |f| f.predicate == 'relatesTo' }.length expect(Operation.all.count).to eq(1) end describe 'relating several assets' do @@ -801,7 +801,7 @@ def create_assets(num, type) tube.facts << FactoryBot.create(:fact, { :predicate => 'relatesTo', :object => rack.relation_id, :object_asset => rack, - :literal => false}) + :literal => false }) end end @@ -809,7 +809,7 @@ def create_assets(num, type) @racks.each(&:reload) @tubes.each do |tube| - assert_equal true, (tube.facts.select{|f| f.predicate == 'relatesTo'}.length>0) + assert_equal true, (tube.facts.select { |f| f.predicate == 'relatesTo' }.length>0) end create_step @@ -818,7 +818,7 @@ def create_assets(num, type) @racks.each(&:reload) @tubes.each do |tube| - assert_equal 0, tube.facts.select{|f| f.predicate == 'relatesTo'}.length + assert_equal 0, tube.facts.select { |f| f.predicate == 'relatesTo' }.length end expect(Operation.all.count).to eq(@racks.length*@tubes.length) end @@ -828,25 +828,25 @@ def create_assets(num, type) tube.facts << FactoryBot.create(:fact, { :predicate => 'relatesTo', :object => @tubes.first.relation_id, :object_asset => @racks.first, - :literal => false}) + :literal => false }) end @racks.each do |rack| rack.facts << FactoryBot.create(:fact, { :predicate => 'relatesTo', :object => @racks.first.relation_id, :object_asset => @racks.first, - :literal => false}) + :literal => false }) end @tubes.each(&:reload) @racks.each(&:reload) @tubes.each do |tube| - assert_equal true, (tube.facts.select{|f| f.predicate == 'relatesTo'}.length>0) + assert_equal true, (tube.facts.select { |f| f.predicate == 'relatesTo' }.length>0) end @racks.each do |rack| - assert_equal true, (rack.facts.select{|f| f.predicate == 'relatesTo'}.length>0) + assert_equal true, (rack.facts.select { |f| f.predicate == 'relatesTo' }.length>0) end create_step @@ -855,11 +855,11 @@ def create_assets(num, type) @racks.each(&:reload) @tubes.each do |tube| - assert_equal 0, tube.facts.select{|f| f.predicate == 'relatesTo'}.length + assert_equal 0, tube.facts.select { |f| f.predicate == 'relatesTo' }.length end @racks.each do |rack| - assert_equal 1, rack.facts.select{|f| f.predicate == 'relatesTo'}.length + assert_equal 1, rack.facts.select { |f| f.predicate == 'relatesTo' }.length end expect(Operation.all.count).to eq(@tubes.length) @@ -869,10 +869,10 @@ def create_assets(num, type) end describe 'with several actions' do setup do - @action = FactoryBot.create(:action, {:action_type => 'removeFacts', - :predicate => 'is', :object => 'Tube'}) - @action2 = FactoryBot.create(:action, {:action_type => 'removeFacts', - :predicate => 'is', :object => 'Full'}) + @action = FactoryBot.create(:action, { :action_type => 'removeFacts', + :predicate => 'is', :object => 'Tube' }) + @action2 = FactoryBot.create(:action, { :action_type => 'removeFacts', + :predicate => 'is', :object => 'Full' }) @step_type.actions << @action @step_type.actions << @action2 diff --git a/spec/models/step_type_spec.rb b/spec/models/step_type_spec.rb index 4acf621f..a9d67469 100644 --- a/spec/models/step_type_spec.rb +++ b/spec/models/step_type_spec.rb @@ -41,13 +41,13 @@ def assert_equal(a,b) describe '#task_type' do let(:step_type) { create(:step_type, step_action: runner_name) } context 'when selecting a runner action' do - let(:runner_name) { 'my_script.rb'} + let(:runner_name) { 'my_script.rb' } it 'set task_type to \"runner\"' do expect(step_type.task_type).to eq('runner') end end context 'when selecting a rdf action' do - let(:runner_name) { 'my_script.n3'} + let(:runner_name) { 'my_script.n3' } it 'set task_type to \"cwm\"' do expect(step_type.task_type).to eq('cwm') end @@ -63,12 +63,12 @@ def assert_equal(a,b) describe '#compatible_with' do setup do @step_type=FactoryBot.create :step_type - @cg1=FactoryBot.create(:condition_group, {:name => 'p'}) + @cg1=FactoryBot.create(:condition_group, { :name => 'p' }) @step_type.condition_groups << @cg1 @cg1.conditions << FactoryBot.create(:condition, { - :predicate => 'is', :object => 'Tube'}) + :predicate => 'is', :object => 'Tube' }) @cg1.conditions << FactoryBot.create(:condition, { - :predicate => 'is', :object => 'Full'}) + :predicate => 'is', :object => 'Full' }) @asset = FactoryBot.create :asset @@ -116,10 +116,10 @@ def assert_equal(a,b) describe "with special configuration" do describe "related with cardinality" do setup do - @assets = 5.times.map{|i| FactoryBot.create :asset, {:facts => [ + @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ]}} + ] }} end it 'is compatible with any number of assets with no cardinality check' do @@ -150,10 +150,10 @@ def assert_equal(a,b) describe 'matching more than one asset' do describe 'for the same condition group' do setup do - @assets = 5.times.map{|i| FactoryBot.create :asset, {:facts => [ + @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ]}} + ] }} end it 'is compatible if all the assets match all the conditions of the rule' do @@ -163,24 +163,24 @@ def assert_equal(a,b) end it 'is not compatible if any of the assets do not match any the conditions of the rule' do - @assets << FactoryBot.create(:asset, {:facts => [ + @assets << FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Empty') - ]}) + ] }) assert_equal false, @step_type.compatible_with?(@assets) end it 'is not compatible if any of the assets do not match all the conditions of the rule' do - @assets << FactoryBot.create(:asset, {:facts => [ + @assets << FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Empty') - ]}) + ] }) assert_equal false, @step_type.compatible_with?(@assets) end end describe 'for different condition groups' do setup do - @cg2 = FactoryBot.create(:condition_group, {:name => 'q'}) + @cg2 = FactoryBot.create(:condition_group, { :name => 'q' }) @cg2.conditions << FactoryBot.create(:condition, { :predicate => 'is', :object => 'Rack' @@ -188,14 +188,14 @@ def assert_equal(a,b) @step_type.condition_groups << @cg2 - @assets = 5.times.map{|i| FactoryBot.create :asset, {:facts => [ + @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ]}} + ] }} - @racks = 5.times.map{|i| FactoryBot.create :asset, {:facts => [ + @racks = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), - ]}} + ] }} end it 'is compatible with both condition groups when cardinality was set for one of them' do @@ -207,7 +207,7 @@ def assert_equal(a,b) it 'is compatible if all the condition groups are matched by the assets' do assert_equal true, @step_type.compatible_with?([@assets, @racks].flatten) - @assets.first.facts << FactoryBot.create(:fact, {:predicate => 'a', :object => 'b'}) + @assets.first.facts << FactoryBot.create(:fact, { :predicate => 'a', :object => 'b' }) assert_equal true, @step_type.compatible_with?([@assets, @racks].flatten) end @@ -218,9 +218,9 @@ def assert_equal(a,b) it 'is not compatible if none of the condition groups are matched by the assets' do a = FactoryBot.create :asset - a.facts << FactoryBot.create(:fact, {:predicate => 'a', :object => 'b'}) + a.facts << FactoryBot.create(:fact, { :predicate => 'a', :object => 'b' }) b = FactoryBot.create :asset - b.facts << FactoryBot.create(:fact, {:predicate => 'c', :object => 'd'}) + b.facts << FactoryBot.create(:fact, { :predicate => 'c', :object => 'd' }) assert_equal false, @step_type.compatible_with?([a,b].flatten) end @@ -236,7 +236,7 @@ def assert_equal(a,b) FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ]}) + ] }) end assert_equal true, @step_type.compatible_with?([@assets, @racks, @tubes_and_racks].flatten) end @@ -249,41 +249,41 @@ def assert_equal(a,b) setup do @cg2 = FactoryBot.create(:condition_group, {}) @cg2.conditions << FactoryBot.create(:condition, { - :predicate => 'is', :object => 'Rack'}) + :predicate => 'is', :object => 'Rack' }) @step_type.condition_groups << @cg2 @cg1.conditions << FactoryBot.create(:condition, { :predicate => 'inRack', :object => 'q', - :object_condition_group_id => @cg2.id}) + :object_condition_group_id => @cg2.id }) - @racks = 5.times.map{|i| FactoryBot.create :asset, {:facts => [ + @racks = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack') - ]}} + ] }} - @bad_racks = 5.times.map{|i| FactoryBot.create :asset, {:facts => [ + @bad_racks = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack') - ]}} + ] }} - @assets = 5.times.map{|i| FactoryBot.create :asset, {:facts => [ + @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), FactoryBot.create(:fact, :predicate => 'inRack', :object_asset_id => @racks[i].id) - ]}} + ] }} end it 'is compatible with condition groups that have relations with elements included in the asset group' do assert_equal true, @step_type.compatible_with?([@assets, @racks].flatten) end it 'is not compatible when the relation is not matching the conditions required' do - @bad_racks = 5.times.map{|i| FactoryBot.create :asset, {:facts => [ + @bad_racks = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'BadRack') - ]}} + ] }} - @assets = 5.times.map{|i| FactoryBot.create :asset, {:facts => [ + @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), FactoryBot.create(:fact, :predicate => 'inRack', :object_asset_id => @bad_racks[i].id) - ]}} + ] }} assert_equal false, @step_type.compatible_with?([@assets, @bad_racks].flatten) end it 'is compatible with condition groups that have relations with elements outside the asset group' do @@ -295,15 +295,15 @@ def assert_equal(a,b) @cg2 = FactoryBot.create(:condition_group, {}) @cg1.conditions << FactoryBot.create(:condition, { :predicate => 'position', - :object_condition_group_id => @cg2.id}) + :object_condition_group_id => @cg2.id }) end it 'is compatible with any literal when met the other conditions' do - @assets = 5.times.map{|i| FactoryBot.create :asset, {:facts => [ + @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), FactoryBot.create(:fact, :predicate => 'position', :object => i) - ]}} + ] }} assert_equal true, @step_type.compatible_with?([@assets].flatten) end end diff --git a/spec/models/steps/background_tasks/inference_spec.rb b/spec/models/steps/background_tasks/inference_spec.rb index 77dccc1b..694959e5 100644 --- a/spec/models/steps/background_tasks/inference_spec.rb +++ b/spec/models/steps/background_tasks/inference_spec.rb @@ -2,7 +2,7 @@ RSpec.describe Steps::BackgroundTasks::Inference do context '#run' do - let(:activity) { create(:activity, state: 'running')} + let(:activity) { create(:activity, state: 'running') } let(:execution) { double('step_execution') } let(:inference) { create :inference, activity: activity } @@ -14,14 +14,14 @@ allow(execution).to receive(:run).and_raise(StandardError) end it 'changes the status to error' do - expect{ + expect { inference.run! - }.to change{inference.failed?}.from(false).to(true) + }.to change { inference.failed? }.from(false).to(true) end it 'adds an output value explaining the error' do - expect{ + expect { inference.run! - }.to change{inference.output.nil?}.to(false) + }.to change { inference.output.nil? }.to(false) end end context 'when there is no error' do @@ -35,7 +35,7 @@ end it 'executes the rest of next steps' do - inferences = 5.times.map{ create :inference, activity: activity } + inferences = 5.times.map { create :inference, activity: activity } inferences.reverse.reduce(nil) do |memo, step| id = (memo && memo.id) || nil step.update_attributes(next_step_id: id) @@ -43,7 +43,7 @@ end inferences.first.run! inferences.each(&:reload) - inferences.each {|i| expect(i.state).to eq('complete')} + inferences.each { |i| expect(i.state).to eq('complete') } end end end diff --git a/spec/models/steps/cancellable_spec.rb b/spec/models/steps/cancellable_spec.rb index 24e88241..6482a1a0 100644 --- a/spec/models/steps/cancellable_spec.rb +++ b/spec/models/steps/cancellable_spec.rb @@ -46,25 +46,25 @@ end it 'cancels your step and all the steps newer than it' do - expect(@steps.any?{|s| s.cancelled?}).to eq(false) + expect(@steps.any? { |s| s.cancelled? }).to eq(false) @steps[5].cancel @steps.each(&:reload) - expect(@steps.select{|s| s.cancelled?}.count).to eq(5) + expect(@steps.select { |s| s.cancelled? }.count).to eq(5) expected_ids = [@steps[5].id, @steps[5].steps_newer_than_me.map(&:id)].flatten.sort - expect(@steps.select{|s| s.cancelled?}.map(&:id).sort).to eq(expected_ids) + expect(@steps.select { |s| s.cancelled? }.map(&:id).sort).to eq(expected_ids) end it 'redoes your step and all the steps older than it' do - expect(@steps.any?{|s| s.cancelled?}).to eq(false) + expect(@steps.any? { |s| s.cancelled? }).to eq(false) @steps[5].cancel @steps.each(&:reload) - expect(@steps.select{|s| s.cancelled?}.count).to eq(5) + expect(@steps.select { |s| s.cancelled? }.count).to eq(5) expected_ids = [@steps[5].id, @steps[5].steps_newer_than_me.map(&:id)].flatten.sort - expect(@steps.select{|s| s.cancelled?}.map(&:id).sort).to eq(expected_ids) + expect(@steps.select { |s| s.cancelled? }.map(&:id).sort).to eq(expected_ids) @steps[9].remake @steps.each(&:reload) - expect(@steps.any?{|s| s.cancelled?}).to eq(false) + expect(@steps.any? { |s| s.cancelled? }).to eq(false) end end diff --git a/spec/models/steps/deprecatable_spec.rb b/spec/models/steps/deprecatable_spec.rb index 780cbfca..9c5b52ee 100644 --- a/spec/models/steps/deprecatable_spec.rb +++ b/spec/models/steps/deprecatable_spec.rb @@ -1,13 +1,13 @@ require 'rails_helper' RSpec.describe 'Steps::Deprecatable' do - let(:activity) { create(:activity)} + let(:activity) { create(:activity) } let(:asset_group) { create(:asset_group) } - let(:step_type) { create(:step_type)} + let(:step_type) { create(:step_type) } context '#execute_actions' do let(:state) { Step::STATE_CANCELLED } it 'deprecates all cancelled steps created before me on step execution' do - steps = 10.times.map{create(:step, state: state, activity: activity)} + steps = 10.times.map { create(:step, state: state, activity: activity) } step = create(:step, activity: activity, asset_group: asset_group, step_type: step_type) expect(steps.all?(&:cancelled?)).to eq(true) @@ -19,7 +19,7 @@ end it 'deprecates all stopped steps created before me on step execution' do - steps = 10.times.map{create(:step, state: Step::STATE_STOPPED, activity: activity)} + steps = 10.times.map { create(:step, state: Step::STATE_STOPPED, activity: activity) } step = create(:step, activity: activity, asset_group: asset_group, step_type: step_type) expect(activity.steps.count).to eq(11) @@ -30,7 +30,7 @@ end it 'does not deprecate anything if is completed' do - steps = 10.times.map{create(:step, state: Step::STATE_COMPLETE, activity: activity)} + steps = 10.times.map { create(:step, state: Step::STATE_COMPLETE, activity: activity) } step = create(:step, activity: activity, state: Step::STATE_PENDING, asset_group: asset_group, step_type: step_type) expect(activity.steps.count).to eq(11) @@ -42,7 +42,7 @@ it 'does not deprecate anything created after me' do step = create(:step, activity: activity, asset_group: asset_group, step_type: step_type) - steps = 10.times.map{create(:step, state: 'cancelled', activity: activity)} + steps = 10.times.map { create(:step, state: 'cancelled', activity: activity) } expect(activity.steps.count).to eq(11) step.run! @@ -52,7 +52,7 @@ end it 'does not deprecate any steps created before me that are in my chain for next_step' do - steps = 10.times.map{create(:step, state: Step::STATE_STOPPED, activity: activity, asset_group: asset_group, step_type: step_type)} + steps = 10.times.map { create(:step, state: Step::STATE_STOPPED, activity: activity, asset_group: asset_group, step_type: step_type) } step = create(:step, activity: activity, asset_group: asset_group, step_type: step_type, next_step: steps.last) expect(activity.steps.count).to eq(11) diff --git a/spec/models/steps/job_spec.rb b/spec/models/steps/job_spec.rb index 1a8e7330..c9bb0850 100644 --- a/spec/models/steps/job_spec.rb +++ b/spec/models/steps/job_spec.rb @@ -5,17 +5,17 @@ let(:step) { create(:step, activity: activity) } context '#execute_actions' do - let(:job_double) { double('job')} + let(:job_double) { double('job') } before do allow(job_double).to receive(:id).and_return('1') allow(step).to receive(:perform_job).and_return(job_double) end context 'if the step is not already processing' do it 'adds the step to the queue to run in future' do - expect{step.run}.to change{step.job_id} + expect { step.run }.to change { step.job_id } end it 'changes the state to running' do - expect{step.run}.to change{step.running?}.from(false).to(true) + expect { step.run }.to change { step.running? }.from(false).to(true) end it 'calls #perform_job asynchronously' do step.run @@ -27,7 +27,7 @@ step.update_columns(state: Step::STATE_RUNNING) end it 'does nothing' do - expect{step.run}.to raise_error(AASM::InvalidTransition) + expect { step.run }.to raise_error(AASM::InvalidTransition) end end end @@ -43,7 +43,7 @@ allow(step).to receive(:process) end it 'changes the state to complete' do - expect{step.perform_job}.to change{step.complete?}.from(false).to(true) + expect { step.perform_job }.to change { step.complete? }.from(false).to(true) end end context 'when there is an error' do @@ -51,10 +51,10 @@ allow(step).to receive(:process).and_raise('boom!!') end it 'does not propagate the exception' do - expect{step.perform_job}.not_to raise_error + expect { step.perform_job }.not_to raise_error end it 'changes the state to error' do - expect{step.perform_job}.to change{step.failed?}.from(false).to(true) + expect { step.perform_job }.to change { step.failed? }.from(false).to(true) end end end diff --git a/spec/models/steps/queueable_job_spec.rb b/spec/models/steps/queueable_job_spec.rb index d371010a..2c3b4097 100644 --- a/spec/models/steps/queueable_job_spec.rb +++ b/spec/models/steps/queueable_job_spec.rb @@ -5,7 +5,7 @@ let(:activity) { create :activity } let(:step_type) { create :step_type } let(:asset_group) { create :asset_group } - let(:user) { create :user, username: 'test'} + let(:user) { create :user, username: 'test' } def build_instance_with_activity @@ -38,7 +38,7 @@ def build_instance_with_activity end context 'when it has several steps configured' do - let(:my_steps) { 5.times.map{build_instance_with_activity }} + let(:my_steps) { 5.times.map { build_instance_with_activity } } it 'does not execute any of the steps' do my_steps.reverse.reduce(nil) do |memo, step| step.update_attributes(next_step: memo) @@ -113,7 +113,7 @@ def build_instance_with_activity end end context 'when it has several steps configured' do - let(:my_steps) { 5.times.map{build_instance_with_activity}} + let(:my_steps) { 5.times.map { build_instance_with_activity } } context 'when all the steps are correct' do it 'executes all steps until the last one' do @@ -167,7 +167,7 @@ def mock_step_completion(s, state) end it 'does not raise an error' do step.update_attributes(next_step: nil) - expect{step.run!}.not_to raise_error + expect { step.run! }.not_to raise_error end end end diff --git a/spec/models/steps/state_spec.rb b/spec/models/steps/state_spec.rb index ac06cd5f..9ac2b176 100644 --- a/spec/models/steps/state_spec.rb +++ b/spec/models/steps/state_spec.rb @@ -4,7 +4,7 @@ let(:activity) { create :activity } let(:step_type) { create :step_type } - let(:job) { double('a job', id: 'an id')} + let(:job) { double('a job', id: 'an id') } it 'creates a step in pending state' do step = create :step, activity: activity, step_type: step_type diff --git a/spec/models/steps/stoppable_spec.rb b/spec/models/steps/stoppable_spec.rb index 400e389d..982b3012 100644 --- a/spec/models/steps/stoppable_spec.rb +++ b/spec/models/steps/stoppable_spec.rb @@ -1,21 +1,21 @@ require 'rails_helper' RSpec.describe 'Steps::Stoppable' do - let(:activity) { create(:activity)} + let(:activity) { create(:activity) } let(:asset_group) { create(:asset_group) } - let(:step_type) { create(:step_type)} + let(:step_type) { create(:step_type) } let(:previous_steps) { - 2.times.map{ + 2.times.map { create(:step, state: Step::STATE_RUNNING, activity: activity, asset_group: asset_group, step_type: step_type) } } let(:next_steps) { - 2.times.map{ + 2.times.map { create(:step, state: Step::STATE_RUNNING, activity: activity, asset_group: asset_group, step_type: step_type) } } - let(:step) { create(:step, state: previous_state, activity: activity, asset_group: asset_group, step_type: step_type)} + let(:step) { create(:step, state: previous_state, activity: activity, asset_group: asset_group, step_type: step_type) } context 'when a step is stopped' do let(:do_action) { @@ -26,7 +26,7 @@ context 'but the step was already completed before' do - let(:previous_state) { Step::STATE_COMPLETE} + let(:previous_state) { Step::STATE_COMPLETE } before do do_action end @@ -70,16 +70,16 @@ } let(:next_steps_stopped) { - 2.times.map{ + 2.times.map { create(:step, state: Step::STATE_STOPPED, activity: activity, asset_group: asset_group, step_type: step_type) } } let(:next_steps_not_stopped) { - 2.times.map{ + 2.times.map { create(:step, state: Step::STATE_FAILED, activity: activity, asset_group: asset_group, step_type: step_type) } } - let(:next_steps) { [next_steps_stopped, next_steps_not_stopped].flatten} + let(:next_steps) { [next_steps_stopped, next_steps_not_stopped].flatten } context 'when the step was stopped before' do let(:previous_state) { Step::STATE_STOPPED } diff --git a/spec/models/steps/task_spec.rb b/spec/models/steps/task_spec.rb index e63bdd93..c9dea0cd 100644 --- a/spec/models/steps/task_spec.rb +++ b/spec/models/steps/task_spec.rb @@ -2,7 +2,7 @@ describe Steps::Task do - let(:user) { create :user, username: 'test'} + let(:user) { create :user, username: 'test' } let(:printer_config) { { "Plate" => "plates", @@ -44,15 +44,15 @@ def create_instance(step_type, activity, group) asset.reload step = create_instance(step_type, activity, group) - expect{ + expect { step.run! - }.to change{Asset.all.count}.by(1).and change{Fact.count} + }.to change { Asset.all.count }.by(1).and change { Fact.count } end end context 'when the step type does have a step action' do let(:step_action) { 'some_action' } context 'when the step action runs correctly' do - let(:valid_changes) { FactChanges.new.tap{|update| update.create_assets(["?p"])}} + let(:valid_changes) { FactChanges.new.tap { |update| update.create_assets(["?p"]) } } let(:correct_execution) { execution = double('step_execution') allow(execution).to receive(:plan).and_return(valid_changes) @@ -66,9 +66,9 @@ def create_instance(step_type, activity, group) asset.reload step = create_instance(step_type, activity, group) - expect{ + expect { step.run! - }.to change{Asset.all.count}.by(2).and change{Fact.count} + }.to change { Asset.all.count }.by(2).and change { Fact.count } end it 'prints the selected list of assets' do @@ -111,9 +111,9 @@ def create_instance(step_type, activity, group) asset.reload # We don't change asset count because assets are never destroyed, only facts step = create_instance(step_type, activity, group) - expect{ + expect { step.run! - }.not_to change{Fact.count} + }.not_to change { Fact.count } end end end diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index 5c10e9c3..9df15804 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -15,8 +15,8 @@ def build_remote_plate(opts = {}) my_double end - def build_remote_well(location, opts={}) - double('well', {aliquots: [build_remote_aliquot], location: location, position: { "name" => location }, uuid: SecureRandom.uuid}.merge(opts)) + def build_remote_well(location, opts = {}) + double('well', { aliquots: [build_remote_aliquot], location: location, position: { "name" => location }, uuid: SecureRandom.uuid }.merge(opts)) end def build_remote_tube_rack(opts = {}) @@ -60,19 +60,19 @@ def build_remote_tube(opts = {}) my_double end - def build_remote_aliquot(opts={}) - double('aliquot', {sample: build_remote_sample, study: build_study}.merge(opts)) + def build_remote_aliquot(opts = {}) + double('aliquot', { sample: build_remote_sample, study: build_study }.merge(opts)) end - def build_study(opts={}) - double('study', {name: 'STDY', uuid: SecureRandom.uuid}) + def build_study(opts = {}) + double('study', { name: 'STDY', uuid: SecureRandom.uuid }) end - def build_remote_sample(opts={}) + def build_remote_sample(opts = {}) attrs_for_sample = { sanger_sample_id: 'TEST-123', name: 'a sample name', - sample_metadata: double('sample_metadata', {supplier_name: 'a supplier', sample_common_name: 'species'}), + sample_metadata: double('sample_metadata', { supplier_name: 'a supplier', sample_common_name: 'species' }), #sanger: double('sanger', { sample_id: 'TEST-123', name: 'a sample name'}), uuid: SecureRandom.uuid, #supplier: double('supplier', {sample_name: 'a supplier'}), diff --git a/spec/requests/api/v1/assets_spec.rb b/spec/requests/api/v1/assets_spec.rb index 7598d475..329fea5b 100644 --- a/spec/requests/api/v1/assets_spec.rb +++ b/spec/requests/api/v1/assets_spec.rb @@ -89,7 +89,7 @@ def key_for_attribute(attr_key) it 'returns the asset' do @body = JSON.parse(response.body) expect(@body['data'].length).to eq 1 - barcodes = @body['data'].map{|o| o['attributes']['barcode']} + barcodes = @body['data'].map { |o| o['attributes']['barcode'] } expect(barcodes.include?('F02')).to eq(true) end it_behaves_like 'a response with the required fields for Traction' diff --git a/spec/script/runners/load_metadata_spec.rb b/spec/script/runners/load_metadata_spec.rb index a7b37920..9d80d935 100644 --- a/spec/script/runners/load_metadata_spec.rb +++ b/spec/script/runners/load_metadata_spec.rb @@ -5,10 +5,10 @@ RSpec.describe 'LoadMetadata' do let(:content) { File.open('test/data/metadata.csv').read } - let(:file) { create(:uploaded_file, data: content )} + let(:file) { create(:uploaded_file, data: content ) } let(:file_asset) { create :asset, uploaded_file: file } - let(:positions) { TokenUtil.generate_positions(('A'..'H').to_a, ('1'..'12').to_a)} + let(:positions) { TokenUtil.generate_positions(('A'..'H').to_a, ('1'..'12').to_a) } let(:wells) { 96.times.map do |i| asset = FactoryBot.create(:asset) @@ -21,23 +21,23 @@ barcode: 'DN1001001', facts: [ create(:fact, predicate: 'a', object: 'TubeRack'), - wells.map{|w| create(:fact, predicate: 'contains', object_asset_id: w.id)} + wells.map { |w| create(:fact, predicate: 'contains', object_asset_id: w.id) } ].flatten)} let(:instance) { LoadMetadata.new(asset_group: group) } context 'when it receives a metadata file' do - let(:group) { create(:asset_group, assets: [rack, file_asset].flatten)} + let(:group) { create(:asset_group, assets: [rack, file_asset].flatten) } let(:added_triples) { instance.process.to_h[:add_facts] } it 'generates the number of changes for the specified assets in the file' do expect(added_triples.length).to eq(96*2) end it 'adds the right set of properties' do - predicates = added_triples.map{|l| l[1]}.uniq + predicates = added_triples.map { |l| l[1] }.uniq expect(predicates).to eq(['data1', 'data2']) end it 'adds to the right number of assets' do - assets = added_triples.map{|l| l[0]}.uniq + assets = added_triples.map { |l| l[0] }.uniq expect(assets.count).to eq(96) end end diff --git a/spec/script/runners/transfer_plate_to_plate_spec.rb b/spec/script/runners/transfer_plate_to_plate_spec.rb index aacaff44..014e46cd 100644 --- a/spec/script/runners/transfer_plate_to_plate_spec.rb +++ b/spec/script/runners/transfer_plate_to_plate_spec.rb @@ -14,7 +14,7 @@ def create_wells def create_rack create(:asset, facts: [ create(:fact, predicate: 'a', object: 'TubeRack'), - create_wells.map{|w| create(:fact, predicate: 'contains', object_asset_id: w.id, literal: false)} + create_wells.map { |w| create(:fact, predicate: 'contains', object_asset_id: w.id, literal: false) } ].flatten) end @@ -41,8 +41,8 @@ def create_rack destination_rack.facts << create(:fact, predicate: 'transferredFrom', object_asset_id: source_rack.id) end - let(:source_wells) {source_rack.facts.with_predicate('contains').map(&:object_asset)} - let(:destination_wells) {destination_rack.facts.with_predicate('contains').map(&:object_asset)} + let(:source_wells) { source_rack.facts.with_predicate('contains').map(&:object_asset) } + let(:destination_wells) { destination_rack.facts.with_predicate('contains').map(&:object_asset) } context 'when the destination is an empty rack' do @@ -54,11 +54,11 @@ def create_rack end it 'transfers the contents of all wells' do added_facts = instance.process.to_h[:add_facts] - destination_well_uuids = added_facts.select{|triple| triple[1] == 'contains'}.map{|t| t[2]} - added_samples = added_facts.select{|triple| triple[1] == 'sample_id'}.map{|triple| [triple[0], triple[2]]} - expect(added_samples).to eq(destination_well_uuids.each_with_index.map{|uuid,i| [uuid, "Sample #{i}"]}) - added_sample_tubes = added_facts.select{|triple| triple[1] == 'sample_tube'}.map{|triple| [triple[0], triple[2]]} - expect(added_sample_tubes).to eq(destination_well_uuids.map{|uuid| [uuid, sample_tube.uuid]}) + destination_well_uuids = added_facts.select { |triple| triple[1] == 'contains' }.map { |t| t[2] } + added_samples = added_facts.select { |triple| triple[1] == 'sample_id' }.map { |triple| [triple[0], triple[2]] } + expect(added_samples).to eq(destination_well_uuids.each_with_index.map { |uuid,i| [uuid, "Sample #{i}"] }) + added_sample_tubes = added_facts.select { |triple| triple[1] == 'sample_tube' }.map { |triple| [triple[0], triple[2]] } + expect(added_sample_tubes).to eq(destination_well_uuids.map { |uuid| [uuid, sample_tube.uuid] }) end context 'with the aliquot defined at destination rack' do @@ -67,8 +67,8 @@ def create_rack end it 'transfers the aliquot across plates into rack and wells' do added_facts = instance.process.to_h[:add_facts] - destination_well_uuids = added_facts.select{|triple| triple[1] == 'contains'}.map{|t| t[2]} - added_aliquots = added_facts.select{|triple| triple[1] == 'aliquotType'}.map{|triple| [triple[0], triple[2]]} + destination_well_uuids = added_facts.select { |triple| triple[1] == 'contains' }.map { |t| t[2] } + added_aliquots = added_facts.select { |triple| triple[1] == 'aliquotType' }.map { |triple| [triple[0], triple[2]] } expect(added_aliquots.sort).to eq(destination_well_uuids.map do |uuid| [uuid, 'DNA'] end.sort) @@ -87,10 +87,10 @@ def create_rack end it 'transfers the contents of all wells' do added_facts = instance.process.to_h[:add_facts] - added_samples = added_facts.select{|triple| triple[1] == 'sample_id'}.map{|triple| [triple[0], triple[2]]} - expect(added_samples).to eq(destination_wells.each_with_index.map{|w,i| [w.uuid, "Sample #{i}"]}) - added_sample_tubes = added_facts.select{|triple| triple[1] == 'sample_tube'}.map{|triple| [triple[0], triple[2]]} - expect(added_sample_tubes).to eq(destination_wells.map{|w| [w.uuid, sample_tube.uuid]}) + added_samples = added_facts.select { |triple| triple[1] == 'sample_id' }.map { |triple| [triple[0], triple[2]] } + expect(added_samples).to eq(destination_wells.each_with_index.map { |w,i| [w.uuid, "Sample #{i}"] }) + added_sample_tubes = added_facts.select { |triple| triple[1] == 'sample_tube' }.map { |triple| [triple[0], triple[2]] } + expect(added_sample_tubes).to eq(destination_wells.map { |w| [w.uuid, sample_tube.uuid] }) end context 'with aliquot defined at source' do @@ -99,7 +99,7 @@ def create_rack end it 'transfers the aliquot across plates into rack and wells' do added_facts = instance.process.to_h[:add_facts] - added_aliquots = added_facts.select{|triple| triple[1] == 'aliquotType'}.map{|triple| [triple[0], triple[2]]} + added_aliquots = added_facts.select { |triple| triple[1] == 'aliquotType' }.map { |triple| [triple[0], triple[2]] } expect(added_aliquots.sort).to eq([destination_rack.uuid].concat(destination_wells.map(&:uuid)).map do |uuid| [uuid, 'DNA'] end.sort) @@ -112,7 +112,7 @@ def create_rack it 'transfers the aliquot' do added_facts = instance.process.to_h[:add_facts] - added_aliquots = added_facts.select{|triple| triple[1] == 'aliquotType'}.map{|triple| [triple[0], triple[2]]} + added_aliquots = added_facts.select { |triple| triple[1] == 'aliquotType' }.map { |triple| [triple[0], triple[2]] } expect(added_aliquots.sort).to eq([destination_rack.uuid].concat(destination_wells.map(&:uuid)).map do |uuid| [uuid, 'DNA'] end.sort) diff --git a/spec/script/runners/transfer_samples_spec.rb b/spec/script/runners/transfer_samples_spec.rb index d9df25c5..58932239 100644 --- a/spec/script/runners/transfer_samples_spec.rb +++ b/spec/script/runners/transfer_samples_spec.rb @@ -2,16 +2,16 @@ require Rails.root.to_s+'/script/runners/transfer_samples' RSpec.describe 'TransferSamples' do - let(:sample) { create(:asset, facts: [create(:fact, predicate: 'sample_name', object: 'sample1')])} + let(:sample) { create(:asset, facts: [create(:fact, predicate: 'sample_name', object: 'sample1')]) } let(:sources) { - 5.times.map{ create(:asset, facts: [ + 5.times.map { create(:asset, facts: [ create(:fact, predicate: 'a', object: 'Tube'), create(:fact, predicate: 'study_name', object: 'Study 1'), create(:fact, predicate: 'sample_tube', object_asset_id: sample.id) ]) } } let(:destinations) { - 5.times.map{ create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } + 5.times.map { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } } let(:instance) { TransferSamples.new(asset_group: group) @@ -22,26 +22,26 @@ added_facts = instance.process.to_h[:add_facts] study_names_transferred = added_facts.select do |triple| triple[1] == 'study_name' - end.map{|triple| [triple[0], triple[2]]} - expect(study_names_transferred).to eq(destinations.map(&:uuid).zip(destinations.length.times.map{'Study 1'})) + end.map { |triple| [triple[0], triple[2]] } + expect(study_names_transferred).to eq(destinations.map(&:uuid).zip(destinations.length.times.map { 'Study 1' })) sample_tubes_transferred = added_facts.select do |triple| triple[1] == 'sample_tube' - end.map{|triple| [triple[0], triple[2]]} - expect(sample_tubes_transferred).to eq(destinations.map(&:uuid).zip(destinations.length.times.map{sample.uuid})) + end.map { |triple| [triple[0], triple[2]] } + expect(sample_tubes_transferred).to eq(destinations.map(&:uuid).zip(destinations.length.times.map { sample.uuid })) end context 'when there is no inverse relation transferredFrom' do it 'creates the inverse relation transferredFrom' do added_facts = instance.process.to_h[:add_facts] transferredFrom = added_facts.select do |triple| triple[1] == 'transferredFrom' - end.map{|triple| [triple[0], triple[2]]} + end.map { |triple| [triple[0], triple[2]] } expect(transferredFrom).to eq(destinations.map(&:uuid).zip(sources.map(&:uuid))) end end end context 'when both sources and destinations are in the group' do - let(:group) { create(:asset_group, assets: [sources, destinations].flatten)} + let(:group) { create(:asset_group, assets: [sources, destinations].flatten) } context 'when the assets are not related' do it 'does nothing with them' do expect(instance.process.to_h.keys.length).to eq(0) @@ -64,17 +64,17 @@ added_facts = instance.process.to_h[:add_facts] study_names_transferred = added_facts.select do |triple| triple[1] == 'study_name' - end.map{|triple| [triple[0], triple[2]]} + end.map { |triple| [triple[0], triple[2]] } expect(study_names_transferred).to eq([[destinations.first.uuid, 'Study 1']]) sample_tubes_transferred = added_facts.select do |triple| triple[1] == 'sample_tube' - end.map{|triple| [triple[0], triple[2]]} + end.map { |triple| [triple[0], triple[2]] } expect(sample_tubes_transferred).to eq([[destinations.first.uuid, sample.uuid]]) end end end context 'when only sources are in the group' do - let(:group) { create(:asset_group, assets: sources)} + let(:group) { create(:asset_group, assets: sources) } before do sources.zip(destinations).each do |s,d| s.facts << create(:fact, predicate: 'transfer', object_asset_id: d.id) @@ -83,7 +83,7 @@ it_behaves_like 'transfers all facts from source to destination' end context 'when only destinations are in the group' do - let(:group) { create(:asset_group, assets: destinations)} + let(:group) { create(:asset_group, assets: destinations) } before do destinations.zip(sources).each do |d,s| d.facts << create(:fact, predicate: 'transferredFrom', object_asset_id: s.id) diff --git a/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb b/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb index cece4422..33813ce2 100644 --- a/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb +++ b/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb @@ -14,16 +14,16 @@ } let(:rack) { create(:asset, facts: [ create(:fact, predicate: 'a', object: 'TubeRack'), - wells.map{|w| create(:fact, predicate: 'contains', object_asset_id: w.id)} + wells.map { |w| create(:fact, predicate: 'contains', object_asset_id: w.id) } ].flatten)} let(:tubes) { - 5.times.map{ create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } + 5.times.map { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } } let(:instance) { TransferTubesToTubeRackByPosition.new(asset_group: group) } context 'when it receives a rack and a set of tubes' do - let(:group) { create(:asset_group, assets: [rack, tubes].flatten)} + let(:group) { create(:asset_group, assets: [rack, tubes].flatten) } context 'when the tubes do not relate with the rack' do it 'does not perform any changes' do expect(instance.process.to_h.keys.length).to eq(0) @@ -37,7 +37,7 @@ end context 'when only some of the tubes are related with the rack' do let(:unrelated_tubes) { - 5.times.map{ create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } + 5.times.map { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } } before do group.assets << unrelated_tubes @@ -45,27 +45,27 @@ it 'transfers the related tubes' do added_facts = instance.process.to_h[:add_facts] expect(added_facts.count).not_to eq(0) - transfers = added_facts.select{|triple| triple[1] == 'transfer'}.map{|triple| [triple[0], triple[2]]} + transfers = added_facts.select { |triple| triple[1] == 'transfer' }.map { |triple| [triple[0], triple[2]] } expect(tubes.map(&:uuid).zip(wells.map(&:uuid))).to eq(transfers) end it 'does not transfer unrelated tubes' do added_facts = instance.process.to_h[:add_facts] expect(added_facts.count).not_to eq(0) - transferred_tubes = added_facts.select{|triple| triple[1] == 'transfer'}.map{|triple| triple[0]} + transferred_tubes = added_facts.select { |triple| triple[1] == 'transfer' }.map { |triple| triple[0] } expect((unrelated_tubes.map(&:uuid) & transferred_tubes).length).to eq(0) end end it 'transfers the tubes into the wells of the rack by column order' do added_facts = instance.process.to_h[:add_facts] expect(added_facts.count).not_to eq(0) - transfers = added_facts.select{|triple| triple[1] == 'transfer'}.map{|triple| [triple[0], triple[2]]} + transfers = added_facts.select { |triple| triple[1] == 'transfer' }.map { |triple| [triple[0], triple[2]] } expect(tubes.map(&:uuid).zip(wells.map(&:uuid))).to eq(transfers) end it 'creates inverse properties transfer and transferredFrom' do added_facts = instance.process.to_h[:add_facts] expect(added_facts.count).not_to eq(0) - transfers = added_facts.select{|triple| triple[1] == 'transfer'}.map{|triple| [triple[0], triple[2]]} - transferredFrom = added_facts.select{|triple| triple[1] == 'transferredFrom'}.map{|triple| [triple[2], triple[0]]} + transfers = added_facts.select { |triple| triple[1] == 'transfer' }.map { |triple| [triple[0], triple[2]] } + transferredFrom = added_facts.select { |triple| triple[1] == 'transferredFrom' }.map { |triple| [triple[2], triple[0]] } expect(transferredFrom).to eq(transfers) end @@ -81,8 +81,8 @@ end context 'when all of the tubes have an aliquot type' do - let(:aliquot_dna) {"DNA"} - let(:aliquot_rna) { "RNA"} + let(:aliquot_dna) { "DNA" } + let(:aliquot_rna) { "RNA" } before do tubes.each do |t| @@ -103,7 +103,7 @@ let(:aliquot) { aliquot_dna } it 'will set up a DNA Stock plate purpose' do added_facts = instance.process.to_h[:add_facts] - purposes = added_facts.select{|triple| triple[1]=='purpose'} + purposes = added_facts.select { |triple| triple[1]=='purpose' } expect(purposes.size).to eq(1) expect(purposes.first[0]).to eq(rack.uuid) expect(purposes.first[2]).to eq("DNA Stock Plate") @@ -113,7 +113,7 @@ let(:aliquot) { aliquot_rna } it 'will set up an RNA Stock plate purpose' do added_facts = instance.process.to_h[:add_facts] - purposes = added_facts.select{|triple| triple[1]=='purpose'} + purposes = added_facts.select { |triple| triple[1]=='purpose' } expect(purposes.size).to eq(1) expect(purposes.first[0]).to eq(rack.uuid) expect(purposes.first[2]).to eq("RNA Stock Plate") @@ -165,14 +165,14 @@ added_facts = instance.process.to_h[:add_facts] expect(added_facts.count).not_to eq(0) - transfers = added_facts.select{|triple| triple[1] == 'transfer'}.map{|triple| [triple[0], triple[2]]} + transfers = added_facts.select { |triple| triple[1] == 'transfer' }.map { |triple| [triple[0], triple[2]] } expect(rest_tubes.map(&:uuid).zip(rest_wells.map(&:uuid))).to eq(transfers) end end context 'when there are no more space left in the rack' do let(:tubes) { - 7.times.map{ create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } + 7.times.map { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } } it 'produces an error' do set_errors = instance.process.to_h[:set_errors] diff --git a/spec/shared_examples/background_step.rb b/spec/shared_examples/background_step.rb index 8303a97e..9bd82239 100644 --- a/spec/shared_examples/background_step.rb +++ b/spec/shared_examples/background_step.rb @@ -41,7 +41,7 @@ context 'when the process of the background task fails' do it 'sets the state to error' do allow(step).to receive(:process).and_raise(StandardError, 'boom!') - expect{ step.execute_actions }.not_to raise_error + expect { step.execute_actions }.not_to raise_error expect(step.state).to eq('error') expect(step.output).to include('boom!') end @@ -67,7 +67,7 @@ context 'when the step fails again' do before do allow(step).to receive(:process).and_raise(StandardError, 'boom!') - expect{ step.execute_actions }.not_to raise_error + expect { step.execute_actions }.not_to raise_error step.reload end it 'sets the right state to the step' do From 4bed111cf563e235e92b9895edbff12de36791b5 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 21 Oct 2020 15:28:12 +0100 Subject: [PATCH 046/303] Add initial message renderer The Message::Activity will be used to help render the json for message sent to the warehouse. --- app/messages/messages/activity.rb | 52 +++++++++++ app/messages/messages/messages.rb | 5 ++ app/models/activity.rb | 18 +++- app/models/asset.rb | 33 +++++-- app/models/fact.rb | 2 +- app/models/kit.rb | 4 + config/database.yml | 2 +- spec/messages/activity_spec.rb | 109 +++++++++++++++++++++++ spec/views/heron_activities_view_spec.rb | 4 +- test/factories/assets.rb | 2 +- 10 files changed, 216 insertions(+), 15 deletions(-) create mode 100644 app/messages/messages/activity.rb create mode 100644 app/messages/messages/messages.rb create mode 100644 spec/messages/activity_spec.rb diff --git a/app/messages/messages/activity.rb b/app/messages/messages/activity.rb new file mode 100644 index 00000000..5e5a0e46 --- /dev/null +++ b/app/messages/messages/activity.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +# Namespace for message render +module Messages + # When an activity is completed we send a record of it to the ML Warehouse + # This class handles the rendering of this message. + class Activity + # The {::Activity} that is being rendered + attr_reader :activity + + def initialize(activity) + @activity = activity + end + + # Hash object used by #to_json to render the message + def as_json + { + sample_extraction_activity: payload, + lims: 'samples_extraction' + } + end + + private + + # Main payload of the message + def payload + { + samples: sample_payload, + activity_type: activity.activity_type_name, + instrument: activity.instrument_name, + kit_barcode: activity.kit_barcode, + kit_type: activity.kit_type, + date: activity.completed_at, + user: activity.last_user_fullname, + _activity_id_: activity.id + } + end + + def sample_payload + activity.assets.flat_map do |asset| + input_barcode = asset.walk_transfers.barcode + asset.supplier_sample_name_facts.map do |fact| + { + supplier_sample_name: fact.object, + input_barcode: input_barcode, + output_barcode: asset.barcode + } + end + end + end + end +end diff --git a/app/messages/messages/messages.rb b/app/messages/messages/messages.rb new file mode 100644 index 00000000..8c25727d --- /dev/null +++ b/app/messages/messages/messages.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Namespace for message render +module Messages +end diff --git a/app/models/activity.rb b/app/models/activity.rb index 1dd2ad77..1b8207f0 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -1,18 +1,21 @@ +# frozen_string_literal: true + require 'date' class Activity < ActiveRecord::Base - validates :activity_type, :presence => true + validates :activity_type, presence: true #validates :asset_group, :presence => true belongs_to :activity_type belongs_to :instrument belongs_to :kit - has_many :owned_asset_groups, :class_name => 'AssetGroup', :foreign_key => 'activity_owner_id' + has_many :owned_asset_groups, class_name: 'AssetGroup', foreign_key: 'activity_owner_id' has_many :steps - has_many :step_types, :through => :activity_type + has_many :step_types, through: :activity_type has_many :uploads belongs_to :asset_group, optional: true - has_many :users, :through => :steps + has_many :assets, through: :asset_group + has_many :users, through: :steps has_one :work_order scope :for_activity_type, ->(activity_type) { @@ -28,5 +31,12 @@ class Activity < ActiveRecord::Base include Activities::State include Activities::WebsocketEvents + delegate :name, to: :activity_type, prefix: true + delegate :barcode, :type, to: :kit, prefix: true + delegate :name, to: :instrument, prefix: true + delegate :fullname, to: :last_user, prefix: true + def last_user + users.order('steps.created_at, steps.id DESC').first + end end diff --git a/app/models/asset.rb b/app/models/asset.rb index f4d83ee0..7a5c6c49 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -15,15 +15,13 @@ class Asset < ActiveRecord::Base alias_attribute :name, :uuid - has_many :facts, :dependent => :delete_all + has_many :facts, dependent: :delete_all has_many :asset_groups_assets, dependent: :destroy has_many :asset_groups, through: :asset_groups_assets - has_many :steps, :through => :asset_groups - + has_many :steps, through: :asset_groups has_many :activities_affected, -> { distinct }, through: :asset_groups, class_name: 'Activity', source: :activity_owner - def update_compatible_activity_type ActivityType.not_deprecated.all.each do |at| activity_types << at if at.compatible_with?(self) @@ -89,6 +87,29 @@ def aliquot_type f ? f.object : "" end + # Returns all facts with the predicate 'supplier_sample_name' + # associated with the asset. This can either be those associated + # directly with the asset (such as for tubes) or + # via contained assets (for a plate) + def supplier_sample_name_facts + if has_predicate?('supplier_sample_name') + facts.with_predicate('supplier_sample_name') + else + facts.with_predicate('contains').flat_map do |fact| + fact.object_asset.supplier_sample_name_facts + end + end + end + + def walk_transfers + parent_fact = facts.with_predicate('transferredFrom').last + if parent_fact&.object_asset + parent_fact.object_asset.walk_transfers + else + self + end + end + def relation_id uuid end @@ -144,7 +165,7 @@ def attrs_for_sequencescape(traversed_list = []) end def study_and_barcode - [study_name, barcode_sequencescaped].join(' ') + "#{study_name} #{barcode_sequencescaped}" end def barcode_sequencescaped @@ -220,7 +241,7 @@ def position_value end def info_line - ["#{class_name}", "#{aliquot}","#{position_value}"].join(' ').strip + "#{class_name} #{aliquot} #{position_value}".strip end def class_name diff --git a/app/models/fact.rb b/app/models/fact.rb index 679d94b0..1ff78438 100644 --- a/app/models/fact.rb +++ b/app/models/fact.rb @@ -1,3 +1,4 @@ +# A Fact stores information about an {Asset} class Fact < ActiveRecord::Base belongs_to :asset, :counter_cache => true belongs_to :object_asset, :class_name => 'Asset' @@ -45,4 +46,3 @@ def canonical_comparison_for_sorting(f2) end end - diff --git a/app/models/kit.rb b/app/models/kit.rb index edca5d97..f96ebbfe 100644 --- a/app/models/kit.rb +++ b/app/models/kit.rb @@ -4,4 +4,8 @@ class Kit < ActiveRecord::Base has_one :activity_type, :through => :kit_type validates :kit_type, :presence => true + + def type + kit_type&.name + end end diff --git a/config/database.yml b/config/database.yml index 0d9540c6..a82d08fe 100644 --- a/config/database.yml +++ b/config/database.yml @@ -14,7 +14,7 @@ default: &default encoding: utf8 pool: 5 username: root - password: + password: development: <<: *default diff --git a/spec/messages/activity_spec.rb b/spec/messages/activity_spec.rb new file mode 100644 index 00000000..892112cb --- /dev/null +++ b/spec/messages/activity_spec.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Messages::Activity do + let(:activity_type) { FactoryBot.create :activity_type, name: 'Illumina Extraction' } + let(:instrument) { FactoryBot.create :instrument, name: 'Instument' } + let(:kit_type) { FactoryBot.create :kit_type, name: 'Kit type' } + let(:kit) { FactoryBot.create :kit, kit_type: kit_type } + let(:user) { FactoryBot.create :user, fullname: 'Users name' } + let(:well_attributes) do + [ + { supplier_sample_name: 'Sample A' }, + { supplier_sample_name: 'Sample B' } + ] + end + let(:target_plate) { FactoryBot.create :plate, well_attributes: well_attributes } + let(:source_plate) { FactoryBot.create :plate, well_attributes: well_attributes } + let(:intermediate_plate) { FactoryBot.create :plate, well_attributes: well_attributes } + let(:asset_group) { FactoryBot.create :asset_group, assets: [target_plate] } + let(:step_type) { FactoryBot.create :step_type, step_action: 'transfer_plate_to_plate.rb' } + # Both first and second transfer specifying the same asset group is based + # on the data I'm actually seeing in production + let(:first_transfer) do + FactoryBot.create :step, step_type: step_type, asset_group: asset_group, + user: user + end + let(:second_transfer) do + FactoryBot.create :step, step_type: step_type, asset_group: asset_group, + user: user + end + + let(:activity) do + FactoryBot.create :finished_activity, + activity_type: activity_type, + asset_group: asset_group, + kit: kit, + instrument: instrument, + steps: [first_transfer, second_transfer] + end + + def create_transfer(step:, from:, to:) + FactoryBot.create :fact, predicate: 'transferredFrom', + asset: to, + object_asset: from + FactoryBot.create :operation, predicate: 'transferredFrom', + asset: to, + step: step, + object_asset: from + end + + before do + activity + create_transfer step: first_transfer, + from: source_plate, + to: intermediate_plate + create_transfer step: second_transfer, + from: intermediate_plate, + to: target_plate + end + + subject(:results) do + described_class.new(activity).as_json + end + + it 'lists finished activities at the sample level' do + expect(results[:sample_extraction_activity][:samples].length).to eq 2 + end + + it 'has the expected keys' do + expect(results[:sample_extraction_activity].keys).to eq [ + :samples, + :activity_type, + :instrument, + :kit_barcode, + :kit_type, + :date, + :user, + :_activity_id_ + ] + end + + it 'lists the correct information' do + expect(results).to eq({ + sample_extraction_activity: { + samples: [ + { + supplier_sample_name: 'Sample A', + input_barcode: source_plate.barcode, + output_barcode: target_plate.barcode + }, + { + supplier_sample_name: 'Sample B', + input_barcode: source_plate.barcode, + output_barcode: target_plate.barcode + } + ], + activity_type: 'Illumina Extraction', + instrument: 'Instument', + kit_barcode: kit.barcode, + kit_type: 'Kit type', + date: activity.completed_at, + user: 'Users name', + _activity_id_: activity.id + }, + lims: 'samples_extraction' + }) + end +end diff --git a/spec/views/heron_activities_view_spec.rb b/spec/views/heron_activities_view_spec.rb index d29cdd1b..41b65c95 100644 --- a/spec/views/heron_activities_view_spec.rb +++ b/spec/views/heron_activities_view_spec.rb @@ -84,10 +84,10 @@ def create_transfer(step:, from:, to:) it 'lists the correct information' do expect(results.to_a).to include( - ['Example', source_plate.barcode, target_plate.barcode, + ['Sample A', source_plate.barcode, target_plate.barcode, 'Illumina Extraction', 'Instument', kit.barcode, 'Kit type', activity.completed_at, 'Users name', activity.id], - ['Example', source_plate.barcode, target_plate.barcode, + ['Sample B', source_plate.barcode, target_plate.barcode, 'Illumina Extraction', 'Instument', kit.barcode, 'Kit type', activity.completed_at, 'Users name', activity.id] ) diff --git a/test/factories/assets.rb b/test/factories/assets.rb index de92d7f0..06d58705 100644 --- a/test/factories/assets.rb +++ b/test/factories/assets.rb @@ -31,7 +31,7 @@ barcode { nil } facts do - build_list :fact, 1, predicate: 'supplier_sample_name', object: 'Example' + build_list :fact, 1, predicate: 'supplier_sample_name', object: supplier_sample_name end end end From bf63c05e1830535728e246619be5ac6ad14b9abf Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 21 Oct 2020 20:06:01 +0100 Subject: [PATCH 047/303] Add brief doc to Activity --- app/models/activity.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/models/activity.rb b/app/models/activity.rb index 1b8207f0..206a40c4 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -2,10 +2,12 @@ require 'date' -class Activity < ActiveRecord::Base - +# An Activity collects together a series of {Step steps} which were performed on +# an {AssetGroup}. The AssetGroup reflects the currently actively processed set +# of {Asset assets} so may be updated as the activity progresses. +class Activity < ApplicationRecord validates :activity_type, presence: true - #validates :asset_group, :presence => true + # validates :asset_group, :presence => true belongs_to :activity_type belongs_to :instrument belongs_to :kit From b1cbd710af20138f018d59e365c3b3e3c4ad192f Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 21 Oct 2020 20:28:05 +0100 Subject: [PATCH 048/303] Switch to ApplicationRecord --- app/models/action.rb | 2 +- app/models/activity_type.rb | 2 +- app/models/activity_type_compatibility.rb | 2 +- app/models/activity_type_step_type.rb | 2 +- app/models/asset.rb | 2 +- app/models/asset_group.rb | 2 +- app/models/asset_groups_asset.rb | 2 +- app/models/condition.rb | 4 ++-- app/models/condition_group.rb | 2 +- app/models/fact.rb | 2 +- app/models/instrument.rb | 2 +- app/models/kit.rb | 2 +- app/models/kit_type.rb | 2 +- app/models/label_template.rb | 2 +- app/models/printer.rb | 2 +- app/models/step.rb | 2 +- app/models/step_message.rb | 2 +- app/models/step_type.rb | 2 +- app/models/user.rb | 2 +- lib/changes_support/transaction_scope.rb | 2 +- 20 files changed, 21 insertions(+), 21 deletions(-) diff --git a/app/models/action.rb b/app/models/action.rb index b26c73f8..741aa0ba 100644 --- a/app/models/action.rb +++ b/app/models/action.rb @@ -1,4 +1,4 @@ -class Action < ActiveRecord::Base +class Action < ApplicationRecord belongs_to :subject_condition_group, :class_name => 'ConditionGroup' belongs_to :object_condition_group, :class_name => 'ConditionGroup' diff --git a/app/models/activity_type.rb b/app/models/activity_type.rb index f04bc47a..37610650 100644 --- a/app/models/activity_type.rb +++ b/app/models/activity_type.rb @@ -1,4 +1,4 @@ -class ActivityType < ActiveRecord::Base +class ActivityType < ApplicationRecord has_many :activities has_many :kit_types has_many :activity_type_step_types diff --git a/app/models/activity_type_compatibility.rb b/app/models/activity_type_compatibility.rb index 65f5f25f..04feebc1 100644 --- a/app/models/activity_type_compatibility.rb +++ b/app/models/activity_type_compatibility.rb @@ -1,4 +1,4 @@ -class ActivityTypeCompatibility < ActiveRecord::Base +class ActivityTypeCompatibility < ApplicationRecord belongs_to :activity_type belongs_to :asset end diff --git a/app/models/activity_type_step_type.rb b/app/models/activity_type_step_type.rb index 4fea8d73..d2b1dd23 100644 --- a/app/models/activity_type_step_type.rb +++ b/app/models/activity_type_step_type.rb @@ -1,4 +1,4 @@ -class ActivityTypeStepType < ActiveRecord::Base +class ActivityTypeStepType < ApplicationRecord belongs_to :activity_type belongs_to :step_type end diff --git a/app/models/asset.rb b/app/models/asset.rb index 7a5c6c49..e500064a 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -3,7 +3,7 @@ require 'pry' -class Asset < ActiveRecord::Base +class Asset < ApplicationRecord include Uuidable include Printables::Instance include Assets::Import diff --git a/app/models/asset_group.rb b/app/models/asset_group.rb index c127fdcd..76bad819 100644 --- a/app/models/asset_group.rb +++ b/app/models/asset_group.rb @@ -1,5 +1,5 @@ -class AssetGroup < ActiveRecord::Base +class AssetGroup < ApplicationRecord include Uuidable has_many :asset_groups_assets, dependent: :destroy diff --git a/app/models/asset_groups_asset.rb b/app/models/asset_groups_asset.rb index f12eedd1..b952e0c7 100644 --- a/app/models/asset_groups_asset.rb +++ b/app/models/asset_groups_asset.rb @@ -1,4 +1,4 @@ -class AssetGroupsAsset < ActiveRecord::Base +class AssetGroupsAsset < ApplicationRecord belongs_to :asset belongs_to :asset_group end diff --git a/app/models/condition.rb b/app/models/condition.rb index c440be64..356d5be7 100644 --- a/app/models/condition.rb +++ b/app/models/condition.rb @@ -1,4 +1,4 @@ -class Condition < ActiveRecord::Base +class Condition < ApplicationRecord belongs_to :condition_group has_many :activity_types, :through => :condition_group belongs_to :object_condition_group, :class_name => 'ConditionGroup' @@ -69,7 +69,7 @@ def runtime_compatible_with?(asset, related_asset) end if (predicate == 'sum') return asset.facts.with_predicate(object).count == 0 - end + end end def is_runtime_evaluable_condition? diff --git a/app/models/condition_group.rb b/app/models/condition_group.rb index 26b3e05b..64cc764e 100644 --- a/app/models/condition_group.rb +++ b/app/models/condition_group.rb @@ -1,4 +1,4 @@ -class ConditionGroup < ActiveRecord::Base +class ConditionGroup < ApplicationRecord belongs_to :step_type has_many :activity_types, :through => :step_type has_many :conditions, dependent: :destroy diff --git a/app/models/fact.rb b/app/models/fact.rb index 1ff78438..57d8ad34 100644 --- a/app/models/fact.rb +++ b/app/models/fact.rb @@ -1,5 +1,5 @@ # A Fact stores information about an {Asset} -class Fact < ActiveRecord::Base +class Fact < ApplicationRecord belongs_to :asset, :counter_cache => true belongs_to :object_asset, :class_name => 'Asset' diff --git a/app/models/instrument.rb b/app/models/instrument.rb index 62e4877b..e168da51 100644 --- a/app/models/instrument.rb +++ b/app/models/instrument.rb @@ -1,4 +1,4 @@ -class Instrument < ActiveRecord::Base +class Instrument < ApplicationRecord has_and_belongs_to_many :activity_types has_many :activities diff --git a/app/models/kit.rb b/app/models/kit.rb index f96ebbfe..4b472abd 100644 --- a/app/models/kit.rb +++ b/app/models/kit.rb @@ -1,4 +1,4 @@ -class Kit < ActiveRecord::Base +class Kit < ApplicationRecord belongs_to :kit_type has_many :activities has_one :activity_type, :through => :kit_type diff --git a/app/models/kit_type.rb b/app/models/kit_type.rb index 8b16cc67..be93a83c 100644 --- a/app/models/kit_type.rb +++ b/app/models/kit_type.rb @@ -1,4 +1,4 @@ -class KitType < ActiveRecord::Base +class KitType < ApplicationRecord belongs_to :activity_type has_many :kits end diff --git a/app/models/label_template.rb b/app/models/label_template.rb index eed63192..4c289213 100644 --- a/app/models/label_template.rb +++ b/app/models/label_template.rb @@ -1,4 +1,4 @@ -class LabelTemplate < ActiveRecord::Base +class LabelTemplate < ApplicationRecord validates_presence_of :name, :external_id validates_uniqueness_of :name, :external_id diff --git a/app/models/printer.rb b/app/models/printer.rb index 49b4a531..9ed2e827 100644 --- a/app/models/printer.rb +++ b/app/models/printer.rb @@ -1,4 +1,4 @@ -class Printer < ActiveRecord::Base +class Printer < ApplicationRecord scope :for_tube, ->() { where(:printer_type => 'Tube') } scope :for_plate, ->() { where(:printer_type => 'Plate') } scope :for_default, ->() { where(:default_printer => true) } diff --git a/app/models/step.rb b/app/models/step.rb index 39adb627..520b3a35 100644 --- a/app/models/step.rb +++ b/app/models/step.rb @@ -1,5 +1,5 @@ -class Step < ActiveRecord::Base +class Step < ApplicationRecord self.inheritance_column = :sti_type diff --git a/app/models/step_message.rb b/app/models/step_message.rb index ea4290ed..9b2ee78b 100644 --- a/app/models/step_message.rb +++ b/app/models/step_message.rb @@ -1,3 +1,3 @@ -class StepMessage < ActiveRecord::Base +class StepMessage < ApplicationRecord belongs_to :step end diff --git a/app/models/step_type.rb b/app/models/step_type.rb index 7beb2aa8..8998648f 100644 --- a/app/models/step_type.rb +++ b/app/models/step_type.rb @@ -1,6 +1,6 @@ require 'support_n3' -class StepType < ActiveRecord::Base +class StepType < ApplicationRecord before_update :remove_previous_conditions after_save :create_next_conditions #, :unless => :for_reasoning? diff --git a/app/models/user.rb b/app/models/user.rb index d9a8c73e..2dd1accf 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,4 @@ -class User < ActiveRecord::Base +class User < ApplicationRecord has_many :steps belongs_to :tube_printer, :class_name => 'Printer', :foreign_key => 'tube_printer_id' diff --git a/lib/changes_support/transaction_scope.rb b/lib/changes_support/transaction_scope.rb index 1b519979..86601cb4 100644 --- a/lib/changes_support/transaction_scope.rb +++ b/lib/changes_support/transaction_scope.rb @@ -37,7 +37,7 @@ def joins(join) end def _result_set_from_database(opts) - if (result_set.respond_to?(:superclass) && (result_set.superclass == ActiveRecord::Base)) + if (result_set.respond_to?(:superclass) && (result_set.superclass == ApplicationRecord)) @result_set = result_set.where(opts) else @result_set = result_set.to_a.concat(@klass.where(opts)) From 54450428bf1291531cb8310366d5c38b0aed1a2d Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 21 Oct 2020 15:16:03 +0100 Subject: [PATCH 049/303] Use bin/setup for travis --- .travis.yml | 6 +----- bin/setup | 11 ++++++++++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 31069c40..df22f636 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,11 +6,7 @@ cache: - node_modules - vendor/bundle install: -- bundle install --deployment -- yarn install -before_script: -- export SECRET_KEY_BASE=`bundle exec rake secret` -- bundle exec rake db:create RAILS_ENV=test +- bin/setup script: - bundle exec rake - yarn test diff --git a/bin/setup b/bin/setup index 636b9eec..1140f4e3 100755 --- a/bin/setup +++ b/bin/setup @@ -38,7 +38,16 @@ Dir.chdir APP_ROOT do end puts "\n== Preparing database ==" - system "bin/rake db:setup" + if ENV['RAILS_ENV'] == 'test' + # If the RAILS_ENV is already set to test (such as on the CI server) then + # not only will rake db:setup generate the test database, but will also seed + # it. This differs from the test database created when an environment is + # unspecified, which is unseeded. We avoid using rake db:setup in this case + # and just create the database and load the schema instead. + system "bin/rake db:create db:schema:load" + else + system "bin/rake db:setup" + end puts "\n== Removing old logs and tempfiles ==" system "rm -f log/*" From 09c9cab8198bd44a932426c306a0a82ad374320a Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 30 Oct 2020 14:29:55 +0000 Subject: [PATCH 050/303] Message broadcast on activity finish --- Gemfile | 9 ++-- Gemfile.lock | 10 +++- app/channels/application_cable/connection.rb | 2 +- app/messages/messages/activity.rb | 31 ++++++++---- app/models/activities/state.rb | 1 + app/models/activity.rb | 22 +++++++-- app/models/fact.rb | 1 + config/application.rb | 4 ++ config/initializers/warren.rb | 5 ++ config/warren.yml | 15 ++++++ lib/tasks/message_addition.rake | 52 ++++++++++++++++++++ spec/messages/activity_spec.rb | 41 ++++++++++----- spec/models/activities/state_spec.rb | 4 ++ spec/models/activity_spec.rb | 12 +++++ spec/spec_helper.rb | 6 +++ test/factories/assets.rb | 6 ++- 16 files changed, 188 insertions(+), 33 deletions(-) create mode 100644 config/initializers/warren.rb create mode 100644 config/warren.yml create mode 100644 lib/tasks/message_addition.rake diff --git a/Gemfile b/Gemfile index 80c69d02..01c40ed1 100644 --- a/Gemfile +++ b/Gemfile @@ -2,6 +2,7 @@ source 'http://rubygems.org' # Service libraries +gem 'sanger_warren' # Wraps bunny and manages connection pools and configuration gem 'puma' gem 'daemons' gem 'redis' @@ -17,7 +18,6 @@ gem 'micro_token' gem 'activerecord-import' gem 'aasm' - # Rails views and UI gem 'turbolinks' gem 'bootstrap_form' @@ -36,18 +36,17 @@ gem 'will_paginate-bootstrap' # Javascript UI gem 'ejs' gem 'dropzonejs-rails' -gem 'rails-assets-tether'#, '>= 1.1.0' +gem 'rails-assets-tether' gem 'ace-rails-ap' # Serializers gem 'rdf-n3' -gem 'jbuilder'#, '~> 2.0' -gem 'yajl-ruby'#, '>= 1.3' +gem 'jbuilder' +gem 'yajl-ruby' gem 'google_hash' # Traction endpoints gem 'jsonapi-resources' - gem 'json_api_client' # Tools diff --git a/Gemfile.lock b/Gemfile.lock index 19194c99..08d8873b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -64,6 +64,7 @@ GEM tzinfo (~> 1.1) addressable (2.6.0) public_suffix (>= 2.0.2, < 4.0) + amq-protocol (2.3.2) arel (8.0.0) ast (2.4.1) autoprefixer-rails (9.6.0) @@ -81,6 +82,8 @@ GEM actionpack (>= 5.0) activemodel (>= 5.0) builder (3.2.3) + bunny (2.17.0) + amq-protocol (~> 2.3, >= 2.3.1) byebug (11.0.1) coderay (1.1.2) concurrent-ruby (1.1.5) @@ -185,7 +188,7 @@ GEM connection_pool (~> 2.2) net-http-pipeline (1.0.1) netrc (0.11.0) - nio4r (2.4.0) + nio4r (2.5.4) nokogiri (1.10.3) mini_portile2 (~> 2.4.0) os (0.9.6) @@ -308,6 +311,10 @@ GEM ruby-progressbar (1.10.1) sane (0.25.8) os (~> 0) + sanger_warren (0.1.0) + bunny (~> 2.17.0) + connection_pool (~> 2.2.0) + multi_json (~> 1.0) sass (3.7.4) sass-listen (~> 4.0.0) sass-listen (4.0.0) @@ -452,6 +459,7 @@ DEPENDENCIES rubocop-rails ruby-growl sanger_barcode_format! + sanger_warren sass-rails sdoc sequencescape-client-api diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index eab38420..a7c9a476 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -4,7 +4,7 @@ class Connection < ActionCable::Connection::Base def connect #self.current_user = nil - token = cookies.encrypted['SOME SECRET']['token'] + token = cookies.encrypted.dig('SOME SECRET', 'token') if token self.current_user = User.find_by(:token => token) return if self.current_user diff --git a/app/messages/messages/activity.rb b/app/messages/messages/activity.rb index 5e5a0e46..34c03ef9 100644 --- a/app/messages/messages/activity.rb +++ b/app/messages/messages/activity.rb @@ -8,40 +8,53 @@ class Activity # The {::Activity} that is being rendered attr_reader :activity - def initialize(activity) + def initialize(activity, state: 'finished') @activity = activity + @state = state + end + + # Used by warren to generate the routing key + def routing_key + "activity.#{@state}.#{activity.id}" + end + + # Interface for warren. Avoids the need to wrap our message in one + # of warren's onw Warren::Message classes + def payload + to_json end # Hash object used by #to_json to render the message - def as_json + def as_json(_args = {}) { - sample_extraction_activity: payload, - lims: 'samples_extraction' + samples_extraction_activity: samples_extraction_activity, + lims: 'SAMPEXT' } end private # Main payload of the message - def payload + def samples_extraction_activity { samples: sample_payload, activity_type: activity.activity_type_name, instrument: activity.instrument_name, kit_barcode: activity.kit_barcode, kit_type: activity.kit_type, - date: activity.completed_at, + completed_at: activity.completed_at, + updated_at: activity.updated_at, user: activity.last_user_fullname, - _activity_id_: activity.id + activity_id: activity.id } end def sample_payload activity.assets.flat_map do |asset| input_barcode = asset.walk_transfers.barcode - asset.supplier_sample_name_facts.map do |fact| + asset.sample_uuid_facts.map do |fact| { - supplier_sample_name: fact.object, + sample_uuid: TokenUtil.unquote(fact.object), input_barcode: input_barcode, output_barcode: asset.barcode } diff --git a/app/models/activities/state.rb b/app/models/activities/state.rb index a2b57de7..ea57a950 100644 --- a/app/models/activities/state.rb +++ b/app/models/activities/state.rb @@ -10,6 +10,7 @@ def finish ActiveRecord::Base.transaction do update_attributes(:completed_at => DateTime.now, state: 'finish') end + after_finish if respond_to?(:after_finish) end def finished? diff --git a/app/models/activity.rb b/app/models/activity.rb index 206a40c4..bda5518c 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -33,12 +33,26 @@ class Activity < ApplicationRecord include Activities::State include Activities::WebsocketEvents - delegate :name, to: :activity_type, prefix: true - delegate :barcode, :type, to: :kit, prefix: true - delegate :name, to: :instrument, prefix: true - delegate :fullname, to: :last_user, prefix: true + delegate :name, to: :activity_type, prefix: true, allow_nil: true + delegate :barcode, :type, to: :kit, prefix: true, allow_nil: true + delegate :name, to: :instrument, prefix: true, allow_nil: true + delegate :fullname, to: :last_user, prefix: true, allow_nil: true + + + # Called following state transition to finish + # Broadcasts the activity to the ML warehouse + def after_finish + send_message + end def last_user users.order('steps.created_at, steps.id DESC').first end + + private + + def send_message + message = Messages::Activity.new(self) + Warren.handler << message + end end diff --git a/app/models/fact.rb b/app/models/fact.rb index 57d8ad34..6a23ae2b 100644 --- a/app/models/fact.rb +++ b/app/models/fact.rb @@ -8,6 +8,7 @@ class Fact < ApplicationRecord scope :with_ns_predicate, ->(namespace) { where(:ns_predicate => namespace) } scope :with_fact, -> (predicate, object) { where(:predicate => predicate, :object => object) } scope :from_remote_asset, ->() { where(:is_remote? => true) } + scope :created_before, ->(date) { date.nil? ? all : where('created_at < ?', date) } validates :object_asset_id, presence: true, unless: :literal? validates :object_asset_id, presence: false, if: :literal? diff --git a/config/application.rb b/config/application.rb index 0f14ce8b..f3fc5d4f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -29,5 +29,9 @@ class Application < Rails::Application config.admin_email = 'admin@test.com' config.barcode_prefix = 'SE' + + # Load the warren configuration from config/warren.yml + # Warren controls connection to the RabbitMQ server + config.warren = config_for(:warren) end end diff --git a/config/initializers/warren.rb b/config/initializers/warren.rb new file mode 100644 index 00000000..08233e44 --- /dev/null +++ b/config/initializers/warren.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +require 'warren' + +Warren.setup(Rails.application.config.warren.deep_symbolize_keys.slice(:type, :config)) diff --git a/config/warren.yml b/config/warren.yml new file mode 100644 index 00000000..021a3d31 --- /dev/null +++ b/config/warren.yml @@ -0,0 +1,15 @@ +development: + type: broadcast + config: # Useful to allow easy switching to broadcast in development + routing_key_prefix: development + server: + host: localhost + port: 5672 + username: guest + password: guest + vhost: / + frame_max: 0 + heartbeat: 30 + exchange: psd.sequencescape +test: + type: test diff --git a/lib/tasks/message_addition.rake b/lib/tasks/message_addition.rake new file mode 100644 index 00000000..914d98f0 --- /dev/null +++ b/lib/tasks/message_addition.rake @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +namespace :message_addition do + desc 'Add uuids to any assets missing them' + task back_populate_uuids: :environment do + # Control how many samples are processed in a batch. Main limitation here + # is the limits on the query to the Sequencescape API. + block_size = 100 + + puts 'Finding samples needing uuids...' + asset_sample_ids = Fact.with_predicate('sanger_sample_id') + .joins("LEFT OUTER JOIN facts AS uuid ON uuid.predicate = 'sample_uuid' AND uuid.asset_id = facts.asset_id") + .where('uuid.object IS NULL') + .pluck('facts.asset_id', 'facts.object') + puts "#{asset_sample_ids.length} to migrate" + asset_sample_ids.each_slice(block_size) do |slice| + puts '=' * 80 + puts "Processing #{slice.first.inspect} to #{slice.last.inspect}" + puts 'Looking up uuids' + sanger_sample_ids = slice.map(&:last) + uuid_hash = SequencescapeClientV2::Sample.where(sanger_sample_id: sanger_sample_ids) + .select(:sanger_sample_id, :uuid) + .all + .each_with_object({}) do |sample, store| + store[sample.sanger_sample_id] = sample.uuid + end + puts 'Building facts' + fact_attributes = slice.map do |asset_id, sanger_sample_id| + next if uuid_hash[sanger_sample_id].nil? + + { asset_id: asset_id, predicate: 'sample_uuid', object: uuid_hash[sanger_sample_id] } + end.compact + puts 'Creating facts' + Fact.create!(fact_attributes) + puts 'Done!' + end + end + + desc 'Broadcast historic activities' + task back_populate_activities: [:environment, :back_populate_uuids] do + # Control how many samples are processed in a batch. Main limitation here + # is the limits on the query to the Sequencescape API. + Activity.finished.find_each do |activity| + puts "Sending activity #{activity.id}" + if activity.steps.empty? + puts 'Skipping... no steps' + next + end + activity.send(:send_message) + end + end +end diff --git a/spec/messages/activity_spec.rb b/spec/messages/activity_spec.rb index 892112cb..3f064934 100644 --- a/spec/messages/activity_spec.rb +++ b/spec/messages/activity_spec.rb @@ -8,10 +8,13 @@ let(:kit_type) { FactoryBot.create :kit_type, name: 'Kit type' } let(:kit) { FactoryBot.create :kit, kit_type: kit_type } let(:user) { FactoryBot.create :user, fullname: 'Users name' } + let(:sample_a_uuid) { SecureRandom.uuid } + let(:sample_b_uuid) { SecureRandom.uuid } let(:well_attributes) do [ - { supplier_sample_name: 'Sample A' }, - { supplier_sample_name: 'Sample B' } + # Quotes around UUID reflect what I'm actually seeing in the DB. + { supplier_sample_name: 'Sample A', sample_uuid: "\"#{sample_a_uuid}\"" }, + { supplier_sample_name: 'Sample B', sample_uuid: "\"#{sample_b_uuid}\"" } ] end let(:target_plate) { FactoryBot.create :plate, well_attributes: well_attributes } @@ -64,33 +67,34 @@ def create_transfer(step:, from:, to:) end it 'lists finished activities at the sample level' do - expect(results[:sample_extraction_activity][:samples].length).to eq 2 + expect(results[:samples_extraction_activity][:samples].length).to eq 2 end it 'has the expected keys' do - expect(results[:sample_extraction_activity].keys).to eq [ + expect(results[:samples_extraction_activity].keys).to eq [ :samples, :activity_type, :instrument, :kit_barcode, :kit_type, - :date, + :completed_at, + :updated_at, :user, - :_activity_id_ + :activity_id ] end it 'lists the correct information' do expect(results).to eq({ - sample_extraction_activity: { + samples_extraction_activity: { samples: [ { - supplier_sample_name: 'Sample A', + sample_uuid: sample_a_uuid, input_barcode: source_plate.barcode, output_barcode: target_plate.barcode }, { - supplier_sample_name: 'Sample B', + sample_uuid: sample_b_uuid, input_barcode: source_plate.barcode, output_barcode: target_plate.barcode } @@ -99,11 +103,24 @@ def create_transfer(step:, from:, to:) instrument: 'Instument', kit_barcode: kit.barcode, kit_type: 'Kit type', - date: activity.completed_at, + # created_at: activity.created_at, # Don't really want this + updated_at: activity.updated_at, + completed_at: activity.completed_at, user: 'Users name', - _activity_id_: activity.id + activity_id: activity.id }, - lims: 'samples_extraction' + lims: 'SAMPEXT' }) end + + describe '#routing_key' do + subject { described_class.new(activity).routing_key } + it { is_expected.to eq "activity.finished.#{activity.id}" } + end + + describe '#payload' do + subject { described_class.new(activity).payload } + it { puts JSON.parse(described_class.new(activity).send(:samples_extraction_activity).to_json) } + it { is_expected.to eq results.to_json } + end end diff --git a/spec/models/activities/state_spec.rb b/spec/models/activities/state_spec.rb index 914c2ce2..8df33b34 100644 --- a/spec/models/activities/state_spec.rb +++ b/spec/models/activities/state_spec.rb @@ -9,5 +9,9 @@ it 'sets up a completion date' do expect { activity.finish }.to change { activity.completed_at }.from(nil) end + it 'calls the after_finish callback' do + expect(activity).to receive(:after_finish) + activity.finish + end end end diff --git a/spec/models/activity_spec.rb b/spec/models/activity_spec.rb index b560e250..d4496a8c 100644 --- a/spec/models/activity_spec.rb +++ b/spec/models/activity_spec.rb @@ -13,4 +13,16 @@ expect(Activity.for_user(user)).to eq([act1]) end end + + describe '#after_finish', warren: true do + let(:activity) { create :activity } + + before do + activity.after_finish + end + + it 'broadcasts the activity message' do + expect(Warren.handler.messages_matching("activity.finished.#{activity.id}")).to eq(1) + end + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ce4d9a3e..37324f72 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -48,6 +48,12 @@ # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups + config.around(:each, warren: true) do |ex| + Warren.handler.enable! + ex.run + Warren.handler.disable! + end + # The settings below are suggested to provide a good initial experience # with RSpec, but feel free to customize to your heart's content. =begin diff --git a/test/factories/assets.rb b/test/factories/assets.rb index 06d58705..a222a46c 100644 --- a/test/factories/assets.rb +++ b/test/factories/assets.rb @@ -26,12 +26,16 @@ factory :well_with_samples do transient do supplier_sample_name { 'Sample Name' } + sample_uuid { SecureRandom.uuid } end barcode { nil } facts do - build_list :fact, 1, predicate: 'supplier_sample_name', object: supplier_sample_name + [ + build(:fact, predicate: 'supplier_sample_name', object: supplier_sample_name), + build(:fact, predicate: 'sample_uuid', object: sample_uuid) + ] end end end From 31ef8d61674d0767ba6b32eb3b89c49a3db4e12f Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 30 Oct 2020 14:30:40 +0000 Subject: [PATCH 051/303] Improve performance of sample pages We've still got quite a bit of N+1 loading going on, but this is an initial attempt to load the required information --- .../samples_not_started_controller.rb | 5 ++- app/controllers/samples_started_controller.rb | 8 ++++- app/models/asset.rb | 36 ++++++++++++++----- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/app/controllers/samples_not_started_controller.rb b/app/controllers/samples_not_started_controller.rb index decd174b..799203bb 100644 --- a/app/controllers/samples_not_started_controller.rb +++ b/app/controllers/samples_not_started_controller.rb @@ -3,7 +3,10 @@ class SamplesNotStartedController < SamplesStatusController private def get_assets_for_activity_type(activity_type) - activity_type.assets.not_started.paginate(pagination_params_for_activity_type(activity_type)) + activity_type.assets + .not_started + .preload(:facts) + .paginate(pagination_params_for_activity_type(activity_type)) end end diff --git a/app/controllers/samples_started_controller.rb b/app/controllers/samples_started_controller.rb index ab97d0cb..986a11c9 100644 --- a/app/controllers/samples_started_controller.rb +++ b/app/controllers/samples_started_controller.rb @@ -3,7 +3,13 @@ class SamplesStartedController < SamplesStatusController private def get_assets_for_activity_type(activity_type) - activity_type.assets.started.joins(:activities).distinct(activities: :id, assets: :id).order(id: :desc).paginate(pagination_params_for_activity_type(activity_type)) + activity_type.assets + .started + .joins(:activities) + .preload(:facts, activities: [:instrument]) + .distinct(activities: :id, assets: :id) + .order(id: :desc) + .paginate(pagination_params_for_activity_type(activity_type)) end end diff --git a/app/models/asset.rb b/app/models/asset.rb index e500064a..e093d760 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -4,6 +4,8 @@ require 'pry' class Asset < ApplicationRecord + DataIntegrityError = Class.new(StandardError) + include Uuidable include Printables::Instance include Assets::Import @@ -15,7 +17,18 @@ class Asset < ApplicationRecord alias_attribute :name, :uuid - has_many :facts, dependent: :delete_all + has_many :facts, dependent: :delete_all do + # If we've already loaded our facts, avoid hitting the database a + # second time. + def with_predicate(predicate) + if loaded? + select { |fact| fact.predicate.casecmp?(predicate) } + else + super + end + end + end + has_many :asset_groups_assets, dependent: :destroy has_many :asset_groups, through: :asset_groups_assets has_many :steps, through: :asset_groups @@ -87,24 +100,29 @@ def aliquot_type f ? f.object : "" end - # Returns all facts with the predicate 'supplier_sample_name' + # Returns all facts with the predicate 'sample_uuid' # associated with the asset. This can either be those associated # directly with the asset (such as for tubes) or # via contained assets (for a plate) - def supplier_sample_name_facts - if has_predicate?('supplier_sample_name') - facts.with_predicate('supplier_sample_name') + def sample_uuid_facts + if has_predicate?('sample_uuid') + facts.with_predicate('sample_uuid') else facts.with_predicate('contains').flat_map do |fact| - fact.object_asset.supplier_sample_name_facts + fact.object_asset.sample_uuid_facts end end end - def walk_transfers - parent_fact = facts.with_predicate('transferredFrom').last + # Walk back down the transfers, until you find the oldest. + # The created_before filter prevents us from an infinite + # loop in the event asset_a > asset_b > asset_a + def walk_transfers(before = nil) + parent_fact = facts.with_predicate('transferredFrom') + .created_before(before) + .last if parent_fact&.object_asset - parent_fact.object_asset.walk_transfers + parent_fact.object_asset.walk_transfers(parent_fact.created_at) else self end From 6c0450a7a469e8ceda11e5d73f7856a50d8ceab6 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 3 Nov 2020 10:34:52 +0000 Subject: [PATCH 052/303] Rollback rack update The rack update was breaking the Rails CSRF protection. I suspect that we'll need to update other gems to allow us to move forward. Probably Rails itself. --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 08d8873b..2cdbe57b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -204,7 +204,7 @@ GEM pusher-client (0.6.2) json websocket (~> 1.0) - rack (2.2.3) + rack (2.0.7) rack-proxy (0.6.5) rack rack-test (1.1.0) From 9503b07ba8f79db8feed6734ab6a62dd82288531 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 3 Nov 2020 10:37:23 +0000 Subject: [PATCH 053/303] Rollback token lookup --- app/channels/application_cable/connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index a7c9a476..eab38420 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -4,7 +4,7 @@ class Connection < ActionCable::Connection::Base def connect #self.current_user = nil - token = cookies.encrypted.dig('SOME SECRET', 'token') + token = cookies.encrypted['SOME SECRET']['token'] if token self.current_user = User.find_by(:token => token) return if self.current_user From 62137f4b6564cf44391525a9d1f529730e28fa23 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 3 Nov 2020 10:38:10 +0000 Subject: [PATCH 054/303] Improve performance - Retrieve sequencescape records in single request - Allow pre-loading on facts --- app/models/asset.rb | 9 ++++++--- lib/fact_changes.rb | 2 +- lib/sequencescape_client.rb | 12 ++++++------ spec/lib/actions/racking_spec.rb | 4 ++-- spec/messages/activity_spec.rb | 11 +++++++---- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index e093d760..78bc6925 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -118,9 +118,12 @@ def sample_uuid_facts # The created_before filter prevents us from an infinite # loop in the event asset_a > asset_b > asset_a def walk_transfers(before = nil) - parent_fact = facts.with_predicate('transferredFrom') - .created_before(before) - .last + transfers = facts.with_predicate('transferredFrom') + parent_fact = if transfers.respond_to?(:created_before) + transfers.created_before(before).last + else + transfers.reverse.detect { |t| before.nil? || (t.created_at < before) } + end if parent_fact&.object_asset parent_fact.object_asset.walk_transfers(parent_fact.created_at) else diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index 8feb0bc2..7c56a3f7 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -302,7 +302,7 @@ def uuid_for_wildcard(wildcard) end def wildcard_for_uuid(uuid) - wildcards.keys.select { |key| wildcards[key] == uuid }.first + wildcards.keys.detect { |key| wildcards[key] == uuid } end def find_instance_from_uuid(klass, uuid) diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 83d522fe..9fd4bb67 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -67,16 +67,16 @@ def self.find_by_uuid(uuid, opts = nil) find_by(uuid: uuid) end + # TODO: In most cases we should know what type of record we're looking up. def self.find_by(search_conditions) [ - SequencescapeClientV2::Plate, - SequencescapeClientV2::Tube, - SequencescapeClientV2::Well, - SequencescapeClientV2::TubeRack + SequencescapeClientV2::Plate.includes('wells.aliquots.sample'), + SequencescapeClientV2::Tube.includes('aliquots.sample'), + SequencescapeClientV2::Well.includes('aliquots.sample'), + SequencescapeClientV2::TubeRack.includes('racked_tubes.tube.aliquots.sample') ].each do |klass| begin - search = klass.where(search_conditions) - search = search.first if search + search = klass.where(search_conditions).first return search if search rescue JsonApiClient::Errors::ClientError => e # Ignore filter error diff --git a/spec/lib/actions/racking_spec.rb b/spec/lib/actions/racking_spec.rb index 29d2f686..446e3471 100644 --- a/spec/lib/actions/racking_spec.rb +++ b/spec/lib/actions/racking_spec.rb @@ -63,10 +63,10 @@ ) send(method, asset_group).apply(another_step) - assets = asset.facts.with_predicate('contains').map(&:object_asset) + assets = asset.reload.facts.with_predicate('contains').map(&:object_asset) expect(assets.count).to eq(0) - assets = actual_parent.facts.with_predicate('contains').map(&:object_asset) + assets = actual_parent.reload.facts.with_predicate('contains').map(&:object_asset) expect(assets.count).to eq(96) assets.each do |a| expect(a.facts.with_predicate('location').count).to eq(1) diff --git a/spec/messages/activity_spec.rb b/spec/messages/activity_spec.rb index 3f064934..8b50fb09 100644 --- a/spec/messages/activity_spec.rb +++ b/spec/messages/activity_spec.rb @@ -42,10 +42,11 @@ steps: [first_transfer, second_transfer] end - def create_transfer(step:, from:, to:) + def create_transfer(step:, from:, to:, created_at:) FactoryBot.create :fact, predicate: 'transferredFrom', asset: to, - object_asset: from + object_asset: from, + created_at: created_at FactoryBot.create :operation, predicate: 'transferredFrom', asset: to, step: step, @@ -56,10 +57,12 @@ def create_transfer(step:, from:, to:) activity create_transfer step: first_transfer, from: source_plate, - to: intermediate_plate + to: intermediate_plate, + created_at: 1.day.ago create_transfer step: second_transfer, from: intermediate_plate, - to: target_plate + to: target_plate, + created_at: 1.hour.ago end subject(:results) do From 51f1499a71868224ce2861934c8603e343cf2065 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 3 Nov 2020 10:40:08 +0000 Subject: [PATCH 055/303] Render exceptions in development mode - Plus strip out debugging --- config/environments/development.rb | 2 +- lib/fact_changes.rb | 2 ++ lib/sequencescape_client.rb | 1 - spec/messages/activity_spec.rb | 1 - 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/environments/development.rb b/config/environments/development.rb index 0a87ca31..1692a807 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -13,7 +13,7 @@ config.eager_load = true # Show full error reports and disable caching. - config.consider_all_requests_local = false + config.consider_all_requests_local = true config.action_controller.perform_caching = false # Don't care if the mailer can't send. diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index 7c56a3f7..881cf615 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -500,6 +500,7 @@ def _remove_facts(step, facts_to_remove, with_operations = true) memo.concat(elems) if elems memo end.concat(Fact.where(id: ids)) + _instances_deletion(Fact, modified_list) do _fact_operations('removeFacts', step, modified_list) if with_operations end @@ -536,6 +537,7 @@ def _fact_operations(action_type, step, facts) Operation.new(:action_type => action_type, :step => step, :asset=> fact.asset, :predicate => fact.predicate, :object => fact.object, object_asset: fact.object_asset) end + modified_assets.flatten.compact.uniq.each(&:touch) operations end diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 9fd4bb67..54793f7f 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -85,4 +85,3 @@ def self.find_by(search_conditions) nil end end - diff --git a/spec/messages/activity_spec.rb b/spec/messages/activity_spec.rb index 8b50fb09..417b9a69 100644 --- a/spec/messages/activity_spec.rb +++ b/spec/messages/activity_spec.rb @@ -123,7 +123,6 @@ def create_transfer(step:, from:, to:, created_at:) describe '#payload' do subject { described_class.new(activity).payload } - it { puts JSON.parse(described_class.new(activity).send(:samples_extraction_activity).to_json) } it { is_expected.to eq results.to_json } end end From 9d2d91db54000b704a8077ea4c574e95905236a0 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 4 Nov 2020 08:16:12 +0000 Subject: [PATCH 056/303] Fix Dockerfile for new ruby version The previous Dockerfile was using an unofficial ruby + node base image. However, this was locked at ruby 2.5. This switches us to the official Ruby image, and installs node manually. --- Dockerfile | 10 ++++++---- config/initializers/warren.rb | 6 +++++- config/warren.yml | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 21c43581..bacb1d5a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,23 @@ -FROM starefossen/ruby-node +FROM ruby:2.6 ENV BUNDLER_VERSION=2.1.4 RUN apt-get update -qq && apt-get install -y -RUN apt-get -y install git vim +# Install node and Yarn +RUN curl -sL https://deb.nodesource.com/setup_15.x | bash - +RUN apt-get install -y nodejs +RUN npm install -g yarn WORKDIR /samples_extraction ADD Gemfile /samples_extraction ADD Gemfile.lock /samples_extraction ADD package.json /samples_extraction ADD yarn.lock /samples_extraction RUN gem install bundler -RUN bundle install +RUN bundle install --jobs=5 --deployment --without development test RUN yarn install ADD . /samples_extraction/ # Compiling assets RUN RAILS_ENV=production bundle exec rake assets:precompile -RUN RAILS_ENV=production bundle exec rake webpacker:compile # Generating sha RUN git rev-parse HEAD > REVISION diff --git a/config/initializers/warren.rb b/config/initializers/warren.rb index 08233e44..8746c2ef 100644 --- a/config/initializers/warren.rb +++ b/config/initializers/warren.rb @@ -2,4 +2,8 @@ require 'warren' -Warren.setup(Rails.application.config.warren.deep_symbolize_keys.slice(:type, :config)) +if Rails.application.config.warren.present? + Warren.setup(Rails.application.config.warren.deep_symbolize_keys.slice(:type, :config)) +else + Rails.logger.warn "Warren.yml not configured for #{ENV['RAILS_ENV']}" +end diff --git a/config/warren.yml b/config/warren.yml index 021a3d31..fed6438c 100644 --- a/config/warren.yml +++ b/config/warren.yml @@ -1,5 +1,5 @@ development: - type: broadcast + type: log config: # Useful to allow easy switching to broadcast in development routing_key_prefix: development server: From 7af09b5a7860762abfb40467311f1006d23f7563 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 4 Nov 2020 08:45:45 +0000 Subject: [PATCH 057/303] Add .dockerignore file Local container builds were breaking due to the contents of the node_modules directory. This change adds a dockerignore file, which prevents them from being copied to the container. We also add a handful of other directories which could potentially cause problems in future, or which are unnecessary to the app running. --- .dockerignore | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..98ca5d5f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,19 @@ +# See https://docs.docker.com/engine/reference/builder/#dockerignore-file +# Avoids copying these files into our docker-container + +# Node modules can break docker-builds on the local machine if it gets +# coppied to the container. (You'll see yarn integrity errors) +node_modules +# .bundle contains bundler configuration which is specific to our local system +.bundle + +# These folders store transisent informatation and aren't relevant between +# systems. They are in our .gitignore, so we also add them here to keep +# local builds consistent. +log +tmp + +# We're building our container for production, so lets exclude the test and +# spec folders. This will keep our container size a little smaller +test +spec From 24b86296fa9beea3bf39d6be578a093612be0c1b Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 4 Nov 2020 10:17:47 +0000 Subject: [PATCH 058/303] Do not require pry --- app/controllers/assets_controller.rb | 1 - app/controllers/instruments_controller.rb | 1 - app/controllers/steps_controller.rb | 1 - app/models/asset.rb | 2 -- lib/sequencescape_client.rb | 1 - 5 files changed, 6 deletions(-) diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index 26215008..c0a952c3 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -1,4 +1,3 @@ -require 'pry' class AssetsController < ApplicationController before_action :set_asset, only: [:show, :edit, :update, :destroy, :print] diff --git a/app/controllers/instruments_controller.rb b/app/controllers/instruments_controller.rb index 6f359ce4..e869fdf0 100644 --- a/app/controllers/instruments_controller.rb +++ b/app/controllers/instruments_controller.rb @@ -1,4 +1,3 @@ -require 'pry' class InstrumentsController < ApplicationController before_action :set_instrument, only: [:show, :edit, :update, :destroy, :use] diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb index 5a98630a..5cf81fa6 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -1,4 +1,3 @@ -require 'pry' class StepsController < ApplicationController before_action :set_step, only: [:update] diff --git a/app/models/asset.rb b/app/models/asset.rb index 78bc6925..7603c6fc 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -1,8 +1,6 @@ require 'sequencescape_client' require 'date' -require 'pry' - class Asset < ApplicationRecord DataIntegrityError = Class.new(StandardError) diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 54793f7f..e4e2aea2 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -1,7 +1,6 @@ #This file is part of SEQUENCESCAPE is distributed under the terms of GNU General Public License version 1 or later; #Please refer to the LICENSE and README files for information on licensing and authorship of this file. #Copyright (C) 2007-2011 Genome Research Ltd. -require 'pry' require 'sequencescape-api' require 'sequencescape' From 6d61fed8237bb53e163acce1a881228b2578165a Mon Sep 17 00:00:00 2001 From: Ben Topping Date: Wed, 17 Feb 2021 11:27:07 +0000 Subject: [PATCH 059/303] removed travis, added test workflow in github actions --- .github/workflows/test.yml | 43 +++++++++++++++++++++++++++++++++++++ .travis.yml | 28 ------------------------ compile-build | 44 -------------------------------------- 3 files changed, 43 insertions(+), 72 deletions(-) create mode 100644 .github/workflows/test.yml delete mode 100644 .travis.yml delete mode 100644 compile-build diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..9bd26000 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,43 @@ +name: Tests + +env: + TZ: Europe/London + +on: + - push + - pull_request + +jobs: + ruby: + + runs-on: ubuntu-latest + + env: + RAILS_ENV: test + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true # Runs bundle install and caches gems. See the ruby_test.yml + # example if you need more control over bundler. + - name: Run tests + run: bundle exec rake + + yarn: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup node + uses: actions/setup-node@v2 + with: + node-version: '14' + + - name: Install + run: yarn install + + - name: Run yarn test + run: yarn test \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index df22f636..00000000 --- a/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -language: ruby -cache: - bundler: true - yarn: true - directories: - - node_modules - - vendor/bundle -install: -- bin/setup -script: -- bundle exec rake -- yarn test -after_success: -- chmod +x ./compile-build -- "./compile-build" -services: -- redis-server -- mysql -deploy: - provider: releases - api_key: - secure: KO46Zxg55+qAiURnkgbu5p5TzFC4rYzgJ4KLqvW4h8c8JKZWgGVAHT6mAgKwuI3Kgzg2PR1M94FCch1DiH7/Y3mMRemWfB0Vy4lP9HE0O9R/Cz7zlBU1W8fgfiQ4qP+h4WurJp7sUEXCupApSZrAEAumUNL80XlQbD1XvCy9pzfz1w2Pt7gvcqTMM+pS/20icjz8VXUz9AGDwDFpKNyfP+kmQPJUKTJ6tJ44X/A3+VfoEjcHub5/egsLKt0h15JPGiR/hLpZDaH/x5f+zeeiHkL+EqduyqzsVHDVlY9zDTeQKmB1LZ3eH0xmTZwwB7pryZT1ldXodwU7Wt2uwwo6nrmAhVPbsS5cQ2TWCNOh2EbO+F1szF0glO5L1TVCK80P4VA0wOG4SrzeURoXPK6bi4SuynCoYJPzzy1KCpfKCdZAH1MtqhQ20oTq4y8KFs/9Q8BEZxNacu4nmyW4UlwYVgDaPdg+l2mDlR79/pKo3pVf6ZxKHBNKJukU4LhQMiVho2eym+ExC274E8PlXXdosgexieUUStFBLaF5i037nQa6YBJPjkS0DAiQs35o7fAanZjIVGkITH9NHGr5/Hh7Sv5q6SKBo1M+GS/nCp0Xu5BAIYizupczcNhqHGYZNmS2B4/zV+vJ5qvDsIInODKSEArMxdC2Y0+k0KxhtlERLhc= - file: release.tar.gz - file_glob: true - skip_cleanup: true - on: - repo: sanger/samples_extraction - tags: true diff --git a/compile-build b/compile-build deleted file mode 100644 index 753b3e5b..00000000 --- a/compile-build +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -set -e -echo 'Cleaning up' -RAILS_ENV=production bundle exec rake assets:clobber -echo 'Compiling assets' -RAILS_ENV=production bundle exec rake assets:precompile -RAILS_ENV=production bundle exec rake webpacker:compile -echo 'Generating sha' -git rev-parse HEAD > REVISION -git tag -l --points-at HEAD --sort -version:refname | head -1 > TAG -git rev-parse --abbrev-ref HEAD > BRANCH -echo 'Compiling tar.gz' -tar \ - --exclude='./*.swp' \ - --exclude='./.bundle' \ - --exclude='./.codeclimate.yml' \ - --exclude='./.git' \ - --exclude='./.gitignore' \ - --exclude='./.rspec' \ - --exclude='./.rubocop*' \ - --exclude='./.simplecov' \ - --exclude='./.tags' \ - --exclude='./.travis.yml' \ - --exclude='./README*' \ - --exclude='./compile-build' \ - --exclude='./coverage' \ - --exclude='./features' \ - --exclude='./knapsack_cucumber_report.json' \ - --exclude='./log/*' \ - --exclude='./node_modules' \ - --exclude='./run_coverage' \ - --exclude='./sbin' \ - --exclude='./*.sublime-project' \ - --exclude='./spec' \ - --exclude='./test' \ - --exclude='./tmp' \ - --exclude='./vendor/bundle' \ - --exclude='./yarn.lock' \ - --exclude='release.tar.gz' \ - -zcf /tmp/release.tar.gz ./ -mv /tmp/release.tar.gz ./release.tar.gz -echo 'Release complete!' -echo `pwd`/release.tar.gz From a5e77b41c6ce50841712d4d09112509f50bf823b Mon Sep 17 00:00:00 2001 From: Ben Topping Date: Wed, 17 Feb 2021 11:45:40 +0000 Subject: [PATCH 060/303] added mysql service for github actions test workflow --- .github/workflows/test.yml | 19 ++++++++++++++++++- config/database.yml | 2 ++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9bd26000..697203fd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,6 +15,18 @@ jobs: env: RAILS_ENV: test + services: + mysql: + # Use the Mysql docker image https://hub.docker.com/_/mysql + image: mysql:5.7 + ports: + - 3306 # Default port mappings + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + env: + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_ROOT_PASSWORD: '' + MYSQL_DATABASE: samples_extraction_test + steps: - uses: actions/checkout@v2 - name: Set up Ruby @@ -22,6 +34,11 @@ jobs: with: bundler-cache: true # Runs bundle install and caches gems. See the ruby_test.yml # example if you need more control over bundler. + - name: Set up environment + env: + DBPORT: ${{ job.services.mysql.ports[3306] }} + run: bin/setup + - name: Run tests run: bundle exec rake @@ -38,6 +55,6 @@ jobs: - name: Install run: yarn install - + - name: Run yarn test run: yarn test \ No newline at end of file diff --git a/config/database.yml b/config/database.yml index a82d08fe..c9b2aceb 100644 --- a/config/database.yml +++ b/config/database.yml @@ -13,6 +13,8 @@ default: &default adapter: mysql2 encoding: utf8 pool: 5 + host: 127.0.0.1 + port: <%= ENV.fetch('DBPORT','3306') %> username: root password: From 5e3c352d69fdda4414065fa5ca8e7ff40c65805e Mon Sep 17 00:00:00 2001 From: Ben Topping Date: Wed, 17 Feb 2021 15:17:49 +0000 Subject: [PATCH 061/303] added DBPORT variable for rake test --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 697203fd..7e4b46a6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,9 +37,11 @@ jobs: - name: Set up environment env: DBPORT: ${{ job.services.mysql.ports[3306] }} - run: bin/setup + run: bin/rake db:create db:schema:load - name: Run tests + env: + DBPORT: ${{ job.services.mysql.ports[3306] }} run: bundle exec rake yarn: From c099c594d8923018b2d58ed2bc7f56eb0c4ca069 Mon Sep 17 00:00:00 2001 From: Ben Topping Date: Wed, 17 Feb 2021 15:23:03 +0000 Subject: [PATCH 062/303] reverted back to correct environment setup --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7e4b46a6..95c177cc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,7 +37,7 @@ jobs: - name: Set up environment env: DBPORT: ${{ job.services.mysql.ports[3306] }} - run: bin/rake db:create db:schema:load + run: bin/setup - name: Run tests env: From faff6b0408863a35079d3824253d42537e62d3bd Mon Sep 17 00:00:00 2001 From: Ben Topping Date: Thu, 18 Feb 2021 10:21:28 +0000 Subject: [PATCH 063/303] added DBHOST variable in database config --- config/database.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/database.yml b/config/database.yml index c9b2aceb..3e1c78cd 100644 --- a/config/database.yml +++ b/config/database.yml @@ -13,7 +13,7 @@ default: &default adapter: mysql2 encoding: utf8 pool: 5 - host: 127.0.0.1 + host: <%= ENV.fetch('DBHOST','127.0.0.1') %> port: <%= ENV.fetch('DBPORT','3306') %> username: root password: From 1204c766a2436d26a1dc0fb27ca914a65251bf5e Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 18 Mar 2021 10:34:45 +0000 Subject: [PATCH 064/303] Add rubocop to CI --- .github/workflows/lint.yml | 22 ++++++++++++++++++++++ app/controllers/steps_controller.rb | 1 - 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..00c936e0 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,22 @@ +name: Tests + +env: + TZ: Europe/London + +on: + - push + - pull_request + +jobs: + ruby: + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true # Runs bundle install and caches gems. See the ruby_test.yml + # example if you need more control over bundler. + - name: Run Rubocop + run: bundle exec rubocop --extra-details --display-style-guide --parallel diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb index 5cf81fa6..c1a24a0a 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -1,4 +1,3 @@ - class StepsController < ApplicationController before_action :set_step, only: [:update] before_action :set_activity, only: [:create] From 0071fe87042e1ee153470a16db6148841134218d Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 18 Mar 2021 10:40:38 +0000 Subject: [PATCH 065/303] Update lint.yml --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 00c936e0..256efef0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,4 +1,4 @@ -name: Tests +name: Linting env: TZ: Europe/London From 0d9e0bc0ec91172e30aa30d7e7c27e392d8d1c8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Apr 2021 09:17:14 +0000 Subject: [PATCH 066/303] Bump y18n from 3.2.1 to 3.2.2 Bumps [y18n](https://github.com/yargs/y18n) from 3.2.1 to 3.2.2. - [Release notes](https://github.com/yargs/y18n/releases) - [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md) - [Commits](https://github.com/yargs/y18n/commits) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c8a9a2b3..c5de7a50 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9316,9 +9316,9 @@ xtend@~3.0.0: integrity sha1-XM50B7r2Qsunvs2laBEcST9ZZlo= y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== y18n@^4.0.0: version "4.0.0" From b6c1338738f0add497a5a5349ea3f5744ff582bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Apr 2021 09:17:15 +0000 Subject: [PATCH 067/303] Bump elliptic from 6.4.1 to 6.5.4 Bumps [elliptic](https://github.com/indutny/elliptic) from 6.4.1 to 6.5.4. - [Release notes](https://github.com/indutny/elliptic/releases) - [Commits](https://github.com/indutny/elliptic/compare/v6.4.1...v6.5.4) Signed-off-by: dependabot[bot] --- yarn.lock | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/yarn.lock b/yarn.lock index c8a9a2b3..e14a6919 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2018,10 +2018,10 @@ bluebird@^3.5.1: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== boolbase@~1.0.0: version "1.0.0" @@ -2052,7 +2052,7 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" -brorand@^1.0.1: +brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= @@ -3220,17 +3220,17 @@ electron-to-chromium@^1.3.191: integrity sha512-+edFdHGxLSmAKftXa5xZIg19rHkkJLiW+tRu0VMVG3RKztyeKX7d3pXf707lS6+BxB9uBun3RShbxCI1PtBAgQ== elliptic@^6.0.0: - version "6.4.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" + bn.js "^4.11.9" + brorand "^1.1.0" hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" emoji-regex@^7.0.1: version "7.0.3" @@ -4260,7 +4260,7 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hmac-drbg@^1.0.0: +hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= @@ -4434,16 +4434,21 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + inquirer@^3.0.6: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" @@ -5779,7 +5784,7 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: +minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= From ce5a0c8bafbe7497662acc3b5a066a63b31c80d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Apr 2021 22:06:55 +0000 Subject: [PATCH 068/303] Bump rexml from 3.2.4 to 3.2.5 Bumps [rexml](https://github.com/ruby/rexml) from 3.2.4 to 3.2.5. - [Release notes](https://github.com/ruby/rexml/releases) - [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md) - [Commits](https://github.com/ruby/rexml/compare/v3.2.4...v3.2.5) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2cdbe57b..fd8c839b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -270,7 +270,7 @@ GEM http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - rexml (3.2.4) + rexml (3.2.5) rspec-core (3.8.1) rspec-support (~> 3.8.0) rspec-expectations (3.8.4) From e6b68304651a8825f24dd84f6b7aa6856605bfec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 8 May 2021 06:53:48 +0000 Subject: [PATCH 069/303] Bump ua-parser-js from 0.7.19 to 0.7.28 Bumps [ua-parser-js](https://github.com/faisalman/ua-parser-js) from 0.7.19 to 0.7.28. - [Release notes](https://github.com/faisalman/ua-parser-js/releases) - [Commits](https://github.com/faisalman/ua-parser-js/compare/0.7.19...0.7.28) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c8a9a2b3..31d6b7f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8836,9 +8836,9 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= ua-parser-js@^0.7.18: - version "0.7.19" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.19.tgz#94151be4c0a7fb1d001af7022fdaca4642659e4b" - integrity sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ== + version "0.7.28" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31" + integrity sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g== uc.micro@^1.0.1: version "1.0.6" From 3fe6651d5376f8b80b24fafb9afb94fc56589f4a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 May 2021 23:45:55 +0000 Subject: [PATCH 070/303] Bump hosted-git-info from 2.7.1 to 2.8.9 Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.7.1 to 2.8.9. - [Release notes](https://github.com/npm/hosted-git-info/releases) - [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md) - [Commits](https://github.com/npm/hosted-git-info/compare/v2.7.1...v2.8.9) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c8a9a2b3..14b1ba06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4278,9 +4278,9 @@ home-or-tmp@^2.0.0: os-tmpdir "^1.0.1" hosted-git-info@^2.1.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== html-comment-regex@^1.1.0: version "1.1.2" From 079833ac8e586a9b146df95fce9d9102bcb88e85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jul 2021 17:34:32 +0000 Subject: [PATCH 071/303] Bump addressable from 2.6.0 to 2.8.0 Bumps [addressable](https://github.com/sporkmonger/addressable) from 2.6.0 to 2.8.0. - [Release notes](https://github.com/sporkmonger/addressable/releases) - [Changelog](https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md) - [Commits](https://github.com/sporkmonger/addressable/compare/addressable-2.6.0...addressable-2.8.0) --- updated-dependencies: - dependency-name: addressable dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2cdbe57b..567910be 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -62,8 +62,8 @@ GEM i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) - addressable (2.6.0) - public_suffix (>= 2.0.2, < 4.0) + addressable (2.8.0) + public_suffix (>= 2.0.2, < 5.0) amq-protocol (2.3.2) arel (8.0.0) ast (2.4.1) @@ -198,7 +198,7 @@ GEM pry (0.12.2) coderay (~> 1.1.0) method_source (~> 0.9.0) - public_suffix (3.1.0) + public_suffix (4.0.6) puma (5.0.2) nio4r (~> 2.0) pusher-client (0.6.2) From fdd969dae03213a976035b7f950c064038b1c93a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Aug 2021 00:55:38 +0000 Subject: [PATCH 072/303] Bump path-parse from 1.0.6 to 1.0.7 Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7. - [Release notes](https://github.com/jbgutierrez/path-parse/releases) - [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7) --- updated-dependencies: - dependency-name: path-parse dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c8a9a2b3..524ad09e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6491,9 +6491,9 @@ path-key@^2.0.0, path-key@^2.0.1: integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-type@^1.0.0: version "1.1.0" From 2b09399137c1591d1104c342ffb2c296a563be0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Sep 2021 06:16:25 +0000 Subject: [PATCH 073/303] Bump tmpl from 1.0.4 to 1.0.5 Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5. - [Release notes](https://github.com/daaku/nodejs-tmpl/releases) - [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5) --- updated-dependencies: - dependency-name: tmpl dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c8a9a2b3..b66e29bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8717,9 +8717,9 @@ tmp@^0.0.33: os-tmpdir "~1.0.2" tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== to-arraybuffer@^1.0.0: version "1.0.1" From 5339b5c473ce88e5a5143717861251a1cee79599 Mon Sep 17 00:00:00 2001 From: Harriet Craven Date: Mon, 24 Jan 2022 16:38:53 +0000 Subject: [PATCH 074/303] Update SS gem version --- .github/workflows/docker.yml | 41 ++++++++++++++++++------------------ Gemfile | 2 +- Gemfile.lock | 16 +++++++------- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 66354e50..2130564f 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -4,6 +4,7 @@ on: branches: - develop - master + - dpl-243-ss-gem-https tags: - release-* - uat-* @@ -17,25 +18,25 @@ jobs: runs-on: ubuntu-18.04 steps: - - run: env + - run: env - - uses: actions/checkout@v1 - - uses: actions/cache@v1 - with: - path: /var/lib/docker - key: ${{ runner.os }}-docker-${{ hashFiles('Dockerfile') }} - restore-keys: | - ${{ runner.os }}-docker-${{ hashFiles('Dockerfile') }} - - name: Build and tag the Docker image - run: docker build . --file Dockerfile --tag docker.pkg.github.com/${IMAGE_NAME}:${GITHUB_REF##*/} - - name: Tag (latest) the Docker image - run: docker tag docker.pkg.github.com/${IMAGE_NAME}:${GITHUB_REF##*/} docker.pkg.github.com/${IMAGE_NAME}:latest - if: github.ref == 'refs/heads/master' + - uses: actions/checkout@v1 + - uses: actions/cache@v1 + with: + path: /var/lib/docker + key: ${{ runner.os }}-docker-${{ hashFiles('Dockerfile') }} + restore-keys: | + ${{ runner.os }}-docker-${{ hashFiles('Dockerfile') }} + - name: Build and tag the Docker image + run: docker build . --file Dockerfile --tag docker.pkg.github.com/${IMAGE_NAME}:${GITHUB_REF##*/} + - name: Tag (latest) the Docker image + run: docker tag docker.pkg.github.com/${IMAGE_NAME}:${GITHUB_REF##*/} docker.pkg.github.com/${IMAGE_NAME}:latest + if: github.ref == 'refs/heads/master' - - name: Login to registry - run: docker login -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }} docker.pkg.github.com - - name: Publish image - run: docker push docker.pkg.github.com/${IMAGE_NAME}:${GITHUB_REF##*/} - - name: Publish image (latest) - run: docker push docker.pkg.github.com/${IMAGE_NAME}:latest - if: github.ref == 'refs/heads/master' + - name: Login to registry + run: docker login -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }} docker.pkg.github.com + - name: Publish image + run: docker push docker.pkg.github.com/${IMAGE_NAME}:${GITHUB_REF##*/} + - name: Publish image (latest) + run: docker push docker.pkg.github.com/${IMAGE_NAME}:latest + if: github.ref == 'refs/heads/master' diff --git a/Gemfile b/Gemfile index 01c40ed1..b061d819 100644 --- a/Gemfile +++ b/Gemfile @@ -56,7 +56,7 @@ gem 'pmb-client', git: 'https://github.com/sanger/pmb-client.git' # Sequencescspae gem 'rest-client' gem 'faraday' -gem 'sequencescape-client-api', require: 'sequencescape' +gem 'sequencescape-client-api', '0.8.2-rcx', require: 'sequencescape' # #gem 'sequencescape-client-api', require: 'sequencescape' diff --git a/Gemfile.lock b/Gemfile.lock index 2cdbe57b..6da2ce98 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -86,7 +86,7 @@ GEM amq-protocol (~> 2.3, >= 2.3.1) byebug (11.0.1) coderay (1.1.2) - concurrent-ruby (1.1.5) + concurrent-ruby (1.1.9) connection_pool (2.2.2) crass (1.0.4) daemons (1.3.1) @@ -139,7 +139,7 @@ GEM highline (1.7.10) http-cookie (1.0.3) domain_name (~> 0.5) - i18n (1.6.0) + i18n (1.8.11) concurrent-ruby (~> 1.0) jbuilder (2.9.1) activesupport (>= 4.2.0) @@ -180,7 +180,7 @@ GEM mime-types-data (3.2019.0331) mini_mime (1.0.2) mini_portile2 (2.4.0) - minitest (5.11.3) + minitest (5.15.0) multi_json (1.13.1) multipart-post (2.1.1) mysql2 (0.5.3) @@ -331,11 +331,11 @@ GEM rake sdoc (1.0.0) rdoc (>= 5.0) - sequencescape-client-api (0.4.2) + sequencescape-client-api (0.8.2.pre.rcx) activemodel (>= 5.0.0) activesupport (>= 5.0.0) i18n - yajl-ruby (>= 1.4.1) + multi_json shoulda-matchers (4.1.0) activesupport (>= 4.2.0) sparql (3.0.2) @@ -379,7 +379,7 @@ GEM turbolinks-source (5.2.0) typhoeus (0.8.0) ethon (>= 0.8.0) - tzinfo (1.2.5) + tzinfo (1.2.9) thread_safe (~> 0.1) tzinfo-data (1.2019.1) tzinfo (>= 1.0.0) @@ -462,7 +462,7 @@ DEPENDENCIES sanger_warren sass-rails sdoc - sequencescape-client-api + sequencescape-client-api (= 0.8.2.pre.rcx) shoulda-matchers spring sprockets-rails @@ -478,4 +478,4 @@ DEPENDENCIES yajl-ruby BUNDLED WITH - 2.1.4 + 2.2.26 From af5e330d23f914ab011ec187f096620134f6f579 Mon Sep 17 00:00:00 2001 From: Harriet Craven Date: Tue, 25 Jan 2022 12:01:43 +0000 Subject: [PATCH 075/303] update ss client version --- Gemfile | 2 +- Gemfile.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index b061d819..fc1f2a19 100644 --- a/Gemfile +++ b/Gemfile @@ -56,7 +56,7 @@ gem 'pmb-client', git: 'https://github.com/sanger/pmb-client.git' # Sequencescspae gem 'rest-client' gem 'faraday' -gem 'sequencescape-client-api', '0.8.2-rcx', require: 'sequencescape' +gem 'sequencescape-client-api', '1.0.0', require: 'sequencescape' # #gem 'sequencescape-client-api', require: 'sequencescape' diff --git a/Gemfile.lock b/Gemfile.lock index 6da2ce98..c4f318f9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -181,7 +181,7 @@ GEM mini_mime (1.0.2) mini_portile2 (2.4.0) minitest (5.15.0) - multi_json (1.13.1) + multi_json (1.15.0) multipart-post (2.1.1) mysql2 (0.5.3) net-http-persistent (3.0.1) @@ -331,7 +331,7 @@ GEM rake sdoc (1.0.0) rdoc (>= 5.0) - sequencescape-client-api (0.8.2.pre.rcx) + sequencescape-client-api (1.0.0) activemodel (>= 5.0.0) activesupport (>= 5.0.0) i18n @@ -462,7 +462,7 @@ DEPENDENCIES sanger_warren sass-rails sdoc - sequencescape-client-api (= 0.8.2.pre.rcx) + sequencescape-client-api (= 1.0.0) shoulda-matchers spring sprockets-rails From f293a25eec5e5721404d93f527969e8dd26d2694 Mon Sep 17 00:00:00 2001 From: Ben Topping Date: Tue, 1 Feb 2022 13:58:56 +0000 Subject: [PATCH 076/303] Added python to dockerfile to fix node build script error --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index bacb1d5a..e14f1238 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,7 @@ RUN apt-get update -qq && apt-get install -y # Install node and Yarn RUN curl -sL https://deb.nodesource.com/setup_15.x | bash - RUN apt-get install -y nodejs +RUN apt-get install -y python2 RUN npm install -g yarn WORKDIR /samples_extraction ADD Gemfile /samples_extraction From ebf3798c2cb207215fe41c14d7a1ec1c23fc7bf9 Mon Sep 17 00:00:00 2001 From: Harriet Craven Date: Thu, 3 Feb 2022 13:11:12 +0000 Subject: [PATCH 077/303] remove manual build of image --- .github/workflows/docker.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 2130564f..3fa562d7 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -4,7 +4,6 @@ on: branches: - develop - master - - dpl-243-ss-gem-https tags: - release-* - uat-* From 7b7a6eceb753aabd5e9c0712b4b118a0fa52b4e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Feb 2022 15:33:18 +0000 Subject: [PATCH 078/303] Bump tar from 2.2.1 to 2.2.2 Bumps [tar](https://github.com/npm/node-tar) from 2.2.1 to 2.2.2. - [Release notes](https://github.com/npm/node-tar/releases) - [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-tar/compare/v2.2.1...v2.2.2) --- updated-dependencies: - dependency-name: tar dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 82 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/yarn.lock b/yarn.lock index de436d3e..f339b661 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1960,9 +1960,9 @@ balanced-match@^0.4.2: integrity sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg= balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base64-js@^1.0.2: version "1.3.0" @@ -3974,10 +3974,10 @@ fsevents@^1.2.7: bindings "^1.5.0" nan "^2.12.1" -fstream@^1.0.0, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= +fstream@^1.0.0, fstream@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" + integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== dependencies: graceful-fs "^4.1.2" inherits "~2.0.0" @@ -4082,7 +4082,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@~7.1.1: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@~7.1.1: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== @@ -4106,6 +4106,18 @@ glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.3: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + globals@^11.0.1: version "11.11.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e" @@ -4130,7 +4142,7 @@ globule@^1.0.0: lodash "~4.17.10" minimatch "~3.0.2" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.15" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== @@ -4140,6 +4152,11 @@ graceful-fs@^4.1.15: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== +graceful-fs@^4.1.2: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -5789,13 +5806,20 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2: +minimatch@^3.0.2, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" +minimatch@^3.0.4: + version "3.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.5.tgz#4da8f1290ee0f0f8e83d60ca69f8f134068604a3" + integrity sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw== + dependencies: + brace-expansion "^1.1.7" + minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" @@ -5806,6 +5830,11 @@ minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" @@ -5843,7 +5872,14 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +"mkdirp@>=0.5 0": + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -7972,20 +8008,20 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@~2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rimraf@^2.6.3: +rimraf@2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" +rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -8661,12 +8697,12 @@ tapable@^0.2.7: integrity sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A== tar@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= + version "2.2.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" + integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== dependencies: block-stream "*" - fstream "^1.0.2" + fstream "^1.0.12" inherits "2" test-exclude@^5.2.3: From 62bd0485636bdae8041062e5a2a4fd280573632f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Feb 2022 21:55:13 +0000 Subject: [PATCH 079/303] Bump puma from 5.0.2 to 5.6.2 Bumps [puma](https://github.com/puma/puma) from 5.0.2 to 5.6.2. - [Release notes](https://github.com/puma/puma/releases) - [Changelog](https://github.com/puma/puma/blob/master/History.md) - [Commits](https://github.com/puma/puma/compare/v5.0.2...v5.6.2) --- updated-dependencies: - dependency-name: puma dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e7e9b92b..b1026806 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -188,7 +188,7 @@ GEM connection_pool (~> 2.2) net-http-pipeline (1.0.1) netrc (0.11.0) - nio4r (2.5.4) + nio4r (2.5.8) nokogiri (1.10.3) mini_portile2 (~> 2.4.0) os (0.9.6) @@ -199,7 +199,7 @@ GEM coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (4.0.6) - puma (5.0.2) + puma (5.6.2) nio4r (~> 2.0) pusher-client (0.6.2) json From 4b134a7b80b4477772584f41e034d67f6aac3f17 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Mar 2022 10:25:21 +0000 Subject: [PATCH 080/303] Bump ws from 5.2.2 to 5.2.3 Bumps [ws](https://github.com/websockets/ws) from 5.2.2 to 5.2.3. - [Release notes](https://github.com/websockets/ws/releases) - [Commits](https://github.com/websockets/ws/compare/5.2.2...5.2.3) --- updated-dependencies: - dependency-name: ws dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 59871142..5c472563 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9330,9 +9330,9 @@ write@^0.2.1: mkdirp "^0.5.1" ws@^5.2.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" - integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== + version "5.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" + integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== dependencies: async-limiter "~1.0.0" From a31ed87c713d7912cc48ea47bfc9cc8b1e77c8d2 Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Fri, 11 Mar 2022 11:15:54 +0000 Subject: [PATCH 081/303] Update nokogiri to version 1.13.3 --- Gemfile.lock | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index b1026806..bd180748 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -179,7 +179,7 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2019.0331) mini_mime (1.0.2) - mini_portile2 (2.4.0) + mini_portile2 (2.8.0) minitest (5.15.0) multi_json (1.15.0) multipart-post (2.1.1) @@ -189,8 +189,9 @@ GEM net-http-pipeline (1.0.1) netrc (0.11.0) nio4r (2.5.8) - nokogiri (1.10.3) - mini_portile2 (~> 2.4.0) + nokogiri (1.13.3) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) os (0.9.6) parallel (1.19.2) parser (2.7.2.0) @@ -204,6 +205,7 @@ GEM pusher-client (0.6.2) json websocket (~> 1.0) + racc (1.6.0) rack (2.0.7) rack-proxy (0.6.5) rack From f0bb59262735b5657fda619c58f6c7c64dca0188 Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Fri, 11 Mar 2022 11:40:57 +0000 Subject: [PATCH 082/303] Update websocket-extensions to version 0.1.5 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index b1026806..198df5f0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -403,7 +403,7 @@ GEM websocket (1.2.8) websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.4) + websocket-extensions (0.1.5) will_paginate (3.1.7) will_paginate-bootstrap (1.0.2) will_paginate (>= 3.0.3) From 51f8a992d4bdb75fe3675ee39130494102ebe1d9 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 9 Mar 2022 11:39:33 +0000 Subject: [PATCH 083/303] Update ruby version to 2.7.5 - Remove the google_hash gem and revert to native ruby hash google_hash hasn't been updated since 2005, and the github repo has vanished. It also blocks update to ruby 2.7. Benchmarking suggests a minor speed improvement for hashing uuids from google_hash. Currently checking what the real-world cost will be. I'd be surprised if it translates to any meaningful difference iun the context of the whole application. --- .ruby-version | 2 +- Gemfile | 1 - Gemfile.lock | 6 ------ lib/changes_support/disjoint_list.rb | 5 +---- lib/fact_changes.rb | 5 ++--- 5 files changed, 4 insertions(+), 15 deletions(-) diff --git a/.ruby-version b/.ruby-version index f6ab44e9..849c0c47 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-2.6.6 +ruby-2.7.5 diff --git a/Gemfile b/Gemfile index fc1f2a19..4a2d1042 100644 --- a/Gemfile +++ b/Gemfile @@ -43,7 +43,6 @@ gem 'ace-rails-ap' gem 'rdf-n3' gem 'jbuilder' gem 'yajl-ruby' -gem 'google_hash' # Traction endpoints gem 'jsonapi-resources' diff --git a/Gemfile.lock b/Gemfile.lock index fcc21daf..3d1a4a71 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -132,8 +132,6 @@ GEM globalid (0.4.2) activesupport (>= 4.2.0) gmetric (0.1.3) - google_hash (0.9.0) - sane (~> 0) hamster (3.0.0) concurrent-ruby (~> 1.0) highline (1.7.10) @@ -192,7 +190,6 @@ GEM nokogiri (1.13.3) mini_portile2 (~> 2.8.0) racc (~> 1.4) - os (0.9.6) parallel (1.19.2) parser (2.7.2.0) ast (~> 2.4.1) @@ -311,8 +308,6 @@ GEM ruby-growl (4.1) uuid (~> 2.3, >= 2.3.5) ruby-progressbar (1.10.1) - sane (0.25.8) - os (~> 0) sanger_warren (0.1.0) bunny (~> 2.17.0) connection_pool (~> 2.2.0) @@ -433,7 +428,6 @@ DEPENDENCIES factory_bot_rails faraday gmetric (~> 0.1.3) - google_hash jbuilder jquery-rails js_cookie_rails diff --git a/lib/changes_support/disjoint_list.rb b/lib/changes_support/disjoint_list.rb index b5bf632e..8f749a86 100644 --- a/lib/changes_support/disjoint_list.rb +++ b/lib/changes_support/disjoint_list.rb @@ -1,5 +1,3 @@ -require 'google_hash' - module ChangesSupport end @@ -19,8 +17,7 @@ class ChangesSupport::DisjointList def initialize(list) @name = "object_id_#{object_id}" - # Replace with a normal hash if we want to stop using it - @location_for_unique_id = GoogleHashDenseLongToRuby.new + @location_for_unique_id = {} @list = [] @disjoint_lists = [self] diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index 881cf615..352d5425 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -1,7 +1,6 @@ require 'token_util' require 'changes_support/disjoint_list' require 'changes_support/transaction_scope' -require 'google_hash' class FactChanges include ChangesSupport::TransactionScope @@ -36,8 +35,8 @@ def reset build_disjoint_lists(:asset_groups_to_create, :asset_groups_to_destroy) build_disjoint_lists(:assets_to_add, :assets_to_remove) - @instances_from_uuid = GoogleHashDenseRubyToRuby.new - @wildcards = GoogleHashDenseRubyToRuby.new + @instances_from_uuid = {} + @wildcards = {} end def build_disjoint_lists(list, opposite) From b745bbdbb89be6f131e70484318ce44fd4864a80 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 9 Mar 2022 11:49:47 +0000 Subject: [PATCH 084/303] Remove travis gems --- Gemfile | 4 ---- Gemfile.lock | 32 -------------------------------- 2 files changed, 36 deletions(-) diff --git a/Gemfile b/Gemfile index 4a2d1042..72320d50 100644 --- a/Gemfile +++ b/Gemfile @@ -99,10 +99,6 @@ group :development do gem 'rubocop', require: false gem 'rubocop-performance' gem 'rubocop-rails' - - - gem 'travis' - gem 'travis-lint' end diff --git a/Gemfile.lock b/Gemfile.lock index 3d1a4a71..40e62906 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -73,7 +73,6 @@ GEM babel-transpiler (0.7.0) babel-source (>= 4.0, < 6) execjs (~> 2.0) - backports (3.15.0) bindex (0.7.0) bootstrap-sass (3.4.1) autoprefixer-rails (>= 5.2.1) @@ -106,8 +105,6 @@ GEM sxp (~> 1.0) ejs (1.1.1) erubi (1.8.0) - ethon (0.12.0) - ffi (>= 1.3.0) exception_notification (4.3.0) actionmailer (>= 4.0, < 6) activesupport (>= 4.0, < 6) @@ -122,19 +119,11 @@ GEM faraday_middleware (0.13.1) faraday (>= 0.7.4, < 1.0) ffi (1.11.1) - gh (0.14.0) - addressable - backports - faraday (~> 0.8) - multi_json (~> 1.0) - net-http-persistent (>= 2.7) - net-http-pipeline globalid (0.4.2) activesupport (>= 4.2.0) gmetric (0.1.3) hamster (3.0.0) concurrent-ruby (~> 1.0) - highline (1.7.10) http-cookie (1.0.3) domain_name (~> 0.5) i18n (1.8.11) @@ -147,7 +136,6 @@ GEM thor (>= 0.14, < 2.0) js_cookie_rails (2.2.0) railties (>= 3.1) - json (2.2.0) json-schema (2.8.1) addressable (>= 2.4) json_api_client (1.12.0) @@ -184,7 +172,6 @@ GEM mysql2 (0.5.3) net-http-persistent (3.0.1) connection_pool (~> 2.2) - net-http-pipeline (1.0.1) netrc (0.11.0) nio4r (2.5.8) nokogiri (1.13.3) @@ -199,9 +186,6 @@ GEM public_suffix (4.0.6) puma (5.6.2) nio4r (~> 2.0) - pusher-client (0.6.2) - json - websocket (~> 1.0) racc (1.6.0) rack (2.0.7) rack-proxy (0.6.5) @@ -360,22 +344,9 @@ GEM thor (0.20.3) thread_safe (0.3.6) tilt (2.0.9) - travis (1.8.10) - backports - faraday (~> 0.9) - faraday_middleware (~> 0.9, >= 0.9.1) - gh (~> 0.13) - highline (~> 1.6) - launchy (~> 2.1) - pusher-client (~> 0.4) - typhoeus (~> 0.6, >= 0.6.8) - travis-lint (2.0.0) - json turbolinks (5.2.0) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - typhoeus (0.8.0) - ethon (>= 0.8.0) tzinfo (1.2.9) thread_safe (~> 0.1) tzinfo-data (1.2019.1) @@ -397,7 +368,6 @@ GEM railties (>= 4.2) webpacker-react (0.3.2) webpacker - websocket (1.2.8) websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) @@ -462,8 +432,6 @@ DEPENDENCIES shoulda-matchers spring sprockets-rails - travis - travis-lint turbolinks tzinfo-data web-console From d66472d1beacd1fc5518b74d5cd7d7fda40e043a Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 9 Mar 2022 11:50:05 +0000 Subject: [PATCH 085/303] Add node version information --- .nvmrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 .nvmrc diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..4ec320b2 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v14.17.6 From 69a17d76f76cea16981c0f2d320b9d2f0b25747a Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 10 Mar 2022 09:47:06 +0000 Subject: [PATCH 086/303] Improve error feedback --- app/models/assets/export.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/assets/export.rb b/app/models/assets/export.rb index 50dad07e..f81b09f6 100644 --- a/app/models/assets/export.rb +++ b/app/models/assets/export.rb @@ -29,7 +29,7 @@ def update_sequencescape(_print_config, user, _step) rescue Timeout::Error => e updates.set_errors(['Sequencescape connection - Timeout error occurred.']) rescue StandardError => err - updates.set_errors(['Sequencescape connection - There was an error while updating Sequencescape'+err.backtrace.to_s]) + updates.set_errors(['Sequencescape connection - There was an error while updating Sequencescape', err.message, err.backtrace.to_s]) end end end From 0ce533a2927b9d04e2fa6ef928b6600bd1bb39a7 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 10 Mar 2022 13:47:48 +0000 Subject: [PATCH 087/303] Update rubocop - Update rubocop and plugins - Enable all cops - Apply and validate safe and unsafe auto-fixes - Add inline disables for the rest - Manually check todos, and convert false positives to disables with comments - Manually fix a few simple todos --- .rubocop.yml | 156 +----------------- Gemfile.lock | 38 ++--- app/channels/activity_channel.rb | 4 +- app/controllers/asset_groups_controller.rb | 4 +- app/controllers/assets_controller.rb | 4 +- app/models/activities/state.rb | 2 +- app/models/activity.rb | 1 - app/models/asset.rb | 6 +- app/models/asset_group.rb | 2 +- app/models/assets/export.rb | 4 +- app/models/assets/traction_fields.rb | 2 +- app/models/fact.rb | 4 +- app/models/kit.rb | 2 - app/models/printables/group.rb | 2 +- app/models/step_type.rb | 13 +- app/models/steps/state.rb | 6 +- config/initializers/jsonapi.rb | 2 +- ...90526185059_change_handler_to_long_text.rb | 2 +- lib/actions/racking.rb | 4 +- lib/changes_support/disjoint_list.rb | 4 +- lib/changes_support/transaction_scope.rb | 4 +- lib/deployed_version.rb | 2 +- lib/fact_changes.rb | 30 ++-- lib/label_templates/ss_plate.rb | 28 ++-- lib/label_templates/ss_tube.rb | 32 ++-- lib/psd_formatter.rb | 2 +- lib/tasks/message_addition.rake | 6 +- lib/token_util.rb | 2 +- script/plate_to_code39.rb | 2 +- script/runners/create_file.rb | 2 +- script/runners/create_layout.rb | 2 +- script/runners/load_metadata.rb | 2 +- script/runners/rack_layout_any_barcode.rb | 2 +- script/runners/rack_layout_creating_tubes.rb | 2 +- spec/lib/actions/racking_spec.rb | 10 +- spec/lib/fact_changes_spec.rb | 3 +- .../lib/parsers/csv_layout/csv_parser_spec.rb | 2 +- .../parsers/csv_metadata/csv_parser_spec.rb | 2 +- spec/lib/support_n3_spec.rb | 28 ++-- spec/models/condition_group_spec.rb | 2 +- spec/models/step_execution_spec.rb | 2 +- .../steps/background_tasks/inference_spec.rb | 5 +- spec/models/steps/job_spec.rb | 2 +- spec/models/steps/queueable_job_spec.rb | 27 ++- spec/requests/api/v1/assets_spec.rb | 8 +- spec/script/runners/load_metadata_spec.rb | 2 +- test/factories/actions.rb | 4 +- test/factories/activity_type_step_types.rb | 4 +- test/factories/activity_types.rb | 4 +- test/factories/asset_groups.rb | 4 +- test/factories/condition_groups.rb | 4 +- test/factories/conditions.rb | 4 +- test/factories/kit_types.rb | 4 +- test/factories/label_templates.rb | 4 +- test/factories/operations.rb | 4 +- test/factories/printers.rb | 4 +- test/factories/step_executions.rb | 4 +- test/factories/step_types.rb | 4 +- test/factories/steps.rb | 3 +- test/factories/uploaded_file.rb | 3 +- test/factories/user_sessions.rb | 3 +- 61 files changed, 181 insertions(+), 349 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index a94be896..a8b2effe 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,6 +4,9 @@ require: - rubocop-performance - rubocop-rails +AllCops: + NewCops: enable + # Blocks are used to structure tests and are part of the shoulda dsl. # The standard BlockLength limits are too stringent for this purpose. # Block DSL is also used in routes @@ -15,7 +18,7 @@ Metrics/BlockLength: - Gemfile - 'db/seeds/**/*' - '**/*.builder' - ExcludedMethods: + IgnoredMethods: - describe - context - background @@ -42,154 +45,3 @@ Metrics/BlockLength: - class_eval - has_metadata - resources - -Layout/BeginEndAlignment: # (new in 0.91) - Enabled: true -Layout/EmptyLinesAroundAttributeAccessor: # (new in 0.83) - Enabled: true -Layout/SpaceAroundMethodCallOperator: # (new in 0.82) - Enabled: true -Lint/BinaryOperatorWithIdenticalOperands: # (new in 0.89) - Enabled: true -Lint/ConstantDefinitionInBlock: # (new in 0.91) - Enabled: true -Lint/DeprecatedOpenSSLConstant: # (new in 0.84) - Enabled: true -Lint/DuplicateElsifCondition: # (new in 0.88) - Enabled: true -Lint/DuplicateRequire: # (new in 0.90) - Enabled: true -Lint/DuplicateRescueException: # (new in 0.89) - Enabled: true -Lint/EmptyConditionalBody: # (new in 0.89) - Enabled: true -Lint/EmptyFile: # (new in 0.90) - Enabled: true -Lint/FloatComparison: # (new in 0.89) - Enabled: true -Lint/HashCompareByIdentity: # (new in 0.93) - Enabled: true -Lint/IdentityComparison: # (new in 0.91) - Enabled: true -Lint/MissingSuper: # (new in 0.89) - Enabled: true -Lint/MixedRegexpCaptureTypes: # (new in 0.85) - Enabled: true -Lint/OutOfRangeRegexpRef: # (new in 0.89) - Enabled: true -Lint/RaiseException: # (new in 0.81) - Enabled: true -Lint/RedundantSafeNavigation: # (new in 0.93) - Enabled: true -Lint/SelfAssignment: # (new in 0.89) - Enabled: true -Lint/StructNewOverride: # (new in 0.81) - Enabled: true -Lint/TopLevelReturnWithArgument: # (new in 0.89) - Enabled: true -Lint/TrailingCommaInAttributeDeclaration: # (new in 0.90) - Enabled: true -Lint/UnreachableLoop: # (new in 0.89) - Enabled: true -Lint/UselessMethodDefinition: # (new in 0.90) - Enabled: true -Lint/UselessTimes: # (new in 0.91) - Enabled: true -Style/AccessorGrouping: # (new in 0.87) - Enabled: true -Style/BisectedAttrAccessor: # (new in 0.87) - Enabled: true -Style/CaseLikeIf: # (new in 0.88) - Enabled: true -Style/ClassEqualityComparison: # (new in 0.93) - Enabled: true -Style/CombinableLoops: # (new in 0.90) - Enabled: true -Style/ExplicitBlockArgument: # (new in 0.89) - Enabled: true -Style/ExponentialNotation: # (new in 0.82) - Enabled: true -Style/GlobalStdStream: # (new in 0.89) - Enabled: true -Style/HashAsLastArrayItem: # (new in 0.88) - Enabled: true -Style/HashEachMethods: # (new in 0.80) - Enabled: true -Style/HashLikeCase: # (new in 0.88) - Enabled: true -Style/HashTransformKeys: # (new in 0.80) - Enabled: true -Style/HashTransformValues: # (new in 0.80) - Enabled: true -Style/KeywordParametersOrder: # (new in 0.90) - Enabled: true -Style/OptionalBooleanParameter: # (new in 0.89) - Enabled: true -Style/RedundantAssignment: # (new in 0.87) - Enabled: true -Style/RedundantFetchBlock: # (new in 0.86) - Enabled: true -Style/RedundantFileExtensionInRequire: # (new in 0.88) - Enabled: true -Style/RedundantRegexpCharacterClass: # (new in 0.85) - Enabled: true -Style/RedundantRegexpEscape: # (new in 0.85) - Enabled: true -Style/RedundantSelfAssignment: # (new in 0.90) - Enabled: true -Style/SingleArgumentDig: # (new in 0.89) - Enabled: true -Style/SlicingWithRange: # (new in 0.83) - Enabled: true -Style/SoleNestedConditional: # (new in 0.89) - Enabled: true -Style/StringConcatenation: # (new in 0.89) - Enabled: true -Rails/ActiveRecordCallbacksOrder: # (new in 2.7) - Enabled: true -Rails/AfterCommitOverride: # (new in 2.8) - Enabled: true -Rails/FindById: # (new in 2.7) - Enabled: true -Rails/Inquiry: # (new in 2.7) - Enabled: true -Rails/MailerName: # (new in 2.7) - Enabled: true -Rails/MatchRoute: # (new in 2.7) - Enabled: true -Rails/NegateInclude: # (new in 2.7) - Enabled: true -Rails/Pluck: # (new in 2.7) - Enabled: true -Rails/PluckInWhere: # (new in 2.7) - Enabled: true -Rails/RenderInline: # (new in 2.7) - Enabled: true -Rails/RenderPlainText: # (new in 2.7) - Enabled: true -Rails/ShortI18n: # (new in 2.7) - Enabled: true -Rails/SquishedSQLHeredocs: # (new in 2.8) - Enabled: true -Rails/WhereExists: # (new in 2.7) - Enabled: true -Rails/WhereNot: # (new in 2.8) - Enabled: true -Performance/AncestorsInclude: # (new in 1.7) - Enabled: true -Performance/BigDecimalWithNumericArgument: # (new in 1.7) - Enabled: true -Performance/RedundantSortBlock: # (new in 1.7) - Enabled: true -Performance/RedundantStringChars: # (new in 1.7) - Enabled: true -Performance/ReverseFirst: # (new in 1.7) - Enabled: true -Performance/SortReverse: # (new in 1.7) - Enabled: true -Performance/Squeeze: # (new in 1.7) - Enabled: true -Performance/StringInclude: # (new in 1.7) - Enabled: true -Performance/Sum: # (new in 1.8) - Enabled: true diff --git a/Gemfile.lock b/Gemfile.lock index 40e62906..dabef7e9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -66,7 +66,7 @@ GEM public_suffix (>= 2.0.2, < 5.0) amq-protocol (2.3.2) arel (8.0.0) - ast (2.4.1) + ast (2.4.2) autoprefixer-rails (9.6.0) execjs babel-source (5.8.35) @@ -126,7 +126,7 @@ GEM concurrent-ruby (~> 1.0) http-cookie (1.0.3) domain_name (~> 0.5) - i18n (1.8.11) + i18n (1.10.0) concurrent-ruby (~> 1.0) jbuilder (2.9.1) activesupport (>= 4.2.0) @@ -177,8 +177,8 @@ GEM nokogiri (1.13.3) mini_portile2 (~> 2.8.0) racc (~> 1.4) - parallel (1.19.2) - parser (2.7.2.0) + parallel (1.21.0) + parser (3.1.1.0) ast (~> 2.4.1) pry (0.12.2) coderay (~> 1.1.0) @@ -223,7 +223,7 @@ GEM method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rainbow (3.0.0) + rainbow (3.1.1) rake (12.3.3) rb-fsevent (0.10.3) rb-inotify (0.10.0) @@ -248,7 +248,7 @@ GEM railties (>= 3.2) tilt redis (4.1.2) - regexp_parser (1.8.2) + regexp_parser (2.2.1) rest-client (2.0.2) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) @@ -271,27 +271,27 @@ GEM rspec-mocks (~> 3.8.0) rspec-support (~> 3.8.0) rspec-support (3.8.2) - rubocop (0.93.1) + rubocop (1.26.0) parallel (~> 1.10) - parser (>= 2.7.1.5) + parser (>= 3.1.0.0) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8) + regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 0.6.0) + rubocop-ast (>= 1.16.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (0.8.0) - parser (>= 2.7.1.5) - rubocop-performance (1.8.1) - rubocop (>= 0.87.0) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.16.0) + parser (>= 3.1.1.0) + rubocop-performance (1.13.3) + rubocop (>= 1.7.0, < 2.0) rubocop-ast (>= 0.4.0) - rubocop-rails (2.8.1) + rubocop-rails (2.13.2) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.87.0) + rubocop (>= 1.7.0, < 2.0) ruby-growl (4.1) uuid (~> 2.3, >= 2.3.5) - ruby-progressbar (1.10.1) + ruby-progressbar (1.11.0) sanger_warren (0.1.0) bunny (~> 2.17.0) connection_pool (~> 2.2.0) @@ -354,7 +354,7 @@ GEM unf (0.1.4) unf_ext unf_ext (0.0.7.6) - unicode-display_width (1.7.0) + unicode-display_width (2.1.0) uuid (2.3.9) macaddr (~> 1.0) web-console (3.7.0) diff --git a/app/channels/activity_channel.rb b/app/channels/activity_channel.rb index 091a9688..73bf1e59 100644 --- a/app/channels/activity_channel.rb +++ b/app/channels/activity_channel.rb @@ -34,9 +34,9 @@ def process_asset_group(strong_params) begin received_list = [] - received_list = assets.map do |uuid_or_barcode| + received_list = assets.filter_map do |uuid_or_barcode| Asset.find_or_import_asset_with_barcode(uuid_or_barcode) - end.compact + end asset_group.update_with_assets(received_list) diff --git a/app/controllers/asset_groups_controller.rb b/app/controllers/asset_groups_controller.rb index 38d6ad3d..1e40aeba 100644 --- a/app/controllers/asset_groups_controller.rb +++ b/app/controllers/asset_groups_controller.rb @@ -63,9 +63,9 @@ def set_asset_group end def perform_assets_update - @asset_group.update_attributes(assets: params_update_asset_group[:assets].map do |uuid_or_barcode| + @asset_group.update_attributes(assets: params_update_asset_group[:assets].filter_map do |uuid_or_barcode| Asset.find_or_import_asset_with_barcode(uuid_or_barcode) - end.compact.uniq) + end.uniq) end def show_alert(data) diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index c0a952c3..e641f252 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -130,12 +130,12 @@ def get_search_results(queries) end def valid_indexes - params.keys.map { |k| k.match(/^[pq](\d*)$/) }.compact.map { |k| k[1] } + params.keys.filter_map { |k| k.match(/^[pq](\d*)$/) }.map { |k| k[1] } end def set_queries @queries = valid_indexes.map do |val| - OpenStruct.new({ :predicate => params["p"+val], :object => params["o"+val] }) + OpenStruct.new({ :predicate => params["p"+val], :object => params["o"+val] }) # rubocop:todo Style/OpenStructUse end end diff --git a/app/models/activities/state.rb b/app/models/activities/state.rb index ea57a950..aa0b857d 100644 --- a/app/models/activities/state.rb +++ b/app/models/activities/state.rb @@ -1,7 +1,7 @@ module Activities::State def self.included(klass) klass.instance_eval do - scope :in_progress, ->() { where('completed_at is null') } + scope :in_progress, ->() { where(completed_at: nil) } scope :finished, ->() { where('completed_at is not null') } end end diff --git a/app/models/activity.rb b/app/models/activity.rb index bda5518c..e6ad48ce 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -6,7 +6,6 @@ # an {AssetGroup}. The AssetGroup reflects the currently actively processed set # of {Asset assets} so may be updated as the activity progresses. class Activity < ApplicationRecord - validates :activity_type, presence: true # validates :asset_group, :presence => true belongs_to :activity_type belongs_to :instrument diff --git a/app/models/asset.rb b/app/models/asset.rb index 7603c6fc..1660e9a0 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -78,12 +78,12 @@ def update_compatible_activity_type memo.joins( "INNER JOIN facts AS facts#{index} ON facts#{index}.asset_id=assets.id" ).where("facts#{index}.predicate" => query.predicate, - "facts#{index}.object_asset_id" => asset.id) + "facts#{index}.object_asset_id" => asset.id) else memo.joins( "INNER JOIN facts AS facts#{index} ON facts#{index}.asset_id=assets.id" ).where("facts#{index}.predicate" => query.predicate, - "facts#{index}.object" => query.object) + "facts#{index}.object" => query.object) end end end @@ -254,7 +254,7 @@ def kit_type end def position_value - val = facts.map(&:position).compact.first + val = facts.filter_map(&:position).first return "" if val.nil? "_#{(val.to_i+1).to_s}" end diff --git a/app/models/asset_group.rb b/app/models/asset_group.rb index 76bad819..b604a195 100644 --- a/app/models/asset_group.rb +++ b/app/models/asset_group.rb @@ -35,7 +35,7 @@ def update_with_assets(assets_to_update) ActiveRecord::Base.transaction do step = Step.create(activity: activity_owner, asset_group: self, - in_progress?: true, state: 'complete', step_type: step_type_for_import) + in_progress?: true, state: 'complete', step_type: step_type_for_import) updates.apply(step) end end diff --git a/app/models/assets/export.rb b/app/models/assets/export.rb index f81b09f6..3f52c7e8 100644 --- a/app/models/assets/export.rb +++ b/app/models/assets/export.rb @@ -93,9 +93,9 @@ def duplicate_locations_in_plate? def attributes_to_send raise DuplicateLocations if duplicate_locations_in_plate? - facts.with_predicate('contains').map(&:object_asset).map do |well| + facts.with_predicate('contains').map(&:object_asset).filter_map do |well| attributes_to_send_for_well(well) - end.compact + end end def has_sample? diff --git a/app/models/assets/traction_fields.rb b/app/models/assets/traction_fields.rb index 085eb292..38826218 100644 --- a/app/models/assets/traction_fields.rb +++ b/app/models/assets/traction_fields.rb @@ -36,7 +36,7 @@ def cost_code _get_values_for_predicate('cost_code') end - def _get_values_for_predicate(predicate, &block) + def _get_values_for_predicate(predicate) list = facts.with_predicate(predicate).map do |a| if block_given? yield a diff --git a/app/models/fact.rb b/app/models/fact.rb index 6a23ae2b..897b5a94 100644 --- a/app/models/fact.rb +++ b/app/models/fact.rb @@ -10,7 +10,9 @@ class Fact < ApplicationRecord scope :from_remote_asset, ->() { where(:is_remote? => true) } scope :created_before, ->(date) { date.nil? ? all : where('created_at < ?', date) } - validates :object_asset_id, presence: true, unless: :literal? + # Confirm test coverage before correcting this one, as its unclear how optional presence validation + # plays with belongs_to_required_by_default. + validates :object_asset_id, presence: true, unless: :literal? # rubocop:todo Rails/RedundantPresenceValidationOnBelongsTo validates :object_asset_id, presence: false, if: :literal? def set_to_remove_by(step) diff --git a/app/models/kit.rb b/app/models/kit.rb index 4b472abd..e313f40c 100644 --- a/app/models/kit.rb +++ b/app/models/kit.rb @@ -3,8 +3,6 @@ class Kit < ApplicationRecord has_many :activities has_one :activity_type, :through => :kit_type - validates :kit_type, :presence => true - def type kit_type&.name end diff --git a/app/models/printables/group.rb b/app/models/printables/group.rb index 08c0cd29..860d3372 100644 --- a/app/models/printables/group.rb +++ b/app/models/printables/group.rb @@ -21,7 +21,7 @@ def print_assets(assets, printer_config, user) classify_for_printing(assets, printer_config).each do |printer_name, info_for_template| info_for_template.each do |label_template, assets| - body_print = assets.map { |a| a.printable_object(user) }.compact.reverse + body_print = assets.filter_map { |a| a.printable_object(user) }.reverse next if body_print.empty? PMB::PrintJob.new( printer_name:printer_name, diff --git a/app/models/step_type.rb b/app/models/step_type.rb index 8998648f..df9f0171 100644 --- a/app/models/step_type.rb +++ b/app/models/step_type.rb @@ -92,9 +92,6 @@ def class_for_task_type Steps::BackgroundTasks::Inference elsif task_type=='runner' Steps::BackgroundTasks::Runner - elsif task_type=='background_step' - Step - #["BackgroundSteps::", step_action.gsub(".rb","").classify].join.constantize else Step end @@ -119,19 +116,19 @@ def remove_previous_conditions def position_for_assets_by_condition_group(assets) all_cgroups = {} - Hash[condition_group_classification_for(assets).map do |asset, cgroups| - [asset.id, Hash[cgroups.map do |cgroup| + condition_group_classification_for(assets).to_h do |asset, cgroups| + [asset.id, cgroups.to_h do |cgroup| all_cgroups[cgroup] = 0 if all_cgroups[cgroup].nil? position = all_cgroups[cgroup] all_cgroups[cgroup] = all_cgroups[cgroup] + 1 [cgroup.id, position] - end]] - end] + end] + end end def condition_group_classification_for(assets, checked_condition_groups = [], wildcard_values = {}) related_assets = [] - h = Hash[assets.map { |asset| [asset, condition_groups_for(asset, related_assets, [], wildcard_values)] }] + h = assets.to_h { |asset| [asset, condition_groups_for(asset, related_assets, [], wildcard_values)] } related_assets.each do |a| h[a]= condition_groups_for(a, [], checked_condition_groups, wildcard_values) end diff --git a/app/models/steps/state.rb b/app/models/steps/state.rb index aa4e0412..2cc5675b 100644 --- a/app/models/steps/state.rb +++ b/app/models/steps/state.rb @@ -62,12 +62,12 @@ def self.included(klass) event :cancel do transitions from: [:complete, :cancelling], to: :cancelling, - after: :cancel_me_and_any_newer_completed_steps + after: :cancel_me_and_any_newer_completed_steps end event :remake do transitions from: [:cancelled, :remaking], to: :remaking, - after: :remake_me_and_any_older_cancelled_steps + after: :remake_me_and_any_older_cancelled_steps end event :continue, guards: [:assets_compatible_with_step_type] do @@ -83,7 +83,7 @@ def self.included(klass) transitions from: :remaking, to: :cancelled, after: [:stop_job, :stop_newer_steps] transitions from: [:failed, :running], to: :stopped, - after: [:stop_job, :stop_newer_steps, :cancel_me] + after: [:stop_job, :stop_newer_steps, :cancel_me] transitions from: :cancelling, to: :complete, after: [:stop_job, :stop_newer_steps] end diff --git a/config/initializers/jsonapi.rb b/config/initializers/jsonapi.rb index 85e6a8f5..6e6c9602 100644 --- a/config/initializers/jsonapi.rb +++ b/config/initializers/jsonapi.rb @@ -1,5 +1,5 @@ JSONAPI.configure do |config| - #:underscored_key, :camelized_key, :dasherized_key, or custom + # :underscored_key, :camelized_key, :dasherized_key, or custom config.json_key_format = :underscored_key config.resource_key_type = :uuid diff --git a/db/migrate/20190526185059_change_handler_to_long_text.rb b/db/migrate/20190526185059_change_handler_to_long_text.rb index 7571f406..c7a0bfd5 100644 --- a/db/migrate/20190526185059_change_handler_to_long_text.rb +++ b/db/migrate/20190526185059_change_handler_to_long_text.rb @@ -1,5 +1,5 @@ class ChangeHandlerToLongText < ActiveRecord::Migration[5.1] def change - change_column :delayed_jobs, :handler, :text, :limit => 4294967295 + change_column :delayed_jobs, :handler, :text, :limit => 4294967295 # rubocop:disable Rails/ReversibleMigration end end diff --git a/lib/actions/racking.rb b/lib/actions/racking.rb index c1a0d130..e31e71dc 100644 --- a/lib/actions/racking.rb +++ b/lib/actions/racking.rb @@ -16,7 +16,7 @@ def initialize(message = nil) def html_error_message(error_messages) ['
    ', error_messages.map do |msg| ['
  • ',msg,'
  • '] - end, '
'].flatten.join('') + end, ''].flatten.join end end @@ -71,7 +71,7 @@ def fact_changes_for_unrack_tubes(list_layout, destination_rack = nil) rerackGroup=nil previous_racks = [] - tubes = list_layout.map { |obj| obj[:asset] }.compact + tubes = list_layout.filter_map { |obj| obj[:asset] } return updates if tubes.empty? tubes_ids = tubes.map(&:id) tubes_list = Asset.where(id: tubes_ids).includes(:facts) diff --git a/lib/changes_support/disjoint_list.rb b/lib/changes_support/disjoint_list.rb index 8f749a86..3b2d0245 100644 --- a/lib/changes_support/disjoint_list.rb +++ b/lib/changes_support/disjoint_list.rb @@ -223,10 +223,10 @@ def _unique_id_for_element(element, deep = 0) elsif (element.has_key?(:predicate)) _unique_id_for_fact(element) else - sum_function_for(element.keys.dup.concat(element.values.map { |val| _unique_id_for_element(val, deep+1) }).join("")) + sum_function_for(element.keys.dup.concat(element.values.map { |val| _unique_id_for_element(val, deep+1) }).join) end elsif element.kind_of?(Enumerable) - sum_function_for(element.map { |o| _unique_id_for_element(o, deep+1) }.join("")) + sum_function_for(element.map { |o| _unique_id_for_element(o, deep+1) }.join) else sum_function_for(element.to_s) end diff --git a/lib/changes_support/transaction_scope.rb b/lib/changes_support/transaction_scope.rb index 86601cb4..458c4e4b 100644 --- a/lib/changes_support/transaction_scope.rb +++ b/lib/changes_support/transaction_scope.rb @@ -58,9 +58,9 @@ def _filter_removed_entries(opts) object_asset = Asset.find(opts[:facts][:object_asset_id]) if opts[:facts][:object_asset_id] ( - (triple[0]==element.uuid) && + ((triple[0]==element.uuid) && (opts[:facts][:predicate] == triple[1]) && - (opts[:facts][:object] == triple[2]) || (object_asset.uuid == triple[2]) + (opts[:facts][:object] == triple[2])) || (object_asset.uuid == triple[2]) ) end end diff --git a/lib/deployed_version.rb b/lib/deployed_version.rb index 9ae3f287..80ea8269 100644 --- a/lib/deployed_version.rb +++ b/lib/deployed_version.rb @@ -112,7 +112,7 @@ def read_file(filename) HOSTNAME = Socket.gethostname require 'ostruct' - DETAILS = OpenStruct.new( + DETAILS = OpenStruct.new( # rubocop:todo Style/OpenStructUse name: nil, version: VERSION_ID, environment: ENVIRONMENT diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index 352d5425..383c098b 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -62,19 +62,19 @@ def asset_group_asset_to_h(asset_group_asset_str) def to_h { - 'set_errors': @errors_added, - 'create_assets': @assets_to_create.map(&:uuid), - 'create_asset_groups': @asset_groups_to_create.map(&:uuid), - 'delete_asset_groups': @asset_groups_to_destroy.map(&:uuid), - 'delete_assets': @assets_to_destroy.map(&:uuid), - 'add_facts': @facts_to_add.map do |f| + set_errors: @errors_added, + create_assets: @assets_to_create.map(&:uuid), + create_asset_groups: @asset_groups_to_create.map(&:uuid), + delete_asset_groups: @asset_groups_to_destroy.map(&:uuid), + delete_assets: @assets_to_destroy.map(&:uuid), + add_facts: @facts_to_add.map do |f| [ f[:asset].nil? ? nil : f[:asset].uuid, f[:predicate], (f[:object] || f[:object_asset].uuid) ] end, - 'remove_facts': @facts_to_destroy.map do |f| + remove_facts: @facts_to_destroy.map do |f| if f[:id] fact = Fact.find(f[:id]) [fact.asset.uuid, fact.predicate, fact.object_value_or_uuid] @@ -86,8 +86,8 @@ def to_h ] end end, - 'add_assets': asset_group_asset_to_h(@assets_to_add), - 'remove_assets': asset_group_asset_to_h(@assets_to_remove) + add_assets: asset_group_asset_to_h(@assets_to_add), + remove_assets: asset_group_asset_to_h(@assets_to_remove) }.reject { |k,v| v.length == 0 } end @@ -242,7 +242,7 @@ def assets_for_printing ((operation.action_type == 'addFacts') && (operation.predicate == 'is') && (operation.object == 'readyForPrint')) - end.map(&:asset).compact.uniq.map(&:uuid) + end.filter_map(&:asset).uniq.map(&:uuid) ids_for_print = asset_ids.concat(ready_for_print_ids).flatten.uniq @assets_for_printing=Asset.for_printing.where(uuid: ids_for_print) @@ -471,7 +471,7 @@ def _create_asset_groups(step, asset_groups, with_operations = true) def _detach_asset_groups(step, asset_groups, with_operations = true) operations = _asset_group_building_operations('deleteAssetGroups', step, asset_groups) if with_operations instances = asset_groups.flatten - ids_to_remove = instances.map(&:id).compact.uniq + ids_to_remove = instances.filter_map(&:id).uniq AssetGroup.where(id: ids_to_remove).update_all(activity_owner_id: nil) if ids_to_remove && !ids_to_remove.empty? operations @@ -549,7 +549,7 @@ def all_values_are_new_records(hash) def _instance_builder_for_import(klass, params_list, &block) - instances = params_list.map do |params_for_instance| + instances = params_list.filter_map do |params_for_instance| unless (params_for_instance.kind_of?(klass)) if (all_values_are_new_records(params_for_instance) || (!klass.exists?(params_for_instance))) @@ -560,7 +560,7 @@ def _instance_builder_for_import(klass, params_list, &block) params_for_instance end end - end.compact.uniq + end.uniq instances.each do |instance| instance.run_callbacks(:save) { false } instance.run_callbacks(:create) { false } @@ -575,9 +575,9 @@ def _instance_builder_for_import(klass, params_list, &block) end def _instances_deletion(klass, instances, &block) - operations = block_given? ? yield(instances) : instances + operations = block ? yield(instances) : instances instances = instances.flatten - ids_to_remove = instances.map(&:id).compact.uniq + ids_to_remove = instances.filter_map(&:id).uniq klass.where(id: ids_to_remove).delete_all if ids_to_remove && !ids_to_remove.empty? operations diff --git a/lib/label_templates/ss_plate.rb b/lib/label_templates/ss_plate.rb index cbd36594..1fbf84d4 100644 --- a/lib/label_templates/ss_plate.rb +++ b/lib/label_templates/ss_plate.rb @@ -3,11 +3,11 @@ # Label template currently defined for sqsc_96plate_label_template (20/Jan/2017) def bitmap_definition(attrs) - { "horizontal_magnification":"05", - "vertical_magnification":"1", - "font":"G", - "space_adjustment":"00", - "rotational_angles":"00" + { horizontal_magnification:"05", + vertical_magnification:"1", + font:"G", + space_adjustment:"00", + rotational_angles:"00" }.merge(attrs) end @@ -18,17 +18,17 @@ def plate_barcode_definition(name, type_id, barcode_type) labels_attributes:[{ name: 'label', bitmaps_attributes:[ - bitmap_definition({ "field_name":"top_left","x_origin":"0030","y_origin":"0035" }), - bitmap_definition({ "field_name":"bottom_left","x_origin":"0030","y_origin":"0065" }), - bitmap_definition({ "field_name":"top_right","x_origin":"0550","y_origin":"0035" }), - bitmap_definition({ "field_name":"bottom_right","x_origin":"0550","y_origin":"0065" }), - bitmap_definition({ "field_name":"top_far_right","x_origin":"0750","y_origin":"0035" }), - bitmap_definition({ "field_name":"bottom_far_right","x_origin":"0750","y_origin":"0065" }), - bitmap_definition({ "field_name":"label_counter_right","x_origin":"0890","y_origin":"0065","rotational_angles":"33" }) + bitmap_definition({ field_name:"top_left",x_origin:"0030",y_origin:"0035" }), + bitmap_definition({ field_name:"bottom_left",x_origin:"0030",y_origin:"0065" }), + bitmap_definition({ field_name:"top_right",x_origin:"0550",y_origin:"0035" }), + bitmap_definition({ field_name:"bottom_right",x_origin:"0550",y_origin:"0065" }), + bitmap_definition({ field_name:"top_far_right",x_origin:"0750",y_origin:"0035" }), + bitmap_definition({ field_name:"bottom_far_right",x_origin:"0750",y_origin:"0065" }), + bitmap_definition({ field_name:"label_counter_right",x_origin:"0890",y_origin:"0065",rotational_angles:"33" }) ], barcodes_attributes:[ - { "field_name":"barcode", "barcode_type": barcode_type,"one_module_width":"02","height":"0070","rotational_angle":nil,"one_cell_width":nil, - "type_of_check_digit":"2","no_of_columns":nil,"bar_height":nil,"x_origin":"0200","y_origin":"0000", + { field_name:"barcode", barcode_type: barcode_type,one_module_width:"02",height:"0070",rotational_angle:nil,one_cell_width:nil, + type_of_check_digit:"2",no_of_columns:nil,bar_height:nil,x_origin:"0200",y_origin:"0000", } ] }] diff --git a/lib/label_templates/ss_tube.rb b/lib/label_templates/ss_tube.rb index 0685fc01..5be624e5 100644 --- a/lib/label_templates/ss_tube.rb +++ b/lib/label_templates/ss_tube.rb @@ -9,24 +9,24 @@ def tube_barcode_definition(name, type_id, barcode_type) labels_attributes:[{ name: 'label', bitmaps_attributes:[ - { "horizontal_magnification":"05","vertical_magnification":"05","font":"H","space_adjustment":"03","rotational_angles":"11", - "x_origin":"0038","y_origin":"0210","field_name":"bottom_line" }, - { "horizontal_magnification":"05","vertical_magnification":"05","font":"H","space_adjustment":"02","rotational_angles":"11", - "x_origin":"0070","y_origin":"0210","field_name":"middle_line" }, - { "horizontal_magnification":"05","vertical_magnification":"05","font":"H","space_adjustment":"02","rotational_angles":"11", - "x_origin":"0120","y_origin":"0210","field_name":"top_line" }, - { "horizontal_magnification":"05","vertical_magnification":"1","font":"G","space_adjustment":"00","rotational_angles":"00", - "x_origin":"0240","y_origin":"0165","field_name":"round_label_top_line" }, - { "horizontal_magnification":"05","vertical_magnification":"1","font":"G","space_adjustment":"00","rotational_angles":"00", - "x_origin":"0220","y_origin":"0193","field_name":"round_label_bottom_line" } + { horizontal_magnification:"05",vertical_magnification:"05",font:"H",space_adjustment:"03",rotational_angles:"11", + x_origin:"0038",y_origin:"0210",field_name:"bottom_line" }, + { horizontal_magnification:"05",vertical_magnification:"05",font:"H",space_adjustment:"02",rotational_angles:"11", + x_origin:"0070",y_origin:"0210",field_name:"middle_line" }, + { horizontal_magnification:"05",vertical_magnification:"05",font:"H",space_adjustment:"02",rotational_angles:"11", + x_origin:"0120",y_origin:"0210",field_name:"top_line" }, + { horizontal_magnification:"05",vertical_magnification:"1",font:"G",space_adjustment:"00",rotational_angles:"00", + x_origin:"0240",y_origin:"0165",field_name:"round_label_top_line" }, + { horizontal_magnification:"05",vertical_magnification:"1",font:"G",space_adjustment:"00",rotational_angles:"00", + x_origin:"0220",y_origin:"0193",field_name:"round_label_bottom_line" } ], barcodes_attributes:[ - { "barcode_type":"Q","one_module_width":"03","height":"0080","rotational_angle":"1","one_cell_width":"03", - "type_of_check_digit":nil, - "no_of_columns":nil,"bar_height":nil,"x_origin":"0300","y_origin":"0145","field_name":"barcode2d" }, - { "barcode_type": barcode_type,"one_module_width":"01","height":"0100","rotational_angle":nil, - "one_cell_width":nil,"type_of_check_digit":"2", - "no_of_columns":nil,"bar_height":nil,"x_origin":"0043","y_origin":"0100","field_name":"barcode" } + { barcode_type:"Q",one_module_width:"03",height:"0080",rotational_angle:"1",one_cell_width:"03", + type_of_check_digit:nil, + no_of_columns:nil,bar_height:nil,x_origin:"0300",y_origin:"0145",field_name:"barcode2d" }, + { barcode_type: barcode_type,one_module_width:"01",height:"0100",rotational_angle:nil, + one_cell_width:nil,type_of_check_digit:"2", + no_of_columns:nil,bar_height:nil,x_origin:"0043",y_origin:"0100",field_name:"barcode" } ] } ] diff --git a/lib/psd_formatter.rb b/lib/psd_formatter.rb index 4be7d1c5..11a60827 100644 --- a/lib/psd_formatter.rb +++ b/lib/psd_formatter.rb @@ -7,7 +7,7 @@ class PsdFormatter < Syslog::Logger::Formatter LINE_FORMAT = "(thread-%s) [%s] %5s -- : %s\n".freeze def initialize(deployment_info) - info = OpenStruct.new(deployment_info) + info = OpenStruct.new(deployment_info) # rubocop:todo Style/OpenStructUse @app_tag = [info.name, info.version, info.environment].compact.join(':').freeze super() end diff --git a/lib/tasks/message_addition.rake b/lib/tasks/message_addition.rake index 914d98f0..2facffab 100644 --- a/lib/tasks/message_addition.rake +++ b/lib/tasks/message_addition.rake @@ -10,7 +10,7 @@ namespace :message_addition do puts 'Finding samples needing uuids...' asset_sample_ids = Fact.with_predicate('sanger_sample_id') .joins("LEFT OUTER JOIN facts AS uuid ON uuid.predicate = 'sample_uuid' AND uuid.asset_id = facts.asset_id") - .where('uuid.object IS NULL') + .where(uuid: { object: nil }) .pluck('facts.asset_id', 'facts.object') puts "#{asset_sample_ids.length} to migrate" asset_sample_ids.each_slice(block_size) do |slice| @@ -25,11 +25,11 @@ namespace :message_addition do store[sample.sanger_sample_id] = sample.uuid end puts 'Building facts' - fact_attributes = slice.map do |asset_id, sanger_sample_id| + fact_attributes = slice.filter_map do |asset_id, sanger_sample_id| next if uuid_hash[sanger_sample_id].nil? { asset_id: asset_id, predicate: 'sample_uuid', object: uuid_hash[sanger_sample_id] } - end.compact + end puts 'Creating facts' Fact.create!(fact_attributes) puts 'Done!' diff --git a/lib/token_util.rb b/lib/token_util.rb index 8f30f2ae..06b84f00 100644 --- a/lib/token_util.rb +++ b/lib/token_util.rb @@ -87,7 +87,7 @@ def self.generate_positions(letters, columns) end def self.pad(str,chr,size) - "#{(size-str.size).times.map { chr }.join('')}#{str}" + "#{(size-str.size).times.map { chr }.join}#{str}" end def self.unpad_location(location) diff --git a/script/plate_to_code39.rb b/script/plate_to_code39.rb index ee2e0589..93134bd2 100644 --- a/script/plate_to_code39.rb +++ b/script/plate_to_code39.rb @@ -6,5 +6,5 @@ external_id = PMB::LabelTemplate.where(name: pmb_template_name).first.id LabelTemplate.create(name: pmb_template_name, - template_type: 'Plate', external_id: external_id) + template_type: 'Plate', external_id: external_id) end diff --git a/script/runners/create_file.rb b/script/runners/create_file.rb index a3ffe13f..3cfda02f 100755 --- a/script/runners/create_file.rb +++ b/script/runners/create_file.rb @@ -7,7 +7,7 @@ barcodes = [] while (num < NUM_BARCODES) do number=(rand*999999).floor.to_s - barcode = ["FR"].concat((6-number.length).times.map { "0" }).concat([number]).join("") + barcode = ["FR"].concat((6-number.length).times.map { "0" }).concat([number]).join found = Asset.find_by(barcode: barcode) unless found barcodes.push(barcode) diff --git a/script/runners/create_layout.rb b/script/runners/create_layout.rb index 21f980cc..65a512ac 100755 --- a/script/runners/create_layout.rb +++ b/script/runners/create_layout.rb @@ -7,7 +7,7 @@ barcodes = [] while (num < NUM_BARCODES) do number=(rand*999999).floor.to_s - barcode = ["FR"].concat((6-number.length).times.map { "0" }).concat([number]).join("") + barcode = ["FR"].concat((6-number.length).times.map { "0" }).concat([number]).join found = Asset.find_by(barcode: barcode) unless found barcodes.push(barcode) diff --git a/script/runners/load_metadata.rb b/script/runners/load_metadata.rb index 89c2cc95..edf44cd6 100644 --- a/script/runners/load_metadata.rb +++ b/script/runners/load_metadata.rb @@ -16,7 +16,7 @@ def find_asset(line_parsed) if line_parsed['location'] parent = Asset.find_by!(barcode: line_parsed['barcode']) facts = parent.facts.where(predicate: 'contains', - object_asset_id: Fact.where(predicate: 'location', object: line_parsed['location']).select(:asset_id)) + object_asset_id: Fact.where(predicate: 'location', object: line_parsed['location']).select(:asset_id)) raise 'More than one asset found' if facts.count > 1 return facts.first.object_asset else diff --git a/script/runners/rack_layout_any_barcode.rb b/script/runners/rack_layout_any_barcode.rb index 1ad5e2fc..39583a28 100644 --- a/script/runners/rack_layout_any_barcode.rb +++ b/script/runners/rack_layout_any_barcode.rb @@ -39,5 +39,5 @@ def process puts ({ set_errors: e.errors }.to_json) rescue StandardError => e - puts ({ set_errors: ['Unknown error while parsing file'+e.to_json+e.backtrace.join('')] }.to_json) + puts ({ set_errors: ['Unknown error while parsing file'+e.to_json+e.backtrace.join] }.to_json) end diff --git a/script/runners/rack_layout_creating_tubes.rb b/script/runners/rack_layout_creating_tubes.rb index 6a5429fc..cbf2cd26 100644 --- a/script/runners/rack_layout_creating_tubes.rb +++ b/script/runners/rack_layout_creating_tubes.rb @@ -39,5 +39,5 @@ def process puts ({ set_errors: e.errors }.to_json) rescue StandardError => e - puts ({ set_errors: ['Unknown error while parsing file'+e.to_json+e.backtrace.join('')] }.to_json) + puts ({ set_errors: ['Unknown error while parsing file'+e.to_json+e.backtrace.join] }.to_json) end diff --git a/spec/lib/actions/racking_spec.rb b/spec/lib/actions/racking_spec.rb index 446e3471..933c97dc 100644 --- a/spec/lib/actions/racking_spec.rb +++ b/spec/lib/actions/racking_spec.rb @@ -2,7 +2,7 @@ require 'actions/racking' RSpec.describe Actions::Racking do - let(:content) { File.open('test/data/layout.csv').read } + let(:content) { File.read('test/data/layout.csv') } let(:file) { create(:uploaded_file, data: content ) } let(:activity) { create(:activity) } let(:asset_group) { create(:asset_group, assets: [asset]) } @@ -80,7 +80,7 @@ let(:num_empty) { 3 } let(:start_pos) { 0 } let(:content) { - add_empty_slots(File.open('test/data/layout.csv').read, num_empty, start_pos) + add_empty_slots(File.read('test/data/layout.csv'), num_empty, start_pos) } def add_empty_slots(content, num_empty, start_pos = 0) csv = CSV.new(content).to_a @@ -145,12 +145,12 @@ def add_empty_slots(content, num_empty, start_pos = 0) it 'only returns the studies of the tubes that are going to be removed' do @tubes.first.facts << create(:fact, predicate: 'study_name', object: 'STDY2') - tubes2 = @tubes.each_with_index.map do |tube, idx| + tubes2 = @tubes.each_with_index.filter_map do |tube, idx| unless idx == 0 tube.facts << create(:fact, predicate: 'study_name', object: 'STDY1') tube end - end.compact + end updates = fact_changes_for_rack_when_unracking_tubes(asset, tubes2) expect(updates.to_h[:remove_facts].select do |triple| @@ -199,7 +199,7 @@ def add_empty_slots(content, num_empty, start_pos = 0) describe '#rack_layout' do before do - csv = CSV.new(File.open('test/data/layout.csv').read).to_a + csv = CSV.new(File.read('test/data/layout.csv')).to_a @tubes = csv.map do |line| create(:asset, barcode: line[1]) end diff --git a/spec/lib/fact_changes_spec.rb b/spec/lib/fact_changes_spec.rb index 0a527f98..2b66f901 100644 --- a/spec/lib/fact_changes_spec.rb +++ b/spec/lib/fact_changes_spec.rb @@ -15,7 +15,7 @@ let(:fact1) { create :fact, asset: asset1, predicate: property, object: value } let(:fact2) { create :fact, asset: asset1, predicate: relation, object_asset: asset2 } let(:step) { create :step, activity: activity, state: Step::STATE_RUNNING } - let(:json) { { :"create_assets" => ["?p", "?q"], :"add_facts" => [["?p", "a", "Plate"]] }.to_json } + let(:json) { { create_assets: ["?p", "?q"], add_facts: [["?p", "a", "Plate"]] }.to_json } describe '#new' do it 'parses a json and loads the config from it' do @@ -1045,4 +1045,3 @@ end end end - diff --git a/spec/lib/parsers/csv_layout/csv_parser_spec.rb b/spec/lib/parsers/csv_layout/csv_parser_spec.rb index e2c42704..9ce38626 100644 --- a/spec/lib/parsers/csv_layout/csv_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/csv_parser_spec.rb @@ -22,7 +22,7 @@ Asset.find_by(barcode: barcode) end - @content = File.open('test/data/layout.csv').read + @content = File.read('test/data/layout.csv') @assets = 96.times.map do |i| FactoryBot.create(:asset, { :barcode => 'FR'+(11200002 + i).to_s diff --git a/spec/lib/parsers/csv_metadata/csv_parser_spec.rb b/spec/lib/parsers/csv_metadata/csv_parser_spec.rb index b1268166..7a865c5d 100644 --- a/spec/lib/parsers/csv_metadata/csv_parser_spec.rb +++ b/spec/lib/parsers/csv_metadata/csv_parser_spec.rb @@ -22,7 +22,7 @@ Asset.find_by(barcode: barcode) end - @content = File.open('test/data/metadata.csv').read + @content = File.read('test/data/metadata.csv') @assets = 96.times.map do |i| FactoryBot.create(:asset, { :barcode => 'FR'+(11200002 + i).to_s diff --git a/spec/lib/support_n3_spec.rb b/spec/lib/support_n3_spec.rb index 2290c80a..db829623 100644 --- a/spec/lib/support_n3_spec.rb +++ b/spec/lib/support_n3_spec.rb @@ -266,20 +266,20 @@ def validates_rule_with(parsed_obj) end it '{ ' \ - '?a :is :A . ' \ - '?a :transfer ?b . ' \ - '?b :is :B . ' \ - '?b :transfer ?c . ' \ - '?c :is :C . ' \ - '?c :transfer ?d . ' \ - '?d :is :D . ' \ - '?d :transfer ?a . ' \ - '} => {' \ - ':step :addFacts { ?a :is :Processed .}. ' \ - ':step :addFacts { ?b :is :Processed .}. ' \ - ':step :addFacts { ?c :is :Processed .}. ' \ - ':step :addFacts { ?d :is :Processed .}. ' \ - '} .' do + '?a :is :A . ' \ + '?a :transfer ?b . ' \ + '?b :is :B . ' \ + '?b :transfer ?c . ' \ + '?c :is :C . ' \ + '?c :transfer ?d . ' \ + '?d :is :D . ' \ + '?d :transfer ?a . ' \ + '} => {' \ + ':step :addFacts { ?a :is :Processed .}. ' \ + ':step :addFacts { ?b :is :Processed .}. ' \ + ':step :addFacts { ?c :is :Processed .}. ' \ + ':step :addFacts { ?d :is :Processed .}. ' \ + '} .' do validates_rule_with({ ConditionGroup => [ { :name => 'a', :step_type => @step_type, :cardinality => nil, diff --git a/spec/models/condition_group_spec.rb b/spec/models/condition_group_spec.rb index 0c54be35..4100f933 100644 --- a/spec/models/condition_group_spec.rb +++ b/spec/models/condition_group_spec.rb @@ -1,4 +1,4 @@ require 'rails_helper' -RSpec.describe ConditionGroup, type: :model do +RSpec.describe ConditionGroup, type: :model do # rubocop:todo Lint/EmptyBlock end diff --git a/spec/models/step_execution_spec.rb b/spec/models/step_execution_spec.rb index 0cfa33fc..db87b34e 100644 --- a/spec/models/step_execution_spec.rb +++ b/spec/models/step_execution_spec.rb @@ -56,7 +56,7 @@ created_assets = {} @step = Step.create(step_type: @step_type, asset_group: @asset_group, - wildcard_values: wildcards, state: Step::STATE_RUNNING) + wildcard_values: wildcards, state: Step::STATE_RUNNING) @step_execution = StepExecution.new({ :step => @step, :asset_group => @asset_group, :created_assets => created_assets }) diff --git a/spec/models/steps/background_tasks/inference_spec.rb b/spec/models/steps/background_tasks/inference_spec.rb index 694959e5..c2606721 100644 --- a/spec/models/steps/background_tasks/inference_spec.rb +++ b/spec/models/steps/background_tasks/inference_spec.rb @@ -39,7 +39,10 @@ inferences.reverse.reduce(nil) do |memo, step| id = (memo && memo.id) || nil step.update_attributes(next_step_id: id) - step + # Step is modified by the accumulator. This is actually shown as a + # 'good' pattern on the Lint/UnmodifiedReduceAccumulator documentation + # so surprised its complaining here. + step # rubocop:disable Lint/UnmodifiedReduceAccumulator end inferences.first.run! inferences.each(&:reload) diff --git a/spec/models/steps/job_spec.rb b/spec/models/steps/job_spec.rb index c9bb0850..02fb17b3 100644 --- a/spec/models/steps/job_spec.rb +++ b/spec/models/steps/job_spec.rb @@ -63,7 +63,7 @@ before do step.update_columns(state: 'stopping') end - it 'does nothing' do + it 'does nothing' do # rubocop:todo Lint/EmptyBlock end end end diff --git a/spec/models/steps/queueable_job_spec.rb b/spec/models/steps/queueable_job_spec.rb index 2c3b4097..730589e0 100644 --- a/spec/models/steps/queueable_job_spec.rb +++ b/spec/models/steps/queueable_job_spec.rb @@ -40,10 +40,13 @@ def build_instance_with_activity context 'when it has several steps configured' do let(:my_steps) { 5.times.map { build_instance_with_activity } } it 'does not execute any of the steps' do - my_steps.reverse.reduce(nil) do |memo, step| - step.update_attributes(next_step: memo) + my_steps.reverse.reduce(nil) do |next_step, step| + step.update_attributes(next_step: next_step) allow(step).to receive(:process) - step + # Step is modified by the accumulator. This is actually shown as a + # 'good' pattern on the Lint/UnmodifiedReduceAccumulator documentation + # so surprised its complaining here. + step # rubocop:disable Lint/UnmodifiedReduceAccumulator end step.update_attributes(next_step: my_steps.first) expect { step.run! }.not_to raise_error @@ -117,12 +120,15 @@ def build_instance_with_activity context 'when all the steps are correct' do it 'executes all steps until the last one' do - my_steps.reverse.reduce(nil) do |memo, step| - step.update_attributes(next_step: memo) + my_steps.reverse.reduce(nil) do |next_step, step| + step.update_attributes(next_step: next_step) allow(step).to receive(:run!) do step.update_attributes(state: 'complete') end - step + # Step is modified by the accumulator. This is actually shown as a + # 'good' pattern on the Lint/UnmodifiedReduceAccumulator documentation + # so surprised its complaining here. + step # rubocop:disable Lint/UnmodifiedReduceAccumulator end my_steps.first.run! expect(my_steps.last).to have_received(:run!) @@ -136,9 +142,12 @@ def mock_step_completion(s, state) end end before do - my_steps.reverse.reduce(nil) do |memo, step| - step.update_attributes(next_step: memo) - step + my_steps.reverse.reduce(nil) do |next_step, step| + step.update_attributes(next_step: next_step) + # Step is modified by the accumulator. This is actually shown as a + # 'good' pattern on the Lint/UnmodifiedReduceAccumulator documentation + # so surprised its complaining here. + step # rubocop:disable Lint/UnmodifiedReduceAccumulator end mock_step_completion(my_steps[0], 'complete') mock_step_completion(my_steps[1], 'complete') diff --git a/spec/requests/api/v1/assets_spec.rb b/spec/requests/api/v1/assets_spec.rb index 329fea5b..2497c8e6 100644 --- a/spec/requests/api/v1/assets_spec.rb +++ b/spec/requests/api/v1/assets_spec.rb @@ -51,8 +51,8 @@ def key_for_attribute(attr_key) before do get api_v1_asset_path(asset.uuid), headers: { - "Content-Type": "application/vnd.api+json", - "Accept": "application/vnd.api+json" + 'Content-Type': "application/vnd.api+json", + Accept: "application/vnd.api+json" } end @@ -82,8 +82,8 @@ def key_for_attribute(attr_key) end before do get api_v1_assets_path, params: { "filter[barcode]" => "F02" }, headers: { - "Content-Type": "application/vnd.api+json", - "Accept": "application/vnd.api+json" + 'Content-Type': "application/vnd.api+json", + Accept: "application/vnd.api+json" } end it 'returns the asset' do diff --git a/spec/script/runners/load_metadata_spec.rb b/spec/script/runners/load_metadata_spec.rb index 9d80d935..f343792c 100644 --- a/spec/script/runners/load_metadata_spec.rb +++ b/spec/script/runners/load_metadata_spec.rb @@ -4,7 +4,7 @@ require 'parsers/csv_metadata/csv_parser' RSpec.describe 'LoadMetadata' do - let(:content) { File.open('test/data/metadata.csv').read } + let(:content) { File.read('test/data/metadata.csv') } let(:file) { create(:uploaded_file, data: content ) } let(:file_asset) { create :asset, uploaded_file: file } diff --git a/test/factories/actions.rb b/test/factories/actions.rb index 3b48132a..d9ff9ba4 100644 --- a/test/factories/actions.rb +++ b/test/factories/actions.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :action do - - end + factory :action end diff --git a/test/factories/activity_type_step_types.rb b/test/factories/activity_type_step_types.rb index 5ade6b7d..27f222bf 100644 --- a/test/factories/activity_type_step_types.rb +++ b/test/factories/activity_type_step_types.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :activity_type_step_type do - - end + factory :activity_type_step_type end diff --git a/test/factories/activity_types.rb b/test/factories/activity_types.rb index 8d3abd98..103b4af4 100644 --- a/test/factories/activity_types.rb +++ b/test/factories/activity_types.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :activity_type do - - end + factory :activity_type end diff --git a/test/factories/asset_groups.rb b/test/factories/asset_groups.rb index 12ad979f..ade82ab9 100644 --- a/test/factories/asset_groups.rb +++ b/test/factories/asset_groups.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :asset_group do - - end + factory :asset_group end diff --git a/test/factories/condition_groups.rb b/test/factories/condition_groups.rb index 70e83ec9..83d13071 100644 --- a/test/factories/condition_groups.rb +++ b/test/factories/condition_groups.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :condition_group, class: 'ConditionGroup' do - - end + factory :condition_group, class: 'ConditionGroup' end diff --git a/test/factories/conditions.rb b/test/factories/conditions.rb index df424897..ebc5b0e7 100644 --- a/test/factories/conditions.rb +++ b/test/factories/conditions.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :condition, class: 'Condition' do - - end + factory :condition, class: 'Condition' end diff --git a/test/factories/kit_types.rb b/test/factories/kit_types.rb index 660ac10d..c4668a95 100644 --- a/test/factories/kit_types.rb +++ b/test/factories/kit_types.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :kit_type do - - end + factory :kit_type end diff --git a/test/factories/label_templates.rb b/test/factories/label_templates.rb index f2718c21..a473f108 100644 --- a/test/factories/label_templates.rb +++ b/test/factories/label_templates.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :label_template do - - end + factory :label_template end diff --git a/test/factories/operations.rb b/test/factories/operations.rb index b714f174..81c3a22a 100644 --- a/test/factories/operations.rb +++ b/test/factories/operations.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :operation do - - end + factory :operation end diff --git a/test/factories/printers.rb b/test/factories/printers.rb index b5511f3a..176742ef 100644 --- a/test/factories/printers.rb +++ b/test/factories/printers.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :printer do - - end + factory :printer end diff --git a/test/factories/step_executions.rb b/test/factories/step_executions.rb index 364b77e4..81d03e7f 100644 --- a/test/factories/step_executions.rb +++ b/test/factories/step_executions.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :step_execution do - - end + factory :step_execution end diff --git a/test/factories/step_types.rb b/test/factories/step_types.rb index b61e6a96..a480cd8f 100644 --- a/test/factories/step_types.rb +++ b/test/factories/step_types.rb @@ -1,5 +1,3 @@ FactoryBot.define do - factory :step_type do - - end + factory :step_type end diff --git a/test/factories/steps.rb b/test/factories/steps.rb index 6ec4521f..4222c099 100644 --- a/test/factories/steps.rb +++ b/test/factories/steps.rb @@ -1,6 +1,5 @@ FactoryBot.define do - factory :step do - end + factory :step factory :background_task, :class => 'Steps::BackgroundTasks::BackgroundTask' do step_type { create :step_type } diff --git a/test/factories/uploaded_file.rb b/test/factories/uploaded_file.rb index 32421511..f883a51a 100644 --- a/test/factories/uploaded_file.rb +++ b/test/factories/uploaded_file.rb @@ -1,4 +1,3 @@ FactoryBot.define do - factory :uploaded_file do - end + factory :uploaded_file end diff --git a/test/factories/user_sessions.rb b/test/factories/user_sessions.rb index 7ed10808..8f9b4972 100644 --- a/test/factories/user_sessions.rb +++ b/test/factories/user_sessions.rb @@ -1,4 +1,3 @@ FactoryBot.define do - factory :user_session do - end + factory :user_session end From 879f6490abda9c2f0a8a8ee3fcf77211143e78da Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 10 Mar 2022 15:36:29 +0000 Subject: [PATCH 088/303] Switch from yajl to oj --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 72320d50..02f40638 100644 --- a/Gemfile +++ b/Gemfile @@ -42,7 +42,7 @@ gem 'ace-rails-ap' # Serializers gem 'rdf-n3' gem 'jbuilder' -gem 'yajl-ruby' +gem 'oj' # Traction endpoints gem 'jsonapi-resources' diff --git a/Gemfile.lock b/Gemfile.lock index dabef7e9..e0971cee 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -177,6 +177,7 @@ GEM nokogiri (1.13.3) mini_portile2 (~> 2.8.0) racc (~> 1.4) + oj (3.13.10) parallel (1.21.0) parser (3.1.1.0) ast (~> 2.4.1) @@ -374,7 +375,6 @@ GEM will_paginate (3.1.7) will_paginate-bootstrap (1.0.2) will_paginate (>= 3.0.3) - yajl-ruby (1.4.1) PLATFORMS ruby @@ -407,6 +407,7 @@ DEPENDENCIES launchy micro_token mysql2 + oj pmb-client! pry puma @@ -439,7 +440,6 @@ DEPENDENCIES webpacker-react will_paginate will_paginate-bootstrap - yajl-ruby BUNDLED WITH 2.2.26 From ca588cd661c543e3ab8a93755a9efa7f4a25c3b4 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 10 Mar 2022 17:05:10 +0000 Subject: [PATCH 089/303] Update sequencescape-client-api --- Gemfile | 4 +--- Gemfile.lock | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 02f40638..89cf99e6 100644 --- a/Gemfile +++ b/Gemfile @@ -55,9 +55,7 @@ gem 'pmb-client', git: 'https://github.com/sanger/pmb-client.git' # Sequencescspae gem 'rest-client' gem 'faraday' -gem 'sequencescape-client-api', '1.0.0', require: 'sequencescape' -# -#gem 'sequencescape-client-api', require: 'sequencescape' +gem 'sequencescape-client-api', require: 'sequencescape' # Debugging gem 'rb-readline' diff --git a/Gemfile.lock b/Gemfile.lock index e0971cee..44ec1fcd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -429,7 +429,7 @@ DEPENDENCIES sanger_warren sass-rails sdoc - sequencescape-client-api (= 1.0.0) + sequencescape-client-api shoulda-matchers spring sprockets-rails From e3d6db6caae0a65dea4847c8b11ed4b9ababf8e7 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 10 Mar 2022 21:04:57 +0000 Subject: [PATCH 090/303] Update Rack Rack updates were resulting in CSRF errors on attempting to log in. This was a result of the fix for CVE-2020-8184 whic results in the cookie keys no-longer being decoded. This was resulting in the session cookie to be under 'SOME+SECRET' rather than 'SOME SECRET'. I've changed the session store back the the default. The value isn't a secret, for one we expose it in our source, but the key is trivially visible to anyone who inspects their cookies. This does have the unfortunate side effect of expiring any sessions. However we can't simply modify the key to 'SOME+SECRET' as that itself is escaped to 'SOME%2BSECRET'. --- Gemfile.lock | 2 +- app/channels/application_cable/connection.rb | 2 +- config/initializers/session_store.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 44ec1fcd..cee4dcd8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -188,7 +188,7 @@ GEM puma (5.6.2) nio4r (~> 2.0) racc (1.6.0) - rack (2.0.7) + rack (2.2.3) rack-proxy (0.6.5) rack rack-test (1.1.0) diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index eab38420..e1d53985 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -4,7 +4,7 @@ class Connection < ActionCable::Connection::Base def connect #self.current_user = nil - token = cookies.encrypted['SOME SECRET']['token'] + token = cookies.encrypted['_samples_extraction_session']['token'] if token self.current_user = User.find_by(:token => token) return if self.current_user diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index d22ad21d..51698dbf 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,4 +1,4 @@ # Be sure to restart your server when you modify this file. #Rails.application.config.session_store :active_record_store, key: '_samples_extraction_session' -Rails.application.config.session_store :cookie_store, key: 'SOME SECRET' +Rails.application.config.session_store :cookie_store, key: '_samples_extraction_session' From 75fb8cea1c1dec3d3839e4f3fd2d623f78f9016d Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 10 Mar 2022 21:05:41 +0000 Subject: [PATCH 091/303] Update sequencescape-client-api --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index cee4dcd8..d405092e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -313,7 +313,7 @@ GEM rake sdoc (1.0.0) rdoc (>= 5.0) - sequencescape-client-api (1.0.0) + sequencescape-client-api (2.0.0) activemodel (>= 5.0.0) activesupport (>= 5.0.0) i18n From b1bbf9a36bba2ee172b440cf14f84cdcfcd59825 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 10 Mar 2022 21:36:43 +0000 Subject: [PATCH 092/303] Upgrade to Rails 5.2 --- Gemfile | 3 +- Gemfile.lock | 116 ++++++++++-------- bin/bundle | 2 +- bin/rails | 7 +- bin/rake | 5 - bin/setup | 58 +++------ bin/update | 31 +++++ config/application.rb | 17 +-- config/boot.rb | 3 +- config/database.yml | 2 +- config/environment.rb | 2 +- config/environments/development.rb | 32 ++++- config/environments/production.rb | 11 +- .../application_controller_renderer.rb | 10 ++ .../initializers/content_security_policy.rb | 27 ++++ .../new_framework_defaults_5_2.rb | 40 ++++++ config/puma.rb | 39 ++++++ config/spring.rb | 8 ++ config/storage.yml | 34 +++++ lefthook.yml | 61 +++++++++ 20 files changed, 377 insertions(+), 131 deletions(-) create mode 100755 bin/update create mode 100644 config/initializers/application_controller_renderer.rb create mode 100644 config/initializers/content_security_policy.rb create mode 100644 config/initializers/new_framework_defaults_5_2.rb create mode 100644 config/puma.rb create mode 100644 config/spring.rb create mode 100644 config/storage.yml create mode 100644 lefthook.yml diff --git a/Gemfile b/Gemfile index 89cf99e6..02504e5c 100644 --- a/Gemfile +++ b/Gemfile @@ -9,9 +9,10 @@ gem 'redis' gem 'delayed_job' gem 'delayed_job_active_record' gem 'mysql2' +gem 'bootsnap', require: false # Rails and framework libraries -gem 'rails', '~> 5.1' +gem 'rails', '~> 5.2' gem 'tzinfo-data' gem 'activerecord-session_store' gem 'micro_token' diff --git a/Gemfile.lock b/Gemfile.lock index d405092e..de1df316 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -17,38 +17,38 @@ GEM aasm (5.0.5) concurrent-ruby (~> 1.0) ace-rails-ap (4.2) - actioncable (5.1.7) - actionpack (= 5.1.7) + actioncable (5.2.6.3) + actionpack (= 5.2.6.3) nio4r (~> 2.0) - websocket-driver (~> 0.6.1) - actionmailer (5.1.7) - actionpack (= 5.1.7) - actionview (= 5.1.7) - activejob (= 5.1.7) + websocket-driver (>= 0.6.1) + actionmailer (5.2.6.3) + actionpack (= 5.2.6.3) + actionview (= 5.2.6.3) + activejob (= 5.2.6.3) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.1.7) - actionview (= 5.1.7) - activesupport (= 5.1.7) - rack (~> 2.0) + actionpack (5.2.6.3) + actionview (= 5.2.6.3) + activesupport (= 5.2.6.3) + rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.1.7) - activesupport (= 5.1.7) + actionview (5.2.6.3) + activesupport (= 5.2.6.3) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.1.7) - activesupport (= 5.1.7) + activejob (5.2.6.3) + activesupport (= 5.2.6.3) globalid (>= 0.3.6) - activemodel (5.1.7) - activesupport (= 5.1.7) - activerecord (5.1.7) - activemodel (= 5.1.7) - activesupport (= 5.1.7) - arel (~> 8.0) + activemodel (5.2.6.3) + activesupport (= 5.2.6.3) + activerecord (5.2.6.3) + activemodel (= 5.2.6.3) + activesupport (= 5.2.6.3) + arel (>= 9.0) activerecord-import (1.0.2) activerecord (>= 3.2) activerecord-session_store (1.1.3) @@ -57,7 +57,11 @@ GEM multi_json (~> 1.11, >= 1.11.2) rack (>= 1.5.2, < 3) railties (>= 4.0) - activesupport (5.1.7) + activestorage (5.2.6.3) + actionpack (= 5.2.6.3) + activerecord (= 5.2.6.3) + marcel (~> 1.0.0) + activesupport (5.2.6.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -65,7 +69,7 @@ GEM addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) amq-protocol (2.3.2) - arel (8.0.0) + arel (9.0.0) ast (2.4.2) autoprefixer-rails (9.6.0) execjs @@ -74,20 +78,22 @@ GEM babel-source (>= 4.0, < 6) execjs (~> 2.0) bindex (0.7.0) + bootsnap (1.10.3) + msgpack (~> 1.2) bootstrap-sass (3.4.1) autoprefixer-rails (>= 5.2.1) sassc (>= 2.0.0) bootstrap_form (4.2.0) actionpack (>= 5.0) activemodel (>= 5.0) - builder (3.2.3) + builder (3.2.4) bunny (2.17.0) amq-protocol (~> 2.3, >= 2.3.1) byebug (11.0.1) coderay (1.1.2) concurrent-ruby (1.1.9) connection_pool (2.2.2) - crass (1.0.4) + crass (1.0.6) daemons (1.3.1) database_cleaner (1.7.0) delayed_job (4.1.7) @@ -104,7 +110,7 @@ GEM rdf (~> 3.0) sxp (~> 1.0) ejs (1.1.1) - erubi (1.8.0) + erubi (1.10.0) exception_notification (4.3.0) actionmailer (>= 4.0, < 6) activesupport (>= 4.0, < 6) @@ -119,8 +125,8 @@ GEM faraday_middleware (0.13.1) faraday (>= 0.7.4, < 1.0) ffi (1.11.1) - globalid (0.4.2) - activesupport (>= 4.2.0) + globalid (1.0.0) + activesupport (>= 5.0) gmetric (0.1.3) hamster (3.0.0) concurrent-ruby (~> 1.0) @@ -152,21 +158,23 @@ GEM launchy (2.4.3) addressable (~> 2.3) link_header (0.0.8) - loofah (2.2.3) + loofah (2.14.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) macaddr (1.7.2) systemu (~> 2.6.5) mail (2.7.1) mini_mime (>= 0.1.1) + marcel (1.0.2) method_source (0.9.2) micro_token (0.0.4) mime-types (3.2.2) mime-types-data (~> 3.2015) mime-types-data (3.2019.0331) - mini_mime (1.0.2) + mini_mime (1.1.2) mini_portile2 (2.8.0) minitest (5.15.0) + msgpack (1.4.5) multi_json (1.15.0) multipart-post (2.1.1) mysql2 (0.5.3) @@ -196,17 +204,18 @@ GEM rack_session_access (0.2.0) builder (>= 2.0.0) rack (>= 1.0.0) - rails (5.1.7) - actioncable (= 5.1.7) - actionmailer (= 5.1.7) - actionpack (= 5.1.7) - actionview (= 5.1.7) - activejob (= 5.1.7) - activemodel (= 5.1.7) - activerecord (= 5.1.7) - activesupport (= 5.1.7) + rails (5.2.6.3) + actioncable (= 5.2.6.3) + actionmailer (= 5.2.6.3) + actionpack (= 5.2.6.3) + actionview (= 5.2.6.3) + activejob (= 5.2.6.3) + activemodel (= 5.2.6.3) + activerecord (= 5.2.6.3) + activestorage (= 5.2.6.3) + activesupport (= 5.2.6.3) bundler (>= 1.3.0) - railties (= 5.1.7) + railties (= 5.2.6.3) sprockets-rails (>= 2.0.0) rails-assets-tether (1.1.1) rails-controller-testing (1.0.4) @@ -216,16 +225,16 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.0.4) - loofah (~> 2.2, >= 2.2.2) - railties (5.1.7) - actionpack (= 5.1.7) - activesupport (= 5.1.7) + rails-html-sanitizer (1.4.2) + loofah (~> 2.3) + railties (5.2.6.3) + actionpack (= 5.2.6.3) + activesupport (= 5.2.6.3) method_source rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) + thor (>= 0.19.0, < 2.0) rainbow (3.1.1) - rake (12.3.3) + rake (13.0.6) rb-fsevent (0.10.3) rb-inotify (0.10.0) ffi (~> 1.0) @@ -335,14 +344,14 @@ GEM sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.1) - actionpack (>= 4.0) - activesupport (>= 4.0) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) sprockets (>= 3.0.0) sxp (1.0.2) rdf (~> 3.0) systemu (2.6.5) - thor (0.20.3) + thor (1.2.1) thread_safe (0.3.6) tilt (2.0.9) turbolinks (5.2.0) @@ -369,7 +378,7 @@ GEM railties (>= 4.2) webpacker-react (0.3.2) webpacker - websocket-driver (0.6.5) + websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) will_paginate (3.1.7) @@ -384,6 +393,7 @@ DEPENDENCIES ace-rails-ap activerecord-import activerecord-session_store + bootsnap bootstrap-sass bootstrap_form byebug @@ -412,7 +422,7 @@ DEPENDENCIES pry puma rack_session_access - rails (~> 5.1) + rails (~> 5.2) rails-assets-tether rails-controller-testing rb-readline diff --git a/bin/bundle b/bin/bundle index 66e9889e..f19acf5b 100755 --- a/bin/bundle +++ b/bin/bundle @@ -1,3 +1,3 @@ #!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails index 0138d79b..07396602 100755 --- a/bin/rails +++ b/bin/rails @@ -1,9 +1,4 @@ #!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') -end -APP_PATH = File.expand_path('../../config/application', __FILE__) +APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' diff --git a/bin/rake b/bin/rake index d87d5f57..17240489 100755 --- a/bin/rake +++ b/bin/rake @@ -1,9 +1,4 @@ #!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') -end require_relative '../config/boot' require 'rake' Rake.application.run diff --git a/bin/setup b/bin/setup index 1140f4e3..94fd4d79 100755 --- a/bin/setup +++ b/bin/setup @@ -1,58 +1,36 @@ #!/usr/bin/env ruby -require 'pathname' +require 'fileutils' +include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = File.expand_path('..', __dir__) -Dir.chdir APP_ROOT do +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do # This script is a starting point to setup your application. - # Add necessary setup steps to this file: + # Add necessary setup steps to this file. - puts "== Installing dependencies ==" - system "gem install bundler --conservative" - system "bundle check || bundle install" + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') # Install JavaScript dependencies if using Yarn - system('bin/yarn') + # system('bin/yarn') # puts "\n== Copying sample files ==" - # unless File.exist?("config/database.yml") - # system "cp config/database.yml.sample config/database.yml" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' # end - unless File.exist?('config/secrets.yml') - puts "\n== Generating secret key ==" - secret = `bundle exec rails secret` - - File.open('config/secrets.yml', 'w') do |file| - content = <<~HTML - development: - secret_key_base: #{secret} - test: - secret_key_base: #{secret} - production: - secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> - HTML - file << content - end - end - puts "\n== Preparing database ==" - if ENV['RAILS_ENV'] == 'test' - # If the RAILS_ENV is already set to test (such as on the CI server) then - # not only will rake db:setup generate the test database, but will also seed - # it. This differs from the test database created when an environment is - # unspecified, which is unseeded. We avoid using rake db:setup in this case - # and just create the database and load the schema instead. - system "bin/rake db:create db:schema:load" - else - system "bin/rake db:setup" - end + system! 'bin/rails db:setup' puts "\n== Removing old logs and tempfiles ==" - system "rm -f log/*" - system "rm -rf tmp/cache" + system! 'bin/rails log:clear tmp:clear' puts "\n== Restarting application server ==" - system "touch tmp/restart.txt" + system! 'bin/rails restart' end diff --git a/bin/update b/bin/update new file mode 100755 index 00000000..58bfaed5 --- /dev/null +++ b/bin/update @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/config/application.rb b/config/application.rb index f3fc5d4f..6d04a53f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,4 +1,4 @@ -require File.expand_path('../boot', __FILE__) +require_relative 'boot' require 'rails/all' @@ -9,19 +9,10 @@ module SamplesExtraction class Application < Rails::Application # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. + # Application configuration can go into files in config/initializers + # -- all .rb files in that directory are automatically loaded after loading + # the framework and any gems in your application. - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - # config.time_zone = 'Central Time (US & Canada)' - - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - # config.i18n.default_locale = :de - - # Do not swallow errors in after_commit/after_rollback callbacks. - #config.active_record.raise_in_transactional_callbacks = true config.active_job.queue_adapter = :delayed_job config.team_name = 'LIMS and Informatics' diff --git a/config/boot.rb b/config/boot.rb index 6b750f00..b9e460ce 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,3 +1,4 @@ -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile. +require 'bootsnap/setup' # Speed up boot time by caching expensive operations. diff --git a/config/database.yml b/config/database.yml index 3e1c78cd..a630d4d1 100644 --- a/config/database.yml +++ b/config/database.yml @@ -20,7 +20,7 @@ default: &default development: <<: *default - database: samples_extraction_development + database: <%= ENV.fetch('DBNAME','uat_se_dump') %> debug: <<: *default diff --git a/config/environment.rb b/config/environment.rb index ee8d90dc..426333bb 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,5 @@ # Load the Rails application. -require File.expand_path('../application', __FILE__) +require_relative 'application' # Initialize the Rails application. Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb index 1692a807..5486ac1b 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -4,27 +4,47 @@ # Settings specified here will take precedence over those in config/application.rb. + benchmarking = ENV['BENCHMARKING'] == 'true' # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. - config.cache_classes = false + config.cache_classes = benchmarking # Do not eager load code on boot. config.eager_load = true - # Show full error reports and disable caching. + # Show full error reports config.consider_all_requests_local = true - config.action_controller.perform_caching = false + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join('tmp/caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false + config.action_mailer.perform_caching = false + # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. @@ -34,6 +54,9 @@ # yet still be able to expire them through the digest params. config.assets.digest = true + # Suppress logger output for asset requests. + config.assets.quiet = true + config.allow_concurrency = true # Adds additional error checking when serving assets at runtime. @@ -48,7 +71,7 @@ config.redis_url = ENV.fetch('SE_REDIS_URI', 'redis://127.0.0.1:6379') config.ss_uri = ENV.fetch('SE_SS_URI', 'http://localhost:3000/api/1/') config.ss_api_v2_uri = ENV.fetch('SE_SS_API_V2_URI', 'http://localhost:3000') - config.ss_authorisation = 'development' + config.ss_authorisation = ENV.fetch('SE_SS_API_AUTH', 'development') config.searcher_name_by_barcode = 'Find assets by barcode' config.searcher_study_by_name = 'Find study by name' config.printing_disabled = true @@ -60,4 +83,5 @@ config.enable_reasoning = false + config.log_level = :warn if benchmarking end diff --git a/config/environments/production.rb b/config/environments/production.rb index 30b6f535..ca2fc276 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -4,17 +4,18 @@ # Settings specified here will take precedence over those in config/application.rb. - # In the development environment your application's code is reloaded on - # every request. This slows down response time but is perfect for development - # since you don't have to restart the web server when you make code changes. + # Code is not reloaded between requests. config.cache_classes = true config.action_cable.allowed_request_origins = [%r{https?://\S+}] - # Do not eager load code on boot. + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. config.eager_load = true - # Show full error reports and disable caching. + # Full error reports are disabled and caching is turned on. config.consider_all_requests_local = false config.action_controller.perform_caching = true diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 00000000..6d56e439 --- /dev/null +++ b/config/initializers/application_controller_renderer.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 00000000..e3c96496 --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https + +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true diff --git a/config/initializers/new_framework_defaults_5_2.rb b/config/initializers/new_framework_defaults_5_2.rb new file mode 100644 index 00000000..c300f213 --- /dev/null +++ b/config/initializers/new_framework_defaults_5_2.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.2 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +# Make Active Record use stable #cache_key alongside new #cache_version method. +# This is needed for recyclable cache keys. +# Rails.application.config.active_record.cache_versioning = true + +# Use AES-256-GCM authenticated encryption for encrypted cookies. +# Also, embed cookie expiry in signed or encrypted cookies for increased security. +# +# This option is not backwards compatible with earlier Rails versions. +# It's best enabled when your entire app is migrated and stable on 5.2. +# +# Existing cookies will be converted on read then written with the new scheme. +# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true + +# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages +# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true. +# Rails.application.config.active_support.use_authenticated_message_encryption = true + +# Add default protection from forgery to ActionController::Base instead of in +# ApplicationController. +# Rails.application.config.action_controller.default_protect_from_forgery = true + +# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and +# 'f' after migrating old data. +# Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true + +# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header. +# Rails.application.config.active_support.use_sha1_digests = true + +# Make `form_with` generate id attributes for any generated HTML tags. +# Rails.application.config.action_view.form_with_generates_ids = true diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 00000000..b5afac5e --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +threads_count = ENV.fetch('RAILS_MAX_THREADS', 5) +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch('PORT', 3000) + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch('RAILS_ENV', 'development') + +# Specifies the `pidfile` that Puma will use. +pidfile ENV.fetch('PIDFILE', 'tmp/pids/server.pid') + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. +# +# preload_app! + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 00000000..c5933e49 --- /dev/null +++ b/config/spring.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +%w[ + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +].each { |path| Spring.watch(path) } diff --git a/config/storage.yml b/config/storage.yml new file mode 100644 index 00000000..d32f76e8 --- /dev/null +++ b/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket + +# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 00000000..1078fe10 --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,61 @@ +# https://github.com/Arkweid/lefthook +# Rubocop globs built based on https://github.com/rubocop-hq/rubocop/blob/master/config/default.yml With globbing support povided by +# https://pkg.go.dev/github.com/gobwas/glob#section-documentation +# Has the advantage of quicker commits when no rubocop files +pre-commit: + parallel: true + commands: + # prettier: + # run: yarn prettier --check {staged_files} --ignore-unknown + rubocop: + glob: "{*.{rb,arb,axlsx,builder,fcgi,gemfile,gemspec,god,jb,jbuilder,mspec,opal,pluginspec,podspec,rabl,rake,rbuild,rbw,rbx,ru,ruby,spec,thor,watchr},.irbrc,.pryrc,.simplecov,buildfile,Appraisals,Berksfile,Brewfile,Buildfile,Capfile,Cheffile,Dangerfile,Deliverfile,Fastfile,*Fastfile,Gemfile,Guardfile,Jarfile,Mavenfile,Podfile,Puppetfile,Rakefile,rakefile,Snapfile,Steepfile,Thorfile,Vagabondfile,Vagrantfile}" + run: rubocop --display-style-guide --extra-details --force-exclusion --parallel {staged_files} || (echo 'Run `lefthook run fix` to run autocorrect on staged files only'; exit 1) + # eslint: + # glob: "app/javascript/**/*.{vue,js}" + # run: yarn lintOnly {staged_files} || (echo 'Run `lefthook run fix` to run autocrrect on staged files only'; exit 1) + +fix: + parallel: true + commands: + # prettier: + # run: yarn prettier --write {staged_files} --ignore-unknown + rubocop: + glob: "{*.{rb,arb,axlsx,builder,fcgi,gemfile,gemspec,god,jb,jbuilder,mspec,opal,pluginspec,podspec,rabl,rake,rbuild,rbw,rbx,ru,ruby,spec,thor,watchr},.irbrc,.pryrc,.simplecov,buildfile,Appraisals,Berksfile,Brewfile,Buildfile,Capfile,Cheffile,Dangerfile,Deliverfile,Fastfile,*Fastfile,Gemfile,Guardfile,Jarfile,Mavenfile,Podfile,Puppetfile,Rakefile,rakefile,Snapfile,Steepfile,Thorfile,Vagabondfile,Vagrantfile}" + run: rubocop --display-style-guide --extra-details --auto-correct --force-exclusion {staged_files} + # eslint: + # glob: "app/javascript/**/*.{vue,js}" + # run: yarn lintOnly {staged_files} --fix +# EXAMPLE USAGE +# Refer for explanation to following link: +# https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md +# +# pre-push: +# commands: +# packages-audit: +# tags: frontend security +# run: yarn audit +# gems-audit: +# tags: backend security +# run: bundle audit +# +# pre-commit: +# parallel: true +# commands: +# eslint: +# glob: "*.{js,ts}" +# run: yarn eslint {staged_files} +# rubocop: +# tags: backend style +# glob: "*.rb" +# exclude: "application.rb|routes.rb" +# run: bundle exec rubocop --force-exclusion {all_files} +# govet: +# tags: backend style +# files: git ls-files -m +# glob: "*.go" +# run: go vet {files} +# scripts: +# "hello.js": +# runner: node +# "any.go": +# runner: go run From f6aeba1112e78cbe275a2550c4ebd03fbf20c0db Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 10 Mar 2022 21:38:45 +0000 Subject: [PATCH 093/303] Update mime-types --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index de1df316..232f9a26 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -168,9 +168,9 @@ GEM marcel (1.0.2) method_source (0.9.2) micro_token (0.0.4) - mime-types (3.2.2) + mime-types (3.4.1) mime-types-data (~> 3.2015) - mime-types-data (3.2019.0331) + mime-types-data (3.2022.0105) mini_mime (1.1.2) mini_portile2 (2.8.0) minitest (5.15.0) From 9205d177d603008995ae837e6700e36850fa4ad1 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 10 Mar 2022 21:42:24 +0000 Subject: [PATCH 094/303] Update delayed_job_active_record --- Gemfile | 1 - Gemfile.lock | 9 ++++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index 02504e5c..0ca09013 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,6 @@ gem 'sanger_warren' # Wraps bunny and manages connection pools and configuration gem 'puma' gem 'daemons' gem 'redis' -gem 'delayed_job' gem 'delayed_job_active_record' gem 'mysql2' gem 'bootsnap', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 232f9a26..fad526d4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -96,10 +96,10 @@ GEM crass (1.0.6) daemons (1.3.1) database_cleaner (1.7.0) - delayed_job (4.1.7) - activesupport (>= 3.0, < 5.3) - delayed_job_active_record (4.1.3) - activerecord (>= 3.0, < 5.3) + delayed_job (4.1.10) + activesupport (>= 3.0, < 8.0) + delayed_job_active_record (4.1.7) + activerecord (>= 3.0, < 8.0) delayed_job (>= 3.0, < 5) diff-lcs (1.3) domain_name (0.5.20180417) @@ -399,7 +399,6 @@ DEPENDENCIES byebug daemons database_cleaner - delayed_job delayed_job_active_record dropzonejs-rails ejs From 32cead548681473cacbea07a7eba38bc1a5c5365 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 11 Mar 2022 10:23:15 +0000 Subject: [PATCH 095/303] Update spring --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index fad526d4..0202004c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -77,7 +77,7 @@ GEM babel-transpiler (0.7.0) babel-source (>= 4.0, < 6) execjs (~> 2.0) - bindex (0.7.0) + bindex (0.8.1) bootsnap (1.10.3) msgpack (~> 1.2) bootstrap-sass (3.4.1) @@ -340,7 +340,7 @@ GEM sparql-client (3.0.1) net-http-persistent (>= 2.9, < 4) rdf (~> 3.0) - spring (2.1.0) + spring (4.0.0) sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) From 9cd32bd26c5f99a6a3d6281b515962b9668f374d Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 11 Mar 2022 10:30:16 +0000 Subject: [PATCH 096/303] Update factory-bot Switch to just defining factory-bot-rails --- Gemfile | 3 +-- Gemfile.lock | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile index 0ca09013..b34a741b 100644 --- a/Gemfile +++ b/Gemfile @@ -67,13 +67,12 @@ gem 'sdoc'#, '~> 0.4.0', group: :doc group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug' - gem 'factory_bot_rails' gem 'pry' gem 'ruby-growl' end group :test do - gem 'factory_bot' + gem 'factory_bot_rails' gem 'rspec-rails' gem 'shoulda-matchers' gem 'rails-controller-testing' diff --git a/Gemfile.lock b/Gemfile.lock index 0202004c..9c5ca9b0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -115,11 +115,11 @@ GEM actionmailer (>= 4.0, < 6) activesupport (>= 4.0, < 6) execjs (2.7.0) - factory_bot (5.0.2) - activesupport (>= 4.2.0) - factory_bot_rails (5.0.2) - factory_bot (~> 5.0.2) - railties (>= 4.2.0) + factory_bot (6.2.0) + activesupport (>= 5.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) + railties (>= 5.0.0) faraday (0.15.4) multipart-post (>= 1.2, < 3) faraday_middleware (0.13.1) @@ -403,7 +403,6 @@ DEPENDENCIES dropzonejs-rails ejs exception_notification - factory_bot factory_bot_rails faraday gmetric (~> 0.1.3) From a0fe866ebe62e5e26d7a8234ba9df11ffe36db92 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 11 Mar 2022 10:31:43 +0000 Subject: [PATCH 097/303] Update pry and byebug - Switch pry to pry-rails for improved console integration - Switch byebug to pry-byebug for improved pry integration --- Gemfile | 6 +++--- Gemfile.lock | 21 +++++++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Gemfile b/Gemfile index b34a741b..2153b3e6 100644 --- a/Gemfile +++ b/Gemfile @@ -65,9 +65,9 @@ gem 'sdoc'#, '~> 0.4.0', group: :doc group :development, :test do - # Call 'byebug' anywhere in the code to stop execution and get a debugger console - gem 'byebug' - gem 'pry' + # Call 'pry' anywhere in the code to stop execution and get a debugger console + gem 'pry-byebug' + gem 'pry-rails' gem 'ruby-growl' end diff --git a/Gemfile.lock b/Gemfile.lock index 9c5ca9b0..ae28dc03 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -89,8 +89,8 @@ GEM builder (3.2.4) bunny (2.17.0) amq-protocol (~> 2.3, >= 2.3.1) - byebug (11.0.1) - coderay (1.1.2) + byebug (11.1.3) + coderay (1.1.3) concurrent-ruby (1.1.9) connection_pool (2.2.2) crass (1.0.6) @@ -166,7 +166,7 @@ GEM mail (2.7.1) mini_mime (>= 0.1.1) marcel (1.0.2) - method_source (0.9.2) + method_source (1.0.0) micro_token (0.0.4) mime-types (3.4.1) mime-types-data (~> 3.2015) @@ -189,9 +189,14 @@ GEM parallel (1.21.0) parser (3.1.1.0) ast (~> 2.4.1) - pry (0.12.2) - coderay (~> 1.1.0) - method_source (~> 0.9.0) + pry (0.13.1) + coderay (~> 1.1) + method_source (~> 1.0) + pry-byebug (3.9.0) + byebug (~> 11.0) + pry (~> 0.13.0) + pry-rails (0.3.9) + pry (>= 0.10.4) public_suffix (4.0.6) puma (5.6.2) nio4r (~> 2.0) @@ -396,7 +401,6 @@ DEPENDENCIES bootsnap bootstrap-sass bootstrap_form - byebug daemons database_cleaner delayed_job_active_record @@ -417,7 +421,8 @@ DEPENDENCIES mysql2 oj pmb-client! - pry + pry-byebug + pry-rails puma rack_session_access rails (~> 5.2) From 177b7454dd8cf876614b2c4833c410f7103d956c Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 11 Mar 2022 10:46:06 +0000 Subject: [PATCH 098/303] Update activerecord-session_store --- Gemfile.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index ae28dc03..d524fbaa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -51,12 +51,12 @@ GEM arel (>= 9.0) activerecord-import (1.0.2) activerecord (>= 3.2) - activerecord-session_store (1.1.3) - actionpack (>= 4.0) - activerecord (>= 4.0) + activerecord-session_store (2.0.0) + actionpack (>= 5.2.4.1) + activerecord (>= 5.2.4.1) multi_json (~> 1.11, >= 1.11.2) - rack (>= 1.5.2, < 3) - railties (>= 4.0) + rack (>= 2.0.8, < 3) + railties (>= 5.2.4.1) activestorage (5.2.6.3) actionpack (= 5.2.6.3) activerecord (= 5.2.6.3) From 0858883e893876b5767d1617bece01927cb7c61b Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 11 Mar 2022 11:43:05 +0000 Subject: [PATCH 099/303] Update webpacker --- .babelrc | 8 +- .postcssrc.yml | 2 +- Gemfile.lock | 12 +- bin/webpack | 1 - bin/webpack-dev-server | 1 - package.json | 3 +- yarn.lock | 7277 +++++++++++++++++++--------------------- 7 files changed, 3441 insertions(+), 3863 deletions(-) diff --git a/.babelrc b/.babelrc index aa27d4ac..3dcb43e0 100644 --- a/.babelrc +++ b/.babelrc @@ -4,13 +4,7 @@ "@babel/preset-react" ], "plugins": [ - "syntax-dynamic-import", + "@babel/plugin-syntax-dynamic-import", "@babel/plugin-proposal-object-rest-spread", - [ - "transform-class-properties", - { - "spec": true - } - ] ] } diff --git a/.postcssrc.yml b/.postcssrc.yml index 150dac3c..908ff000 100644 --- a/.postcssrc.yml +++ b/.postcssrc.yml @@ -1,3 +1,3 @@ plugins: postcss-import: {} - postcss-cssnext: {} + postcss-preset-env: {} diff --git a/Gemfile.lock b/Gemfile.lock index d524fbaa..952fbe02 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -136,7 +136,7 @@ GEM concurrent-ruby (~> 1.0) jbuilder (2.9.1) activesupport (>= 4.2.0) - jquery-rails (4.3.5) + jquery-rails (4.4.0) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) @@ -202,7 +202,7 @@ GEM nio4r (~> 2.0) racc (1.6.0) rack (2.2.3) - rack-proxy (0.6.5) + rack-proxy (0.7.2) rack rack-test (1.1.0) rack (>= 1.0, < 3) @@ -327,6 +327,7 @@ GEM rake sdoc (1.0.0) rdoc (>= 5.0) + semantic_range (3.0.0) sequencescape-client-api (2.0.0) activemodel (>= 5.0.0) activesupport (>= 5.0.0) @@ -377,10 +378,11 @@ GEM activemodel (>= 5.0) bindex (>= 0.4.0) railties (>= 5.0) - webpacker (4.0.7) - activesupport (>= 4.2) + webpacker (5.4.3) + activesupport (>= 5.2) rack-proxy (>= 0.6.1) - railties (>= 4.2) + railties (>= 5.2) + semantic_range (>= 2.3.0) webpacker-react (0.3.2) webpacker websocket-driver (0.7.5) diff --git a/bin/webpack b/bin/webpack index 008ecb22..1031168d 100755 --- a/bin/webpack +++ b/bin/webpack @@ -7,7 +7,6 @@ require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) -require "rubygems" require "bundler/setup" require "webpacker" diff --git a/bin/webpack-dev-server b/bin/webpack-dev-server index a931a9b7..dd966273 100755 --- a/bin/webpack-dev-server +++ b/bin/webpack-dev-server @@ -7,7 +7,6 @@ require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) -require "rubygems" require "bundler/setup" require "webpacker" diff --git a/package.json b/package.json index 56199769..07a2b8d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@rails/webpacker": "^3.2.2", + "@rails/webpacker": "^5.4.3", "ajv": "^6.4.0", "classnames": "^2.2.6", "eslint": "^4.19.1", @@ -41,6 +41,7 @@ "identity-obj-proxy": "^3.0.0", "jest": "^24.9.0", "jest-enzyme": "^7.1.0", + "postcss-preset-env": "^6.7.1", "regenerator-runtime": "^0.13.3" }, "scripts": { diff --git a/yarn.lock b/yarn.lock index 59871142..340c73c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@ampproject/remapping@^2.1.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" + integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.0" + "@babel/cli@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.5.5.tgz#bdb6d9169e93e241a08f5f7b0265195bf38ef5ec" @@ -19,58 +26,62 @@ optionalDependencies: chokidar "^2.0.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== - dependencies: - "@babel/highlight" "^7.0.0" - -"@babel/core@^7.1.0", "@babel/core@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" - integrity sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.5.5" - "@babel/helpers" "^7.5.5" - "@babel/parser" "^7.5.5" - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - convert-source-map "^1.1.0" +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" + integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== + +"@babel/core@^7.1.0", "@babel/core@^7.15.0", "@babel/core@^7.5.5": + version "7.17.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.5.tgz#6cd2e836058c28f06a4ca8ee7ed955bbf37c8225" + integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.17.2" + "@babel/parser" "^7.17.3" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" + convert-source-map "^1.7.0" debug "^4.1.0" - json5 "^2.1.0" - lodash "^4.17.13" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" -"@babel/generator@^7.4.0", "@babel/generator@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.5.tgz#873a7f936a3c89491b43536d12245b626664e3cf" - integrity sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ== +"@babel/generator@^7.17.3", "@babel/generator@^7.4.0": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" + integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== dependencies: - "@babel/types" "^7.5.5" + "@babel/types" "^7.17.0" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" - trim-right "^1.0.1" -"@babel/helper-annotate-as-pure@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" - integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== +"@babel/helper-annotate-as-pure@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" + integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.16.7" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" - integrity sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b" + integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== dependencies: - "@babel/helper-explode-assignable-expression" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-explode-assignable-expression" "^7.16.7" + "@babel/types" "^7.16.7" "@babel/helper-builder-react-jsx@^7.3.0": version "7.3.0" @@ -80,446 +91,645 @@ "@babel/types" "^7.3.0" esutils "^2.0.0" -"@babel/helper-call-delegate@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz#87c1f8ca19ad552a736a7a27b1c1fcf8b1ff1f43" - integrity sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" + integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== dependencies: - "@babel/helper-hoist-variables" "^7.4.4" - "@babel/traverse" "^7.4.4" - "@babel/types" "^7.4.4" + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" + browserslist "^4.17.5" + semver "^6.3.0" -"@babel/helper-define-map@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" - integrity sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg== +"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.6": + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz#3778c1ed09a7f3e65e6d6e0f6fbfcc53809d92c9" + integrity sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg== dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/types" "^7.5.5" - lodash "^4.17.13" + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" -"@babel/helper-explode-assignable-expression@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" - integrity sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA== +"@babel/helper-create-regexp-features-plugin@^7.16.7": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1" + integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA== dependencies: - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-annotate-as-pure" "^7.16.7" + regexpu-core "^5.0.1" -"@babel/helper-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== +"@babel/helper-define-polyfill-provider@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" + integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== dependencies: - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-get-function-arity@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-explode-assignable-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a" + integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== dependencies: - "@babel/types" "^7.0.0" + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" -"@babel/helper-hoist-variables@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" - integrity sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w== - dependencies: - "@babel/types" "^7.4.4" +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-member-expression-to-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" + integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-transforms@^7.16.7": + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz#3c3b03cc6617e33d68ef5a27a67419ac5199ccd0" + integrity sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.3" + "@babel/types" "^7.17.0" + +"@babel/helper-optimise-call-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" + integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" + integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + +"@babel/helper-remap-async-to-generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3" + integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-wrap-function" "^7.16.8" + "@babel/types" "^7.16.8" + +"@babel/helper-replace-supers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" + integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-simple-access@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" + integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" + integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== + +"@babel/helper-wrap-function@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200" + integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw== + dependencies: + "@babel/helper-function-name" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.8" + "@babel/types" "^7.16.8" + +"@babel/helpers@^7.17.2": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" + integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.0" + "@babel/types" "^7.17.0" + +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" -"@babel/helper-member-expression-to-functions@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" - integrity sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA== +"@babel/parser@^7.1.0", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.4.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" + integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" + integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" + integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + +"@babel/plugin-proposal-async-generator-functions@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" + integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.14.5", "@babel/plugin-proposal-class-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" + integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-class-static-block@^7.16.7": + version "7.17.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz#164e8fd25f0d80fa48c5a4d1438a6629325ad83c" + integrity sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.17.6" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-proposal-dynamic-import@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" + integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-proposal-export-namespace-from@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" + integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" + integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" + integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" + integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== dependencies: - "@babel/types" "^7.5.5" - -"@babel/helper-module-imports@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" - integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-numeric-separator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" + integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== dependencies: - "@babel/types" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" - integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/template" "^7.4.4" - "@babel/types" "^7.5.5" - lodash "^4.17.13" - -"@babel/helper-optimise-call-expression@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" - integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g== +"@babel/plugin-proposal-object-rest-spread@^7.14.7", "@babel/plugin-proposal-object-rest-spread@^7.16.7", "@babel/plugin-proposal-object-rest-spread@^7.5.5": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390" + integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw== dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== + "@babel/compat-data" "^7.17.0" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.16.7" -"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" - integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== +"@babel/plugin-proposal-optional-catch-binding@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" + integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== dependencies: - lodash "^4.17.13" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/helper-remap-async-to-generator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" - integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== +"@babel/plugin-proposal-optional-chaining@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" + integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-wrap-function" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/helper-replace-supers@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" - integrity sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg== +"@babel/plugin-proposal-private-methods@^7.16.11": + version "7.16.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" + integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== dependencies: - "@babel/helper-member-expression-to-functions" "^7.5.5" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" + "@babel/helper-create-class-features-plugin" "^7.16.10" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/helper-simple-access@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" - integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== +"@babel/plugin-proposal-private-property-in-object@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" + integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== dependencies: - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/helper-split-export-declaration@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" - integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== +"@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" + integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== dependencies: - "@babel/types" "^7.4.4" + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/helper-wrap-function@^7.1.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" - integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ== +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.2.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/helpers@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.5.5.tgz#63908d2a73942229d1e6685bc2a0e730dde3b75e" - integrity sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g== +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" + "@babel/helper-plugin-utils" "^7.12.13" -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" - integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== + "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-proposal-async-generator-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" - integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-proposal-dynamic-import@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz#e532202db4838723691b10a67b8ce509e397c506" - integrity sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw== +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-dynamic-import" "^7.2.0" + "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" - integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-proposal-object-rest-spread@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz#61939744f71ba76a3ae46b5eea18a54c16d22e58" - integrity sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw== +"@babel/plugin-syntax-jsx@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7" + integrity sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" -"@babel/plugin-proposal-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" - integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78" - integrity sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA== +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-async-generators@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" - integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-dynamic-import@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" - integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" - integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7" - integrity sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw== +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" - integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" - integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-arrow-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" - integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== +"@babel/plugin-transform-arrow-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" + integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-async-to-generator@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz#89a3848a0166623b5bc481164b5936ab947e887e" - integrity sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg== +"@babel/plugin-transform-async-to-generator@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" + integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" -"@babel/plugin-transform-block-scoped-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" - integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== +"@babel/plugin-transform-block-scoped-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" + integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-block-scoping@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz#a35f395e5402822f10d2119f6f8e045e3639a2ce" - integrity sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg== +"@babel/plugin-transform-block-scoping@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" + integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - lodash "^4.17.13" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-classes@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz#d094299d9bd680a14a2a0edae38305ad60fb4de9" - integrity sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg== +"@babel/plugin-transform-classes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" + integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.5.5" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" - "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" - integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== +"@babel/plugin-transform-computed-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" + integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-destructuring@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz#f6c09fdfe3f94516ff074fe877db7bc9ef05855a" - integrity sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ== +"@babel/plugin-transform-destructuring@^7.14.7", "@babel/plugin-transform-destructuring@^7.16.7": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz#c445f75819641788a27a0a3a759d9df911df6abc" + integrity sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" - integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg== +"@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241" + integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-duplicate-keys@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" - integrity sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ== +"@babel/plugin-transform-duplicate-keys@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" + integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-exponentiation-operator@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" - integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== +"@babel/plugin-transform-exponentiation-operator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b" + integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-for-of@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" - integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== +"@babel/plugin-transform-for-of@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" + integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-function-name@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" - integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA== +"@babel/plugin-transform-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" + integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" - integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== +"@babel/plugin-transform-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" + integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-member-expression-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" - integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA== +"@babel/plugin-transform-member-expression-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" + integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-modules-amd@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" - integrity sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg== +"@babel/plugin-transform-modules-amd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" + integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - babel-plugin-dynamic-import-node "^2.3.0" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz#425127e6045231360858eeaa47a71d75eded7a74" - integrity sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ== +"@babel/plugin-transform-modules-commonjs@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" + integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== dependencies: - "@babel/helper-module-transforms" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - babel-plugin-dynamic-import-node "^2.3.0" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz#e75266a13ef94202db2a0620977756f51d52d249" - integrity sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg== +"@babel/plugin-transform-modules-systemjs@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7" + integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== dependencies: - "@babel/helper-hoist-variables" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" - babel-plugin-dynamic-import-node "^2.3.0" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" - integrity sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw== +"@babel/plugin-transform-modules-umd@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" + integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-named-capturing-groups-regex@^7.4.5": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz#9d269fd28a370258199b4294736813a60bbdd106" - integrity sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg== +"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" + integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== dependencies: - regexp-tree "^0.1.6" + "@babel/helper-create-regexp-features-plugin" "^7.16.7" -"@babel/plugin-transform-new-target@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" - integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== +"@babel/plugin-transform-new-target@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" + integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-object-super@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" - integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ== +"@babel/plugin-transform-object-super@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" + integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" -"@babel/plugin-transform-parameters@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" - integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== +"@babel/plugin-transform-parameters@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" + integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== dependencies: - "@babel/helper-call-delegate" "^7.4.4" - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-property-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" - integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ== +"@babel/plugin-transform-property-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" + integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-react-display-name@^7.0.0": version "7.2.0" @@ -553,121 +763,173 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-jsx" "^7.2.0" -"@babel/plugin-transform-regenerator@^7.4.5": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" - integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== - dependencies: - regenerator-transform "^0.14.0" - -"@babel/plugin-transform-reserved-words@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634" - integrity sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-shorthand-properties@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" - integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-spread@^7.2.0": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" - integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w== +"@babel/plugin-transform-regenerator@^7.14.5", "@babel/plugin-transform-regenerator@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" + integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-sticky-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" - integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" + regenerator-transform "^0.14.2" -"@babel/plugin-transform-template-literals@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" - integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== +"@babel/plugin-transform-reserved-words@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" + integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-typeof-symbol@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" - integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== +"@babel/plugin-transform-runtime@^7.15.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz#0a2e08b5e2b2d95c4b1d3b3371a2180617455b70" + integrity sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.5.0" + babel-plugin-polyfill-regenerator "^0.3.0" + semver "^6.3.0" -"@babel/plugin-transform-unicode-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" - integrity sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" +"@babel/plugin-transform-shorthand-properties@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" + integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-spread@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" + integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + +"@babel/plugin-transform-sticky-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" + integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-template-literals@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" + integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-typeof-symbol@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" + integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-unicode-escapes@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3" + integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-unicode-regex@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" + integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/preset-env@^7.15.0", "@babel/preset-env@^7.5.5": + version "7.16.11" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" + integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== + dependencies: + "@babel/compat-data" "^7.16.8" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-async-generator-functions" "^7.16.8" + "@babel/plugin-proposal-class-properties" "^7.16.7" + "@babel/plugin-proposal-class-static-block" "^7.16.7" + "@babel/plugin-proposal-dynamic-import" "^7.16.7" + "@babel/plugin-proposal-export-namespace-from" "^7.16.7" + "@babel/plugin-proposal-json-strings" "^7.16.7" + "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" + "@babel/plugin-proposal-numeric-separator" "^7.16.7" + "@babel/plugin-proposal-object-rest-spread" "^7.16.7" + "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-private-methods" "^7.16.11" + "@babel/plugin-proposal-private-property-in-object" "^7.16.7" + "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-transform-arrow-functions" "^7.16.7" + "@babel/plugin-transform-async-to-generator" "^7.16.8" + "@babel/plugin-transform-block-scoped-functions" "^7.16.7" + "@babel/plugin-transform-block-scoping" "^7.16.7" + "@babel/plugin-transform-classes" "^7.16.7" + "@babel/plugin-transform-computed-properties" "^7.16.7" + "@babel/plugin-transform-destructuring" "^7.16.7" + "@babel/plugin-transform-dotall-regex" "^7.16.7" + "@babel/plugin-transform-duplicate-keys" "^7.16.7" + "@babel/plugin-transform-exponentiation-operator" "^7.16.7" + "@babel/plugin-transform-for-of" "^7.16.7" + "@babel/plugin-transform-function-name" "^7.16.7" + "@babel/plugin-transform-literals" "^7.16.7" + "@babel/plugin-transform-member-expression-literals" "^7.16.7" + "@babel/plugin-transform-modules-amd" "^7.16.7" + "@babel/plugin-transform-modules-commonjs" "^7.16.8" + "@babel/plugin-transform-modules-systemjs" "^7.16.7" + "@babel/plugin-transform-modules-umd" "^7.16.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8" + "@babel/plugin-transform-new-target" "^7.16.7" + "@babel/plugin-transform-object-super" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-property-literals" "^7.16.7" + "@babel/plugin-transform-regenerator" "^7.16.7" + "@babel/plugin-transform-reserved-words" "^7.16.7" + "@babel/plugin-transform-shorthand-properties" "^7.16.7" + "@babel/plugin-transform-spread" "^7.16.7" + "@babel/plugin-transform-sticky-regex" "^7.16.7" + "@babel/plugin-transform-template-literals" "^7.16.7" + "@babel/plugin-transform-typeof-symbol" "^7.16.7" + "@babel/plugin-transform-unicode-escapes" "^7.16.7" + "@babel/plugin-transform-unicode-regex" "^7.16.7" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.16.8" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.5.0" + babel-plugin-polyfill-regenerator "^0.3.0" + core-js-compat "^3.20.2" + semver "^6.3.0" -"@babel/preset-env@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.5.5.tgz#bc470b53acaa48df4b8db24a570d6da1fef53c9a" - integrity sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A== +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== dependencies: - "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-async-generator-functions" "^7.2.0" - "@babel/plugin-proposal-dynamic-import" "^7.5.0" - "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.5.5" - "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-syntax-async-generators" "^7.2.0" - "@babel/plugin-syntax-dynamic-import" "^7.2.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" - "@babel/plugin-transform-arrow-functions" "^7.2.0" - "@babel/plugin-transform-async-to-generator" "^7.5.0" - "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.5.5" - "@babel/plugin-transform-classes" "^7.5.5" - "@babel/plugin-transform-computed-properties" "^7.2.0" - "@babel/plugin-transform-destructuring" "^7.5.0" "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/plugin-transform-duplicate-keys" "^7.5.0" - "@babel/plugin-transform-exponentiation-operator" "^7.2.0" - "@babel/plugin-transform-for-of" "^7.4.4" - "@babel/plugin-transform-function-name" "^7.4.4" - "@babel/plugin-transform-literals" "^7.2.0" - "@babel/plugin-transform-member-expression-literals" "^7.2.0" - "@babel/plugin-transform-modules-amd" "^7.5.0" - "@babel/plugin-transform-modules-commonjs" "^7.5.0" - "@babel/plugin-transform-modules-systemjs" "^7.5.0" - "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.4.5" - "@babel/plugin-transform-new-target" "^7.4.4" - "@babel/plugin-transform-object-super" "^7.5.5" - "@babel/plugin-transform-parameters" "^7.4.4" - "@babel/plugin-transform-property-literals" "^7.2.0" - "@babel/plugin-transform-regenerator" "^7.4.5" - "@babel/plugin-transform-reserved-words" "^7.2.0" - "@babel/plugin-transform-shorthand-properties" "^7.2.0" - "@babel/plugin-transform-spread" "^7.2.0" - "@babel/plugin-transform-sticky-regex" "^7.2.0" - "@babel/plugin-transform-template-literals" "^7.4.4" - "@babel/plugin-transform-typeof-symbol" "^7.2.0" - "@babel/plugin-transform-unicode-regex" "^7.4.4" - "@babel/types" "^7.5.5" - browserslist "^4.6.0" - core-js-compat "^3.1.1" - invariant "^2.2.2" - js-levenshtein "^1.1.3" - semver "^5.5.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" "@babel/preset-react@^7.0.0": version "7.0.0" @@ -680,44 +942,44 @@ "@babel/plugin-transform-react-jsx-self" "^7.0.0" "@babel/plugin-transform-react-jsx-source" "^7.0.0" -"@babel/runtime@^7.1.2": - version "7.3.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" - integrity sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g== - dependencies: - regenerator-runtime "^0.12.0" - -"@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" - integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.4.4" - "@babel/types" "^7.4.4" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb" - integrity sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.5.5" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.5.5" - "@babel/types" "^7.5.5" +"@babel/runtime@^7.1.2", "@babel/runtime@^7.15.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" + integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@^7.16.7", "@babel/template@^7.4.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3", "@babel/traverse@^7.4.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" + integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.17.3" + "@babel/types" "^7.17.0" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" - integrity sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw== +"@babel/types@^7.0.0", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== dependencies: - esutils "^2.0.2" - lodash "^4.17.13" + "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" "@cnakazawa/watch@^1.0.3": @@ -728,6 +990,16 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@csstools/convert-colors@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" + integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== + +"@gar/promisify@^1.0.1": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" + integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== + "@jest/console@^24.7.1", "@jest/console@^24.9.0": version "24.9.0" resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" @@ -876,36 +1148,83 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" -"@rails/webpacker@^3.2.2": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@rails/webpacker/-/webpacker-3.6.0.tgz#89f50421934a40cad7193cd62756a18fa5027251" - integrity sha512-QlEPgdi++lBjc2rGp2s3hhT9vbhskeMSpHWOxVnpoMjIspTvjSyRWBV8t15d9M4cy5W5Zxlt87aVce7gVI4lFA== - dependencies: - babel-core "^6.26.3" - babel-loader "^7.1.5" - babel-plugin-syntax-dynamic-import "^6.18.0" - babel-plugin-transform-class-properties "^6.24.1" - babel-plugin-transform-object-rest-spread "^6.26.0" - babel-polyfill "^6.26.0" - babel-preset-env "^1.7.0" - case-sensitive-paths-webpack-plugin "^2.1.2" - compression-webpack-plugin "^1.1.11" - css-loader "^0.28.11" - extract-text-webpack-plugin "^3.0.2" - file-loader "^1.1.11" - glob "^7.1.2" - js-yaml "^3.12.0" - node-sass "^4.9.2" - optimize-css-assets-webpack-plugin "^3.2.0" +"@jridgewell/resolve-uri@^3.0.3": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" + integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.11" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" + integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + +"@jridgewell/trace-mapping@^0.3.0": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" + integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@npmcli/fs@^1.0.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" + integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== + dependencies: + "@gar/promisify" "^1.0.1" + semver "^7.3.5" + +"@npmcli/move-file@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" + integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== + dependencies: + mkdirp "^1.0.4" + rimraf "^3.0.2" + +"@rails/webpacker@^5.4.3": + version "5.4.3" + resolved "https://registry.yarnpkg.com/@rails/webpacker/-/webpacker-5.4.3.tgz#cfe2d8faffe7db5001bad50a1534408b4f2efb2f" + integrity sha512-tEM8tpUtfx6FxKwcuQ9+v6pzgqM5LeAdhT6IJ4Te3BPKFO1xrGrXugqeRuZ+gE8ASDZRTOK6yuQkapOpuX5JdA== + dependencies: + "@babel/core" "^7.15.0" + "@babel/plugin-proposal-class-properties" "^7.14.5" + "@babel/plugin-proposal-object-rest-spread" "^7.14.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.14.7" + "@babel/plugin-transform-regenerator" "^7.14.5" + "@babel/plugin-transform-runtime" "^7.15.0" + "@babel/preset-env" "^7.15.0" + "@babel/runtime" "^7.15.3" + babel-loader "^8.2.2" + babel-plugin-dynamic-import-node "^2.3.3" + babel-plugin-macros "^2.8.0" + case-sensitive-paths-webpack-plugin "^2.4.0" + compression-webpack-plugin "^4.0.1" + core-js "^3.16.2" + css-loader "^3.6.0" + file-loader "^6.2.0" + flatted "^3.2.2" + glob "^7.1.7" + js-yaml "^3.14.1" + mini-css-extract-plugin "^0.9.0" + optimize-css-assets-webpack-plugin "^5.0.8" path-complete-extname "^1.0.0" - postcss-cssnext "^3.1.0" - postcss-import "^11.1.0" - postcss-loader "^2.1.5" - sass-loader "^6.0.7" - style-loader "^0.21.0" - uglifyjs-webpack-plugin "^1.2.7" - webpack "^3.12.0" - webpack-manifest-plugin "^1.3.2" + pnp-webpack-plugin "^1.7.0" + postcss-flexbugs-fixes "^4.2.1" + postcss-import "^12.0.1" + postcss-loader "^3.0.0" + postcss-preset-env "^6.7.0" + postcss-safe-parser "^4.0.2" + regenerator-runtime "^0.13.9" + sass "^1.38.0" + sass-loader "10.1.1" + style-loader "^1.3.0" + terser-webpack-plugin "^4.2.3" + webpack "^4.46.0" + webpack-assets-manifest "^3.1.1" + webpack-cli "^3.3.12" + webpack-sources "^1.4.3" "@types/babel__core@^7.1.0": version "7.1.2" @@ -960,10 +1279,25 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": + version "7.0.9" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + "@types/node@*": - version "12.7.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44" - integrity sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg== + version "17.0.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" + integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + +"@types/q@^1.5.1": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df" + integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ== "@types/stack-utils@^1.0.1": version "1.0.1" @@ -982,23 +1316,166 @@ dependencies: "@types/yargs-parser" "*" +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== + dependencies: + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== + +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== + +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== + +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== + dependencies: + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== + +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== + dependencies: + "@webassemblyjs/ast" "1.9.0" + +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== + +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== + +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + "@xtuc/long" "4.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + abab@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" integrity sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -acorn-dynamic-import@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" - integrity sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ= - dependencies: - acorn "^4.0.3" - acorn-globals@^4.1.0: version "4.3.3" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.3.tgz#a86f75b69680b8780d30edd21eee4e0ea170c05e" @@ -1024,20 +1501,28 @@ acorn@^3.0.4: resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= -acorn@^4.0.3: - version "4.0.13" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= - -acorn@^5.0.0, acorn@^5.5.0, acorn@^5.5.3: +acorn@^5.5.0, acorn@^5.5.3: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== -acorn@^6.0.1: - version "6.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" - integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== +acorn@^6.0.1, acorn@^6.4.1: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== + +acorn@^8.5.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" airbnb-prop-types@^2.13.2: version "2.15.0" @@ -1055,17 +1540,22 @@ airbnb-prop-types@^2.13.2: prop-types-exact "^1.2.0" react-is "^16.9.0" +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= -ajv-keywords@^3.1.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.0.tgz#4b831e7b531415a7cc518cd404e73f6193c6349d" - integrity sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw== +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^5.0.0, ajv@^5.2.3, ajv@^5.3.0: +ajv@^5.2.3, ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= @@ -1075,35 +1565,21 @@ ajv@^5.0.0, ajv@^5.2.3, ajv@^5.3.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ajv@^6.1.0, ajv@^6.4.0, ajv@^6.5.5: - version "6.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" - integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== +ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.4.0, ajv@^6.5.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: - fast-deep-equal "^2.0.1" + fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" -align-text@^0.1.1, align-text@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= - dependencies: - kind-of "^3.0.2" - longest "^1.0.1" - repeat-string "^1.5.2" - -alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: +alphanum-sort@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - ansi-escapes@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -1144,19 +1620,19 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -aproba@^1.0.3, aproba@^1.1.1: +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1189,11 +1665,6 @@ array-filter@^1.0.0: resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -1221,14 +1692,15 @@ asap@~2.0.3: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" asn1@~0.2.3: version "0.2.4" @@ -1243,10 +1715,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assert@^1.1.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== dependencies: + object-assign "^4.1.1" util "0.10.3" assign-symbols@^1.0.0: @@ -1260,60 +1733,37 @@ astral-regex@^1.0.0: integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== async-each@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= - -async-foreach@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" - integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@^2.1.2, async@^2.4.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" - integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== - dependencies: - lodash "^4.17.11" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob@^2.1.1: +atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@^6.3.1: - version "6.7.7" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" - integrity sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ= - dependencies: - browserslist "^1.7.6" - caniuse-db "^1.0.30000634" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^5.2.16" - postcss-value-parser "^3.2.3" - -autoprefixer@^7.1.1: - version "7.2.6" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.2.6.tgz#256672f86f7c735da849c4f07d008abb056067dc" - integrity sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ== +autoprefixer@^9.6.1: + version "9.8.8" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.8.tgz#fd4bd4595385fa6f06599de749a4d5f7a474957a" + integrity sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA== dependencies: - browserslist "^2.11.3" - caniuse-lite "^1.0.30000805" + browserslist "^4.12.0" + caniuse-lite "^1.0.30001109" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^6.0.17" - postcss-value-parser "^3.2.3" + picocolors "^0.2.1" + postcss "^7.0.32" + postcss-value-parser "^4.1.0" aws-sign2@~0.7.0: version "0.7.0" @@ -1325,7 +1775,7 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== -babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: +babel-code-frame@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= @@ -1334,162 +1784,10 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-core@^6.26.0, babel-core@^6.26.3: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-jest@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54" - integrity sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw== +babel-jest@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54" + integrity sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw== dependencies: "@jest/transform" "^24.9.0" "@jest/types" "^24.9.0" @@ -1499,43 +1797,20 @@ babel-jest@^24.9.0: chalk "^2.4.2" slash "^2.0.0" -babel-loader@^7.1.5: - version "7.1.5" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.5.tgz#e3ee0cd7394aa557e013b02d3e492bfd07aa6d68" - integrity sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw== - dependencies: - find-cache-dir "^1.0.0" - loader-utils "^1.0.2" - mkdirp "^0.5.1" - -babel-loader@^8.0.6: - version "8.0.6" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb" - integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw== - dependencies: - find-cache-dir "^2.0.0" - loader-utils "^1.0.2" - mkdirp "^0.5.1" - pify "^4.0.1" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= +babel-loader@^8.0.6, babel-loader@^8.2.2: + version "8.2.3" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" + integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== dependencies: - babel-runtime "^6.22.0" + find-cache-dir "^3.3.1" + loader-utils "^1.4.0" + make-dir "^3.1.0" + schema-utils "^2.6.5" -babel-plugin-dynamic-import-node@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: object.assign "^4.1.0" @@ -1556,328 +1831,45 @@ babel-plugin-jest-hoist@^24.9.0: dependencies: "@types/babel__traverse" "^7.0.6" -babel-plugin-react-transform@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/babel-plugin-react-transform/-/babel-plugin-react-transform-3.0.0.tgz#402f25137b7bb66e9b54ead75557dfbc7ecaaa74" - integrity sha512-4vJGddwPiHAOgshzZdGwYy4zRjjIr5SMY7gkOaCyIASjgpcsyLTlZNuB5rHOFoaTvGlhfo8/g4pobXPyHqm/3w== +babel-plugin-macros@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" + integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== dependencies: - lodash "^4.6.1" + "@babel/runtime" "^7.7.2" + cosmiconfig "^6.0.0" + resolve "^1.12.0" -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= - -babel-plugin-syntax-class-properties@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94= - -babel-plugin-syntax-dynamic-import@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" - integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo= - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= - -babel-plugin-syntax-object-rest-spread@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= - -babel-plugin-transform-async-to-generator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-class-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw= - dependencies: - babel-helper-function-name "^6.24.1" - babel-plugin-syntax-class-properties "^6.8.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.23.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-object-rest-spread@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= +babel-plugin-polyfill-corejs2@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" + integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.26.0" + "@babel/compat-data" "^7.13.11" + "@babel/helper-define-polyfill-provider" "^0.3.1" + semver "^6.1.1" -babel-plugin-transform-regenerator@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= +babel-plugin-polyfill-corejs3@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" + integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== dependencies: - regenerator-transform "^0.10.0" + "@babel/helper-define-polyfill-provider" "^0.3.1" + core-js-compat "^3.21.0" -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= +babel-plugin-polyfill-regenerator@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" + integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" + "@babel/helper-define-polyfill-provider" "^0.3.1" -babel-polyfill@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" - integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM= +babel-plugin-react-transform@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-react-transform/-/babel-plugin-react-transform-3.0.0.tgz#402f25137b7bb66e9b54ead75557dfbc7ecaaa74" + integrity sha512-4vJGddwPiHAOgshzZdGwYy4zRjjIr5SMY7gkOaCyIASjgpcsyLTlZNuB5rHOFoaTvGlhfo8/g4pobXPyHqm/3w== dependencies: - babel-runtime "^6.26.0" - core-js "^2.5.0" - regenerator-runtime "^0.10.5" - -babel-preset-env@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^3.2.6" - invariant "^2.2.2" - semver "^5.3.0" + lodash "^4.6.1" babel-preset-jest@^24.9.0: version "24.9.0" @@ -1887,87 +1879,15 @@ babel-preset-jest@^24.9.0: "@babel/plugin-syntax-object-rest-spread" "^7.0.0" babel-plugin-jest-hoist "^24.9.0" -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - -balanced-match@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.1.0.tgz#b504bd05869b39259dd0c5efc35d843176dccc4a" - integrity sha1-tQS9BYabOSWd0MXvw12EMXbczEo= - -balanced-match@^0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" - integrity sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg= - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base64-js@^1.0.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== base@^0.11.1: version "0.11.2" @@ -1995,9 +1915,14 @@ big.js@^5.2.2: integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== binary-extensions@^1.0.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.0.tgz#9523e001306a32444b907423f1de2164222f6ab1" - integrity sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw== + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== bindings@^1.5.0: version "1.5.0" @@ -2006,24 +1931,22 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" +bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bluebird@^3.5.1: - version "3.5.3" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" - integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -boolbase@~1.0.0: +bn.js@^5.0.0, bn.js@^5.1.1: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + +boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= @@ -2052,6 +1975,13 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -2100,26 +2030,28 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== dependencies: - bn.js "^4.1.0" + bn.js "^5.0.0" randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= - dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" browserify-zlib@^0.2.0: version "0.2.0" @@ -2128,38 +2060,16 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: - version "1.7.7" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" - integrity sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk= +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.17.5, browserslist@^4.19.1, browserslist@^4.6.4: + version "4.20.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.0.tgz#35951e3541078c125d36df76056e94738a52ebe9" + integrity sha512-bnpOoa+DownbciXj0jVGENf8VYQnE2LNWomhYuCsMmmx9Jd9lwq0WXODuwpSsp8AVdKM2/HorrzxAfbKvWTByQ== dependencies: - caniuse-db "^1.0.30000639" - electron-to-chromium "^1.2.7" - -browserslist@^2.0.0, browserslist@^2.11.3: - version "2.11.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2" - integrity sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA== - dependencies: - caniuse-lite "^1.0.30000792" - electron-to-chromium "^1.3.30" - -browserslist@^3.2.6: - version "3.2.8" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== - dependencies: - caniuse-lite "^1.0.30000844" - electron-to-chromium "^1.3.47" - -browserslist@^4.6.0, browserslist@^4.6.6: - version "4.6.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.6.tgz#6e4bf467cde520bc9dbdf3747dafa03531cec453" - integrity sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA== - dependencies: - caniuse-lite "^1.0.30000984" - electron-to-chromium "^1.3.191" - node-releases "^1.1.25" + caniuse-lite "^1.0.30001313" + electron-to-chromium "^1.4.76" + escalade "^3.1.1" + node-releases "^2.0.2" + picocolors "^1.0.0" bser@^2.0.0: version "2.1.0" @@ -2169,9 +2079,9 @@ bser@^2.0.0: node-int64 "^0.4.0" buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== buffer-xor@^1.0.3: version "1.0.3" @@ -2179,9 +2089,9 @@ buffer-xor@^1.0.3: integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^4.3.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -2192,25 +2102,51 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= -cacache@^10.0.1, cacache@^10.0.4: - version "10.0.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460" - integrity sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA== +cacache@^12.0.2: + version "12.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" + integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== dependencies: - bluebird "^3.5.1" - chownr "^1.0.1" - glob "^7.1.2" - graceful-fs "^4.1.11" - lru-cache "^4.1.1" - mississippi "^2.0.0" + bluebird "^3.5.5" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.4" + graceful-fs "^4.1.15" + infer-owner "^1.0.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" mkdirp "^0.5.1" move-concurrently "^1.0.1" promise-inflight "^1.0.1" - rimraf "^2.6.2" - ssri "^5.2.4" - unique-filename "^1.1.0" + rimraf "^2.6.3" + ssri "^6.0.1" + unique-filename "^1.1.1" y18n "^4.0.0" +cacache@^15.0.5: + version "15.3.0" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" + integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== + dependencies: + "@npmcli/fs" "^1.0.0" + "@npmcli/move-file" "^1.0.1" + chownr "^2.0.0" + fs-minipass "^2.0.0" + glob "^7.1.4" + infer-owner "^1.0.4" + lru-cache "^6.0.0" + minipass "^3.1.1" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^1.0.3" + p-map "^4.0.0" + promise-inflight "^1.0.1" + rimraf "^3.0.2" + ssri "^8.0.1" + tar "^6.0.2" + unique-filename "^1.1.1" + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -2226,6 +2162,21 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" @@ -2233,78 +2184,47 @@ caller-path@^0.1.0: dependencies: callsites "^0.2.0" +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - -camelcase@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= - -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= - -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= - camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-api@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" - integrity sha1-tTTnxzTE+B7F++isoq0kNUuWLGw= - dependencies: - browserslist "^1.3.6" - caniuse-db "^1.0.30000529" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-api@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-2.0.0.tgz#b1ddb5a5966b16f48dc4998444d4bbc6c7d9d834" - integrity sha1-sd21pZZrFvSNxJmERNS7xsfZ2DQ= +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== dependencies: - browserslist "^2.0.0" + browserslist "^4.0.0" caniuse-lite "^1.0.0" lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000942" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000942.tgz#e29e4c6afa3558edafe7c190c7f8bdd93fb7c486" - integrity sha512-HB+j2/Gywe+0JPtEMw8ioTi4ykIOco9nfSGspMGIBocqi4aMYZYALP992RmhVcUyB0oS5h8nrKGk9fCF9L1VXA== - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000844: - version "1.0.30000942" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000942.tgz#454139b28274bce70bfe1d50c30970df7430c6e4" - integrity sha512-wLf+IhZUy2rfz48tc40OH7jHjXjnvDFEYqBHluINs/6MgzoNLPf25zhE4NOVzqxLKndf+hau81sAW0RcGHIaBQ== - -caniuse-lite@^1.0.30000984: - version "1.0.30000989" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz#b9193e293ccf7e4426c5245134b8f2a56c0ac4b9" - integrity sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001313: + version "1.0.30001314" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001314.tgz#65c7f9fb7e4594fca0a333bec1d8939662377596" + integrity sha512-0zaSO+TnCHtHJIbpLroX7nsD+vYuOVjl3uzFbJO1wMVbuveJA0RK2WcQA9ZUIOiO0/ArMiMgHJLxfEZhQiC0kw== capture-exit@^2.0.0: version "2.0.0" @@ -2313,30 +2233,22 @@ capture-exit@^2.0.0: dependencies: rsvp "^4.8.4" -case-sensitive-paths-webpack-plugin@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.2.0.tgz#3371ef6365ef9c25fa4b81c16ace0e9c7dc58c3e" - integrity sha512-u5ElzokS8A1pm9vM3/iDgTcI3xqHxuCao94Oz8etI3cf0Tio0p8izkDYbTIn09uP3yUUr6+veaE6IkjnTYS46g== +case-sensitive-paths-webpack-plugin@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4" + integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -center-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60= - dependencies: - align-text "^0.1.3" - lazy-cache "^1.0.3" - chain-function@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.1.tgz#c63045e5b4b663fb86f1c6e186adaf1de402a1cc" integrity sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg== -chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= @@ -2347,7 +2259,7 @@ chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2373,26 +2285,22 @@ cheerio@^1.0.0-rc.2: lodash "^4.15.0" parse5 "^3.0.1" -chokidar@^2.0.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.2.tgz#9c23ea40b01638439e0513864d362aeacc5ad058" - integrity sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.0" +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.1: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" optionalDependencies: - fsevents "^1.2.7" + fsevents "~2.3.2" -chokidar@^2.0.4: +chokidar@^2.0.4, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -2411,10 +2319,20 @@ chokidar@^2.0.4: optionalDependencies: fsevents "^1.2.7" -chownr@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" - integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== ci-info@^2.0.0: version "2.0.0" @@ -2439,13 +2357,6 @@ circular-json@^0.3.1: resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== -clap@^1.0.9: - version "1.2.3" - resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" - integrity sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA== - dependencies: - chalk "^1.1.3" - class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -2461,6 +2372,11 @@ classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -2473,24 +2389,6 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= -cliui@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= - dependencies: - center-align "^0.1.1" - right-align "^0.1.1" - wordwrap "0.0.2" - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -2500,38 +2398,20 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" -clone-deep@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713" - integrity sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ== - dependencies: - for-own "^1.0.0" - is-plain-object "^2.0.4" - kind-of "^6.0.0" - shallow-clone "^1.0.0" - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= -coa@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" - integrity sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0= +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" q "^1.1.2" -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -2540,7 +2420,7 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.3.0, color-convert@^1.8.2, color-convert@^1.9.0, color-convert@^1.9.1: +color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -2557,59 +2437,21 @@ color-name@^1.0.0: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" - integrity sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE= - dependencies: - color-name "^1.0.0" - -color-string@^1.4.0, color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== +color-string@^1.6.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.0.tgz#63b6ebd1bec11999d1df3a79a7569451ac2be8aa" + integrity sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" -color@^0.11.0: - version "0.11.4" - resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" - integrity sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q= - dependencies: - clone "^1.0.2" - color-convert "^1.3.0" - color-string "^0.3.0" - -color@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/color/-/color-1.0.3.tgz#e48e832d85f14ef694fb468811c2d5cfe729b55d" - integrity sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0= - dependencies: - color-convert "^1.8.2" - color-string "^1.4.0" - -color@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color/-/color-2.0.1.tgz#e4ed78a3c4603d0891eba5430b04b86314f4c839" - integrity sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw== - dependencies: - color-convert "^1.9.1" - color-string "^1.5.2" - -colormin@^1.0.5: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" - integrity sha1-6i90IKcrlogaOKrlnsEkpvcpgTM= +color@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" + integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== dependencies: - color "^0.11.0" - css-color-names "0.0.4" - has "^1.0.1" - -colors@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" - integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= + color-convert "^1.9.3" + color-string "^1.6.0" combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.7" @@ -2618,15 +2460,10 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^2.19.0, commander@^2.8.1, commander@~2.20.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" - integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== - -commander@~2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" - integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA== +commander@^2.19.0, commander@^2.20.0, commander@^2.8.1, commander@~2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== commondir@^1.0.1: version "1.0.1" @@ -2634,20 +2471,20 @@ commondir@^1.0.1: integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== -compression-webpack-plugin@^1.1.11: - version "1.1.12" - resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-1.1.12.tgz#becd2aec620ace96bb3fe9a42a55cf48acc8b4d4" - integrity sha512-UpBXSHbrCSdSZieAffqXlAQpLO2fikVVRYibrWlbHYzKpOw1Y4jwkVZ/+S91GzWuJvXSbc8SBy/e8fQJh8uEMQ== +compression-webpack-plugin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-4.0.1.tgz#33eda97f1170dd38c5556771de10f34245aa0274" + integrity sha512-0mg6PgwTsUe5LEcUrOu3ob32vraDx2VdbMGAT1PARcOV+UJWDYZFdkSo6RbHoGQ061mmmkC7XpRKOlvwm/gzJQ== dependencies: - cacache "^10.0.1" - find-cache-dir "^1.0.0" - neo-async "^2.5.0" - serialize-javascript "^1.4.0" - webpack-sources "^1.0.1" + cacache "^15.0.5" + find-cache-dir "^3.3.1" + schema-utils "^2.7.0" + serialize-javascript "^4.0.0" + webpack-sources "^1.4.3" concat-map@0.0.1: version "0.0.1" @@ -2665,26 +2502,19 @@ concat-stream@^1.5.0, concat-stream@^1.6.0: typedarray "^0.0.6" console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= - dependencies: - date-now "^0.1.4" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== +convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== dependencies: safe-buffer "~5.1.1" @@ -2705,48 +2535,64 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.1.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.2.1.tgz#0cbdbc2e386e8e00d3b85dc81c848effec5b8150" - integrity sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A== +core-js-compat@^3.20.2, core-js-compat@^3.21.0: + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.1.tgz#cac369f67c8d134ff8f9bd1623e3bc2c42068c82" + integrity sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g== dependencies: - browserslist "^4.6.6" - semver "^6.3.0" + browserslist "^4.19.1" + semver "7.0.0" core-js@^1.0.0: version "1.2.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= -core-js@^2.4.0, core-js@^2.5.0: - version "2.6.5" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895" - integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A== +core-js@^3.16.2: + version "3.21.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" + integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig== -core-util-is@1.0.2, core-util-is@~1.0.0: +core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" - integrity sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ== +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cosmiconfig@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== dependencies: + import-fresh "^2.0.0" is-directory "^0.3.1" - js-yaml "^3.9.0" + js-yaml "^3.13.1" parse-json "^4.0.0" - require-from-string "^2.0.1" + +cosmiconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" + integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.7.2" create-ecdh@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== dependencies: bn.js "^4.1.0" - elliptic "^6.0.0" + elliptic "^6.5.3" -create-hash@^1.1.0, create-hash@^1.1.2: +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== @@ -2757,7 +2603,7 @@ create-hash@^1.1.0, create-hash@^1.1.2: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -2778,15 +2624,7 @@ create-react-class@^15.5.3: loose-envify "^1.3.1" object-assign "^4.1.1" -cross-spawn@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" - integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI= - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^5.0.1, cross-spawn@^5.1.0: +cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= @@ -2795,7 +2633,7 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.0: +cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -2823,40 +2661,74 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" -css-color-function@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/css-color-function/-/css-color-function-1.3.3.tgz#8ed24c2c0205073339fafa004bc8c141fccb282e" - integrity sha1-jtJMLAIFBzM5+voAS8jBQfzLKC4= +css-blank-pseudo@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" + integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== dependencies: - balanced-match "0.1.0" - color "^0.11.0" - debug "^3.1.0" - rgb "~0.1.0" + postcss "^7.0.5" -css-color-names@0.0.4: +css-color-names@0.0.4, css-color-names@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= -css-loader@^0.28.11: - version "0.28.11" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.11.tgz#c3f9864a700be2711bb5a2462b2389b1a392dab7" - integrity sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg== - dependencies: - babel-code-frame "^6.26.0" - css-selector-tokenizer "^0.7.0" - cssnano "^3.10.0" - icss-utils "^2.1.0" - loader-utils "^1.0.2" - lodash.camelcase "^4.3.0" - object-assign "^4.1.1" - postcss "^5.0.6" - postcss-modules-extract-imports "^1.2.0" - postcss-modules-local-by-default "^1.2.0" - postcss-modules-scope "^1.1.0" - postcss-modules-values "^1.3.0" - postcss-value-parser "^3.3.0" - source-list-map "^2.0.0" +css-declaration-sorter@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" + integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== + dependencies: + postcss "^7.0.1" + timsort "^0.3.0" + +css-has-pseudo@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" + integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^5.0.0-rc.4" + +css-loader@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" + integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== + dependencies: + camelcase "^5.3.1" + cssesc "^3.0.0" + icss-utils "^4.1.1" + loader-utils "^1.2.3" + normalize-path "^3.0.0" + postcss "^7.0.32" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.2" + postcss-modules-scope "^2.2.0" + postcss-modules-values "^3.0.0" + postcss-value-parser "^4.1.0" + schema-utils "^2.7.0" + semver "^6.3.0" + +css-prefers-color-scheme@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" + integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== + dependencies: + postcss "^7.0.5" + +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== + dependencies: + boolbase "^1.0.0" + css-what "^3.2.1" + domutils "^1.7.0" + nth-check "^1.0.2" css-select@~1.2.0: version "1.2.0" @@ -2868,75 +2740,121 @@ css-select@~1.2.0: domutils "1.5.1" nth-check "~1.0.1" -css-selector-tokenizer@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz#a177271a8bca5019172f4f891fc6eed9cbf68d5d" - integrity sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA== +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== dependencies: - cssesc "^0.1.0" - fastparse "^1.1.1" - regexpu-core "^1.0.0" + mdn-data "2.0.4" + source-map "^0.6.1" -css-unit-converter@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" - integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= +css-tree@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" css-what@2.1: version "2.1.3" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== -cssesc@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" - integrity sha1-yBSQPkViM3GgR3tAEJqq++6t27Q= +css-what@^3.2.1: + version "3.4.2" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" + integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== -cssnano@^3.10.0, cssnano@^3.4.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" - integrity sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg= +cssdb@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" + integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== + +cssesc@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" + integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssnano-preset-default@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz#920622b1fc1e95a34e8838203f1397a504f2d3ff" + integrity sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ== + dependencies: + css-declaration-sorter "^4.0.1" + cssnano-util-raw-cache "^4.0.1" + postcss "^7.0.0" + postcss-calc "^7.0.1" + postcss-colormin "^4.0.3" + postcss-convert-values "^4.0.1" + postcss-discard-comments "^4.0.2" + postcss-discard-duplicates "^4.0.2" + postcss-discard-empty "^4.0.1" + postcss-discard-overridden "^4.0.1" + postcss-merge-longhand "^4.0.11" + postcss-merge-rules "^4.0.3" + postcss-minify-font-values "^4.0.2" + postcss-minify-gradients "^4.0.2" + postcss-minify-params "^4.0.2" + postcss-minify-selectors "^4.0.2" + postcss-normalize-charset "^4.0.1" + postcss-normalize-display-values "^4.0.2" + postcss-normalize-positions "^4.0.2" + postcss-normalize-repeat-style "^4.0.2" + postcss-normalize-string "^4.0.2" + postcss-normalize-timing-functions "^4.0.2" + postcss-normalize-unicode "^4.0.1" + postcss-normalize-url "^4.0.1" + postcss-normalize-whitespace "^4.0.2" + postcss-ordered-values "^4.1.2" + postcss-reduce-initial "^4.0.3" + postcss-reduce-transforms "^4.0.2" + postcss-svgo "^4.0.3" + postcss-unique-selectors "^4.0.1" + +cssnano-util-get-arguments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= + +cssnano-util-get-match@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= + +cssnano-util-raw-cache@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" + integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== dependencies: - autoprefixer "^6.3.1" - decamelize "^1.1.2" - defined "^1.0.0" - has "^1.0.1" - object-assign "^4.0.1" - postcss "^5.0.14" - postcss-calc "^5.2.0" - postcss-colormin "^2.1.8" - postcss-convert-values "^2.3.4" - postcss-discard-comments "^2.0.4" - postcss-discard-duplicates "^2.0.1" - postcss-discard-empty "^2.0.1" - postcss-discard-overridden "^0.1.1" - postcss-discard-unused "^2.2.1" - postcss-filter-plugins "^2.0.0" - postcss-merge-idents "^2.1.5" - postcss-merge-longhand "^2.0.1" - postcss-merge-rules "^2.0.3" - postcss-minify-font-values "^1.0.2" - postcss-minify-gradients "^1.0.1" - postcss-minify-params "^1.0.4" - postcss-minify-selectors "^2.0.4" - postcss-normalize-charset "^1.1.0" - postcss-normalize-url "^3.0.7" - postcss-ordered-values "^2.1.0" - postcss-reduce-idents "^2.2.2" - postcss-reduce-initial "^1.0.0" - postcss-reduce-transforms "^1.0.3" - postcss-svgo "^2.1.1" - postcss-unique-selectors "^2.0.2" - postcss-value-parser "^3.2.3" - postcss-zindex "^2.0.1" + postcss "^7.0.0" -csso@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" - integrity sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U= +cssnano-util-same-parent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" + integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== + +cssnano@^4.1.10: + version "4.1.11" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.11.tgz#c7b5f5b81da269cb1fd982cb960c1200910c9a99" + integrity sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g== dependencies: - clap "^1.0.9" - source-map "^0.5.3" + cosmiconfig "^5.0.0" + cssnano-preset-default "^4.0.8" + is-resolvable "^1.0.0" + postcss "^7.0.0" + +csso@^4.0.2: + version "4.2.0" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" + integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== + dependencies: + css-tree "^1.1.2" cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": version "0.3.8" @@ -2950,24 +2868,10 @@ cssstyle@^1.0.0: dependencies: cssom "0.3.x" -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - -cyclist@~0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" - integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= - -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8= - dependencies: - es5-ext "^0.10.9" +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= dashdash@^1.12.0: version "1.14.1" @@ -2985,12 +2889,7 @@ data-urls@^1.0.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= - -debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -3005,13 +2904,13 @@ debug@^3.1.0: ms "^2.1.1" debug@^4.1.0, debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== dependencies: - ms "^2.1.1" + ms "2.1.2" -decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: +decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -3062,35 +2961,23 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -defined@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= - dependencies: - repeating "^2.0.0" +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= detect-newline@^2.1.0: version "2.1.0" @@ -3131,9 +3018,9 @@ dom-helpers@^3.2.0, dom-helpers@^3.3.1: "@babel/runtime" "^7.1.2" dom-serializer@0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.1.tgz#13650c850daffea35d8b626a4cfc4d3a17643fdb" - integrity sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q== + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== dependencies: domelementtype "^2.0.1" entities "^2.0.0" @@ -3157,9 +3044,9 @@ domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== domelementtype@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" - integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" + integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== domexception@^1.0.1: version "1.0.1" @@ -3183,7 +3070,7 @@ domutils@1.5.1: dom-serializer "0" domelementtype "1" -domutils@^1.5.1: +domutils@^1.5.1, domutils@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== @@ -3191,6 +3078,13 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" +dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== + dependencies: + is-obj "^2.0.0" + duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -3209,17 +3103,12 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.47: - version "1.3.113" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz#b1ccf619df7295aea17bc6951dc689632629e4a9" - integrity sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g== - -electron-to-chromium@^1.3.191: - version "1.3.243" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.243.tgz#32f64f00fa121532d1d49f5c0a15fd77f52ae889" - integrity sha512-+edFdHGxLSmAKftXa5xZIg19rHkkJLiW+tRu0VMVG3RKztyeKX7d3pXf707lS6+BxB9uBun3RShbxCI1PtBAgQ== +electron-to-chromium@^1.4.76: + version "1.4.81" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.81.tgz#a9ce8997232fb9fb0ec53de8931a85b18c0a7383" + integrity sha512-Gs7xVpIZ7tYYSDA+WgpzwpPvfGwUk3KSIjJ0akuj5XQHFdyQnsUoM76EA4CIHXNLPiVwTwOFay9RMb0ChG3OBw== -elliptic@^6.0.0: +elliptic@^6.5.3: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -3237,10 +3126,10 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== encoding@^0.1.11: version "0.1.12" @@ -3250,21 +3139,20 @@ encoding@^0.1.11: iconv-lite "~0.4.13" end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" -enhanced-resolve@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" - integrity sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24= +enhanced-resolve@^4.1.1, enhanced-resolve@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" + integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== dependencies: graceful-fs "^4.1.2" - memory-fs "^0.4.0" - object-assign "^4.0.1" - tapable "^0.2.7" + memory-fs "^0.5.0" + tapable "^1.0.0" entities@^1.1.1, entities@~1.1.1: version "1.1.2" @@ -3272,9 +3160,9 @@ entities@^1.1.1, entities@~1.1.1: integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== enzyme-adapter-react-16@^1.14.0: version "1.14.0" @@ -3345,98 +3233,58 @@ enzyme@^3.10.0: string.prototype.trim "^1.1.2" errno@^0.1.3, errno@~0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== dependencies: prr "~1.0.1" -error-ex@^1.2.0, error-ex@^1.3.1: +error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" -es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.5.1: - version "1.13.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== +es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.17.2, es-abstract@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" + integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== dependencies: - es-to-primitive "^1.2.0" + call-bind "^1.0.2" + es-to-primitive "^1.2.1" function-bind "^1.1.1" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" has "^1.0.3" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-keys "^1.0.12" - -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.1" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" + is-string "^1.0.7" + is-weakref "^1.0.1" + object-inspect "^1.11.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" is-symbol "^1.0.2" -es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.48" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.48.tgz#9a0b31eeded39e64453bcedf6f9d50bbbfb43850" - integrity sha512-CdRvPlX/24Mj5L4NVxTs4804sxiS2CjVprgCmrgoDkdmjdY4D+ySHa7K3jJf8R40dFg0tIm3z/dk326LrnuSGw== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.1" - next-tick "1" - -es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-map@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-set "~0.1.5" - es6-symbol "~3.1.1" - event-emitter "~0.3.5" - -es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: +escalade@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= - dependencies: - d "1" - es5-ext "~0.10.14" - -es6-weak-map@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - integrity sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8= - dependencies: - d "1" - es5-ext "^0.10.14" - es6-iterator "^2.0.1" - es6-symbol "^3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" @@ -3451,19 +3299,9 @@ escodegen@^1.9.1: esprima "^3.1.3" estraverse "^4.2.0" esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= - dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" - esrecurse "^4.1.0" - estraverse "^4.1.1" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" eslint-config-prettier@^2.3.0: version "2.10.0" @@ -3480,6 +3318,14 @@ eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" @@ -3537,11 +3383,6 @@ espree@^3.5.4: acorn "^5.5.0" acorn-jsx "^3.0.0" -esprima@^2.6.0: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= - esprima@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -3560,44 +3401,31 @@ esquery@^1.0.0: estraverse "^4.0.0" esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: - estraverse "^4.1.0" - -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= + estraverse "^5.2.0" -estraverse@^4.2.0: +estraverse@^4.0.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -esutils@^2.0.0: +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.0, esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= - -event-emitter@~0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= - dependencies: - d "1" - es5-ext "~0.10.14" - events@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" @@ -3612,19 +3440,6 @@ exec-sh@^0.3.2: resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.2.tgz#6738de2eb7c8e671d0366aea0b0db8c6f7d7391b" integrity sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg== -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -3656,6 +3471,13 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + expect@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca" @@ -3711,16 +3533,6 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-text-webpack-plugin@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz#5f043eaa02f9750a9258b78c0a6e0dc1408fb2f7" - integrity sha512-bt/LZ4m5Rqt/Crl2HiKuAl/oqg0psx1tsTLkvWbJen1CtD+fftkZhMaQ9HOtY2gWsl2Wq+sABmMVi9z3DhKWQQ== - dependencies: - async "^2.4.1" - loader-utils "^1.1.0" - schema-utils "^0.3.0" - webpack-sources "^1.0.1" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -3736,26 +3548,21 @@ fast-deep-equal@^1.0.0: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -fastparse@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" - integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== - fb-watchman@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" @@ -3776,6 +3583,11 @@ fbjs@^0.8.9: setimmediate "^1.0.5" ua-parser-js "^0.7.18" +figgy-pudding@^3.5.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== + figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" @@ -3791,13 +3603,13 @@ file-entry-cache@^2.0.0: flat-cache "^1.2.1" object-assign "^4.0.1" -file-loader@^1.1.11: - version "1.1.11" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-1.1.11.tgz#6fe886449b0f2a936e43cabaac0cdbfb369506f8" - integrity sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg== +file-loader@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== dependencies: - loader-utils "^1.0.2" - schema-utils "^0.4.5" + loader-utils "^2.0.0" + schema-utils "^3.0.0" file-uri-to-path@1.0.0: version "1.0.0" @@ -3814,16 +3626,14 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -find-cache-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" - integrity sha1-kojj6ePMN0hxfTnq3hfPcfww7m8= +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: - commondir "^1.0.1" - make-dir "^1.0.0" - pkg-dir "^2.0.0" + to-regex-range "^5.0.1" -find-cache-dir@^2.0.0: +find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== @@ -3832,20 +3642,14 @@ find-cache-dir@^2.0.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= +find-cache-dir@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== dependencies: - locate-path "^2.0.0" + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" find-up@^3.0.0: version "3.0.0" @@ -3854,6 +3658,24 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +findup-sync@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" + integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== + dependencies: + detect-file "^1.0.0" + is-glob "^4.0.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + fine-uploader-wrappers@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fine-uploader-wrappers/-/fine-uploader-wrappers-1.0.1.tgz#044a9432076bd02ac1404866ec6e197fc662fcbf" @@ -3876,10 +3698,15 @@ flat-cache@^1.2.1: rimraf "~2.6.2" write "^0.2.1" +flatted@^3.2.2: + version "3.2.5" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" + integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== + flatten@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" - integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I= + version "1.0.3" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" + integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== flush-write-stream@^1.0.0: version "1.1.1" @@ -3889,23 +3716,11 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" -for-in@^0.1.3: - version "0.1.8" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1" - integrity sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE= - -for-in@^1.0.1, for-in@^1.0.2: +for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= -for-own@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" - integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= - dependencies: - for-in "^1.0.1" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -3935,16 +3750,12 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" -fs-extra@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - path-is-absolute "^1.0.0" - rimraf "^2.2.8" + minipass "^3.0.0" fs-readdir-recursive@^1.1.0: version "1.1.0" @@ -3974,15 +3785,10 @@ fsevents@^1.2.7: bindings "^1.5.0" nan "^2.12.1" -fstream@^1.0.0, fstream@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" - integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== function-bind@^1.1.1: version "1.1.1" @@ -4009,52 +3815,30 @@ functions-have-names@^1.1.1: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.1.1.tgz#79d35927f07b8e7103d819fed475b64ccf7225ea" integrity sha512-U0kNHUoxwPNPWOJaMG7Z00d4a/qZVrFtzWJRaK8V9goaVOCXBSQSJpt3MYGNtkScKEBKovxLjnNdC9MlXwo5Pw== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -gaze@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" - integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== - dependencies: - globule "^1.0.0" - -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" get-stdin@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" integrity sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g= -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -4062,6 +3846,14 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -4082,31 +3874,14 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@~7.1.1: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.1: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" + is-glob "^4.0.1" -glob@^7.1.3: +glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.7: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -4118,41 +3893,48 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^11.0.1: - version "11.11.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e" - integrity sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw== - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" -globule@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" - integrity sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ== +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= dependencies: - glob "~7.1.1" - lodash "~4.17.10" - minimatch "~3.0.2" + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" -graceful-fs@^4.1.11, graceful-fs@^4.1.6, graceful-fs@^4.1.9: - version "4.1.15" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" - integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" -graceful-fs@^4.1.15: - version "4.2.2" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" - integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== +globals@^11.0.1, globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -graceful-fs@^4.1.2: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: version "4.2.9" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== @@ -4198,30 +3980,32 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= +has-symbols@^1.0.1, has-symbols@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" has-value@^0.3.1: version "0.3.1" @@ -4254,7 +4038,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.1, has@^1.0.3: +has@^1.0.0, has@^1.0.1, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -4262,12 +4046,13 @@ has@^1.0.1, has@^1.0.3: function-bind "^1.1.1" hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" @@ -4277,6 +4062,11 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hex-color-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -4286,23 +4076,27 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" + parse-passwd "^1.0.0" hosted-git-info@^2.1.4: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== -html-comment-regex@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" - integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== +hsl-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= + +hsla-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= html-element-map@^1.0.0: version "1.1.0" @@ -4360,17 +4154,12 @@ iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@~0.4.13: dependencies: safer-buffer ">= 2.1.2 < 3" -icss-replace-symbols@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" - integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= - -icss-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962" - integrity sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI= +icss-utils@^4.0.0, icss-utils@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== dependencies: - postcss "^6.0.1" + postcss "^7.0.14" identity-obj-proxy@^3.0.0: version "3.0.0" @@ -4380,9 +4169,9 @@ identity-obj-proxy@^3.0.0: harmony-reflect "^1.4.6" ieee754@^1.1.4: - version "1.1.12" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" - integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== iferr@^0.1.5: version "0.1.5" @@ -4394,6 +4183,11 @@ ignore@^3.3.3: resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== +immutable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" + integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + import-cwd@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" @@ -4401,6 +4195,22 @@ import-cwd@^2.0.0: dependencies: import-from "^2.1.0" +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-from@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" @@ -4421,27 +4231,20 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -in-publish@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" - integrity sha1-4g/146KvwmkDILbcVSaCqcf631E= - -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= - dependencies: - repeating "^2.0.0" +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= +infer-owner@^1.0.3, infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== inflight@^1.0.4: version "1.0.6" @@ -4451,7 +4254,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -4466,6 +4269,11 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +ini@^1.3.4, ini@^1.3.5: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + inquirer@^3.0.6: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" @@ -4486,23 +4294,27 @@ inquirer@^3.0.6: strip-ansi "^4.0.0" through "^2.3.6" -interpret@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +interpret@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -invariant@^2.2.2, invariant@^2.2.4: +invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" @@ -4532,6 +4344,13 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -4539,20 +4358,30 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" -is-boolean-object@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93" - integrity sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M= +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.0.0, is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.1.4, is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== is-ci@^2.0.0: version "2.0.0" @@ -4561,6 +4390,25 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-color-stop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= + dependencies: + css-color-names "^0.0.4" + hex-color-regex "^1.1.0" + hsl-regex "^1.0.0" + hsla-regex "^1.0.0" + rgb-regex "^1.0.1" + rgba-regex "^1.0.0" + +is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -4576,9 +4424,11 @@ is-data-descriptor@^1.0.0: kind-of "^6.0.0" is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" is-descriptor@^0.1.0: version "0.1.6" @@ -4620,20 +4470,6 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" @@ -4651,17 +4487,24 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" -is-number-object@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799" - integrity sha1-8mWrian0RQNO9q/xWo8AsA9VF5k= +is-negative-zero@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.3, is-number-object@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" + integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + dependencies: + has-tostringtag "^1.0.0" is-number@^3.0.0: version "3.0.0" @@ -4670,12 +4513,22 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= -is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: +is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== @@ -4687,58 +4540,61 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= +is-regex@^1.0.4, is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== dependencies: - has "^1.0.1" + call-bind "^1.0.2" + has-tostringtag "^1.0.0" is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== +is-shared-array-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" + integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== + is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= -is-string@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.4.tgz#cc3a9b69857d621e963725a24caeec873b826e64" - integrity sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ= +is-string@^1.0.4, is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" is-subset@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY= -is-svg@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" - integrity sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk= - dependencies: - html-comment-regex "^1.1.0" - -is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== dependencies: - has-symbols "^1.0.0" + has-symbols "^1.0.2" is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= +is-weakref@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" -is-windows@^1.0.2: +is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== @@ -4758,11 +4614,6 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -isnumeric@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/isnumeric/-/isnumeric-0.2.0.tgz#a2347ba360de19e33d0ffd590fddf7755cbf2e64" - integrity sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ= - isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -5195,6 +5046,15 @@ jest-worker@^24.6.0, jest-worker@^24.9.0: merge-stream "^2.0.0" supports-color "^6.1.0" +jest-worker@^26.5.0: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^7.0.0" + jest@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171" @@ -5208,16 +5068,6 @@ jquery@^3.4.1: resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2" integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw== -js-base64@^2.1.8, js-base64@^2.1.9: - version "2.5.1" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" - integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== - -js-levenshtein@^1.1.3: - version "1.1.6" - resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" - integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -5228,22 +5078,14 @@ js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= -js-yaml@^3.12.0, js-yaml@^3.9.0, js-yaml@^3.9.1: - version "3.12.2" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.2.tgz#ef1d067c5a9d9cb65bd72f285b5d8105c77f14fc" - integrity sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q== +js-yaml@^3.13.1, js-yaml@^3.14.1, js-yaml@^3.9.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@~3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" - integrity sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A= - dependencies: - argparse "^1.0.7" - esprima "^2.6.0" - jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -5281,11 +5123,6 @@ jsdom@^11.5.1: ws "^5.2.0" xml-name-validator "^3.0.0" -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -5296,16 +5133,16 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= -json-loader@^0.5.4: - version "0.5.7" - resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" - integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== - -json-parse-better-errors@^1.0.1: +json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" @@ -5331,11 +5168,6 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -5343,19 +5175,12 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -json5@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" - integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== - dependencies: - minimist "^1.2.0" - -jsonfile@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= - optionalDependencies: - graceful-fs "^4.1.6" +json5@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" jsprim@^1.2.2: version "1.4.1" @@ -5387,41 +5212,27 @@ kind-of@^5.0.0: integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - -klaw@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= - optionalDependencies: - graceful-fs "^4.1.9" + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -last-call-webpack-plugin@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-2.1.2.tgz#ad80c6e310998294d2ed2180a68e9589e4768c44" - integrity sha512-CZc+m2xZm51J8qSwdODeiiNeqh8CYkKEq6Rw8IkE4i/4yqf2cJhjQPsA6BtAV970ePRNhwEOXhy2U5xc5Jwh9Q== - dependencies: - lodash "^4.17.4" - webpack-sources "^1.0.1" - -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= +klona@^2.0.4: + version "2.0.5" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" + integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= +last-call-webpack-plugin@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" + integrity sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w== dependencies: - invert-kv "^1.0.0" + lodash "^4.17.5" + webpack-sources "^1.1.0" left-pad@^1.3.0: version "1.3.0" @@ -5441,6 +5252,11 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + linkify-it@^1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-1.2.4.tgz#0773526c317c8fd13bd534ee1d180ff88abf881a" @@ -5448,27 +5264,6 @@ linkify-it@^1.2.1: dependencies: uc.micro "^1.0.1" -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -5479,33 +5274,34 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -loader-runner@^2.3.0: +loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== -loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== +loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== dependencies: big.js "^5.2.2" - emojis-list "^2.0.0" + emojis-list "^3.0.0" json5 "^1.0.1" +loader-utils@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" + integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + loaders.css@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/loaders.css/-/loaders.css-0.1.2.tgz#3a9fb43726c73334a38142af9d0629019b658743" integrity sha1-Op+0NybHMzSjgUKvnQYpAZtlh0M= -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -5514,6 +5310,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash._baseisequal@^3.0.0: version "3.0.7" resolved "https://registry.yarnpkg.com/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz#d8025f76339d29342767dcc887ce5cb95a5b51f1" @@ -5533,15 +5336,10 @@ lodash._getnative@^3.0.0: resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= -lodash._reinterpolate@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash.escape@^4.0.1: version "4.0.1" @@ -5553,6 +5351,16 @@ lodash.flattendeep@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= +lodash.get@^4.0: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + +lodash.has@^4.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.has/-/lodash.has-4.5.2.tgz#d19f4dc1095058cccbe2b0cdf4ee0fe4aa37c862" + integrity sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI= + lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -5600,45 +5408,15 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash.tail@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" - integrity sha1-0jM6NtnncXyK0vfKyv7HwytERmQ= - -lodash.template@^4.2.4: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" - integrity sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A= - dependencies: - lodash._reinterpolate "~3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316" - integrity sha1-K01OlbpEDZFf8IvImeRVNmZxMxY= - dependencies: - lodash._reinterpolate "~3.0.0" - lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.3.0, lodash@~4.17.10: - version "4.17.11" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== - -lodash@^4.15.0, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.6.1: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -longest@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= +lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.6.1: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" @@ -5647,15 +5425,7 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4 dependencies: js-tokens "^3.0.0 || ^4.0.0" -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - -lru-cache@^4.0.1, lru-cache@^4.1.1: +lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== @@ -5663,12 +5433,19 @@ lru-cache@^4.0.1, lru-cache@^4.1.1: pseudomap "^1.0.2" yallist "^2.1.2" -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: - pify "^3.0.0" + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" @@ -5678,6 +5455,13 @@ make-dir@^2.0.0, make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" +make-dir@^3.0.2, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -5690,11 +5474,6 @@ map-cache@^0.2.2: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -5702,11 +5481,6 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -math-expression-evaluator@^1.2.14: - version "1.2.17" - resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" - integrity sha1-3oGf282E3M2PrlnGrreWFbnSZqw= - md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -5716,14 +5490,17 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= - dependencies: - mimic-fn "^1.0.0" +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== -memory-fs@^0.4.0, memory-fs@~0.4.1: +memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= @@ -5731,28 +5508,20 @@ memory-fs@^0.4.0, memory-fs@~0.4.1: errno "^0.1.3" readable-stream "^2.0.1" -meow@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -micromatch@^3.1.10, micromatch@^3.1.4: +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -5796,6 +5565,16 @@ mimic-fn@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== +mini-css-extract-plugin@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e" + integrity sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A== + dependencies: + loader-utils "^1.1.0" + normalize-url "1.9.1" + schema-utils "^1.0.0" + webpack-sources "^1.1.0" + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -5806,31 +5585,14 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@^3.0.2, minimatch@~3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^3.0.4: - version "3.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.5.tgz#4da8f1290ee0f0f8e83d60ca69f8f134068604a3" - integrity sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw== +minimatch@^3.0.2, minimatch@^3.0.4: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minimist@^1.2.5: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -5840,10 +5602,46 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -mississippi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f" - integrity sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw== +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== + dependencies: + minipass "^3.0.0" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.2: + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0, minipass@^3.1.1: + version "3.1.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" + integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== + dependencies: + yallist "^4.0.0" + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== dependencies: concat-stream "^1.5.0" duplexify "^3.4.2" @@ -5851,40 +5649,30 @@ mississippi@^2.0.0: flush-write-stream "^1.0.0" from2 "^2.1.0" parallel-transform "^1.1.0" - pump "^2.0.1" + pump "^3.0.0" pumpify "^1.3.3" stream-each "^1.1.0" through2 "^2.0.0" mixin-deep@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" -mixin-object@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e" - integrity sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4= - dependencies: - for-in "^0.1.3" - is-extendable "^0.1.1" - -"mkdirp@>=0.5 0": +mkdirp@^0.5, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" -mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" +mkdirp@^1.0.3, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== moment@^2.22.2: version "2.24.0" @@ -5913,20 +5701,25 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + ms@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@^2.12.1, nan@^2.13.2: - version "2.14.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" - integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== +nan@^2.12.1: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== nanomatch@^1.2.9: version "1.2.13" @@ -5961,20 +5754,10 @@ nearley@^2.7.10: randexp "0.4.6" semver "^5.4.1" -neo-async@^2.5.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" - integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA== - -neo-async@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== - -next-tick@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= +neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1, neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== nice-try@^1.0.4: version "1.0.5" @@ -5994,33 +5777,15 @@ node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" -node-gyp@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" - integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== - dependencies: - fstream "^1.0.0" - glob "^7.0.3" - graceful-fs "^4.1.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - osenv "0" - request "^2.87.0" - rimraf "2" - semver "~5.3.0" - tar "^2.0.0" - which "1" - node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= -node-libs-browser@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.0.tgz#c72f60d9d46de08a940dedbb25f3ffa2f9bbaa77" - integrity sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA== +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -6032,7 +5797,7 @@ node-libs-browser@^2.0.0: events "^3.0.0" https-browserify "^1.0.0" os-browserify "^0.3.0" - path-browserify "0.0.0" + path-browserify "0.0.1" process "^0.11.10" punycode "^1.2.4" querystring-es3 "^0.2.0" @@ -6044,7 +5809,7 @@ node-libs-browser@^2.0.0: tty-browserify "0.0.0" url "^0.11.0" util "^0.11.0" - vm-browserify "0.0.4" + vm-browserify "^1.0.1" node-modules-regexp@^1.0.0: version "1.0.0" @@ -6062,35 +5827,10 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" -node-releases@^1.1.25: - version "1.1.28" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.28.tgz#503c3c70d0e4732b84e7aaa2925fbdde10482d4a" - integrity sha512-AQw4emh6iSXnCpDiFe0phYcThiccmkNWMZnFZ+lDJjAP8J0m2fVd59duvUUyuTirQOhIAajTFkzG6FHCLBO59g== - dependencies: - semver "^5.3.0" - -node-sass@^4.9.2: - version "4.14.1" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5" - integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g== - dependencies: - async-foreach "^0.1.3" - chalk "^1.1.1" - cross-spawn "^3.0.0" - gaze "^1.0.0" - get-stdin "^4.0.1" - glob "^7.0.3" - in-publish "^2.0.0" - lodash "^4.17.15" - meow "^3.7.0" - mkdirp "^0.5.1" - nan "^2.13.2" - node-gyp "^3.8.0" - npmlog "^4.0.0" - request "^2.88.0" - sass-graph "2.2.5" - stdout-stream "^1.4.0" - "true-case-path" "^1.0.2" +node-releases@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" + integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== node@^10.0.0: version "10.15.3" @@ -6099,14 +5839,7 @@ node@^10.0.0: dependencies: node-bin-setup "^1.0.0" -"nopt@2 || 3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= - dependencies: - abbrev "1" - -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: +normalize-package-data@^2.3.2: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -6123,7 +5856,7 @@ normalize-path@^2.1.1: dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -6133,7 +5866,7 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= -normalize-url@^1.4.0: +normalize-url@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= @@ -6143,6 +5876,11 @@ normalize-url@^1.4.0: query-string "^4.1.0" sort-keys "^1.0.0" +normalize-url@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -6150,17 +5888,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -nth-check@~1.0.1: +nth-check@^1.0.2, nth-check@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== @@ -6172,11 +5900,6 @@ num2fraction@^1.2.2: resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - nwsapi@^2.0.7: version "2.1.4" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.1.4.tgz#e006a878db23636f8e8a67d33ca0e4edf61a842f" @@ -6206,26 +5929,21 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== +object-inspect@^1.11.0, object-inspect@^1.6.0, object-inspect@^1.9.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" + integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== object-is@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= -object-keys@^1.0.11: +object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-keys@^1.0.12: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" - integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== - object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" @@ -6233,15 +5951,15 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== +object.assign@^4.1.0, object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" object.entries@^1.0.4, object.entries@^1.1.0: version "1.1.0" @@ -6263,13 +5981,14 @@ object.fromentries@^2.0.0: function-bind "^1.1.1" has "^1.0.1" -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= +object.getownpropertydescriptors@^2.1.0: + version "2.1.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e" + integrity sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw== dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" object.pick@^1.3.0: version "1.3.0" @@ -6279,14 +5998,13 @@ object.pick@^1.3.0: isobject "^3.0.1" object.values@^1.0.4, object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.12.0" - function-bind "^1.1.1" - has "^1.0.3" + es-abstract "^1.19.1" once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" @@ -6295,11 +6013,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onecolor@^3.0.4: - version "3.1.0" - resolved "https://registry.yarnpkg.com/onecolor/-/onecolor-3.1.0.tgz#b72522270a49569ac20d244b3cd40fe157fda4d2" - integrity sha512-YZSypViXzu3ul5LMu/m6XjJ9ol8qAy9S2VjHl5E6UlhUH1KGKWabyEJifn0Jjpw23bYDzC2ucKMPGiH5kfwSGQ== - onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" @@ -6315,13 +6028,13 @@ optimist@^0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" -optimize-css-assets-webpack-plugin@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-3.2.0.tgz#09a40c4cefde1dd0142444a873c56aa29eb18e6f" - integrity sha512-Fjn7wyyadPAriuH2DHamDQw5B8GohEWbroBkKoPeP+vSF2PIAPI7WDihi8WieMRb/At4q7Ea7zTKaMDuSoIAAg== +optimize-css-assets-webpack-plugin@^5.0.8: + version "5.0.8" + resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.8.tgz#cbccdcf5a6ef61d4f8cc78cf083a67446e5f402a" + integrity sha512-mgFS1JdOtEGzD8l+EuISqL57cKO+We9GcoiQEmdCWRqqck+FGNmYJtx9qfAPzEz+lRrlThWMuGDaRkI/yWNx/Q== dependencies: - cssnano "^3.4.0" - last-call-webpack-plugin "^2.1.2" + cssnano "^4.1.10" + last-call-webpack-plugin "^3.0.0" optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" @@ -6340,33 +6053,11 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@0: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - output-file-sync@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-2.0.1.tgz#f53118282f5f553c2799541792b723a4c71430c0" @@ -6388,26 +6079,19 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: - p-limit "^1.1.0" + yocto-queue "^0.1.0" p-locate@^3.0.0: version "3.0.0" @@ -6416,54 +6100,62 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + p-reduce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== pako@~1.0.5: - version "1.0.10" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" - integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== parallel-transform@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" - integrity sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY= + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== dependencies: - cyclist "~0.2.2" + cyclist "^1.0.1" inherits "^2.0.3" readable-stream "^2.1.5" -parse-asn1@^5.0.0: - version "5.1.4" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" - integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== dependencies: - asn1.js "^4.0.0" + asn1.js "^5.2.0" browserify-aes "^1.0.0" - create-hash "^1.1.0" evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" safe-buffer "^5.1.1" -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -6472,6 +6164,21 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + parse5@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" @@ -6489,10 +6196,10 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== path-complete-extname@^1.0.0: version "1.0.0" @@ -6504,19 +6211,17 @@ path-dirname@^1.0.0: resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= @@ -6531,27 +6236,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= -path-parse@^1.0.6: +path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= - dependencies: - pify "^2.0.0" - path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -6559,10 +6248,15 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + pbkdf2@^3.0.3: - version "3.0.17" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -6575,7 +6269,22 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -pify@^2.0.0, pify@^2.3.0: +picocolors@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= @@ -6590,18 +6299,6 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" @@ -6609,22 +6306,6 @@ pirates@^4.0.1: dependencies: node-modules-regexp "^1.0.0" -pixrem@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pixrem/-/pixrem-4.0.1.tgz#2da4a1de6ec4423c5fc3794e930b81d4490ec686" - integrity sha1-LaSh3m7EQjxfw3lOkwuB1EkOxoY= - dependencies: - browserslist "^2.0.0" - postcss "^6.0.0" - reduce-css-calc "^1.2.7" - -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -6632,13 +6313,12 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" -pleeease-filters@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pleeease-filters/-/pleeease-filters-4.0.0.tgz#6632b2fb05648d2758d865384fbced79e1ccaec7" - integrity sha1-ZjKy+wVkjSdY2GU4T7zteeHMrsc= +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: - onecolor "^3.0.4" - postcss "^6.0.1" + find-up "^4.0.0" pluralize@^7.0.0: version "7.0.0" @@ -6650,582 +6330,657 @@ pn@^1.1.0: resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== +pnp-webpack-plugin@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.7.0.tgz#65741384f6d8056f36e2255a8d67ffc20866f5c9" + integrity sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg== + dependencies: + ts-pnp "^1.1.6" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= -postcss-apply@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/postcss-apply/-/postcss-apply-0.8.0.tgz#14e544bbb5cb6f1c1e048857965d79ae066b1343" - integrity sha1-FOVEu7XLbxweBIhXll15rgZrE0M= - dependencies: - babel-runtime "^6.23.0" - balanced-match "^0.4.2" - postcss "^6.0.0" - -postcss-attribute-case-insensitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-2.0.0.tgz#94dc422c8f90997f16bd33a3654bbbec084963b4" - integrity sha1-lNxCLI+QmX8WvTOjZUu77AhJY7Q= +postcss-attribute-case-insensitive@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" + integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA== dependencies: - postcss "^6.0.0" - postcss-selector-parser "^2.2.3" + postcss "^7.0.2" + postcss-selector-parser "^6.0.2" -postcss-calc@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" - integrity sha1-d7rnypKK2FcW4v2kLyYb98HWW14= +postcss-calc@^7.0.1: + version "7.0.5" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" + integrity sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg== dependencies: - postcss "^5.0.2" - postcss-message-helpers "^2.0.0" - reduce-css-calc "^1.2.6" + postcss "^7.0.27" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.2" -postcss-calc@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-6.0.2.tgz#4d9a43e27dbbf27d095fecb021ac6896e2318337" - integrity sha512-fiznXjEN5T42Qm7qqMCVJXS3roaj9r4xsSi+meaBVe7CJBl8t/QLOXu02Z2E6oWAMWIvCuF6JrvzFekmVEbOKA== +postcss-color-functional-notation@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" + integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== dependencies: - css-unit-converter "^1.1.1" postcss "^7.0.2" - postcss-selector-parser "^2.2.2" - reduce-css-calc "^2.0.0" + postcss-values-parser "^2.0.0" -postcss-color-function@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-function/-/postcss-color-function-4.0.1.tgz#402b3f2cebc3f6947e618fb6be3654fbecef6444" - integrity sha1-QCs/LOvD9pR+YY+2vjZU++zvZEQ= +postcss-color-gray@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" + integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== dependencies: - css-color-function "~1.3.3" - postcss "^6.0.1" - postcss-message-helpers "^2.0.0" - postcss-value-parser "^3.3.0" + "@csstools/convert-colors" "^1.4.0" + postcss "^7.0.5" + postcss-values-parser "^2.0.0" -postcss-color-gray@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-4.1.0.tgz#e5581ed57eaa826fb652ca11b1e2b7b136a9f9df" - integrity sha512-L4iLKQLdqChz6ZOgGb6dRxkBNw78JFYcJmBz1orHpZoeLtuhDDGegRtX9gSyfoCIM7rWZ3VNOyiqqvk83BEN+w== +postcss-color-hex-alpha@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" + integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw== dependencies: - color "^2.0.1" - postcss "^6.0.14" - postcss-message-helpers "^2.0.0" - reduce-function-call "^1.0.2" + postcss "^7.0.14" + postcss-values-parser "^2.0.1" -postcss-color-hex-alpha@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-3.0.0.tgz#1e53e6c8acb237955e8fd08b7ecdb1b8b8309f95" - integrity sha1-HlPmyKyyN5Vej9CLfs2xuLgwn5U= +postcss-color-mod-function@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" + integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== dependencies: - color "^1.0.3" - postcss "^6.0.1" - postcss-message-helpers "^2.0.0" + "@csstools/convert-colors" "^1.4.0" + postcss "^7.0.2" + postcss-values-parser "^2.0.0" -postcss-color-hsl@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-hsl/-/postcss-color-hsl-2.0.0.tgz#12703666fa310430e3f30a454dac1386317d5844" - integrity sha1-EnA2ZvoxBDDj8wpFTawThjF9WEQ= +postcss-color-rebeccapurple@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" + integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== dependencies: - postcss "^6.0.1" - postcss-value-parser "^3.3.0" - units-css "^0.4.0" + postcss "^7.0.2" + postcss-values-parser "^2.0.0" -postcss-color-hwb@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-hwb/-/postcss-color-hwb-3.0.0.tgz#3402b19ef4d8497540c1fb5072be9863ca95571e" - integrity sha1-NAKxnvTYSXVAwftQcr6YY8qVVx4= +postcss-colormin@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" + integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== dependencies: - color "^1.0.3" - postcss "^6.0.1" - postcss-message-helpers "^2.0.0" - reduce-function-call "^1.0.2" + browserslist "^4.0.0" + color "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-color-rebeccapurple@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-3.1.0.tgz#ce1269ecc2d0d8bf92aab44bd884e633124c33ec" - integrity sha512-212hJUk9uSsbwO5ECqVjmh/iLsmiVL1xy9ce9TVf+X3cK/ZlUIlaMdoxje/YpsL9cmUH3I7io+/G2LyWx5rg1g== +postcss-convert-values@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" + integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== dependencies: - postcss "^6.0.22" - postcss-values-parser "^1.5.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-color-rgb@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-rgb/-/postcss-color-rgb-2.0.0.tgz#14539c8a7131494b482e0dd1cc265ff6514b5263" - integrity sha1-FFOcinExSUtILg3RzCZf9lFLUmM= +postcss-custom-media@^7.0.8: + version "7.0.8" + resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" + integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg== dependencies: - postcss "^6.0.1" - postcss-value-parser "^3.3.0" + postcss "^7.0.14" -postcss-color-rgba-fallback@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-rgba-fallback/-/postcss-color-rgba-fallback-3.0.0.tgz#37d5c9353a07a09270912a82606bb42a0d702c04" - integrity sha1-N9XJNToHoJJwkSqCYGu0Kg1wLAQ= +postcss-custom-properties@^8.0.11: + version "8.0.11" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" + integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA== dependencies: - postcss "^6.0.6" - postcss-value-parser "^3.3.0" - rgb-hex "^2.1.0" + postcss "^7.0.17" + postcss-values-parser "^2.0.1" -postcss-colormin@^2.1.8: - version "2.2.2" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" - integrity sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks= +postcss-custom-selectors@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" + integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== dependencies: - colormin "^1.0.5" - postcss "^5.0.13" - postcss-value-parser "^3.2.3" + postcss "^7.0.2" + postcss-selector-parser "^5.0.0-rc.3" -postcss-convert-values@^2.3.4: - version "2.6.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" - integrity sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0= +postcss-dir-pseudo-class@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" + integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== dependencies: - postcss "^5.0.11" - postcss-value-parser "^3.1.2" + postcss "^7.0.2" + postcss-selector-parser "^5.0.0-rc.3" -postcss-cssnext@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-cssnext/-/postcss-cssnext-3.1.0.tgz#927dc29341a938254cde38ea60a923b9dfedead9" - integrity sha512-awPDhI4OKetcHCr560iVCoDuP6e/vn0r6EAqdWPpAavJMvkBSZ6kDpSN4b3mB3Ti57hQMunHHM8Wvx9PeuYXtA== - dependencies: - autoprefixer "^7.1.1" - caniuse-api "^2.0.0" - chalk "^2.0.1" - pixrem "^4.0.0" - pleeease-filters "^4.0.0" - postcss "^6.0.5" - postcss-apply "^0.8.0" - postcss-attribute-case-insensitive "^2.0.0" - postcss-calc "^6.0.0" - postcss-color-function "^4.0.0" - postcss-color-gray "^4.0.0" - postcss-color-hex-alpha "^3.0.0" - postcss-color-hsl "^2.0.0" - postcss-color-hwb "^3.0.0" - postcss-color-rebeccapurple "^3.0.0" - postcss-color-rgb "^2.0.0" - postcss-color-rgba-fallback "^3.0.0" - postcss-custom-media "^6.0.0" - postcss-custom-properties "^6.1.0" - postcss-custom-selectors "^4.0.1" - postcss-font-family-system-ui "^3.0.0" - postcss-font-variant "^3.0.0" - postcss-image-set-polyfill "^0.3.5" - postcss-initial "^2.0.0" - postcss-media-minmax "^3.0.0" - postcss-nesting "^4.0.1" - postcss-pseudo-class-any-link "^4.0.0" - postcss-pseudoelements "^5.0.0" - postcss-replace-overflow-wrap "^2.0.0" - postcss-selector-matches "^3.0.1" - postcss-selector-not "^3.0.1" - -postcss-custom-media@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-6.0.0.tgz#be532784110ecb295044fb5395a18006eb21a737" - integrity sha1-vlMnhBEOyylQRPtTlaGABushpzc= +postcss-discard-comments@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" + integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== dependencies: - postcss "^6.0.1" + postcss "^7.0.0" -postcss-custom-properties@^6.1.0: - version "6.3.1" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-6.3.1.tgz#5c52abde313d7ec9368c4abf67d27a656cba8b39" - integrity sha512-zoiwn4sCiUFbr4KcgcNZLFkR6gVQom647L+z1p/KBVHZ1OYwT87apnS42atJtx6XlX2yI7N5fjXbFixShQO2QQ== +postcss-discard-duplicates@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" + integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== dependencies: - balanced-match "^1.0.0" - postcss "^6.0.18" + postcss "^7.0.0" -postcss-custom-selectors@^4.0.1: +postcss-discard-empty@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-4.0.1.tgz#781382f94c52e727ef5ca4776ea2adf49a611382" - integrity sha1-eBOC+UxS5yfvXKR3bqKt9JphE4I= + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" + integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== dependencies: - postcss "^6.0.1" - postcss-selector-matches "^3.0.0" + postcss "^7.0.0" -postcss-discard-comments@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" - integrity sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0= +postcss-discard-overridden@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" + integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== dependencies: - postcss "^5.0.14" + postcss "^7.0.0" -postcss-discard-duplicates@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" - integrity sha1-uavye4isGIFYpesSq8riAmO5GTI= +postcss-double-position-gradients@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" + integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== dependencies: - postcss "^5.0.4" + postcss "^7.0.5" + postcss-values-parser "^2.0.0" -postcss-discard-empty@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" - integrity sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU= +postcss-env-function@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" + integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== dependencies: - postcss "^5.0.14" + postcss "^7.0.2" + postcss-values-parser "^2.0.0" -postcss-discard-overridden@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" - integrity sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg= +postcss-flexbugs-fixes@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz#9218a65249f30897deab1033aced8578562a6690" + integrity sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ== dependencies: - postcss "^5.0.16" + postcss "^7.0.26" -postcss-discard-unused@^2.2.1: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" - integrity sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM= +postcss-focus-visible@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" + integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== dependencies: - postcss "^5.0.14" - uniqs "^2.0.0" + postcss "^7.0.2" -postcss-filter-plugins@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz#82245fdf82337041645e477114d8e593aa18b8ec" - integrity sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ== +postcss-focus-within@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" + integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== dependencies: - postcss "^5.0.4" + postcss "^7.0.2" -postcss-font-family-system-ui@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-font-family-system-ui/-/postcss-font-family-system-ui-3.0.0.tgz#675fe7a9e029669f05f8dba2e44c2225ede80623" - integrity sha512-58G/hTxMSSKlIRpcPUjlyo6hV2MEzvcVO2m4L/T7Bb2fJTG4DYYfQjQeRvuimKQh1V1sOzCIz99g+H2aFNtlQw== +postcss-font-variant@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz#42d4c0ab30894f60f98b17561eb5c0321f502641" + integrity sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA== dependencies: - postcss "^6.0" + postcss "^7.0.2" -postcss-font-variant@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-3.0.0.tgz#08ccc88f6050ba82ed8ef2cc76c0c6a6b41f183e" - integrity sha1-CMzIj2BQuoLtjvLMdsDGprQfGD4= +postcss-gap-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" + integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== dependencies: - postcss "^6.0.1" + postcss "^7.0.2" -postcss-image-set-polyfill@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/postcss-image-set-polyfill/-/postcss-image-set-polyfill-0.3.5.tgz#0f193413700cf1f82bd39066ef016d65a4a18181" - integrity sha1-Dxk0E3AM8fgr05Bm7wFtZaShgYE= +postcss-image-set-function@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" + integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== dependencies: - postcss "^6.0.1" - postcss-media-query-parser "^0.2.3" + postcss "^7.0.2" + postcss-values-parser "^2.0.0" -postcss-import@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-11.1.0.tgz#55c9362c9192994ec68865d224419df1db2981f0" - integrity sha512-5l327iI75POonjxkXgdRCUS+AlzAdBx4pOvMEhTKTCjb1p8IEeVR9yx3cPbmN7LIWJLbfnIXxAhoB4jpD0c/Cw== +postcss-import@^12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-12.0.1.tgz#cf8c7ab0b5ccab5649024536e565f841928b7153" + integrity sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw== dependencies: - postcss "^6.0.1" + postcss "^7.0.1" postcss-value-parser "^3.2.3" read-cache "^1.0.0" resolve "^1.1.7" -postcss-initial@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-2.0.0.tgz#72715f7336e0bb79351d99ee65c4a253a8441ba4" - integrity sha1-cnFfczbgu3k1HZnuZcSiU6hEG6Q= +postcss-initial@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.4.tgz#9d32069a10531fe2ecafa0b6ac750ee0bc7efc53" + integrity sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg== + dependencies: + postcss "^7.0.2" + +postcss-lab-function@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" + integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== dependencies: - lodash.template "^4.2.4" - postcss "^6.0.1" + "@csstools/convert-colors" "^1.4.0" + postcss "^7.0.2" + postcss-values-parser "^2.0.0" postcss-load-config@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484" - integrity sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ== + version "2.1.2" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.2.tgz#c5ea504f2c4aef33c7359a34de3573772ad7502a" + integrity sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw== dependencies: - cosmiconfig "^4.0.0" + cosmiconfig "^5.0.0" import-cwd "^2.0.0" -postcss-loader@^2.1.5: - version "2.1.6" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.1.6.tgz#1d7dd7b17c6ba234b9bed5af13e0bea40a42d740" - integrity sha512-hgiWSc13xVQAq25cVw80CH0l49ZKlAnU1hKPOdRrNj89bokRr/bZF2nT+hebPPF9c9xs8c3gw3Fr2nxtmXYnNg== +postcss-loader@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" + integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA== dependencies: loader-utils "^1.1.0" - postcss "^6.0.0" + postcss "^7.0.0" postcss-load-config "^2.0.0" - schema-utils "^0.4.0" + schema-utils "^1.0.0" -postcss-media-minmax@^3.0.0: +postcss-logical@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-3.0.0.tgz#675256037a43ef40bc4f0760bfd06d4dc69d48d2" - integrity sha1-Z1JWA3pD70C8Twdgv9BtTcadSNI= + resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" + integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== dependencies: - postcss "^6.0.1" + postcss "^7.0.2" -postcss-media-query-parser@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" - integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ= +postcss-media-minmax@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" + integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== + dependencies: + postcss "^7.0.2" -postcss-merge-idents@^2.1.5: - version "2.1.7" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" - integrity sha1-TFUwMTwI4dWzu/PSu8dH4njuonA= +postcss-merge-longhand@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" + integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== dependencies: - has "^1.0.1" - postcss "^5.0.10" - postcss-value-parser "^3.1.1" + css-color-names "0.0.4" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + stylehacks "^4.0.0" -postcss-merge-longhand@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" - integrity sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg= +postcss-merge-rules@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" + integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + cssnano-util-same-parent "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + vendors "^1.0.0" + +postcss-minify-font-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" + integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== dependencies: - postcss "^5.0.4" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-merge-rules@^2.0.3: - version "2.1.2" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" - integrity sha1-0d9d+qexrMO+VT8OnhDofGG19yE= +postcss-minify-gradients@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" + integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== dependencies: - browserslist "^1.5.2" - caniuse-api "^1.5.2" - postcss "^5.0.4" - postcss-selector-parser "^2.2.2" - vendors "^1.0.0" + cssnano-util-get-arguments "^4.0.0" + is-color-stop "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-message-helpers@^2.0.0: +postcss-minify-params@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" + integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== + dependencies: + alphanum-sort "^1.0.0" + browserslist "^4.0.0" + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + uniqs "^2.0.0" + +postcss-minify-selectors@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" + integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== + dependencies: + alphanum-sort "^1.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +postcss-modules-extract-imports@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" - integrity sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4= + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== + dependencies: + postcss "^7.0.5" -postcss-minify-font-values@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" - integrity sha1-S1jttWZB66fIR0qzUmyv17vey2k= +postcss-modules-local-by-default@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== dependencies: - object-assign "^4.0.1" - postcss "^5.0.4" - postcss-value-parser "^3.0.2" + icss-utils "^4.1.1" + postcss "^7.0.32" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" -postcss-minify-gradients@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" - integrity sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE= +postcss-modules-scope@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== dependencies: - postcss "^5.0.12" - postcss-value-parser "^3.3.0" + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" -postcss-minify-params@^1.0.4: - version "1.2.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" - integrity sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM= +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== dependencies: - alphanum-sort "^1.0.1" - postcss "^5.0.2" - postcss-value-parser "^3.0.2" - uniqs "^2.0.0" + icss-utils "^4.0.0" + postcss "^7.0.6" -postcss-minify-selectors@^2.0.4: - version "2.1.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" - integrity sha1-ssapjAByz5G5MtGkllCBFDEXNb8= +postcss-nesting@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" + integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg== dependencies: - alphanum-sort "^1.0.2" - has "^1.0.1" - postcss "^5.0.14" - postcss-selector-parser "^2.0.0" + postcss "^7.0.2" -postcss-modules-extract-imports@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz#dc87e34148ec7eab5f791f7cd5849833375b741a" - integrity sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw== +postcss-normalize-charset@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" + integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== dependencies: - postcss "^6.0.1" + postcss "^7.0.0" -postcss-modules-local-by-default@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" - integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk= +postcss-normalize-display-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" + integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== dependencies: - css-selector-tokenizer "^0.7.0" - postcss "^6.0.1" + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-modules-scope@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" - integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A= +postcss-normalize-positions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" + integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== dependencies: - css-selector-tokenizer "^0.7.0" - postcss "^6.0.1" + cssnano-util-get-arguments "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-modules-values@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" - integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA= +postcss-normalize-repeat-style@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" + integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== dependencies: - icss-replace-symbols "^1.1.0" - postcss "^6.0.1" + cssnano-util-get-arguments "^4.0.0" + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-nesting@^4.0.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-4.2.1.tgz#0483bce338b3f0828ced90ff530b29b98b00300d" - integrity sha512-IkyWXICwagCnlaviRexi7qOdwPw3+xVVjgFfGsxmztvRVaNxAlrypOIKqDE5mxY+BVxnId1rnUKBRQoNE2VDaA== +postcss-normalize-string@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" + integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== dependencies: - postcss "^6.0.11" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-normalize-charset@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" - integrity sha1-757nEhLX/nWceO0WL2HtYrXLk/E= +postcss-normalize-timing-functions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" + integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-unicode@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" + integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== dependencies: - postcss "^5.0.5" + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-normalize-url@^3.0.7: - version "3.0.8" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" - integrity sha1-EI90s/L82viRov+j6kWSJ5/HgiI= +postcss-normalize-url@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" + integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== dependencies: is-absolute-url "^2.0.0" - normalize-url "^1.4.0" - postcss "^5.0.14" - postcss-value-parser "^3.2.3" + normalize-url "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-ordered-values@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" - integrity sha1-7sbCpntsQSqNsgQud/6NpD+VwR0= +postcss-normalize-whitespace@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" + integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== dependencies: - postcss "^5.0.4" - postcss-value-parser "^3.0.1" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-pseudo-class-any-link@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-4.0.0.tgz#9152a0613d3450720513e8892854bae42d0ee68e" - integrity sha1-kVKgYT00UHIFE+iJKFS65C0O5o4= +postcss-ordered-values@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" + integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== dependencies: - postcss "^6.0.1" - postcss-selector-parser "^2.2.3" + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-pseudoelements@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-pseudoelements/-/postcss-pseudoelements-5.0.0.tgz#eef194e8d524645ca520a949e95e518e812402cb" - integrity sha1-7vGU6NUkZFylIKlJ6V5RjoEkAss= +postcss-overflow-shorthand@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" + integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== dependencies: - postcss "^6.0.0" + postcss "^7.0.2" -postcss-reduce-idents@^2.2.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" - integrity sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM= +postcss-page-break@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" + integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== dependencies: - postcss "^5.0.4" - postcss-value-parser "^3.0.2" + postcss "^7.0.2" -postcss-reduce-initial@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" - integrity sha1-aPgGlfBF0IJjqHmtJA343WT2ROo= +postcss-place@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" + integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== + dependencies: + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-preset-env@^6.7.0, postcss-preset-env@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.1.tgz#26563d2e9395d626a45a836450844540694bfcef" + integrity sha512-rlRkgX9t0v2On33n7TK8pnkcYOATGQSv48J2RS8GsXhqtg+xk6AummHP88Y5mJo0TLJelBjePvSjScTNkj3+qw== + dependencies: + autoprefixer "^9.6.1" + browserslist "^4.6.4" + caniuse-lite "^1.0.30000981" + css-blank-pseudo "^0.1.4" + css-has-pseudo "^0.10.0" + css-prefers-color-scheme "^3.1.1" + cssdb "^4.4.0" + postcss "^7.0.17" + postcss-attribute-case-insensitive "^4.0.1" + postcss-color-functional-notation "^2.0.1" + postcss-color-gray "^5.0.0" + postcss-color-hex-alpha "^5.0.3" + postcss-color-mod-function "^3.0.3" + postcss-color-rebeccapurple "^4.0.1" + postcss-custom-media "^7.0.8" + postcss-custom-properties "^8.0.11" + postcss-custom-selectors "^5.1.2" + postcss-dir-pseudo-class "^5.0.0" + postcss-double-position-gradients "^1.0.0" + postcss-env-function "^2.0.2" + postcss-focus-visible "^4.0.0" + postcss-focus-within "^3.0.0" + postcss-font-variant "^4.0.0" + postcss-gap-properties "^2.0.0" + postcss-image-set-function "^3.0.1" + postcss-initial "^3.0.0" + postcss-lab-function "^2.0.1" + postcss-logical "^3.0.0" + postcss-media-minmax "^4.0.0" + postcss-nesting "^7.0.0" + postcss-overflow-shorthand "^2.0.0" + postcss-page-break "^2.0.0" + postcss-place "^4.0.1" + postcss-pseudo-class-any-link "^6.0.0" + postcss-replace-overflow-wrap "^3.0.0" + postcss-selector-matches "^4.0.0" + postcss-selector-not "^4.0.0" + +postcss-pseudo-class-any-link@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" + integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== dependencies: - postcss "^5.0.4" + postcss "^7.0.2" + postcss-selector-parser "^5.0.0-rc.3" -postcss-reduce-transforms@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" - integrity sha1-/3b02CEkN7McKYpC0uFEQCV3GuE= +postcss-reduce-initial@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" + integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== dependencies: - has "^1.0.1" - postcss "^5.0.8" - postcss-value-parser "^3.0.1" + browserslist "^4.0.0" + caniuse-api "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" -postcss-replace-overflow-wrap@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-2.0.0.tgz#794db6faa54f8db100854392a93af45768b4e25b" - integrity sha1-eU22+qVPjbEAhUOSqTr0V2i04ls= +postcss-reduce-transforms@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" + integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== dependencies: - postcss "^6.0.1" + cssnano-util-get-match "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" -postcss-selector-matches@^3.0.0, postcss-selector-matches@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-3.0.1.tgz#e5634011e13950881861bbdd58c2d0111ffc96ab" - integrity sha1-5WNAEeE5UIgYYbvdWMLQER/8lqs= +postcss-replace-overflow-wrap@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" + integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== dependencies: - balanced-match "^0.4.2" - postcss "^6.0.1" + postcss "^7.0.2" -postcss-selector-not@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-3.0.1.tgz#2e4db2f0965336c01e7cec7db6c60dff767335d9" - integrity sha1-Lk2y8JZTNsAefOx9tsYN/3ZzNdk= +postcss-safe-parser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz#a6d4e48f0f37d9f7c11b2a581bf00f8ba4870b96" + integrity sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g== dependencies: - balanced-match "^0.4.2" - postcss "^6.0.1" + postcss "^7.0.26" -postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2, postcss-selector-parser@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" - integrity sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A= +postcss-selector-matches@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" + integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== dependencies: - flatten "^1.0.2" + balanced-match "^1.0.0" + postcss "^7.0.2" + +postcss-selector-not@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz#263016eef1cf219e0ade9a913780fc1f48204cbf" + integrity sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ== + dependencies: + balanced-match "^1.0.0" + postcss "^7.0.2" + +postcss-selector-parser@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" + integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== + dependencies: + dot-prop "^5.2.0" indexes-of "^1.0.1" uniq "^1.0.1" -postcss-svgo@^2.1.1: - version "2.1.6" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" - integrity sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0= +postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== dependencies: - is-svg "^2.0.0" - postcss "^5.0.14" - postcss-value-parser "^3.2.3" - svgo "^0.7.0" + cssesc "^2.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" -postcss-unique-selectors@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" - integrity sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0= +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: + version "6.0.9" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" + integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-svgo@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.3.tgz#343a2cdbac9505d416243d496f724f38894c941e" + integrity sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + svgo "^1.0.0" + +postcss-unique-selectors@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" + integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== dependencies: - alphanum-sort "^1.0.1" - postcss "^5.0.4" + alphanum-sort "^1.0.0" + postcss "^7.0.0" uniqs "^2.0.0" -postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: +postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3: version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-values-parser@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz#5d9fa63e2bcb0179ce48f3235303765eb89f3047" - integrity sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ== +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" + integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== dependencies: flatten "^1.0.2" indexes-of "^1.0.1" uniq "^1.0.1" -postcss-zindex@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" - integrity sha1-0hCd3AVbka9n/EyzsCWUZjnSryI= - dependencies: - has "^1.0.1" - postcss "^5.0.4" - uniqs "^2.0.0" - -postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16: - version "5.2.18" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" - integrity sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg== - dependencies: - chalk "^1.1.3" - js-base64 "^2.1.9" - source-map "^0.5.6" - supports-color "^3.2.3" - -postcss@^6.0, postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.14, postcss@^6.0.17, postcss@^6.0.18, postcss@^6.0.22, postcss@^6.0.5, postcss@^6.0.6: - version "6.0.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" - -postcss@^7.0.2: - version "7.0.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" - integrity sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg== +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" + integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== dependencies: - chalk "^2.4.2" + picocolors "^0.2.1" source-map "^0.6.1" - supports-color "^6.1.0" prelude-ls@~1.1.2: version "1.1.2" @@ -7247,15 +7002,10 @@ pretty-format@^24.9.0: ansi-styles "^3.2.0" react-is "^16.8.4" -private@^0.1.6, private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== process@^0.11.10: version "0.11.10" @@ -7315,12 +7065,7 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -psl@^1.1.24: - version "1.1.31" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" - integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== - -psl@^1.1.28: +psl@^1.1.24, psl@^1.1.28: version "1.3.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.3.0.tgz#e1ebf6a3b5564fa8376f3da2275da76d875ca1bd" integrity sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag== @@ -7337,7 +7082,7 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" -pump@^2.0.0, pump@^2.0.1: +pump@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== @@ -7425,7 +7170,7 @@ randexp@0.4.6: discontinuous-range "1.0.0" ret "~0.1.10" -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== @@ -7477,12 +7222,7 @@ react-inlinesvg@^0.8.1: httpplease "^0.16.4" once "^1.4.0" -react-is@^16.8.1: - version "16.8.4" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2" - integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA== - -react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: +react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: version "16.9.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb" integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw== @@ -7599,22 +7339,6 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - read-pkg-up@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" @@ -7623,24 +7347,6 @@ read-pkg-up@^4.0.0: find-up "^3.0.0" read-pkg "^3.0.0" -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -7650,10 +7356,10 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -7663,10 +7369,10 @@ read-pkg@^3.0.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.1.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" - integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== +readable-stream@^3.1.1, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -7681,6 +7387,13 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + realpath-native@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" @@ -7688,90 +7401,34 @@ realpath-native@^1.1.0: dependencies: util.promisify "^1.0.0" -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - -reduce-css-calc@^1.2.6, reduce-css-calc@^1.2.7: - version "1.3.0" - resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" - integrity sha1-dHyRTgSWFKTJz7umKYca0dKSdxY= - dependencies: - balanced-match "^0.4.2" - math-expression-evaluator "^1.2.14" - reduce-function-call "^1.0.1" - -reduce-css-calc@^2.0.0: - version "2.1.6" - resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.6.tgz#050fe6ee7d98a1d70775d2e93ce0b713cee394d2" - integrity sha512-+l5/qlQmdsbM9h6JerJ/y5vR5Ci0k93aszLNpCmbadC3nBcbRGmIBm0s9Nj59i22LvCjTGftWzdQRwdknayxhw== - dependencies: - css-unit-converter "^1.1.1" - postcss-value-parser "^3.3.0" - -reduce-function-call@^1.0.1, reduce-function-call@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99" - integrity sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk= - dependencies: - balanced-match "^0.4.2" - reflect.ownkeys@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460" integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA= -regenerate-unicode-properties@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" - integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== +regenerate-unicode-properties@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" + integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== dependencies: - regenerate "^1.4.0" - -regenerate@^1.2.1, regenerate@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== - -regenerator-runtime@^0.10.5: - version "0.10.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= + regenerate "^1.4.2" -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -regenerator-runtime@^0.12.0: - version "0.12.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" - integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.13.3: - version "0.13.3" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" - integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== - -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" +regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.9: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== -regenerator-transform@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" - integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== +regenerator-transform@^0.14.2: + version "0.14.5" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== dependencies: - private "^0.1.6" + "@babel/runtime" "^7.8.4" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" @@ -7781,67 +7438,32 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp-tree@^0.1.6: - version "0.1.12" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.12.tgz#28eaaa6e66eeb3527c15108a3ff740d9e574e420" - integrity sha512-TsXZ8+cv2uxMEkLfgwO0E068gsNMLfuYwMMhiUxf0Kw2Vcgzq93vgl6wIlIYuPmfMqMjfQ9zAporiozqCnwLuQ== - regexpp@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== -regexpu-core@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" - integrity sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs= - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regexpu-core@^4.5.4: - version "4.5.5" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.5.tgz#aaffe61c2af58269b3e516b61a73790376326411" - integrity sha512-FpI67+ky9J+cDizQUJlIlNZFKual/lUkFr1AG6zOCpwZ9cLrg8UUVakyUQJD7fCDIe9Z2nwTQJNPyonatNmDFQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.1.0" - regjsgen "^0.5.0" - regjsparser "^0.6.0" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.1.0" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= - -regjsgen@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" - integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA== - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= +regexpu-core@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3" + integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw== dependencies: - jsesc "~0.5.0" + regenerate "^1.4.2" + regenerate-unicode-properties "^10.0.1" + regjsgen "^0.6.0" + regjsparser "^0.8.2" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.0.0" -regjsparser@^0.6.0: +regjsgen@^0.6.0: version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" - integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d" + integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== + +regjsparser@^0.8.2: + version "0.8.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f" + integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== dependencies: jsesc "~0.5.0" @@ -7851,22 +7473,15 @@ remove-trailing-separator@^1.0.1: integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== -repeat-string@^1.5.2, repeat-string@^1.6.1: +repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - request-promise-core@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" @@ -7883,7 +7498,7 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.87.0, request@^2.88.0: +request@^2.87.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -7914,16 +7529,6 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -require-from-string@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= - require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" @@ -7944,6 +7549,14 @@ resolve-cwd@^2.0.0: dependencies: resolve-from "^3.0.0" +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" @@ -7954,6 +7567,11 @@ resolve-from@^3.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" integrity sha1-six699nWiBvItuZTM17rywoYh0g= +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -7964,19 +7582,14 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.1.7, resolve@^1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" - integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== - dependencies: - path-parse "^1.0.6" - -resolve@^1.3.2: - version "1.12.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" - integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== +resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== dependencies: - path-parse "^1.0.6" + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" restore-cursor@^2.0.0: version "2.0.0" @@ -7991,31 +7604,31 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -rgb-hex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/rgb-hex/-/rgb-hex-2.1.0.tgz#c773c5fe2268a25578d92539a82a7a5ce53beda6" - integrity sha1-x3PF/iJoolV42SU5qCp6XOU77aY= - -rgb@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/rgb/-/rgb-0.1.0.tgz#be27b291e8feffeac1bd99729721bfa40fc037b5" - integrity sha1-vieykej+/+rBvZlylyG/pA/AN7U= +rgb-regex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= -right-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= - dependencies: - align-text "^0.1.1" +rgba-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2, rimraf@^2.6.3: +rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" -rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@~2.6.2: +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -8069,16 +7682,16 @@ rx-lite@*, rx-lite@^4.0.8: resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@~5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -8106,28 +7719,27 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sass-graph@2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8" - integrity sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag== +sass-loader@10.1.1: + version "10.1.1" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.1.1.tgz#4ddd5a3d7638e7949065dd6e9c7c04037f7e663d" + integrity sha512-W6gVDXAd5hR/WHsPicvZdjAWHBcEJ44UahgxcIE196fW2ong0ZHMPO1kZuI5q0VlvMQZh32gpv69PLWQm70qrw== dependencies: - glob "^7.0.0" - lodash "^4.0.0" - scss-tokenizer "^0.2.3" - yargs "^13.3.2" + klona "^2.0.4" + loader-utils "^2.0.0" + neo-async "^2.6.2" + schema-utils "^3.0.0" + semver "^7.3.2" -sass-loader@^6.0.7: - version "6.0.7" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-6.0.7.tgz#dd2fdb3e7eeff4a53f35ba6ac408715488353d00" - integrity sha512-JoiyD00Yo1o61OJsoP2s2kb19L1/Y2p3QFcCdWdF6oomBGKVYuZyqHWemRBfQ2uGYsk+CH3eCguXNfpjzlcpaA== +sass@^1.38.0: + version "1.49.9" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.49.9.tgz#b15a189ecb0ca9e24634bae5d1ebc191809712f9" + integrity sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A== dependencies: - clone-deep "^2.0.1" - loader-utils "^1.0.1" - lodash.tail "^4.1.1" - neo-async "^2.5.0" - pify "^3.0.0" + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" -sax@^1.2.4, sax@~1.2.1: +sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -8148,73 +7760,78 @@ scheduler@^0.15.0: loose-envify "^1.1.0" object-assign "^4.1.1" -schema-utils@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf" - integrity sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8= - dependencies: - ajv "^5.0.0" - -schema-utils@^0.4.0, schema-utils@^0.4.5: - version "0.4.7" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" - integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ== +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== dependencies: ajv "^6.1.0" + ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -scss-tokenizer@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" - integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE= +schema-utils@^2.6.5, schema-utils@^2.7.0: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== dependencies: - js-base64 "^2.1.8" - source-map "^0.4.2" + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" -"semver@2 || 3 || 4 || 5", semver@^5.3.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== +schema-utils@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" -semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= +semver@^7.3.2, semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" -serialize-javascript@^1.4.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879" - integrity sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw== +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" + +serialize-javascript@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== + dependencies: + randombytes "^2.1.0" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" - -set-value@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -8234,15 +7851,6 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -shallow-clone@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571" - integrity sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA== - dependencies: - is-extendable "^0.1.1" - kind-of "^5.0.0" - mixin-object "^2.0.1" - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -8260,6 +7868,15 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -8277,11 +7894,6 @@ sisteransi@^1.0.3: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.3.tgz#98168d62b79e3a5e758e27ae63c4a053d748f4eb" integrity sha512-SbEG75TzH8G7eVXFSN5f9EExILKfly7SUvVY5DhhYLvfhKqhDFY0OzevWa/zwak0RLRfWS5AvfMWpd9gJvr5Yg== -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - slash@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" @@ -8336,45 +7948,36 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== +"source-map-js@>=0.6.2 <2.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: - atob "^2.1.1" + atob "^2.1.2" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - -source-map-support@^0.5.6: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== +source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - integrity sha1-66T12pwNyZneaAMti092FzZSA2s= - dependencies: - amdefine ">=0.0.4" + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: +source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -8384,6 +7987,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +source-map@~0.7.2: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + spdx-correct@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" @@ -8437,12 +8045,24 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -ssri@^5.2.4: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06" - integrity sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ== +ssri@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" + integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== dependencies: - safe-buffer "^5.1.1" + figgy-pudding "^3.5.1" + +ssri@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" + integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== + dependencies: + minipass "^3.1.1" + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== stack-utils@^1.0.1: version "1.0.2" @@ -8457,13 +8077,6 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -stdout-stream@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" - integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== - dependencies: - readable-stream "^2.0.1" - stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" @@ -8497,9 +8110,9 @@ stream-http@^2.7.2: xtend "^4.0.0" stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== strict-uri-encode@^1.0.0: version "1.1.0" @@ -8514,16 +8127,7 @@ string-length@^2.0.0: astral-regex "^1.0.0" strip-ansi "^4.0.0" -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: +string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -8549,14 +8153,23 @@ string.prototype.trim@^1.1.2: es-abstract "^1.13.0" function-bind "^1.1.1" -string_decoder@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== dependencies: - safe-buffer "~5.1.0" + call-bind "^1.0.2" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" -string_decoder@^1.1.1: +string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -8570,7 +8183,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^3.0.0, strip-ansi@^3.0.1: +strip-ansi@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= @@ -8591,13 +8204,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -8608,46 +8214,34 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= - dependencies: - get-stdin "^4.0.1" - strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -style-loader@^0.21.0: - version "0.21.0" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.21.0.tgz#68c52e5eb2afc9ca92b6274be277ee59aea3a852" - integrity sha512-T+UNsAcl3Yg+BsPKs1vd22Fr8sVT+CJMtzqc6LEw9bbJZb43lm9GoeIfUcDEefBSWC0BhYbcdupV1GtI4DGzxg== +style-loader@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" + integrity sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q== dependencies: - loader-utils "^1.1.0" - schema-utils "^0.4.5" + loader-utils "^2.0.0" + schema-utils "^2.7.0" + +stylehacks@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" + integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= -supports-color@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= - dependencies: - has-flag "^1.0.0" - -supports-color@^4.2.1: - version "4.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" - integrity sha1-vnoN5ITexcXN34s9WRJQRJEvY1s= - dependencies: - has-flag "^2.0.0" - -supports-color@^5.3.0, supports-color@^5.4.0: +supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -8661,18 +8255,36 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" -svgo@^0.7.0: - version "0.7.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" - integrity sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U= +supports-color@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +svgo@^1.0.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== dependencies: - coa "~1.0.1" - colors "~1.1.2" - csso "~2.3.1" - js-yaml "~3.7.0" + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" mkdirp "~0.5.1" - sax "~1.2.1" - whet.extend "~0.9.9" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" symbol-tree@^3.2.2: version "3.2.4" @@ -8691,19 +8303,71 @@ table@4.0.2: slice-ansi "1.0.0" string-width "^2.1.1" -tapable@^0.2.7: - version "0.2.9" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.9.tgz#af2d8bbc9b04f74ee17af2b4d9048f807acd18a8" - integrity sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A== +tapable@^1.0.0, tapable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +tar@^6.0.2: + version "6.1.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +terser-webpack-plugin@^1.4.3: + version "1.4.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" + integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^4.0.0" + source-map "^0.6.1" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" + +terser-webpack-plugin@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz#28daef4a83bd17c1db0297070adc07fc8cfc6a9a" + integrity sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ== + dependencies: + cacache "^15.0.5" + find-cache-dir "^3.3.1" + jest-worker "^26.5.0" + p-limit "^3.0.2" + schema-utils "^3.0.0" + serialize-javascript "^5.0.1" + source-map "^0.6.1" + terser "^5.3.4" + webpack-sources "^1.4.3" -tar@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" - integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== +terser@^4.1.2: + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== dependencies: - block-stream "*" - fstream "^1.0.12" - inherits "2" + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +terser@^5.3.4: + version "5.12.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.12.0.tgz#728c6bff05f7d1dcb687d8eace0644802a9dae8a" + integrity sha512-R3AUhNBGWiFc77HXag+1fXpAxTAFRQTJemlJKjAgD9r8xXTpjNKqIXwHM/o7Rh+O0kUJtS3WQVdBeMKFk5sw9A== + dependencies: + acorn "^8.5.0" + commander "^2.20.0" + source-map "~0.7.2" + source-map-support "~0.5.20" test-exclude@^5.2.3: version "5.2.3" @@ -8739,12 +8403,17 @@ through@^2.3.6: integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= timers-browserify@^2.0.4: - version "2.0.10" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" - integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== + version "2.0.12" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== dependencies: setimmediate "^1.0.4" +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= + tlds@^1.121.0: version "1.203.1" resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.203.1.tgz#4dc9b02f53de3315bc98b80665e13de3edfc1dfc" @@ -8767,11 +8436,6 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -8792,6 +8456,13 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" @@ -8825,22 +8496,10 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - -"true-case-path@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" - integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== - dependencies: - glob "^7.1.2" +ts-pnp@^1.1.6: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" + integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== tty-browserify@0.0.0: version "0.0.0" @@ -8886,24 +8545,6 @@ uc.micro@^1.0.1: resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== -uglify-es@^3.3.4: - version "3.3.9" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" - integrity sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ== - dependencies: - commander "~2.13.0" - source-map "~0.6.1" - -uglify-js@^2.8.29: - version "2.8.29" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= - dependencies: - source-map "~0.5.1" - yargs "~3.10.0" - optionalDependencies: - uglify-to-browserify "~1.0.0" - uglify-js@^3.1.4: version "3.6.0" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5" @@ -8912,66 +8553,48 @@ uglify-js@^3.1.4: commander "~2.20.0" source-map "~0.6.1" -uglify-to-browserify@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= - -uglifyjs-webpack-plugin@^0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" - integrity sha1-uVH0q7a9YX5m9j64kUmOORdj4wk= - dependencies: - source-map "^0.5.6" - uglify-js "^2.8.29" - webpack-sources "^1.0.1" - -uglifyjs-webpack-plugin@^1.2.7: - version "1.3.0" - resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz#75f548160858163a08643e086d5fefe18a5d67de" - integrity sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw== +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== dependencies: - cacache "^10.0.4" - find-cache-dir "^1.0.0" - schema-utils "^0.4.5" - serialize-javascript "^1.4.0" - source-map "^0.6.1" - uglify-es "^3.3.4" - webpack-sources "^1.1.0" - worker-farm "^1.5.2" + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" -unicode-match-property-value-ecmascript@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" - integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== +unicode-match-property-value-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" + integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== -unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" - integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== +unicode-property-aliases-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" + integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== union-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== dependencies: arr-union "^3.1.0" get-value "^2.0.6" is-extendable "^0.1.1" - set-value "^0.4.3" + set-value "^2.0.1" uniq@^1.0.1: version "1.0.1" @@ -8983,7 +8606,7 @@ uniqs@^2.0.0: resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= -unique-filename@^1.1.0: +unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== @@ -8991,19 +8614,16 @@ unique-filename@^1.1.0: unique-slug "^2.0.0" unique-slug@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.1.tgz#5e9edc6d1ce8fb264db18a507ef9bd8544451ca6" - integrity sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== dependencies: imurmurhash "^0.1.4" -units-css@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/units-css/-/units-css-0.4.0.tgz#d6228653a51983d7c16ff28f8b9dc3b1ffed3a07" - integrity sha1-1iKGU6UZg9fBb/KPi53Dsf/tOgc= - dependencies: - isnumeric "^0.2.0" - viewport-dimensions "^0.2.0" +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= unset-value@^1.0.0: version "1.0.0" @@ -9013,20 +8633,15 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.0.5, upath@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.1.tgz#497f7c1090b0818f310bbfb06783586a68d28014" - integrity sha512-D0yetkpIOKiZQquxjM2Syvy48Y1DbZ0SWxgsZiwd9GCWRpc75vN8ytzem14WDSg+oiX6+Qt31FpiS/ExODCrLg== - -upath@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" - integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== +upath@^1.0.5, upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" @@ -9055,18 +8670,20 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -util.promisify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== +util.promisify@^1.0.0, util.promisify@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" util@0.10.3: version "0.10.3" @@ -9087,6 +8704,11 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== +v8-compile-cache@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -9096,9 +8718,9 @@ validate-npm-package-license@^3.0.1: spdx-expression-parse "^3.0.0" vendors@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801" - integrity sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ== + version "1.0.4" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" + integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== verror@1.10.0: version "1.10.0" @@ -9109,17 +8731,10 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -viewport-dimensions@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz#de740747db5387fd1725f5175e91bac76afdf36c" - integrity sha1-3nQHR9tTh/0XJfUXXpG6x2r982w= - -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= - dependencies: - indexof "0.0.1" +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== w3c-hr-time@^1.0.1: version "1.0.1" @@ -9142,63 +8757,95 @@ warning@^3.0.0: dependencies: loose-envify "^1.0.0" -watchpack@^1.4.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== +watchpack-chokidar2@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" + integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.7.4: + version "1.7.5" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" + integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== dependencies: - chokidar "^2.0.2" graceful-fs "^4.1.2" neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.1" + watchpack-chokidar2 "^2.0.1" webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-manifest-plugin@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-1.3.2.tgz#5ea8ee5756359ddc1d98814324fe43496349a7d4" - integrity sha512-MX60Bv2G83Zks9pi3oLOmRgnPAnwrlMn+lftMrWBm199VQjk46/xgzBi9lPfpZldw2+EI2S+OevuLIaDuxCWRw== +webpack-assets-manifest@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/webpack-assets-manifest/-/webpack-assets-manifest-3.1.1.tgz#39bbc3bf2ee57fcd8ba07cda51c9ba4a3c6ae1de" + integrity sha512-JV9V2QKc5wEWQptdIjvXDUL1ucbPLH2f27toAY3SNdGZp+xSaStAgpoMcvMZmqtFrBc9a5pTS1058vxyMPOzRQ== + dependencies: + chalk "^2.0" + lodash.get "^4.0" + lodash.has "^4.0" + mkdirp "^0.5" + schema-utils "^1.0.0" + tapable "^1.0.0" + webpack-sources "^1.0.0" + +webpack-cli@^3.3.12: + version "3.3.12" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" + integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag== dependencies: - fs-extra "^0.30.0" - lodash ">=3.5 <5" + chalk "^2.4.2" + cross-spawn "^6.0.5" + enhanced-resolve "^4.1.1" + findup-sync "^3.0.0" + global-modules "^2.0.0" + import-local "^2.0.0" + interpret "^1.4.0" + loader-utils "^1.4.0" + supports-color "^6.1.0" + v8-compile-cache "^2.1.1" + yargs "^13.3.2" -webpack-sources@^1.0.1, webpack-sources@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" - integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== +webpack-sources@^1.0.0, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== dependencies: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^3.12.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.12.0.tgz#3f9e34360370602fcf639e97939db486f4ec0d74" - integrity sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ== - dependencies: - acorn "^5.0.0" - acorn-dynamic-import "^2.0.0" - ajv "^6.1.0" - ajv-keywords "^3.1.0" - async "^2.1.2" - enhanced-resolve "^3.4.0" - escope "^3.6.0" - interpret "^1.0.0" - json-loader "^0.5.4" - json5 "^0.5.1" - loader-runner "^2.3.0" - loader-utils "^1.1.0" - memory-fs "~0.4.1" - mkdirp "~0.5.0" - node-libs-browser "^2.0.0" - source-map "^0.5.3" - supports-color "^4.2.1" - tapable "^0.2.7" - uglifyjs-webpack-plugin "^0.4.6" - watchpack "^1.4.0" - webpack-sources "^1.0.1" - yargs "^8.0.2" +webpack@^4.46.0: + version "4.46.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" + integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.5.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.3" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.7.4" + webpack-sources "^1.4.1" webpacker-react@^0.3.2: version "0.3.2" @@ -9240,40 +8887,29 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" -whet.extend@~0.9.9: - version "0.9.9" - resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" - integrity sha1-+HfVv2SMl+WqVC+twW1qJZucEaE= +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1, which@^1.2.9, which@^1.3.0: +which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -window-size@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= - -wordwrap@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= - wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" @@ -9284,21 +8920,13 @@ wordwrap@~1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= -worker-farm@^1.5.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" - integrity sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ== +worker-farm@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" + integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== dependencies: errno "~0.1.7" -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" @@ -9347,37 +8975,39 @@ xmlhttprequest@*: integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== xtend@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" integrity sha1-XM50B7r2Qsunvs2laBEcST9ZZlo= -y18n@^3.2.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" - integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== - y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^1.7.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== yargs-parser@^13.1.2: version "13.1.2" @@ -9387,30 +9017,7 @@ yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - integrity sha1-jQrELxbqVd69MyyvTEA4s+P139k= - dependencies: - camelcase "^4.1.0" - -yargs@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.1" - -yargs@^13.3.2: +yargs@^13.3.0, yargs@^13.3.2: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== @@ -9426,31 +9033,7 @@ yargs@^13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" -yargs@^8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" - integrity sha1-YpmpBVsc78lp/355wdkY3Osiw2A= - dependencies: - camelcase "^4.1.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - read-pkg-up "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^7.0.0" - -yargs@~3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= - dependencies: - camelcase "^1.0.2" - cliui "^2.1.0" - decamelize "^1.0.0" - window-size "0.1.0" +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From e8144a74bcd365d1fa97cec73c73c113baea4b13 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 11 Mar 2022 11:44:21 +0000 Subject: [PATCH 100/303] Update sanger_warren --- Gemfile.lock | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 952fbe02..e2670201 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -87,12 +87,13 @@ GEM actionpack (>= 5.0) activemodel (>= 5.0) builder (3.2.4) - bunny (2.17.0) + bunny (2.19.0) amq-protocol (~> 2.3, >= 2.3.1) + sorted_set (~> 1, >= 1.0.2) byebug (11.1.3) coderay (1.1.3) concurrent-ruby (1.1.9) - connection_pool (2.2.2) + connection_pool (2.2.5) crass (1.0.6) daemons (1.3.1) database_cleaner (1.7.0) @@ -244,6 +245,7 @@ GEM rb-inotify (0.10.0) ffi (~> 1.0) rb-readline (0.5.5) + rbtree (0.4.5) rdf (3.0.12) hamster (~> 3.0) link_header (~> 0.0, >= 0.0.8) @@ -307,10 +309,11 @@ GEM ruby-growl (4.1) uuid (~> 2.3, >= 2.3.5) ruby-progressbar (1.11.0) - sanger_warren (0.1.0) - bunny (~> 2.17.0) - connection_pool (~> 2.2.0) + sanger_warren (0.4.1) + bunny (~> 2.17) + connection_pool (~> 2.2) multi_json (~> 1.0) + thor (~> 1.1) sass (3.7.4) sass-listen (~> 4.0.0) sass-listen (4.0.0) @@ -333,8 +336,12 @@ GEM activesupport (>= 5.0.0) i18n multi_json + set (1.0.2) shoulda-matchers (4.1.0) activesupport (>= 4.2.0) + sorted_set (1.0.3) + rbtree + set (~> 1.0) sparql (3.0.2) builder (~> 3.2) ebnf (~> 1.1) From 1c3ecbd4e574ae3017cd7a43c898fb1564ffd496 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 11 Mar 2022 11:49:28 +0000 Subject: [PATCH 101/303] Update rspec --- Gemfile.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e2670201..ccb39159 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -102,7 +102,7 @@ GEM delayed_job_active_record (4.1.7) activerecord (>= 3.0, < 8.0) delayed_job (>= 3.0, < 5) - diff-lcs (1.3) + diff-lcs (1.5.0) domain_name (0.5.20180417) unf (>= 0.0.5, < 1.0.0) dropzonejs-rails (0.8.4) @@ -271,23 +271,23 @@ GEM mime-types (>= 1.16, < 4.0) netrc (~> 0.8) rexml (3.2.5) - rspec-core (3.8.1) - rspec-support (~> 3.8.0) - rspec-expectations (3.8.4) + rspec-core (3.11.0) + rspec-support (~> 3.11.0) + rspec-expectations (3.11.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.8.0) - rspec-mocks (3.8.1) + rspec-support (~> 3.11.0) + rspec-mocks (3.11.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.8.0) - rspec-rails (3.8.2) - actionpack (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-core (~> 3.8.0) - rspec-expectations (~> 3.8.0) - rspec-mocks (~> 3.8.0) - rspec-support (~> 3.8.0) - rspec-support (3.8.2) + rspec-support (~> 3.11.0) + rspec-rails (5.1.1) + actionpack (>= 5.2) + activesupport (>= 5.2) + railties (>= 5.2) + rspec-core (~> 3.10) + rspec-expectations (~> 3.10) + rspec-mocks (~> 3.10) + rspec-support (~> 3.10) + rspec-support (3.11.0) rubocop (1.26.0) parallel (~> 1.10) parser (>= 3.1.0.0) From 749ae2b68cca0dea28a32065b76a5de9e9bd9a0f Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 11 Mar 2022 11:53:29 +0000 Subject: [PATCH 102/303] Update test environment gems --- Gemfile.lock | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index ccb39159..39916609 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -96,7 +96,12 @@ GEM connection_pool (2.2.5) crass (1.0.6) daemons (1.3.1) - database_cleaner (1.7.0) + database_cleaner (2.0.1) + database_cleaner-active_record (~> 2.0.0) + database_cleaner-active_record (2.0.1) + activerecord (>= 5.a) + database_cleaner-core (~> 2.0.0) + database_cleaner-core (2.0.1) delayed_job (4.1.10) activesupport (>= 3.0, < 8.0) delayed_job_active_record (4.1.7) @@ -156,8 +161,8 @@ GEM activerecord (>= 4.1) concurrent-ruby railties (>= 4.1) - launchy (2.4.3) - addressable (~> 2.3) + launchy (2.5.0) + addressable (~> 2.7) link_header (0.0.8) loofah (2.14.0) crass (~> 1.0.2) @@ -224,10 +229,10 @@ GEM railties (= 5.2.6.3) sprockets-rails (>= 2.0.0) rails-assets-tether (1.1.1) - rails-controller-testing (1.0.4) - actionpack (>= 5.0.1.x) - actionview (>= 5.0.1.x) - activesupport (>= 5.0.1.x) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) @@ -337,8 +342,8 @@ GEM i18n multi_json set (1.0.2) - shoulda-matchers (4.1.0) - activesupport (>= 4.2.0) + shoulda-matchers (5.1.0) + activesupport (>= 5.2.0) sorted_set (1.0.3) rbtree set (~> 1.0) From 301a9afc87c0165e0cbdc921b3fd0a2e1f9315f6 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 11 Mar 2022 11:54:15 +0000 Subject: [PATCH 103/303] Remove dump.rdb from repo --- .gitignore | 3 +++ dump.rdb | Bin 92 -> 0 bytes 2 files changed, 3 insertions(+) delete mode 100644 dump.rdb diff --git a/.gitignore b/.gitignore index 7d2198d6..7bacad99 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,6 @@ bower.json /node_modules yarn-debug.log* .yarn-integrity + +# Ignore Rediscache +dump.rdb diff --git a/dump.rdb b/dump.rdb deleted file mode 100644 index 180779667fa623486b8fc875b7ebff8fbeb55ca0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92 zcmWG?b@2=~Ffg$E#aWb^l3A= Date: Fri, 11 Mar 2022 12:49:41 +0000 Subject: [PATCH 104/303] Merge test groups --- Gemfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Gemfile b/Gemfile index 2153b3e6..3a651226 100644 --- a/Gemfile +++ b/Gemfile @@ -78,9 +78,6 @@ group :test do gem 'rails-controller-testing' gem 'database_cleaner' gem 'json-schema' -end - -group :test do gem 'launchy' gem 'rack_session_access' end From bba85d62abb91e7e96a026a16f020da2cf64f067 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 11 Mar 2022 13:03:22 +0000 Subject: [PATCH 105/303] Clean up Lint/UnreachableCode I ran across a branch of unreachable code when looking at begining performance optimization, so decided to clean it up first to simplify the process. Enabled the cop to detect other cases. --- .rubocop_todo.yml | 7 ------- app/helpers/activities_helper.rb | 7 +------ app/models/activity_type.rb | 9 --------- lib/inference_engines/runner/step_execution.rb | 9 --------- 4 files changed, 1 insertion(+), 31 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index e868a180..f2a12052 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1152,13 +1152,6 @@ Lint/ToJSON: Exclude: - 'lib/fact_changes.rb' -# Offense count: 3 -Lint/UnreachableCode: - Exclude: - - 'app/helpers/activities_helper.rb' - - 'app/models/activity_type.rb' - - 'lib/inference_engines/runner/step_execution.rb' - # Offense count: 57 # Cop supports --auto-correct. # Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. diff --git a/app/helpers/activities_helper.rb b/app/helpers/activities_helper.rb index 89d928c5..de6706ec 100644 --- a/app/helpers/activities_helper.rb +++ b/app/helpers/activities_helper.rb @@ -154,13 +154,8 @@ def step_type_templates_data_for_step_types(activity, step_types, asset_group) end def data_asset_display_for_asset_group(asset_group) - asset_group.assets.reduce({}) do |memo, asset| + asset_group.assets.each_with_object({}) do |asset, memo| memo[asset.uuid] = data_asset_display(asset.facts) - next memo - if ((asset.has_literal?('a', 'TubeRack')) || ((asset.has_literal?('a', 'Plate')))) - memo[asset.uuid] = data_asset_display(asset.facts) - end - memo end end diff --git a/app/models/activity_type.rb b/app/models/activity_type.rb index 37610650..3c29ccbb 100644 --- a/app/models/activity_type.rb +++ b/app/models/activity_type.rb @@ -20,8 +20,6 @@ def touch_activities activities.each(&:touch) end - before_update :parse_n3 - attr_accessor :n3_definition def create_activity(params) @@ -41,13 +39,6 @@ def available? superceded_by.nil? end - def parse_n3 - return - unless n3_definition.nil? - SupportN3::parse_string(n3_definition, {}) - end - end - def after_deprecate superceded_by.update_attributes( activities: superceded_by.activities | activities, diff --git a/lib/inference_engines/runner/step_execution.rb b/lib/inference_engines/runner/step_execution.rb index f0e673ee..a85b364d 100644 --- a/lib/inference_engines/runner/step_execution.rb +++ b/lib/inference_engines/runner/step_execution.rb @@ -38,15 +38,6 @@ def run_from_class end def generate_plan - return generate_plan2 - if @step.step_type.actions.length > 0 - run_from_class - else - generate_plan2 - end - end - - def generate_plan2 if @step.step_type.step_action.match(/\.rb$/) cmd = ["bin/rails", "runner", "#{Rails.root}/script/runners/#{@step.step_type.step_action}"] else From e4eb0c97014388ebe5a12dac1f4ff1e48140788c Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 15 Mar 2022 13:59:19 +0000 Subject: [PATCH 106/303] Move reracking actions into same process Spinning up a whole process for each job is quite expensive, and makes debugging much trickier. This change moves the re-racking issues into the Delayed::Worker. This change is a temporary fix. I'll update the corresponding database entries once everything is working smoothly. Its probably also worth updating the rest of the scripts, but that lack of test coverage makes me nervous. This is mostly a case of moving scripts into new files, however a few Cops activated following the move so I made the minimum fixes to get them working. --- app/models/activities/tasks.rb | 21 +- app/models/steps/task.rb | 12 ++ .../move_barcodes_from_tube_rack_to_plate.rb | 189 ++++++++++++++++++ .../rack_layout_creating_tubes.rb | 37 ++++ config/initializers/delayed_job_config.rb | 2 +- .../runner/step_execution.rb | 58 ++++-- processing_a_step.md | 59 ++++++ script/runners/rack_layout_creating_tubes.rb | 12 +- 8 files changed, 359 insertions(+), 31 deletions(-) create mode 100644 app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb create mode 100644 app/step_planners/step_planner/rack_layout_creating_tubes.rb create mode 100644 processing_a_step.md diff --git a/app/models/activities/tasks.rb b/app/models/activities/tasks.rb index ee776a46..7b6bd05e 100644 --- a/app/models/activities/tasks.rb +++ b/app/models/activities/tasks.rb @@ -2,16 +2,17 @@ module Activities module Tasks def create_step(params) - step = params[:step_type].class_for_task_type.create!({ - activity: self, - printer_config: params[:printer_config], - step_type: params[:step_type], - asset_group: params[:asset_group], - user: params[:user] }) - - connected_tasks = create_connected_tasks(step, params[:asset_group], params[:printer_config], params[:user]) - step.run! - step + params[:step_type].class_for_task_type + .create!( + activity: self, + printer_config: params[:printer_config], + step_type: params[:step_type], + asset_group: params[:asset_group], + user: params[:user] + ).tap do |step| + create_connected_tasks(step, params[:asset_group], params[:printer_config], params[:user]) + step.run! + end end end diff --git a/app/models/steps/task.rb b/app/models/steps/task.rb index faf5819f..95fe1d7d 100644 --- a/app/models/steps/task.rb +++ b/app/models/steps/task.rb @@ -2,9 +2,15 @@ module Steps::Task def process if operations.count > 0 + remake_me updates = FactChanges.new else + + # StepExecution here will either be InferenceEngines::Cwm::StepExecution or + # InferenceEngines::Default::StepExecution depending on the configuration + # parameter Rails.configuration.inference_engine which appears to be set to + # Default. step_execution = StepExecution.new(step: self, asset_group: asset_group) updates = step_execution.plan return stop! unless apply_changes(updates) @@ -13,16 +19,22 @@ def process assets_for_printing = updates.assets_for_printing unless step_type.step_action.nil? || step_type.step_action.empty? + runner = InferenceEngines::Runner::StepExecution.new( :step => self, :asset_group => asset_group, :created_assets => {}, :step_types => [step_type] ) + updates = runner.plan + return stop! unless apply_changes(updates) + assets_for_printing = assets_for_printing.to_a.concat(updates.assets_for_printing) + end + if assets_for_printing.length > 0 AssetGroup.new(assets: assets_for_printing).print(printer_config, user.username) end diff --git a/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb b/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb new file mode 100644 index 00000000..eeebc2fd --- /dev/null +++ b/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb @@ -0,0 +1,189 @@ +# frozen_string_literal: true + +# # This rule applies the barcodes from a rack into a plate +# { +# ?plate se:a Plate . +# ?rack se:a TubeRack . +# ?rack se:mergeInto ?plate . +# ?rack se:contains ?tube . +# ?plate se:contains ?well . +# ?tube se:location ?location . +# ?tube se:barcode ?barcode . +# ?well se:location ?location . +# } => { +# :step :addFacts { ?well se:barcode ?barcode . } . +# :step :removeFacts { ?tube se:barcode ?barcode . } . +# :step :addFacts { ?tube se:barcode . } . +# :step :addFacts { ?tube se:previousBarcode ?barcode . } . +# :step :addFacts { ?tube se:appliedBarcodeTo ?well . } . +# :step :addFacts { ?rack se:mergedInto ?plate .}. +# :step :addFacts { ?plate se:mergedFrom ?rack .}. +# }. +module StepPlanner + class MoveBarcodesFromTubeRackToPlate + attr_reader :asset_group + + def initialize(input_url, _step_url) + asset_group_id = input_url.match(/(\d*)\.json/)[1] + @asset_group = AssetGroup.find(asset_group_id) + end + + def assets_compatible_with_step_type + [plate, tube_rack].flatten.compact.count > 0 + end + + def plate + asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'Plate').count > 0 }.first + end + + def tube_rack + asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'TubeRack').count > 0 }.first + end + + def wells_for(asset) + asset.facts.where(predicate: 'contains').map(&:object_asset) + end + + def well_at_location(asset, location) + wells_for(asset).select do |w| + location_facts = w.facts.where(predicate: 'location') + if (location_facts.count == 1) + location_fact = location_facts.first + (TokenUtil.pad_location(location_fact.object) == TokenUtil.pad_location(location)) + end + end.first + end + + def traverse_wells(asset, &block) + wells_for(asset).each do |w| + location = w.facts.where(predicate: 'location').first.object + yield w, TokenUtil.pad_location(location) + end + end + + def process + FactChanges.new.tap do |updates| + if assets_compatible_with_step_type + traverse_wells(tube_rack) do |well_from_tube_rack, location| + well_from_plate = well_at_location(plate, location) + barcode = well_from_tube_rack.barcode + updates.remove_where(well_from_tube_rack, 'barcode', barcode) + updates.add(well_from_tube_rack, 'previousBarcode', barcode) + updates.add(well_from_tube_rack, 'appliedBarcodeTo', well_from_plate) + well_from_tube_rack.update_attributes(barcode: nil) + well_from_plate.update_attributes(barcode: barcode) + updates.add(well_from_plate, 'barcode', barcode) + end + + updates.add(tube_rack, 'mergedInto', plate) + updates.add(plate, 'mergedFrom', tube_rack) + end + end + end + + def updates + ActiveRecord::Base.transaction { process.to_json } + rescue StandardError => e + { set_errors: ["Unknown error while applying barcodes: #{e.message}, #{e.backtrace}"] } + end + end +end + +# # # This rule applies the barcodes from a rack into a plate +# # { +# # ?plate se:a Plate . +# # ?rack se:a TubeRack . +# # ?rack se:mergeInto ?plate . +# # ?rack se:contains ?tube . +# # ?plate se:contains ?well . +# # ?tube se:location ?location . +# # ?tube se:barcode ?barcode . +# # ?well se:location ?location . +# # } => { +# # :step :addFacts { ?well se:barcode ?barcode . } . +# # :step :removeFacts { ?tube se:barcode ?barcode . } . +# # :step :addFacts { ?tube se:barcode . } . +# # :step :addFacts { ?tube se:previousBarcode ?barcode . } . +# # :step :addFacts { ?tube se:appliedBarcodeTo ?well . } . +# # :step :addFacts { ?rack se:mergedInto ?plate .}. +# # :step :addFacts { ?plate se:mergedFrom ?rack .}. +# # }. + +# class MoveBarcodesFromTubeRackToPlate +# attr_reader :asset_group + + +# def initialize(params) +# @asset_group = params[:asset_group] +# end + +# def assets_compatible_with_step_type +# [plate, tube_rack].flatten.compact.count > 0 +# end + + +# def plate +# asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'Plate').count > 0 }.first +# end + +# def tube_rack +# asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'TubeRack').count > 0 }.first +# end + +# def wells_for(asset) +# asset.facts.where(predicate: 'contains').map(&:object_asset) +# end + +# def well_at_location(asset, location) +# wells_for(asset).select do |w| +# location_facts = w.facts.where(predicate: 'location') +# if (location_facts.count == 1) +# location_fact = location_facts.first +# (TokenUtil.pad_location(location_fact.object) == TokenUtil.pad_location(location)) +# end +# end.first +# end + +# def traverse_wells(asset, &block) +# wells_for(asset).each do |w| +# location = w.facts.where(predicate: 'location').first.object +# yield w, TokenUtil.pad_location(location) +# end +# end + +# def process +# FactChanges.new.tap do |updates| +# if assets_compatible_with_step_type +# traverse_wells(tube_rack) do |well_from_tube_rack, location| +# well_from_plate = well_at_location(plate, location) +# barcode = well_from_tube_rack.barcode +# updates.remove_where(well_from_tube_rack, 'barcode', barcode) +# updates.add(well_from_tube_rack, 'previousBarcode', barcode) +# updates.add(well_from_tube_rack, 'appliedBarcodeTo', well_from_plate) +# well_from_tube_rack.update_attributes(barcode: nil) +# well_from_plate.update_attributes(barcode: barcode) +# updates.add(well_from_plate, 'barcode', barcode) +# end + +# updates.add(tube_rack, 'mergedInto', plate) +# updates.add(plate, 'mergedFrom', tube_rack) +# end +# end +# end +# end + + +# args = ARGV[0] +# asset_group_id = args.match(/(\d*)\.json/)[1] +# asset_group = AssetGroup.find(asset_group_id) +# begin +# updates = nil +# ActiveRecord::Base.transaction do +# updates = MoveBarcodesFromTubeRackToPlate.new(asset_group: asset_group).process +# end +# json = updates.to_json +# JSON.parse(json) +# puts json +# rescue StandardError => e +# puts ({ set_errors: ['Unknown error while applying barcodes'+e.backtrace.to_s] }.to_json) +# end diff --git a/app/step_planners/step_planner/rack_layout_creating_tubes.rb b/app/step_planners/step_planner/rack_layout_creating_tubes.rb new file mode 100644 index 00000000..273055e4 --- /dev/null +++ b/app/step_planners/step_planner/rack_layout_creating_tubes.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'actions/racking' + +module StepPlanner + class RackLayoutCreatingTubes + attr_reader :asset_group + + include Actions::Racking + + def initialize(input_url, _step_url) + asset_group_id = input_url.match(/(\d*)\.json/)[1] + @asset_group = AssetGroup.find(asset_group_id) + end + + def assets_compatible_with_step_type + asset_group.uploaded_files + end + + def process + FactChanges.new.tap do |updates| + if assets_compatible_with_step_type.any? + updates.merge(rack_layout_creating_tubes(@asset_group)) + updates.remove_assets([[asset_group.uploaded_files.first.asset.uuid]]) + end + end + end + + def updates + ActiveRecord::Base.transaction { process.to_json } + rescue InvalidDataParams => e + { set_errors: e.errors } + rescue StandardError => e + { set_errors: ["Unknown error while applying barcodes: #{e.message}, #{e.backtrace}"] } + end + end +end diff --git a/config/initializers/delayed_job_config.rb b/config/initializers/delayed_job_config.rb index d6ad9697..4885e152 100644 --- a/config/initializers/delayed_job_config.rb +++ b/config/initializers/delayed_job_config.rb @@ -1,5 +1,5 @@ Delayed::Worker.destroy_failed_jobs = false -Delayed::Worker.sleep_delay = 0 +Delayed::Worker.sleep_delay = 0.5 Delayed::Worker.max_attempts = Float::INFINITY Delayed::Worker.max_run_time = 5.minutes Delayed::Worker.read_ahead = 10 diff --git a/lib/inference_engines/runner/step_execution.rb b/lib/inference_engines/runner/step_execution.rb index a85b364d..36991347 100644 --- a/lib/inference_engines/runner/step_execution.rb +++ b/lib/inference_engines/runner/step_execution.rb @@ -4,6 +4,12 @@ module InferenceEngines module Runner class StepExecution + # Temporary constant to assist refactor + # @todo Remove this and migrate actions instead + CONVERTED_CLASS_ACTIONS = { + 'move_barcodes_from_tube_rack_to_plate.rb' => 'StepPlanner::MoveBarcodesFromTubeRackToPlate', + 'rack_layout_creating_tubes.rb' => 'StepPlanner::RackLayoutCreatingTubes' + } include StepExecutionProcess attr_accessor :step, :asset_group, :original_assets, @@ -30,30 +36,43 @@ def debug_log(params) end end - def run_from_class - require("#{Rails.root}/script/runners/#{@step.step_type.step_action}") - @content = @step.step_type.step_action.gsub("\.rb", '').camelize.constantize.new(asset_group: @asset_group, step: @step).process.to_json - step.update_columns(output: @content) - @updates = FactChanges.new(@content) + def step_action + CONVERTED_CLASS_ACTIONS.fetch(@step.step_type.step_action, @step.step_type.step_action) + end + + def handled_by_class? + step_action.starts_with?('StepPlanner::') end def generate_plan - if @step.step_type.step_action.match(/\.rb$/) - cmd = ["bin/rails", "runner", "#{Rails.root}/script/runners/#{@step.step_type.step_action}"] + if handled_by_class? + generate_plan_from_class + else + generate_plan_from_external_process + end + end + + def generate_plan_from_class + klass = step_action.constantize + + step_planner = klass.new(input_url, step_url) + @content = step_planner.updates + step.update_attributes(output: @content) + @updates = FactChanges.new(content) + end + + def generate_plan_from_external_process + if step_action.match(/\.rb$/) + cmd = ["bin/rails", "runner", "#{Rails.root}/script/runners/#{step_action}"] else - cmd = "#{Rails.root}/script/runners/#{@step.step_type.step_action}" + cmd = "#{Rails.root}/script/runners/#{step_action}" end - call_list = [ - cmd, - input_url = Rails.application.routes.url_helpers.asset_group_url(@asset_group.id)+".json", - step_url = Rails.application.routes.url_helpers.step_url(@step.id)+".json" - ].flatten + call_list = [cmd, input_url, step_url].flatten call_str = call_list.join(" ") line = "# EXECUTING: #{call_str}" - Open3.popen3(*[call_list].flatten) do |stdin, stdout, stderror, thr| @content = stdout.read output = [line, content].join("\n") @@ -132,6 +151,17 @@ def unselect_asset(uuids) #@step.asset_group.remove_assets(assets) end end + + private + + def input_url + Rails.application.routes.url_helpers.asset_group_url(@asset_group.id)+".json" + end + + def step_url + Rails.application.routes.url_helpers.step_url(@step.id)+".json" + end + end end end diff --git a/processing_a_step.md b/processing_a_step.md new file mode 100644 index 00000000..1c242fdc --- /dev/null +++ b/processing_a_step.md @@ -0,0 +1,59 @@ +# Process diagram for step processing + +This diagram is an attempt to map out the step process to aid performance +optimizations. It is *not* and exhaustive map of all calls in the process. + +## Sequence Diagram + +```mermaid +sequenceDiagram + participant C As StepsController + participant A As Activity + participant S As Step + participant SE As StepExecution + participant SBTI As Steps::BackgroundTasks::Inference + participant SBTR As Steps::BackgroundTasks::Runner + participant ISE As InferenceEngines::Runner::StepExecution + C->>A: create_step + + alt background_step + A->>S: create! + S-->>A: instance + A->>+S: run + S->>S: create_job + S-)S: perform_job + S->>S: process + alt has_operations + S--)S:remake_me + else + S->>SE: plan + SE-->>S: updates + S->>S: apply_changes + end + + alt has step action + S->>ISE:plan + ISE->>ISE:generate_plan + ISE->>ExternalScript:Execute + ExternalScript-->>ISE:plan + + ISE-->>S:updates + S->>S: apply_changes + end + + + + deactivate S + else cwm + A->>SBTI: create! + SBTI-->>A: instance + A->>+SBTI: run + deactivate SBTI + else runner + A->>SBTR: create! + SBTR-->>A: instance + A->>+SBTR: run + deactivate SBTR + end + +``` diff --git a/script/runners/rack_layout_creating_tubes.rb b/script/runners/rack_layout_creating_tubes.rb index cbf2cd26..c048b4d6 100644 --- a/script/runners/rack_layout_creating_tubes.rb +++ b/script/runners/rack_layout_creating_tubes.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'actions/racking' class RackLayoutCreatingTubes @@ -13,10 +15,9 @@ def assets_compatible_with_step_type asset_group.uploaded_files end - def process FactChanges.new.tap do |updates| - if assets_compatible_with_step_type.count > 0 + if assets_compatible_with_step_type.any? updates.merge(rack_layout_creating_tubes(@asset_group)) updates.remove_assets([[asset_group.uploaded_files.first.asset.uuid]]) end @@ -24,7 +25,7 @@ def process end end -return unless ARGV.any? { |s| s.match(".json") } +return unless ARGV.any? { |s| s.match('.json') } args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] @@ -36,8 +37,7 @@ def process JSON.parse(json) puts json rescue InvalidDataParams => e - puts ({ set_errors: e.errors }.to_json) + puts({ set_errors: e.errors }.to_json) rescue StandardError => e - - puts ({ set_errors: ['Unknown error while parsing file'+e.to_json+e.backtrace.join] }.to_json) + puts({ set_errors: ['Unknown error while parsing file' + e.to_json + e.backtrace.join] }.to_json) end From 745044896ec537cf1fdbd301cb5d2be1c9aebd6c Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 15 Mar 2022 15:55:50 +0000 Subject: [PATCH 107/303] Remove valid? from null context valid? here returns a boolean, which itself doesn't actually do anything in this context. While we *do* populate the errors object, we don't use this in any context, without actually caling valid? first. This re-runs the validation and obliterates the orignal errors. This action is surprisingly expensive, and, although we hope to make it cheaper, we don't want to be running this operation needelessly. --- lib/parsers/csv_layout/csv_parser.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/parsers/csv_layout/csv_parser.rb b/lib/parsers/csv_layout/csv_parser.rb index 8fcf9eba..19cb137f 100644 --- a/lib/parsers/csv_layout/csv_parser.rb +++ b/lib/parsers/csv_layout/csv_parser.rb @@ -29,7 +29,6 @@ def initialize(str, component_defs = {}) @parsed = false @input = str @components = self.class::DEFAULT_COMPONENTS.merge(component_defs) - valid? end def parsed? From ff39f6824586ff7ffb1361e6c783a9c96b59f717 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 16 Mar 2022 11:46:12 +0000 Subject: [PATCH 108/303] Move Regexps into constants Rubocop was complaining while I cleaned up performance, so fixing ahead of the big commit. --- app/controllers/assets_controller.rb | 5 +-- .../validators/location_validator.rb | 2 +- lib/token_util.rb | 36 ++++++------------- 3 files changed, 12 insertions(+), 31 deletions(-) diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index e641f252..92088a7d 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -118,7 +118,7 @@ def destroy # Use callbacks to share common setup or constraints between actions. def set_asset - @asset = if UUID_REGEXP.match(params[:id]) + @asset = if TokenUtil::UUID_REGEXP.match(params[:id]) Asset.find_by(uuid: params[:id]) else Asset.find(params[:id]) @@ -143,7 +143,4 @@ def set_queries def asset_params params.require(:asset).permit(:barcode) end - - UUID_REGEXP = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/ - end diff --git a/lib/parsers/csv_layout/validators/location_validator.rb b/lib/parsers/csv_layout/validators/location_validator.rb index 845b37f2..35fbdff8 100644 --- a/lib/parsers/csv_layout/validators/location_validator.rb +++ b/lib/parsers/csv_layout/validators/location_validator.rb @@ -11,7 +11,7 @@ def validate(record) protected def valid_location?(record) - !record.location.nil? && !!record.location.match(TokenUtil.LOCATION_REGEXP) + record.location.present? && record.location.match?(TokenUtil::LOCATION_REGEXP) end end end diff --git a/lib/token_util.rb b/lib/token_util.rb index 06b84f00..b5cedfad 100644 --- a/lib/token_util.rb +++ b/lib/token_util.rb @@ -1,28 +1,21 @@ module TokenUtil - # rubocop:todo Naming/MethodName - def self.UUID_REGEXP - /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ - end + LOCATION_REGEXP = /^([A-H])(\d{1,2})$/.freeze + UUID_REGEXP = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.freeze + MACHINE_BARCODE = /^\d*$/.freeze + HUMAN_BARCODE = /^\w*$/.freeze + WILDCARD_REGEXP = /\?\w*/.freeze def self.fluidx_barcode_prefix 'F' end - def self.MACHINE_BARCODE - /^\d*$/ - end - - def self.HUMAN_BARCODE - /^\w*$/ - end - def self.invalid_barcode?(barcode) barcode.nil? || (barcode.kind_of?(String) && barcode.to_s.empty?) end def self.machine_barcode?(barcode) return false if invalid_barcode?(barcode) - barcode.to_s.match?(TokenUtil.MACHINE_BARCODE) + barcode.to_s.match?(MACHINE_BARCODE) end def self.human_barcode?(barcode) @@ -41,16 +34,8 @@ def self.human_barcode(barcode) barcode.to_s end - def self.WILDCARD_REGEXP - /\?\w*/ - end - - def self.LOCATION_REGEXP - /^([A-H])(\d{1,2})$/ - end - def self.is_uuid?(str) - str.kind_of?(String) && !str.match(TokenUtil.UUID_REGEXP).nil? + str.kind_of?(String) && !str.match(UUID_REGEXP).nil? end def self.quote_if_uuid(str) @@ -63,11 +48,11 @@ def self.is_valid_fluidx_barcode?(barcode) end def self.uuid(str) - str.match(TokenUtil.UUID_REGEXP)[0] + str.match(UUID_REGEXP)[0] end def self.is_wildcard?(str) - str.kind_of?(String) && !str.match(TokenUtil.WILDCARD_REGEXP).nil? + str.kind_of?(String) && !str.match(WILDCARD_REGEXP).nil? end def self.kind_of_asset_id?(str) @@ -98,7 +83,7 @@ def self.unpad_location(location) def self.pad_location(location) return location unless location - parts = location.match(TokenUtil.LOCATION_REGEXP) + parts = location.match(LOCATION_REGEXP) return nil if parts.length == 0 letter = parts[1] number = parts[2] @@ -115,5 +100,4 @@ def self.unquote(str) return str unless str str.gsub(/\"/,"") end - # rubocop:enable Naming/MethodName end From 79617c3ec35aad9af0bbcdebedc106a30d2d2985 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 16 Mar 2022 11:54:34 +0000 Subject: [PATCH 109/303] Minor code refactors in preparatio These changes themselves are unlikely to yield significant performance improvements, but are mainly about tidying the codebase ahead of a refactor. - Remove valid? at end of initiaizers - Avoid unecessary conversion to json - Slight code clean up --- .rubocop.yml | 2 +- .rubocop_todo.yml | 17 -- app/controllers/steps_controller.rb | 4 +- app/models/step.rb | 7 - app/models/step_type.rb | 4 +- .../move_barcodes_from_tube_rack_to_plate.rb | 168 ++++-------------- .../rack_layout_creating_tubes.rb | 6 +- lib/actions/racking.rb | 20 +-- lib/fact_changes.rb | 4 +- .../runner/step_execution.rb | 5 +- lib/parsers/csv_layout/barcode_parser.rb | 25 +-- lib/parsers/csv_layout/line_parser.rb | 56 +++--- lib/parsers/csv_layout/location_parser.rb | 10 +- .../validators/any_barcode_validator.rb | 8 +- .../validators/fluidx_barcode_validator.rb | 9 +- .../validators/location_validator.rb | 7 +- lib/parsers/csv_metadata/line_parser.rb | 6 +- .../validators/headers_validator.rb | 7 +- 18 files changed, 120 insertions(+), 245 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index a8b2effe..7c86f5b3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -12,7 +12,7 @@ AllCops: # Block DSL is also used in routes # We should be careful keeping rake tasks here, as large tasks are still an issue. # Not sure if we need to split namespaces across several files though. -# We exclude builders, as they are concerned with rendering xml +# We exclude builders, as the are concerned with rendering xml Metrics/BlockLength: Exclude: - Gemfile diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index f2a12052..734faf9c 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -2176,15 +2176,11 @@ Style/Documentation: - 'lib/parsers/csv_layout/line_parser.rb' - 'lib/parsers/csv_layout/line_reader.rb' - 'lib/parsers/csv_layout/location_parser.rb' - - 'lib/parsers/csv_layout/validators/any_barcode_validator.rb' - - 'lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb' - - 'lib/parsers/csv_layout/validators/location_validator.rb' - 'lib/parsers/csv_metadata/csv_parser.rb' - 'lib/parsers/csv_metadata/data_parser.rb' - 'lib/parsers/csv_metadata/datum_parser.rb' - 'lib/parsers/csv_metadata/headers_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - - 'lib/parsers/csv_metadata/validators/headers_validator.rb' - 'lib/psd_formatter.rb' - 'lib/sequencescape_client.rb' - 'lib/sequencescape_client_v2.rb' @@ -2522,15 +2518,11 @@ Style/FrozenStringLiteralComment: - 'lib/parsers/csv_layout/line_parser.rb' - 'lib/parsers/csv_layout/line_reader.rb' - 'lib/parsers/csv_layout/location_parser.rb' - - 'lib/parsers/csv_layout/validators/any_barcode_validator.rb' - - 'lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb' - - 'lib/parsers/csv_layout/validators/location_validator.rb' - 'lib/parsers/csv_metadata/csv_parser.rb' - 'lib/parsers/csv_metadata/data_parser.rb' - 'lib/parsers/csv_metadata/datum_parser.rb' - 'lib/parsers/csv_metadata/headers_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - - 'lib/parsers/csv_metadata/validators/headers_validator.rb' - 'lib/sequencescape_client.rb' - 'lib/sequencescape_client_v2.rb' - 'lib/step_execution_process.rb' @@ -2694,9 +2686,6 @@ Style/GuardClause: - 'lib/label_template_setup.rb' - 'lib/parsers/csv_layout/csv_parser.rb' - 'lib/parsers/csv_layout/line_parser.rb' - - 'lib/parsers/csv_layout/validators/any_barcode_validator.rb' - - 'lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb' - - 'lib/parsers/csv_layout/validators/location_validator.rb' - 'lib/parsers/csv_metadata/csv_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - 'lib/step_execution_process.rb' @@ -2845,12 +2834,8 @@ Style/IfUnlessModifier: - 'lib/label_template_setup.rb' - 'lib/parsers/csv_layout/csv_parser.rb' - 'lib/parsers/csv_layout/line_parser.rb' - - 'lib/parsers/csv_layout/validators/any_barcode_validator.rb' - - 'lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb' - - 'lib/parsers/csv_layout/validators/location_validator.rb' - 'lib/parsers/csv_metadata/csv_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - - 'lib/parsers/csv_metadata/validators/headers_validator.rb' - 'lib/support_n3.rb' - 'script/aliquot_type_inference.rb' - 'script/claim_uuids.rb' @@ -3369,8 +3354,6 @@ Style/StringLiterals: - 'lib/label_types/tube.rb' - 'lib/parsers/csv_layout/barcode_parser.rb' - 'lib/parsers/csv_layout/csv_parser.rb' - - 'lib/parsers/csv_layout/validators/any_barcode_validator.rb' - - 'lib/parsers/csv_layout/validators/location_validator.rb' - 'lib/parsers/csv_metadata/csv_parser.rb' - 'lib/sequencescape_client_v2.rb' - 'lib/support_n3.rb' diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb index c1a24a0a..dc42825e 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -12,12 +12,12 @@ def new end def create - @activity.create_step({ + @activity.create_step( step_type: @step_type, user: @current_user, printer_config: @printer_config, asset_group: @asset_group - }) + ) head :ok end diff --git a/app/models/step.rb b/app/models/step.rb index 520b3a35..bdf07938 100644 --- a/app/models/step.rb +++ b/app/models/step.rb @@ -37,14 +37,7 @@ class Step < ApplicationRecord include Steps::State include Steps::WebsocketEvents - def set_errors(errors) - #activity.send_wss_event({error: {type: 'danger', msg: errors.first} }) - #wss_event - #step_messages.delete_all - #errors.each do |error| - # step_messages << StepMessage.new(content: error) - #end ActiveRecord::Base.transaction do step_messages.each(&:destroy) errors.each do |error| diff --git a/app/models/step_type.rb b/app/models/step_type.rb index df9f0171..fc359078 100644 --- a/app/models/step_type.rb +++ b/app/models/step_type.rb @@ -82,8 +82,8 @@ def all_step_actions end def task_type - return 'background_step' if (actions.count > 0) || (step_action.nil?) - return 'cwm' if step_action && step_action.end_with?('.n3') + return 'background_step' if (actions.count > 0) || step_action.nil? + return 'cwm' if step_action&.end_with?('.n3') return 'runner' end diff --git a/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb b/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb index eeebc2fd..6d2cf4b5 100644 --- a/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb +++ b/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb @@ -1,43 +1,46 @@ # frozen_string_literal: true -# # This rule applies the barcodes from a rack into a plate -# { -# ?plate se:a Plate . -# ?rack se:a TubeRack . -# ?rack se:mergeInto ?plate . -# ?rack se:contains ?tube . -# ?plate se:contains ?well . -# ?tube se:location ?location . -# ?tube se:barcode ?barcode . -# ?well se:location ?location . -# } => { -# :step :addFacts { ?well se:barcode ?barcode . } . -# :step :removeFacts { ?tube se:barcode ?barcode . } . -# :step :addFacts { ?tube se:barcode . } . -# :step :addFacts { ?tube se:previousBarcode ?barcode . } . -# :step :addFacts { ?tube se:appliedBarcodeTo ?well . } . -# :step :addFacts { ?rack se:mergedInto ?plate .}. -# :step :addFacts { ?plate se:mergedFrom ?rack .}. -# }. module StepPlanner + # # This rule applies the barcodes from a rack into a plate + # { + # ?plate se:a Plate . + # ?rack se:a TubeRack . + # ?rack se:mergeInto ?plate . + # ?rack se:contains ?tube . + # ?plate se:contains ?well . + # ?tube se:location ?location . + # ?tube se:barcode ?barcode . + # ?well se:location ?location . + # } => { + # :step :addFacts { ?well se:barcode ?barcode . } . + # :step :removeFacts { ?tube se:barcode ?barcode . } . + # :step :addFacts { ?tube se:barcode . } . + # :step :addFacts { ?tube se:previousBarcode ?barcode . } . + # :step :addFacts { ?tube se:appliedBarcodeTo ?well . } . + # :step :addFacts { ?rack se:mergedInto ?plate .}. + # :step :addFacts { ?plate se:mergedFrom ?rack .}. + # }. class MoveBarcodesFromTubeRackToPlate attr_reader :asset_group - def initialize(input_url, _step_url) - asset_group_id = input_url.match(/(\d*)\.json/)[1] + def initialize(asset_group_id, _step_id) @asset_group = AssetGroup.find(asset_group_id) end def assets_compatible_with_step_type - [plate, tube_rack].flatten.compact.count > 0 + [plate, tube_rack].flatten.any? end def plate - asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'Plate').count > 0 }.first + # TODO: Scope for improvement here, just adapted it sufficiently to make rubocop happy as I want to keep this + # commit focussed on the move to using the same process + asset_group.assets.detect { |a| a.facts.exists?(predicate: 'a', object: 'Plate') } end def tube_rack - asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'TubeRack').count > 0 }.first + # TODO: Scope for improvement here, just adapted it sufficiently to make rubocop happy as I want to keep this + # commit focussed on the move to using the same process + asset_group.assets.detect { |a| a.facts.exists?(predicate: 'a', object: 'TubeRack') } end def wells_for(asset) @@ -45,16 +48,16 @@ def wells_for(asset) end def well_at_location(asset, location) - wells_for(asset).select do |w| + wells_for(asset).detect do |w| location_facts = w.facts.where(predicate: 'location') - if (location_facts.count == 1) + if location_facts.count == 1 location_fact = location_facts.first - (TokenUtil.pad_location(location_fact.object) == TokenUtil.pad_location(location)) + (TokenUtil.pad_location(location_fact.object) == TokenUtil.pad_location(location)) end - end.first + end end - def traverse_wells(asset, &block) + def traverse_wells(asset) wells_for(asset).each do |w| location = w.facts.where(predicate: 'location').first.object yield w, TokenUtil.pad_location(location) @@ -66,12 +69,12 @@ def process if assets_compatible_with_step_type traverse_wells(tube_rack) do |well_from_tube_rack, location| well_from_plate = well_at_location(plate, location) - barcode = well_from_tube_rack.barcode + barcode = well_from_tube_rack.barcode updates.remove_where(well_from_tube_rack, 'barcode', barcode) updates.add(well_from_tube_rack, 'previousBarcode', barcode) updates.add(well_from_tube_rack, 'appliedBarcodeTo', well_from_plate) - well_from_tube_rack.update_attributes(barcode: nil) - well_from_plate.update_attributes(barcode: barcode) + well_from_tube_rack.update(barcode: nil) + well_from_plate.update(barcode: barcode) updates.add(well_from_plate, 'barcode', barcode) end @@ -82,108 +85,9 @@ def process end def updates - ActiveRecord::Base.transaction { process.to_json } + ActiveRecord::Base.transaction { process.to_h } rescue StandardError => e { set_errors: ["Unknown error while applying barcodes: #{e.message}, #{e.backtrace}"] } end end end - -# # # This rule applies the barcodes from a rack into a plate -# # { -# # ?plate se:a Plate . -# # ?rack se:a TubeRack . -# # ?rack se:mergeInto ?plate . -# # ?rack se:contains ?tube . -# # ?plate se:contains ?well . -# # ?tube se:location ?location . -# # ?tube se:barcode ?barcode . -# # ?well se:location ?location . -# # } => { -# # :step :addFacts { ?well se:barcode ?barcode . } . -# # :step :removeFacts { ?tube se:barcode ?barcode . } . -# # :step :addFacts { ?tube se:barcode . } . -# # :step :addFacts { ?tube se:previousBarcode ?barcode . } . -# # :step :addFacts { ?tube se:appliedBarcodeTo ?well . } . -# # :step :addFacts { ?rack se:mergedInto ?plate .}. -# # :step :addFacts { ?plate se:mergedFrom ?rack .}. -# # }. - -# class MoveBarcodesFromTubeRackToPlate -# attr_reader :asset_group - - -# def initialize(params) -# @asset_group = params[:asset_group] -# end - -# def assets_compatible_with_step_type -# [plate, tube_rack].flatten.compact.count > 0 -# end - - -# def plate -# asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'Plate').count > 0 }.first -# end - -# def tube_rack -# asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'TubeRack').count > 0 }.first -# end - -# def wells_for(asset) -# asset.facts.where(predicate: 'contains').map(&:object_asset) -# end - -# def well_at_location(asset, location) -# wells_for(asset).select do |w| -# location_facts = w.facts.where(predicate: 'location') -# if (location_facts.count == 1) -# location_fact = location_facts.first -# (TokenUtil.pad_location(location_fact.object) == TokenUtil.pad_location(location)) -# end -# end.first -# end - -# def traverse_wells(asset, &block) -# wells_for(asset).each do |w| -# location = w.facts.where(predicate: 'location').first.object -# yield w, TokenUtil.pad_location(location) -# end -# end - -# def process -# FactChanges.new.tap do |updates| -# if assets_compatible_with_step_type -# traverse_wells(tube_rack) do |well_from_tube_rack, location| -# well_from_plate = well_at_location(plate, location) -# barcode = well_from_tube_rack.barcode -# updates.remove_where(well_from_tube_rack, 'barcode', barcode) -# updates.add(well_from_tube_rack, 'previousBarcode', barcode) -# updates.add(well_from_tube_rack, 'appliedBarcodeTo', well_from_plate) -# well_from_tube_rack.update_attributes(barcode: nil) -# well_from_plate.update_attributes(barcode: barcode) -# updates.add(well_from_plate, 'barcode', barcode) -# end - -# updates.add(tube_rack, 'mergedInto', plate) -# updates.add(plate, 'mergedFrom', tube_rack) -# end -# end -# end -# end - - -# args = ARGV[0] -# asset_group_id = args.match(/(\d*)\.json/)[1] -# asset_group = AssetGroup.find(asset_group_id) -# begin -# updates = nil -# ActiveRecord::Base.transaction do -# updates = MoveBarcodesFromTubeRackToPlate.new(asset_group: asset_group).process -# end -# json = updates.to_json -# JSON.parse(json) -# puts json -# rescue StandardError => e -# puts ({ set_errors: ['Unknown error while applying barcodes'+e.backtrace.to_s] }.to_json) -# end diff --git a/app/step_planners/step_planner/rack_layout_creating_tubes.rb b/app/step_planners/step_planner/rack_layout_creating_tubes.rb index 273055e4..7740c297 100644 --- a/app/step_planners/step_planner/rack_layout_creating_tubes.rb +++ b/app/step_planners/step_planner/rack_layout_creating_tubes.rb @@ -3,13 +3,13 @@ require 'actions/racking' module StepPlanner + # Allows the upload of a tube rack layout to register the tubes class RackLayoutCreatingTubes attr_reader :asset_group include Actions::Racking - def initialize(input_url, _step_url) - asset_group_id = input_url.match(/(\d*)\.json/)[1] + def initialize(asset_group_id, _step_id) @asset_group = AssetGroup.find(asset_group_id) end @@ -27,7 +27,7 @@ def process end def updates - ActiveRecord::Base.transaction { process.to_json } + ActiveRecord::Base.transaction { process.to_h } rescue InvalidDataParams => e { set_errors: e.errors } rescue StandardError => e diff --git a/lib/actions/racking.rb b/lib/actions/racking.rb index e31e71dc..b03dbebe 100644 --- a/lib/actions/racking.rb +++ b/lib/actions/racking.rb @@ -10,7 +10,6 @@ class InvalidDataParams < StandardError def initialize(message = nil) super(message) @errors = message - #@msg = html_error_message([message].flatten) end def html_error_message(error_messages) @@ -31,6 +30,11 @@ module Racking RNA_ALIQUOT = 'RNA' TUBE_TO_PLATE_TRANSFERRABLE_PROPERTIES = [:study_name,:aliquotType] + ALIQUOT_PURPOSE = { + DNA_ALIQUOT => DNA_STOCK_PLATE_PURPOSE, + RNA_ALIQUOT => RNA_STOCK_PLATE_PURPOSE + } + # Actions def rack_layout(asset_group) content = selected_file(asset_group).data @@ -121,13 +125,7 @@ def fact_changes_for_unrack_tubes(list_layout, destination_rack = nil) end def purpose_for_aliquot(aliquot) - if aliquot == DNA_ALIQUOT - DNA_STOCK_PLATE_PURPOSE - elsif aliquot == RNA_ALIQUOT - RNA_STOCK_PLATE_PURPOSE - else - STOCK_PLATE_PURPOSE - end + ALIQUOT_PURPOSE.fetch(aliquot, STOCK_PLATE_PURPOSE) end def fact_changes_for_add_purpose(rack, aliquot) @@ -288,10 +286,12 @@ def csv_parsing(asset_group, parser) error_messages = [] error_locations = [] - if asset_group.assets.with_fact('a', 'TubeRack').empty? + tube_racks = asset_group.assets.with_fact('a', 'TubeRack').includes(facts: { object_asset: { facts: :object } }) + + if tube_racks.empty? error_messages.push("No TubeRacks found to perform the layout process") end - if asset_group.assets.with_fact('a', 'TubeRack').count > 1 + if tube_racks.many? error_messages.push("Too many TubeRacks found to perform the layout process") end raise InvalidDataParams, error_messages if error_messages.count > 0 diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index 383c098b..0f74a857 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -17,7 +17,7 @@ class FactChanges def initialize(json = nil) @assets_updated=[] reset - parse_json(json) if json + parse_json(json) unless json.nil? end def parsing_valid? @@ -96,7 +96,7 @@ def to_json end def parse_json(json) - obj = JSON.parse(json) + obj = json.is_a?(String) ? JSON.parse(json) : json.deep_stringify_keys ['set_errors', 'create_assets', 'create_asset_groups', 'delete_asset_groups', 'remove_facts', 'add_facts', 'delete_assets', 'add_assets', 'remove_assets'].each do |action_type| if obj[action_type] diff --git a/lib/inference_engines/runner/step_execution.rb b/lib/inference_engines/runner/step_execution.rb index 36991347..b9f3620f 100644 --- a/lib/inference_engines/runner/step_execution.rb +++ b/lib/inference_engines/runner/step_execution.rb @@ -9,7 +9,7 @@ class StepExecution CONVERTED_CLASS_ACTIONS = { 'move_barcodes_from_tube_rack_to_plate.rb' => 'StepPlanner::MoveBarcodesFromTubeRackToPlate', 'rack_layout_creating_tubes.rb' => 'StepPlanner::RackLayoutCreatingTubes' - } + }.freeze include StepExecutionProcess attr_accessor :step, :asset_group, :original_assets, @@ -55,7 +55,7 @@ def generate_plan def generate_plan_from_class klass = step_action.constantize - step_planner = klass.new(input_url, step_url) + step_planner = klass.new(@asset_group.id, @step.id) @content = step_planner.updates step.update_attributes(output: @content) @updates = FactChanges.new(content) @@ -161,7 +161,6 @@ def input_url def step_url Rails.application.routes.url_helpers.step_url(@step.id)+".json" end - end end end diff --git a/lib/parsers/csv_layout/barcode_parser.rb b/lib/parsers/csv_layout/barcode_parser.rb index 5f0dc0de..5a12704e 100644 --- a/lib/parsers/csv_layout/barcode_parser.rb +++ b/lib/parsers/csv_layout/barcode_parser.rb @@ -9,7 +9,8 @@ class BarcodeParser include ActiveModel::Validations - validates :asset, presence: { message: "Cannot find the barcode" } + validates :asset, presence: { message: "Cannot find the barcode" }, if: :barcode? + validates :barcode, presence: true validate :validations def validations @@ -20,26 +21,26 @@ def validations def initialize(line, parser) @parser = parser - _parse(line) - - valid? + @parsing_error = nil + parse(line) end def no_read_barcode? - !barcode.nil? && barcode.downcase.start_with?(NO_READ_BARCODE) + barcode&.downcase&.start_with?(NO_READ_BARCODE) end def asset Asset.find_or_import_asset_with_barcode(barcode) end - protected - def _parse(line) - begin - @barcode = line[1].strip - rescue StandardError => e - errors.add(:barcode, 'There was an error while parsing the barcode') - end + def barcode? + barcode.present? && !no_read_barcode? + end + + private + + def parse(line) + @barcode = line[1]&.strip end end end diff --git a/lib/parsers/csv_layout/line_parser.rb b/lib/parsers/csv_layout/line_parser.rb index 23c83490..8305effd 100644 --- a/lib/parsers/csv_layout/line_parser.rb +++ b/lib/parsers/csv_layout/line_parser.rb @@ -2,21 +2,17 @@ module Parsers module CsvLayout class LineParser include ActiveModel::Validations - attr_reader :parsed_content validate :validate_parsed_content def initialize(input_reader, parser) @parser = parser - @parsed_content = [] - @parsed=false @input_reader = input_reader - valid? end def parsed_data if valid? - @parsed_content.select { |e| !e[:barcode_parser].no_read_barcode? }.map do |entry| + parsed_content.select { |e| !e[:barcode_parser].no_read_barcode? }.map do |entry| { location: entry[:location_parser].location, asset: entry[:barcode_parser].asset @@ -25,9 +21,9 @@ def parsed_data end end - def error_list_for_parser(parser, numline) + def error_list_for_parser(parser, line_number) parser.errors.messages.values.map do |msg| - "At line #{numline}: #{msg[0]}" + "At line #{line_number}: #{msg[0]}" end end @@ -40,41 +36,37 @@ def error_list end.flatten end + def parsed_content + @parsed_content ||= parse + end + protected def validate_parsed_content - parse unless @parsed - errors.clear - @parsed_content.each do |entry| - unless entry[:location_parser].valid? && entry[:barcode_parser].valid? - errors.add(:base, "There is an error at line #{entry[:num_line]}") - end + parsed_content.each do |entry| + next if entry[:location_parser].valid? && entry[:barcode_parser].valid? + + errors.add(:base, "There is an error at line #{entry[:num_line]}") end end def parse - num_line = 1 - @input_reader.lines.reduce(@parsed_content) do |memo, line| - unless is_empty_line?(line) - barcode_parser = @parser.components[:barcode_parser].new(line, @parser) - unless barcode_parser.no_read_barcode? - location_parser = @parser.components[:location_parser].new(line, @parser) - memo.push({ - location_parser: location_parser, - barcode_parser: barcode_parser, - num_line: num_line - }) - end - end - num_line = num_line+1 - memo - end - @parsed = true + @input_reader.lines.filter_map.with_index do |line, num_line| + next if empty_line?(line) - parsed_data + barcode_parser = @parser.components[:barcode_parser].new(line, @parser) + next if barcode_parser.no_read_barcode? + + location_parser = @parser.components[:location_parser].new(line, @parser) + { + location_parser: location_parser, + barcode_parser: barcode_parser, + num_line: num_line + } + end end - def is_empty_line?(line) + def empty_line?(line) (line.nil? || (line.length == 0) || line.all?(&:nil?)) end end diff --git a/lib/parsers/csv_layout/location_parser.rb b/lib/parsers/csv_layout/location_parser.rb index 5b50f8aa..1362b445 100644 --- a/lib/parsers/csv_layout/location_parser.rb +++ b/lib/parsers/csv_layout/location_parser.rb @@ -13,18 +13,16 @@ def validations def initialize(line, parser) @parser = parser - _parse(line) - - valid? + parse(line) end - protected + private - def _parse(line) + def parse(line) begin @location = TokenUtil.pad_location(line[0].strip) rescue StandardError => e - errors.add(:location, 'There was an error while parsing the location') + @location = nil end end diff --git a/lib/parsers/csv_layout/validators/any_barcode_validator.rb b/lib/parsers/csv_layout/validators/any_barcode_validator.rb index bd4da75f..92f9f512 100644 --- a/lib/parsers/csv_layout/validators/any_barcode_validator.rb +++ b/lib/parsers/csv_layout/validators/any_barcode_validator.rb @@ -1,11 +1,13 @@ +# frozen_string_literal: true + module Parsers module CsvLayout module Validators + # Validates that a barcode is present, but doesn't care if the asset + # exists class AnyBarcodeValidator < ActiveModel::Validator def validate(record) - if record.barcode.blank? - record.errors.add(:barcode, "Barcode is empty") - end + record.errors.add(:barcode, 'is empty') if record.barcode.blank? end end end diff --git a/lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb b/lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb index d4f96b6f..26841f59 100644 --- a/lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb +++ b/lib/parsers/csv_layout/validators/fluidx_barcode_validator.rb @@ -1,11 +1,14 @@ +# frozen_string_literal: true + module Parsers module CsvLayout module Validators + # Validates that the barcode matches the Fluidx format class FluidxBarcodeValidator < ActiveModel::Validator def validate(record) - unless valid_fluidx_barcode?(record) - record.errors.add(:barcode, "Invalid fluidx barcode format #{record.barcode}") - end + return if valid_fluidx_barcode?(record) + + record.errors.add(:barcode, "Invalid fluidx barcode format #{record.barcode}") end protected diff --git a/lib/parsers/csv_layout/validators/location_validator.rb b/lib/parsers/csv_layout/validators/location_validator.rb index 35fbdff8..6cda66ea 100644 --- a/lib/parsers/csv_layout/validators/location_validator.rb +++ b/lib/parsers/csv_layout/validators/location_validator.rb @@ -1,11 +1,12 @@ +# frozen_string_literal: true + module Parsers module CsvLayout module Validators + # Validates a location is presentandin the expected format (eg. H12) class LocationValidator < ActiveModel::Validator def validate(record) - unless valid_location?(record) - record.errors.add(:location, "Invalid location") - end + record.errors.add(:location, 'Invalid location') unless valid_location?(record) end protected diff --git a/lib/parsers/csv_metadata/line_parser.rb b/lib/parsers/csv_metadata/line_parser.rb index bc1dedba..1ab2cbba 100644 --- a/lib/parsers/csv_metadata/line_parser.rb +++ b/lib/parsers/csv_metadata/line_parser.rb @@ -11,7 +11,6 @@ def initialize(input_reader, parser) @parsed_content = [] @parsed=false @input_reader = input_reader - valid? end def parsed_data @@ -38,7 +37,6 @@ def error_list def validate_parsed_content parse unless @parsed - errors.clear @parsed_content.each do |entry| unless entry[:data_parser].valid? errors.add(:base, "There is an error at line #{entry[:num_line]}") @@ -52,7 +50,7 @@ def parse if num_line == 1 @parser.headers_parser = @parser.components[:headers_parser].new(line, @parser) else - unless is_empty_line?(line) + unless empty_line?(line) data_parser = @parser.components[:data_parser].new(line, @parser) memo.push(num_line: num_line, data_parser: data_parser) end @@ -65,7 +63,7 @@ def parse parsed_data end - def is_empty_line?(line) + def empty_line?(line) (line.nil? || (line.length == 0) || line.all?(&:nil?)) end end diff --git a/lib/parsers/csv_metadata/validators/headers_validator.rb b/lib/parsers/csv_metadata/validators/headers_validator.rb index 21b67949..20a9992e 100644 --- a/lib/parsers/csv_metadata/validators/headers_validator.rb +++ b/lib/parsers/csv_metadata/validators/headers_validator.rb @@ -1,12 +1,13 @@ +# frozen_string_literal: true + module Parsers module CsvMetadata module Validators + # Validates that the headers aren't empty class HeadersValidator < ActiveModel::Validator def validate(record) record.headers.each_with_index do |header, index| - if header.empty? - record.errors.add(:header, "Header #{index} is empty") - end + record.errors.add(:header, "Header #{index} is empty") if header.empty? end end end From 3831e306b18c48d6074846669895e81d215eb99a Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 16 Mar 2022 13:14:07 +0000 Subject: [PATCH 110/303] Rubocop Layout Autofixes --- .rubocop.yml | 5 + .rubocop_todo.yml | 1060 ----------------- Gemfile | 9 +- app/channels/activity_channel.rb | 10 +- app/channels/application_cable/connection.rb | 2 +- app/controllers/activities_controller.rb | 97 +- app/controllers/activity_types_controller.rb | 17 +- app/controllers/application_controller.rb | 4 +- app/controllers/asset_groups_controller.rb | 56 +- app/controllers/assets_controller.rb | 26 +- app/controllers/changes_controller.rb | 7 +- app/controllers/instruments_controller.rb | 16 +- app/controllers/kit_types_controller.rb | 23 +- app/controllers/kits_controller.rb | 23 +- app/controllers/printers_controller.rb | 17 +- app/controllers/reracking_controller.rb | 3 - .../samples_not_started_controller.rb | 2 - app/controllers/samples_started_controller.rb | 2 - app/controllers/samples_status_controller.rb | 5 +- app/controllers/step_types_controller.rb | 33 +- app/controllers/steps_controller.rb | 63 +- app/controllers/uploaded_files_controller.rb | 3 +- app/controllers/user_sessions_controller.rb | 3 +- app/controllers/users_controller.rb | 17 +- app/helpers/activities_helper.rb | 50 +- app/helpers/application_helper.rb | 26 +- app/helpers/assets_helper.rb | 24 +- app/helpers/step_types_helper.rb | 17 +- app/models/action.rb | 19 +- app/models/activities/background_tasks.rb | 2 - app/models/activities/json_attributes.rb | 16 +- app/models/activities/state.rb | 1 - app/models/activities/steps_management.rb | 6 +- app/models/activities/tasks.rb | 2 - app/models/activities/websocket_events.rb | 5 +- app/models/activity.rb | 1 - app/models/activity_type.rb | 10 +- app/models/asset.rb | 71 +- app/models/asset_group.rb | 12 +- app/models/assets/export.rb | 10 +- app/models/assets/facts_management.rb | 6 +- app/models/assets/import.rb | 24 +- app/models/assets/traction_fields.rb | 6 +- app/models/concerns/deprecatable.rb | 4 +- app/models/concerns/uuidable.rb | 1 - app/models/condition.rb | 5 +- app/models/condition_group.rb | 3 +- app/models/fact.rb | 7 +- app/models/instrument.rb | 3 +- app/models/label_template.rb | 3 +- app/models/operation.rb | 11 +- app/models/printables/group.rb | 9 +- app/models/printables/instance.rb | 5 +- app/models/printables/print_asset.rb | 4 +- app/models/printer.rb | 2 +- app/models/step.rb | 15 +- app/models/step_type.rb | 42 +- .../steps/background_tasks/inference.rb | 2 - app/models/steps/background_tasks/runner.rb | 2 - app/models/steps/cancellable.rb | 4 +- app/models/steps/compatible.rb | 5 +- app/models/steps/deprecatable.rb | 6 +- app/models/steps/job.rb | 5 +- app/models/steps/queueable_job.rb | 2 - app/models/steps/retryable.rb | 1 - app/models/steps/state.rb | 15 +- app/models/steps/stoppable.rb | 1 - app/models/steps/task.rb | 1 + app/models/steps/websocket_events.rb | 5 +- app/models/uploaded_file.rb | 5 +- app/models/user.rb | 6 +- app/resources/api/v1/asset_resource.rb | 2 +- app/views/printers/_printer.json.jbuilder | 2 +- app/views/printers/index.json.jbuilder | 2 +- app/views/printers/show.json.jbuilder | 2 +- app/views/users/index.json.jbuilder | 2 +- app/views/users/show.json.jbuilder | 2 +- config/environments/development.rb | 6 +- config/environments/production.rb | 8 +- config/environments/test.rb | 6 +- config/initializers/inference_engine.rb | 1 + config/initializers/session_store.rb | 2 +- config/routes.rb | 12 +- .../20160626224627_create_condition_groups.rb | 1 - db/migrate/20160705084036_create_uploads.rb | 2 +- .../20170122173205_add_state_to_step.rb | 2 +- ...8170039_add_namespace_to_fact_predicate.rb | 2 +- ...70212120729_add_group_owned_to_activity.rb | 2 +- .../20170608101740_remove_unneeded_tables.rb | 1 + ...20170917175535_add_from_remote_to_facts.rb | 8 +- .../20171205163743_add_work_orders_table.rb | 2 +- db/migrate/20171210183629_add_sti_to_step.rb | 2 +- .../20180428131814_create_uploaded_files.rb | 6 +- ...190407165821_add_task_type_to_step_type.rb | 2 +- ...07165921_migrate_reasoning_to_task_type.rb | 2 +- db/migrate/20190717130805_change_sti_type.rb | 1 - ...0709123033_create_heron_activities_view.rb | 2 +- db/seeds.rb | 2 +- db/views_schema.rb | 6 +- lib/actions/plate_transfer.rb | 5 +- lib/actions/racking.rb | 33 +- lib/actions/tube_transfer.rb | 4 +- lib/changes_support/disjoint_list.rb | 22 +- lib/changes_support/transaction_scope.rb | 25 +- lib/fact_changes.rb | 78 +- lib/inference_engines/cwm/step_execution.rb | 17 +- .../default/step_execution.rb | 9 +- .../runner/step_execution.rb | 20 +- lib/label_template_setup.rb | 16 +- lib/label_templates/ss_plate.rb | 44 +- lib/label_templates/ss_tube.rb | 54 +- lib/label_types/plate.rb | 20 +- lib/label_types/tube.rb | 23 +- .../csv_layout/barcode_creatable_parser.rb | 2 +- lib/parsers/csv_layout/barcode_parser.rb | 1 - lib/parsers/csv_layout/csv_parser.rb | 13 +- lib/parsers/csv_layout/line_reader.rb | 4 +- lib/parsers/csv_layout/location_parser.rb | 1 - lib/parsers/csv_metadata/csv_parser.rb | 2 - lib/parsers/csv_metadata/headers_parser.rb | 2 +- lib/parsers/csv_metadata/line_parser.rb | 4 +- lib/sequencescape_client.rb | 16 +- lib/sequencescape_client_v2.rb | 1 - lib/step_execution_process.rb | 3 +- lib/support_n3.rb | 99 +- lib/tasks/setup_templates.rake | 2 - lib/token_util.rb | 25 +- script/aliquot_type_inference.rb | 7 +- script/claim_uuids.rb | 5 +- script/container_inferences.rb | 6 +- script/purpose_name_inference.rb | 3 +- script/recreate_steptypes.rb | 4 +- script/remove_duplicates.rb | 2 +- script/runners/create_12_tubes.rb | 7 +- script/runners/create_file.rb | 8 +- script/runners/create_layout.rb | 10 +- script/runners/create_stamped_plate.rb | 2 - script/runners/full_rack_generator.rb | 2 +- script/runners/load_metadata.rb | 6 +- .../move_barcodes_from_tube_rack_to_plate.rb | 15 +- script/runners/print_barcodes.rb | 1 - .../put_tubes_into_rack_by_column_order.rb | 2 - script/runners/rack_layout.rb | 3 +- script/runners/rack_layout_any_barcode.rb | 4 +- script/runners/transfer_plate_to_plate.rb | 5 +- script/runners/transfer_samples.rb | 1 - ...transfer_tubes_to_tube_rack_by_position.rb | 3 +- script/runners/update_sequencescape.rb | 1 - script/study_name_inference.rb | 2 +- .../tasks/runners/aliquot_type_inference.rb | 5 +- script/test2.rb | 2 - spec/concerns/deprecatable_spec.rb | 5 +- .../controllers/activities_controller_spec.rb | 9 +- .../activity_types_controller_spec.rb | 10 +- .../asset_groups_controller_spec.rb | 19 +- spec/controllers/assets_controller_spec.rb | 2 +- .../instruments_controller_spec.rb | 10 +- spec/controllers/kit_types_controller_spec.rb | 6 +- spec/controllers/kits_controller_spec.rb | 10 +- spec/controllers/printers_controller_spec.rb | 12 +- .../controllers/step_types_controller_spec.rb | 21 +- spec/controllers/steps_controller_spec.rb | 27 +- spec/inferences_helper.rb | 11 +- spec/integration/inference_spec.rb | 17 +- spec/integration/inferences_data.rb | 166 +-- spec/lib/actions/plate_transfer_spec.rb | 18 +- spec/lib/actions/racking_spec.rb | 29 +- spec/lib/actions/tube_transfer_spec.rb | 5 +- .../lib/changes_support/disjoint_list_spec.rb | 84 +- .../changes_support/transaction_scope_spec.rb | 4 +- spec/lib/fact_changes_spec.rb | 129 +- .../barcode_creatable_parser_spec.rb | 23 +- .../parsers/csv_layout/barcode_parser_spec.rb | 23 +- .../lib/parsers/csv_layout/csv_parser_spec.rb | 39 +- .../parsers/csv_layout/line_parser_spec.rb | 55 +- .../parsers/csv_layout/line_reader_spec.rb | 2 +- .../csv_layout/location_parser_spec.rb | 16 +- .../fluidx_barcode_validator_spec.rb | 2 - .../validators/location_validator_spec.rb | 2 - .../parsers/csv_metadata/csv_parser_spec.rb | 24 +- spec/lib/support_n3_spec.rb | 382 +++--- spec/models/action_spec.rb | 73 +- .../activities/background_tasks_spec.rb | 6 +- .../activities/steps_management_spec.rb | 34 +- spec/models/activity_type_spec.rb | 2 +- spec/models/asset_group_spec.rb | 1 - spec/models/asset_spec.rb | 6 +- spec/models/assets/export_spec.rb | 42 +- spec/models/assets/facts_management_spec.rb | 2 - spec/models/assets/import_spec.rb | 71 +- spec/models/assets/traction_fields_spec.rb | 1 - spec/models/condition_spec.rb | 33 +- spec/models/fact_spec.rb | 1 - spec/models/step_execution_spec.rb | 26 +- spec/models/step_spec.rb | 328 +++-- spec/models/step_type_spec.rb | 151 ++- .../steps/background_tasks/inference_spec.rb | 46 +- spec/models/steps/cancellable_spec.rb | 1 - spec/models/steps/queueable_job_spec.rb | 17 +- spec/models/steps/state_spec.rb | 5 +- spec/models/steps/stoppable_spec.rb | 1 - spec/models/steps/task_spec.rb | 20 +- spec/rails_helper.rb | 2 - spec/remote_assets_helper.rb | 184 +-- spec/requests/api/v1/assets_spec.rb | 7 +- spec/script/runners/load_metadata_spec.rb | 20 +- .../runners/transfer_plate_to_plate_spec.rb | 18 +- spec/script/runners/transfer_samples_spec.rb | 21 +- ...fer_tubes_to_tube_rack_by_position_spec.rb | 29 +- spec/shared_examples/background_step.rb | 2 - test/factories/barcode_creatable.rb | 2 +- test/factories/instruments.rb | 2 +- test/factories/kits.rb | 3 +- test/factories/steps.rb | 2 - test/factories/users.rb | 5 +- test/test_helper.rb | 2 +- 216 files changed, 1929 insertions(+), 3125 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 7c86f5b3..b177bde0 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -6,6 +6,11 @@ require: AllCops: NewCops: enable + inherit_mode: + merge: + - Exclude + Exclude: + - 'db/views_schema.rb' # Blocks are used to structure tests and are part of the shoulda dsl. # The standard BlockLength limits are too stringent for this purpose. diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 734faf9c..154de920 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -14,1066 +14,6 @@ Bundler/OrderedGems: Exclude: - 'Gemfile' -# Offense count: 29 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: with_first_argument, with_fixed_indentation -Layout/ArgumentAlignment: - Exclude: - - 'app/controllers/steps_controller.rb' - - 'app/models/condition.rb' - - 'app/resources/api/v1/asset_resource.rb' - - 'lib/actions/tube_transfer.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/runner/step_execution.rb' - - 'lib/support_n3.rb' - - 'spec/controllers/steps_controller_spec.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - - 'spec/models/assets/import_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/models/steps/task_spec.rb' - - 'spec/script/runners/load_metadata_spec.rb' - -# Offense count: 16 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: with_first_element, with_fixed_indentation -Layout/ArrayAlignment: - Exclude: - - 'app/models/assets/export.rb' - - 'lib/fact_changes.rb' - - 'lib/label_templates/ss_tube.rb' - - 'spec/inferences_helper.rb' - - 'spec/integration/inferences_data.rb' - - 'spec/lib/support_n3_spec.rb' - -# Offense count: 21 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyleAlignWith. -# SupportedStylesAlignWith: either, start_of_block, start_of_line -Layout/BlockAlignment: - Exclude: - - 'app/controllers/asset_groups_controller.rb' - - 'app/helpers/assets_helper.rb' - - 'app/models/asset.rb' - - 'script/aliquot_type_inference.rb' - - 'script/tasks/runners/aliquot_type_inference.rb' - - 'spec/controllers/activity_types_controller_spec.rb' - - 'spec/controllers/kits_controller_spec.rb' - - 'spec/controllers/printers_controller_spec.rb' - - 'spec/controllers/step_types_controller_spec.rb' - - 'spec/models/assets/import_spec.rb' - - 'spec/models/step_spec.rb' - -# Offense count: 30 -# Cop supports --auto-correct. -Layout/BlockEndNewline: - Exclude: - - 'spec/controllers/steps_controller_spec.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/lib/changes_support/disjoint_list_spec.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - - 'spec/models/action_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/script/runners/load_metadata_spec.rb' - - 'spec/script/runners/transfer_samples_spec.rb' - - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' - -# Offense count: 7 -# Cop supports --auto-correct. -Layout/ClosingParenthesisIndentation: - Exclude: - - 'app/models/activity_type.rb' - - 'app/models/asset.rb' - - 'db/migrate/20200709123033_create_heron_activities_view.rb' - - 'lib/actions/racking.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -Layout/CommentIndentation: - Exclude: - - 'app/controllers/assets_controller.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -Layout/ElseAlignment: - Exclude: - - 'spec/models/assets/import_spec.rb' - -# Offense count: 90 -# Cop supports --auto-correct. -Layout/EmptyLineAfterGuardClause: - Exclude: - - 'app/channels/activity_channel.rb' - - 'app/controllers/activities_controller.rb' - - 'app/helpers/activities_helper.rb' - - 'app/helpers/application_helper.rb' - - 'app/models/action.rb' - - 'app/models/activities/steps_management.rb' - - 'app/models/asset.rb' - - 'app/models/asset_group.rb' - - 'app/models/assets/import.rb' - - 'app/models/assets/traction_fields.rb' - - 'app/models/condition.rb' - - 'app/models/condition_group.rb' - - 'app/models/label_template.rb' - - 'app/models/printables/group.rb' - - 'app/models/printables/instance.rb' - - 'app/models/step_type.rb' - - 'app/models/steps/cancellable.rb' - - 'app/models/steps/compatible.rb' - - 'app/models/steps/deprecatable.rb' - - 'app/models/steps/job.rb' - - 'app/models/steps/state.rb' - - 'app/models/steps/task.rb' - - 'app/models/uploaded_file.rb' - - 'config/initializers/inference_engine.rb' - - 'lib/actions/plate_transfer.rb' - - 'lib/actions/racking.rb' - - 'lib/changes_support/disjoint_list.rb' - - 'lib/changes_support/transaction_scope.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'lib/inference_engines/runner/step_execution.rb' - - 'lib/label_template_setup.rb' - - 'lib/step_execution_process.rb' - - 'lib/token_util.rb' - - 'script/aliquot_type_inference.rb' - - 'script/container_inferences.rb' - - 'script/purpose_name_inference.rb' - - 'script/runners/create_12_tubes.rb' - - 'script/runners/load_metadata.rb' - - 'script/study_name_inference.rb' - - 'spec/inferences_helper.rb' - - 'spec/requests/api/v1/assets_spec.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -Layout/EmptyLineAfterMagicComment: - Exclude: - - 'db/migrate/20170608101740_remove_unneeded_tables.rb' - -# Offense count: 47 -# Cop supports --auto-correct. -# Configuration parameters: AllowAdjacentOneLineDefs, NumberOfEmptyLines. -Layout/EmptyLineBetweenDefs: - Exclude: - - 'app/controllers/activities_controller.rb' - - 'app/controllers/asset_groups_controller.rb' - - 'app/controllers/assets_controller.rb' - - 'app/controllers/reracking_controller.rb' - - 'app/controllers/step_types_controller.rb' - - 'app/helpers/activities_helper.rb' - - 'app/models/activity_type.rb' - - 'app/models/asset.rb' - - 'app/models/assets/facts_management.rb' - - 'app/models/assets/import.rb' - - 'app/models/step_type.rb' - - 'app/models/steps/cancellable.rb' - - 'lib/actions/plate_transfer.rb' - - 'lib/actions/racking.rb' - - 'lib/changes_support/disjoint_list.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'lib/inference_engines/default/step_execution.rb' - - 'lib/inference_engines/runner/step_execution.rb' - - 'lib/support_n3.rb' - - 'script/aliquot_type_inference.rb' - - 'script/container_inferences.rb' - - 'script/runners/load_metadata.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - - 'script/runners/rack_layout.rb' - - 'script/runners/rack_layout_any_barcode.rb' - - 'script/runners/rack_layout_creating_tubes.rb' - - 'script/tasks/runners/aliquot_type_inference.rb' - - 'spec/models/activities/background_tasks_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/script/runners/transfer_plate_to_plate_spec.rb' - -# Offense count: 114 -# Cop supports --auto-correct. -Layout/EmptyLines: - Exclude: - - 'Gemfile' - - 'app/controllers/activities_controller.rb' - - 'app/controllers/asset_groups_controller.rb' - - 'app/controllers/assets_controller.rb' - - 'app/controllers/reracking_controller.rb' - - 'app/controllers/step_types_controller.rb' - - 'app/controllers/uploaded_files_controller.rb' - - 'app/controllers/user_sessions_controller.rb' - - 'app/helpers/activities_helper.rb' - - 'app/models/action.rb' - - 'app/models/activity.rb' - - 'app/models/activity_type.rb' - - 'app/models/asset.rb' - - 'app/models/assets/facts_management.rb' - - 'app/models/assets/import.rb' - - 'app/models/step.rb' - - 'app/models/step_type.rb' - - 'app/models/steps/cancellable.rb' - - 'app/models/steps/state.rb' - - 'app/models/user.rb' - - 'config/environments/production.rb' - - 'config/environments/test.rb' - - 'config/routes.rb' - - 'lib/actions/plate_transfer.rb' - - 'lib/actions/racking.rb' - - 'lib/changes_support/disjoint_list.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'lib/inference_engines/default/step_execution.rb' - - 'lib/inference_engines/runner/step_execution.rb' - - 'lib/label_template_setup.rb' - - 'lib/label_templates/ss_tube.rb' - - 'lib/parsers/csv_metadata/csv_parser.rb' - - 'lib/support_n3.rb' - - 'script/container_inferences.rb' - - 'script/runners/load_metadata.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - - 'script/runners/put_tubes_into_rack_by_column_order.rb' - - 'script/runners/rack_layout.rb' - - 'script/runners/rack_layout_any_barcode.rb' - - 'script/runners/rack_layout_creating_tubes.rb' - - 'script/runners/transfer_plate_to_plate.rb' - - 'spec/controllers/asset_groups_controller_spec.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/lib/changes_support/disjoint_list_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/validators/location_validator_spec.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/models/steps/queueable_job_spec.rb' - - 'spec/models/steps/state_spec.rb' - - 'spec/models/steps/stoppable_spec.rb' - - 'spec/rails_helper.rb' - - 'spec/script/runners/transfer_plate_to_plate_spec.rb' - - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' - - 'test/factories/steps.rb' - -# Offense count: 8 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: around, only_before -Layout/EmptyLinesAroundAccessModifier: - Exclude: - - 'app/controllers/activity_types_controller.rb' - - 'app/controllers/instruments_controller.rb' - - 'app/controllers/kit_types_controller.rb' - - 'app/controllers/kits_controller.rb' - - 'app/controllers/printers_controller.rb' - - 'app/controllers/step_types_controller.rb' - - 'app/controllers/users_controller.rb' - - 'lib/parsers/csv_layout/barcode_parser.rb' - -# Offense count: 99 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: empty_lines, no_empty_lines -Layout/EmptyLinesAroundBlockBody: - Exclude: - - 'app/controllers/assets_controller.rb' - - 'app/models/assets/facts_management.rb' - - 'config/environments/development.rb' - - 'config/environments/production.rb' - - 'config/routes.rb' - - 'db/migrate/20190717130805_change_sti_type.rb' - - 'spec/controllers/activities_controller_spec.rb' - - 'spec/controllers/asset_groups_controller_spec.rb' - - 'spec/controllers/step_types_controller_spec.rb' - - 'spec/controllers/steps_controller_spec.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/lib/actions/tube_transfer_spec.rb' - - 'spec/lib/changes_support/disjoint_list_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb' - - 'spec/lib/parsers/csv_layout/validators/location_validator_spec.rb' - - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/action_spec.rb' - - 'spec/models/activities/background_tasks_spec.rb' - - 'spec/models/assets/facts_management_spec.rb' - - 'spec/models/assets/traction_fields_spec.rb' - - 'spec/models/condition_spec.rb' - - 'spec/models/fact_spec.rb' - - 'spec/models/step_execution_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/models/steps/cancellable_spec.rb' - - 'spec/models/steps/queueable_job_spec.rb' - - 'spec/models/steps/state_spec.rb' - - 'spec/models/steps/task_spec.rb' - - 'spec/rails_helper.rb' - - 'spec/requests/api/v1/assets_spec.rb' - - 'spec/script/runners/transfer_plate_to_plate_spec.rb' - - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' - - 'spec/shared_examples/background_step.rb' - - 'test/factories/activity_types.rb' - - 'test/factories/condition_groups.rb' - - 'test/factories/conditions.rb' - - 'test/factories/kits.rb' - - 'test/factories/steps.rb' - - 'test/factories/users.rb' - -# Offense count: 54 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only -Layout/EmptyLinesAroundClassBody: - Exclude: - - 'app/channels/activity_channel.rb' - - 'app/controllers/activities_controller.rb' - - 'app/controllers/application_controller.rb' - - 'app/controllers/asset_groups_controller.rb' - - 'app/controllers/assets_controller.rb' - - 'app/controllers/changes_controller.rb' - - 'app/controllers/instruments_controller.rb' - - 'app/controllers/reracking_controller.rb' - - 'app/controllers/samples_not_started_controller.rb' - - 'app/controllers/samples_started_controller.rb' - - 'app/controllers/samples_status_controller.rb' - - 'app/controllers/step_types_controller.rb' - - 'app/controllers/steps_controller.rb' - - 'app/models/action.rb' - - 'app/models/activities/background_tasks.rb' - - 'app/models/activity.rb' - - 'app/models/asset_group.rb' - - 'app/models/fact.rb' - - 'app/models/operation.rb' - - 'app/models/step.rb' - - 'app/models/step_type.rb' - - 'app/models/steps/background_tasks/inference.rb' - - 'app/models/steps/background_tasks/runner.rb' - - 'app/models/user.rb' - - 'lib/actions/racking.rb' - - 'lib/changes_support/disjoint_list.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/default/step_execution.rb' - - 'lib/label_template_setup.rb' - - 'lib/parsers/csv_layout/barcode_parser.rb' - - 'lib/parsers/csv_layout/csv_parser.rb' - - 'lib/parsers/csv_layout/line_reader.rb' - - 'lib/parsers/csv_layout/location_parser.rb' - - 'lib/parsers/csv_metadata/csv_parser.rb' - - 'script/container_inferences.rb' - - 'script/purpose_name_inference.rb' - - 'script/runners/create_stamped_plate.rb' - - 'script/runners/print_barcodes.rb' - - 'script/runners/transfer_plate_to_plate.rb' - - 'script/runners/transfer_samples.rb' - - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - - 'script/study_name_inference.rb' - -# Offense count: 2 -# Cop supports --auto-correct. -Layout/EmptyLinesAroundExceptionHandlingKeywords: - Exclude: - - 'script/runners/rack_layout_any_barcode.rb' - - 'script/runners/rack_layout_creating_tubes.rb' - -# Offense count: 6 -# Cop supports --auto-correct. -Layout/EmptyLinesAroundMethodBody: - Exclude: - - 'app/controllers/activities_controller.rb' - - 'app/controllers/assets_controller.rb' - - 'lib/actions/racking.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'script/runners/transfer_plate_to_plate.rb' - -# Offense count: 40 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines -Layout/EmptyLinesAroundModuleBody: - Exclude: - - 'app/helpers/activities_helper.rb' - - 'app/helpers/application_helper.rb' - - 'app/helpers/step_types_helper.rb' - - 'app/models/activities/background_tasks.rb' - - 'app/models/activities/state.rb' - - 'app/models/activities/tasks.rb' - - 'app/models/activities/websocket_events.rb' - - 'app/models/assets/facts_management.rb' - - 'app/models/assets/import.rb' - - 'app/models/assets/traction_fields.rb' - - 'app/models/concerns/uuidable.rb' - - 'app/models/steps/cancellable.rb' - - 'app/models/steps/compatible.rb' - - 'app/models/steps/deprecatable.rb' - - 'app/models/steps/job.rb' - - 'app/models/steps/queueable_job.rb' - - 'app/models/steps/retryable.rb' - - 'app/models/steps/state.rb' - - 'app/models/steps/stoppable.rb' - - 'app/models/steps/websocket_events.rb' - - 'lib/actions/racking.rb' - - 'lib/changes_support/transaction_scope.rb' - - 'lib/label_template_setup.rb' - - 'lib/sequencescape_client_v2.rb' - - 'lib/step_execution_process.rb' - - 'lib/support_n3.rb' - - 'lib/token_util.rb' - - 'script/claim_uuids.rb' - - 'spec/inferences_helper.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyleAlignWith, Severity. -# SupportedStylesAlignWith: keyword, variable, start_of_line -Layout/EndAlignment: - Exclude: - - 'spec/models/assets/import_spec.rb' - -# Offense count: 43 -# Cop supports --auto-correct. -# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. -Layout/ExtraSpacing: - Exclude: - - 'app/helpers/application_helper.rb' - - 'app/models/asset.rb' - - 'app/models/fact.rb' - - 'app/models/step.rb' - - 'app/models/step_type.rb' - - 'app/models/steps/state.rb' - - 'app/models/user.rb' - - 'config/environments/development.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - - 'spec/controllers/activities_controller_spec.rb' - - 'spec/controllers/activity_types_controller_spec.rb' - - 'spec/controllers/instruments_controller_spec.rb' - - 'spec/controllers/kit_types_controller_spec.rb' - - 'spec/controllers/kits_controller_spec.rb' - - 'spec/controllers/printers_controller_spec.rb' - - 'spec/controllers/step_types_controller_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/models/action_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/steps/state_spec.rb' - - 'test/factories/instruments.rb' - - 'test/factories/kits.rb' - - 'test/factories/users.rb' - -# Offense count: 3 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: consistent, consistent_relative_to_receiver, special_for_inner_method_call, special_for_inner_method_call_in_parentheses -Layout/FirstArgumentIndentation: - Exclude: - - 'app/models/printables/group.rb' - - 'db/views_schema.rb' - - 'lib/actions/racking.rb' - -# Offense count: 63 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: special_inside_parentheses, consistent, align_brackets -Layout/FirstArrayElementIndentation: - Exclude: - - 'lib/label_templates/ss_tube.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/lib/changes_support/transaction_scope_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/action_spec.rb' - - 'spec/models/activities/steps_management_spec.rb' - - 'spec/models/assets/export_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/script/runners/transfer_plate_to_plate_spec.rb' - - 'spec/script/runners/transfer_samples_spec.rb' - - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' - -# Offense count: 134 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: special_inside_parentheses, consistent, align_braces -Layout/FirstHashElementIndentation: - Exclude: - - 'app/controllers/steps_controller.rb' - - 'app/helpers/activities_helper.rb' - - 'app/helpers/application_helper.rb' - - 'app/helpers/step_types_helper.rb' - - 'app/models/activities/json_attributes.rb' - - 'app/models/activities/tasks.rb' - - 'app/models/activity_type.rb' - - 'app/models/asset.rb' - - 'lib/actions/racking.rb' - - 'lib/label_types/plate.rb' - - 'lib/label_types/tube.rb' - - 'lib/parsers/csv_layout/csv_parser.rb' - - 'lib/parsers/csv_layout/line_parser.rb' - - 'lib/support_n3.rb' - - 'spec/controllers/asset_groups_controller_spec.rb' - - 'spec/controllers/steps_controller_spec.rb' - - 'spec/integration/inferences_data.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' - - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/activities/steps_management_spec.rb' - - 'spec/models/assets/export_spec.rb' - - 'spec/models/condition_spec.rb' - - 'spec/models/step_execution_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/models/steps/queueable_job_spec.rb' - - 'spec/remote_assets_helper.rb' - -# Offense count: 195 -# Cop supports --auto-correct. -# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. -# SupportedHashRocketStyles: key, separator, table -# SupportedColonStyles: key, separator, table -# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit -Layout/HashAlignment: - Exclude: - - 'app/helpers/step_types_helper.rb' - - 'app/models/activities/json_attributes.rb' - - 'app/models/activity_type.rb' - - 'app/models/asset.rb' - - 'app/models/asset_group.rb' - - 'app/models/printables/group.rb' - - 'app/models/printables/instance.rb' - - 'app/models/steps/state.rb' - - 'lib/fact_changes.rb' - - 'lib/label_templates/ss_plate.rb' - - 'lib/label_templates/ss_tube.rb' - - 'lib/label_types/tube.rb' - - 'lib/sequencescape_client.rb' - - 'lib/support_n3.rb' - - 'script/plate_to_code39.rb' - - 'script/runners/load_metadata.rb' - - 'spec/controllers/asset_groups_controller_spec.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/action_spec.rb' - - 'spec/models/activities/steps_management_spec.rb' - - 'spec/models/asset_spec.rb' - - 'spec/models/condition_spec.rb' - - 'spec/models/step_execution_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/steps/task_spec.rb' - -# Offense count: 61 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: normal, indented_internal_methods -Layout/IndentationConsistency: - Exclude: - - 'app/controllers/activities_controller.rb' - - 'app/controllers/activity_types_controller.rb' - - 'app/controllers/asset_groups_controller.rb' - - 'app/controllers/assets_controller.rb' - - 'app/controllers/changes_controller.rb' - - 'app/controllers/instruments_controller.rb' - - 'app/controllers/kit_types_controller.rb' - - 'app/controllers/kits_controller.rb' - - 'app/controllers/printers_controller.rb' - - 'app/controllers/step_types_controller.rb' - - 'app/controllers/steps_controller.rb' - - 'app/controllers/users_controller.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/assets/import_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/models/steps/background_tasks/inference_spec.rb' - -# Offense count: 124 -# Cop supports --auto-correct. -# Configuration parameters: IndentationWidth, EnforcedStyle. -# SupportedStyles: spaces, tabs -Layout/IndentationStyle: - Exclude: - - 'app/models/condition.rb' - - 'db/migrate/20170917175535_add_from_remote_to_facts.rb' - - 'db/migrate/20171210183629_add_sti_to_step.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - - 'spec/models/assets/import_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/models/steps/background_tasks/inference_spec.rb' - - 'spec/remote_assets_helper.rb' - -# Offense count: 93 -# Cop supports --auto-correct. -# Configuration parameters: Width, IgnoredPatterns. -Layout/IndentationWidth: - Exclude: - - 'app/controllers/activities_controller.rb' - - 'app/controllers/activity_types_controller.rb' - - 'app/controllers/asset_groups_controller.rb' - - 'app/controllers/assets_controller.rb' - - 'app/controllers/changes_controller.rb' - - 'app/controllers/instruments_controller.rb' - - 'app/controllers/kit_types_controller.rb' - - 'app/controllers/kits_controller.rb' - - 'app/controllers/printers_controller.rb' - - 'app/controllers/step_types_controller.rb' - - 'app/controllers/steps_controller.rb' - - 'app/controllers/users_controller.rb' - - 'app/helpers/activities_helper.rb' - - 'app/models/asset.rb' - - 'app/models/step.rb' - - 'db/migrate/20170917175535_add_from_remote_to_facts.rb' - - 'db/migrate/20171210183629_add_sti_to_step.rb' - - 'spec/controllers/activity_types_controller_spec.rb' - - 'spec/controllers/kits_controller_spec.rb' - - 'spec/controllers/printers_controller_spec.rb' - - 'spec/controllers/step_types_controller_spec.rb' - - 'spec/integration/inferences_data.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/models/assets/import_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/steps/background_tasks/inference_spec.rb' - - 'spec/remote_assets_helper.rb' - -# Offense count: 91 -# Cop supports --auto-correct. -# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment. -Layout/LeadingCommentSpace: - Exclude: - - 'Gemfile' - - 'app/channels/activity_channel.rb' - - 'app/channels/application_cable/connection.rb' - - 'app/controllers/activities_controller.rb' - - 'app/controllers/asset_groups_controller.rb' - - 'app/controllers/assets_controller.rb' - - 'app/models/action.rb' - - 'app/models/activities/websocket_events.rb' - - 'app/models/activity.rb' - - 'app/models/asset.rb' - - 'app/models/asset_group.rb' - - 'app/models/assets/import.rb' - - 'app/models/operation.rb' - - 'app/models/step.rb' - - 'app/models/step_type.rb' - - 'app/models/steps/state.rb' - - 'app/models/steps/websocket_events.rb' - - 'config/application.rb' - - 'config/environments/test.rb' - - 'config/initializers/session_store.rb' - - 'config/routes.rb' - - 'db/migrate/20180428131814_create_uploaded_files.rb' - - 'db/migrate/20190407165921_migrate_reasoning_to_task_type.rb' - - 'db/seeds.rb' - - 'lib/actions/racking.rb' - - 'lib/changes_support/disjoint_list.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/runner/step_execution.rb' - - 'lib/sequencescape_client.rb' - - 'lib/support_n3.rb' - - 'script/remove_duplicates.rb' - - 'script/runners/transfer_plate_to_plate.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/models/condition_spec.rb' - - 'spec/models/step_execution_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/steps/queueable_job_spec.rb' - - 'spec/models/steps/task_spec.rb' - - 'spec/remote_assets_helper.rb' - - 'test/test_helper.rb' - -# Offense count: 6 -# Cop supports --auto-correct. -Layout/LeadingEmptyLines: - Exclude: - - 'app/models/asset_group.rb' - - 'app/models/step.rb' - - 'config/routes.rb' - - 'lib/tasks/setup_templates.rake' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - - 'script/test2.rb' - -# Offense count: 16 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: symmetrical, new_line, same_line -Layout/MultilineArrayBraceLayout: - Exclude: - - 'app/models/instrument.rb' - - 'app/models/step_type.rb' - - 'lib/label_templates/ss_tube.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/assets/export_spec.rb' - -# Offense count: 31 -# Cop supports --auto-correct. -Layout/MultilineBlockLayout: - Exclude: - - 'spec/controllers/steps_controller_spec.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/lib/changes_support/disjoint_list_spec.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - - 'spec/models/action_spec.rb' - - 'spec/models/activities/steps_management_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/script/runners/load_metadata_spec.rb' - - 'spec/script/runners/transfer_samples_spec.rb' - - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' - -# Offense count: 31 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: symmetrical, new_line, same_line -Layout/MultilineHashBraceLayout: - Exclude: - - 'app/helpers/application_helper.rb' - - 'app/models/activities/tasks.rb' - - 'app/models/activity_type.rb' - - 'app/models/asset.rb' - - 'lib/label_templates/ss_plate.rb' - - 'lib/support_n3.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/condition_spec.rb' - - 'spec/models/step_execution_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - -# Offense count: 6 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: symmetrical, new_line, same_line -Layout/MultilineMethodCallBraceLayout: - Exclude: - - 'app/models/asset.rb' - - 'lib/support_n3.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/models/assets/import_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/steps/task_spec.rb' - -# Offense count: 26 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: aligned, indented, indented_relative_to_receiver -Layout/MultilineMethodCallIndentation: - Exclude: - - 'spec/lib/changes_support/disjoint_list_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - -# Offense count: 7 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: aligned, indented -Layout/MultilineOperationIndentation: - Exclude: - - 'app/models/assets/export.rb' - - 'app/models/step_type.rb' - -# Offense count: 129 -# Cop supports --auto-correct. -Layout/SpaceAfterColon: - Exclude: - - 'app/channels/activity_channel.rb' - - 'app/models/assets/export.rb' - - 'app/models/printables/group.rb' - - 'app/models/printables/instance.rb' - - 'lib/fact_changes.rb' - - 'lib/label_template_setup.rb' - - 'lib/label_templates/ss_plate.rb' - - 'lib/label_templates/ss_tube.rb' - - 'lib/label_types/tube.rb' - - 'spec/controllers/kits_controller_spec.rb' - - 'spec/controllers/step_types_controller_spec.rb' - - 'test/factories/barcode_creatable.rb' - -# Offense count: 316 -# Cop supports --auto-correct. -Layout/SpaceAfterComma: - Exclude: - - 'app/controllers/activities_controller.rb' - - 'app/controllers/samples_status_controller.rb' - - 'app/controllers/step_types_controller.rb' - - 'app/controllers/uploaded_files_controller.rb' - - 'app/models/action.rb' - - 'app/models/activities/steps_management.rb' - - 'app/models/asset.rb' - - 'app/models/asset_group.rb' - - 'app/models/assets/import.rb' - - 'app/models/condition_group.rb' - - 'app/models/label_template.rb' - - 'app/models/printer.rb' - - 'app/models/step_type.rb' - - 'app/models/steps/state.rb' - - 'config/environments/development.rb' - - 'config/environments/production.rb' - - 'config/environments/test.rb' - - 'lib/actions/racking.rb' - - 'lib/changes_support/transaction_scope.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'lib/inference_engines/default/step_execution.rb' - - 'lib/label_template_setup.rb' - - 'lib/label_templates/ss_plate.rb' - - 'lib/label_templates/ss_tube.rb' - - 'lib/label_types/tube.rb' - - 'lib/support_n3.rb' - - 'lib/token_util.rb' - - 'script/runners/create_12_tubes.rb' - - 'script/runners/load_metadata.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/lib/actions/plate_transfer_spec.rb' - - 'spec/lib/changes_support/disjoint_list_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/line_reader_spec.rb' - - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/action_spec.rb' - - 'spec/models/activities/steps_management_spec.rb' - - 'spec/models/assets/import_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/script/runners/transfer_plate_to_plate_spec.rb' - - 'spec/script/runners/transfer_samples_spec.rb' - - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' - - 'test/factories/barcode_creatable.rb' - -# Offense count: 311 -# Cop supports --auto-correct. -# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator. -# SupportedStylesForExponentOperator: space, no_space -Layout/SpaceAroundOperators: - Exclude: - - 'app/channels/activity_channel.rb' - - 'app/controllers/activities_controller.rb' - - 'app/controllers/application_controller.rb' - - 'app/controllers/assets_controller.rb' - - 'app/controllers/samples_status_controller.rb' - - 'app/controllers/user_sessions_controller.rb' - - 'app/helpers/activities_helper.rb' - - 'app/helpers/application_helper.rb' - - 'app/helpers/assets_helper.rb' - - 'app/helpers/step_types_helper.rb' - - 'app/models/action.rb' - - 'app/models/asset.rb' - - 'app/models/asset_group.rb' - - 'app/models/assets/export.rb' - - 'app/models/assets/facts_management.rb' - - 'app/models/assets/import.rb' - - 'app/models/assets/traction_fields.rb' - - 'app/models/condition.rb' - - 'app/models/fact.rb' - - 'app/models/step_type.rb' - - 'app/models/steps/compatible.rb' - - 'app/models/steps/deprecatable.rb' - - 'app/models/steps/job.rb' - - 'app/models/uploaded_file.rb' - - 'config/environments/development.rb' - - 'config/environments/production.rb' - - 'lib/actions/plate_transfer.rb' - - 'lib/actions/racking.rb' - - 'lib/changes_support/disjoint_list.rb' - - 'lib/changes_support/transaction_scope.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'lib/inference_engines/default/step_execution.rb' - - 'lib/inference_engines/runner/step_execution.rb' - - 'lib/label_template_setup.rb' - - 'lib/parsers/csv_layout/line_parser.rb' - - 'lib/parsers/csv_layout/line_reader.rb' - - 'lib/parsers/csv_metadata/headers_parser.rb' - - 'lib/parsers/csv_metadata/line_parser.rb' - - 'lib/sequencescape_client.rb' - - 'lib/support_n3.rb' - - 'lib/token_util.rb' - - 'script/claim_uuids.rb' - - 'script/recreate_steptypes.rb' - - 'script/runners/create_12_tubes.rb' - - 'script/runners/create_file.rb' - - 'script/runners/create_layout.rb' - - 'script/runners/full_rack_generator.rb' - - 'script/runners/load_metadata.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - - 'script/runners/rack_layout.rb' - - 'script/runners/rack_layout_any_barcode.rb' - - 'script/runners/rack_layout_creating_tubes.rb' - - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - - 'spec/concerns/deprecatable_spec.rb' - - 'spec/controllers/assets_controller_spec.rb' - - 'spec/inferences_helper.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/lib/actions/plate_transfer_spec.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/lib/actions/tube_transfer_spec.rb' - - 'spec/lib/changes_support/disjoint_list_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/action_spec.rb' - - 'spec/models/activities/background_tasks_spec.rb' - - 'spec/models/assets/export_spec.rb' - - 'spec/models/assets/import_spec.rb' - - 'spec/models/condition_spec.rb' - - 'spec/models/step_execution_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/remote_assets_helper.rb' - - 'spec/script/runners/load_metadata_spec.rb' - - 'spec/script/runners/transfer_plate_to_plate_spec.rb' - - 'spec/script/runners/transfer_samples_spec.rb' - - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' - -# Offense count: 5 -# Cop supports --auto-correct. -Layout/SpaceBeforeComma: - Exclude: - - 'db/migrate/20160705084036_create_uploads.rb' - - 'db/migrate/20180428131814_create_uploaded_files.rb' - - 'lib/parsers/csv_layout/barcode_creatable_parser.rb' - - 'spec/models/step_type_spec.rb' - -# Offense count: 6 -# Cop supports --auto-correct. -Layout/SpaceBeforeComment: - Exclude: - - 'Gemfile' - - 'app/models/step_type.rb' - -# Offense count: 2 -# Cop supports --auto-correct. -Layout/SpaceBeforeSemicolon: - Exclude: - - 'app/models/assets/export.rb' - - 'app/models/assets/import.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: require_no_space, require_space -Layout/SpaceInLambdaLiteral: - Exclude: - - 'app/models/fact.rb' - -# Offense count: 9 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. -# SupportedStyles: space, no_space, compact -# SupportedStylesForEmptyBrackets: space, no_space -Layout/SpaceInsideArrayLiteralBrackets: - Exclude: - - 'lib/inference_engines/cwm/step_execution.rb' - - 'script/runners/create_layout.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/models/steps/task_spec.rb' - -# Offense count: 6 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: space, no_space -Layout/SpaceInsideParens: - Exclude: - - 'app/models/concerns/deprecatable.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/script/runners/load_metadata_spec.rb' - -# Offense count: 4 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: space, no_space -Layout/SpaceInsideStringInterpolation: - Exclude: - - 'app/helpers/activities_helper.rb' - -# Offense count: 35 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: final_newline, final_blank_line -Layout/TrailingEmptyLines: - Exclude: - - 'app/models/activities/steps_management.rb' - - 'app/models/fact.rb' - - 'app/models/printables/print_asset.rb' - - 'app/views/printers/_printer.json.jbuilder' - - 'app/views/printers/index.json.jbuilder' - - 'app/views/printers/show.json.jbuilder' - - 'app/views/users/index.json.jbuilder' - - 'app/views/users/show.json.jbuilder' - - 'db/migrate/20160626224627_create_condition_groups.rb' - - 'lib/label_templates/ss_plate.rb' - - 'lib/label_templates/ss_tube.rb' - - 'lib/label_types/tube.rb' - - 'lib/sequencescape_client.rb' - - 'lib/step_execution_process.rb' - - 'lib/tasks/setup_templates.rake' - - 'script/aliquot_type_inference.rb' - - 'script/claim_uuids.rb' - - 'script/container_inferences.rb' - - 'script/purpose_name_inference.rb' - - 'script/runners/create_stamped_plate.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - - 'script/runners/transfer_plate_to_plate.rb' - - 'script/runners/update_sequencescape.rb' - - 'script/study_name_inference.rb' - - 'spec/concerns/deprecatable_spec.rb' - - 'spec/controllers/step_types_controller_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb' - - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - - 'spec/models/activity_type_spec.rb' - - 'spec/models/asset_group_spec.rb' - - 'spec/models/condition_spec.rb' - - 'spec/models/steps/state_spec.rb' - - 'spec/script/runners/transfer_samples_spec.rb' - -# Offense count: 42 -# Cop supports --auto-correct. -# Configuration parameters: AllowInHeredoc. -Layout/TrailingWhitespace: - Exclude: - - 'app/helpers/assets_helper.rb' - - 'app/models/activities/steps_management.rb' - - 'app/models/condition.rb' - - 'app/models/printables/print_asset.rb' - - 'db/migrate/20170122173205_add_state_to_step.rb' - - 'db/migrate/20170128170039_add_namespace_to_fact_predicate.rb' - - 'db/migrate/20170212120729_add_group_owned_to_activity.rb' - - 'db/migrate/20171205163743_add_work_orders_table.rb' - - 'db/migrate/20180428131814_create_uploaded_files.rb' - - 'db/migrate/20190407165821_add_task_type_to_step_type.rb' - - 'lib/label_templates/ss_plate.rb' - - 'lib/label_templates/ss_tube.rb' - - 'spec/concerns/deprecatable_spec.rb' - - 'spec/controllers/kit_types_controller_spec.rb' - - 'spec/models/action_spec.rb' - - 'spec/models/condition_spec.rb' - - 'test/factories/actions.rb' - - 'test/factories/activity_type_step_types.rb' - - 'test/factories/asset_groups.rb' - - 'test/factories/kit_types.rb' - - 'test/factories/label_templates.rb' - - 'test/factories/operations.rb' - - 'test/factories/printers.rb' - - 'test/factories/step_executions.rb' - - 'test/factories/step_types.rb' - # Offense count: 9 Lint/AmbiguousBlockAssociation: Exclude: diff --git a/Gemfile b/Gemfile index 3a651226..f55424d5 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,5 @@ source 'http://rubygems.org' - # Service libraries gem 'sanger_warren' # Wraps bunny and manages connection pools and configuration gem 'puma' @@ -32,7 +31,6 @@ gem 'bootstrap-sass' gem 'will_paginate' gem 'will_paginate-bootstrap' - # Javascript UI gem 'ejs' gem 'dropzonejs-rails' @@ -61,8 +59,7 @@ gem 'sequencescape-client-api', require: 'sequencescape' gem 'rb-readline' # Docs -gem 'sdoc'#, '~> 0.4.0', group: :doc - +gem 'sdoc' # , '~> 0.4.0', group: :doc group :development, :test do # Call 'pry' anywhere in the code to stop execution and get a debugger console @@ -82,10 +79,9 @@ group :test do gem 'rack_session_access' end - group :development do # Access an IRB console on exception pages or by using <%= console %> in views - gem 'web-console'#, '~> 2.0' + gem 'web-console' # , '~> 2.0' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' @@ -95,7 +91,6 @@ group :development do gem 'rubocop-rails' end - group :deployment do gem 'exception_notification' gem 'gmetric', '~>0.1.3' diff --git a/app/channels/activity_channel.rb b/app/channels/activity_channel.rb index 73bf1e59..dca9bb58 100644 --- a/app/channels/activity_channel.rb +++ b/app/channels/activity_channel.rb @@ -1,5 +1,4 @@ class ActivityChannel < ApplicationCable::Channel - def self.connection_for_redis ActionCable.server.pubsub.redis_connection_for_subscriptions end @@ -19,6 +18,7 @@ def redis def self.subscribed_ids value = connection_for_redis.get('SUBSCRIBED_IDS') return [] unless value + JSON.parse(value) end @@ -40,8 +40,8 @@ def process_asset_group(strong_params) asset_group.update_with_assets(received_list) - #asset_group.update_attributes(assets: received_list) - #asset_group.touch + # asset_group.update_attributes(assets: received_list) + # asset_group.touch rescue Errno::ECONNREFUSED => e asset_group.activity.send_wss_event({ error: { type: 'danger', msg: 'Cannot connect with sequencescape' } }) rescue StandardError => e @@ -66,7 +66,7 @@ def process_activity(strong_params) end def self.default_activity_attributes - { stepTypes: true, stepsPending: true, stepsRunning:true, stepsFailed: true, stepsFinished: false }.as_json + { stepTypes: true, stepsPending: true, stepsRunning: true, stepsFailed: true, stepsFinished: false }.as_json end def self.activity_attributes(id) @@ -104,7 +104,7 @@ def subscribed def unsubscribed previous_value = subscribed_ids - connection_for_redis.set('SUBSCRIBED_IDS', previous_value.reject { |v| v== stream_id }) + connection_for_redis.set('SUBSCRIBED_IDS', previous_value.reject { |v| v == stream_id }) stop_all_streams end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index e1d53985..5b3255c3 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -3,7 +3,7 @@ class Connection < ActionCable::Connection::Base identified_by :current_user def connect - #self.current_user = nil + # self.current_user = nil token = cookies.encrypted['_samples_extraction_session']['token'] if token self.current_user = User.find_by(:token => token) diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb index 48f49893..87b7ebb5 100644 --- a/app/controllers/activities_controller.rb +++ b/app/controllers/activities_controller.rb @@ -7,14 +7,14 @@ class ActivitiesController < ApplicationController before_action :set_activity_type, only: [:create] before_action :set_user, only: [:update] - #before_action :session_authenticate, only: [:update, :create] + # before_action :session_authenticate, only: [:update, :create] def session_authenticate raise ActionController::InvalidAuthenticityToken unless session[:session_id] end def update - @activity.finish if activity_params[:state]=='finish' + @activity.finish if activity_params[:state] == 'finish' respond_to do |format| format.html { render :show } @@ -22,9 +22,7 @@ def update end end - def show - respond_to do |format| format.html { render :show } format.json { render :show, status: :created, location: @activity } @@ -36,7 +34,7 @@ def index end def create - @activity = @activity_type.create_activity(instrument: @instrument,kit: @kit) + @activity = @activity_type.create_activity(instrument: @instrument, kit: @kit) respond_to do |format| if @activity.save @@ -51,58 +49,57 @@ def create private - def set_user - @user = @current_user - if @user.nil? - flash[:danger] = 'User not found' - redirect_to :back - end - end - - def set_kit - return true if activity_params[:activity_type_id] - @kit = Kit.find_by_barcode!(activity_params[:kit_barcode]) - rescue ActiveRecord::RecordNotFound => e - flash[:danger] = 'Kit not found' - redirect_back(fallback_location: use_instrument_path(@instrument)) + def set_user + @user = @current_user + if @user.nil? + flash[:danger] = 'User not found' + redirect_to :back end + end - def set_instrument - return true if activity_params[:activity_type_id] - @instrument = Instrument.find_by_barcode!(activity_params[:instrument_barcode]) - rescue ActiveRecord::RecordNotFound => e - flash[:danger] = 'Instrument not found' - redirect_back(fallback_location: instruments_path) - end + def set_kit + return true if activity_params[:activity_type_id] - def set_activity_type - if activity_params[:activity_type_id] - begin - @activity_type = ActivityType.find(activity_params[:activity_type_id]) - rescue ActiveRecord::RecordNotFound => e - flash[:danger] = 'Activity type not found' - redirect_back(fallback_location: instruments_path) and return - end - else - unless @instrument.compatible_with_kit?(@kit) - flash[:danger] = "Instrument not compatible with kit type '#{@kit.kit_type.name}'" - redirect_back(fallback_location: use_instrument_path(@instrument)) - end - @activity_type = @kit.kit_type.activity_type - end - @activity_type - end + @kit = Kit.find_by_barcode!(activity_params[:kit_barcode]) + rescue ActiveRecord::RecordNotFound => e + flash[:danger] = 'Kit not found' + redirect_back(fallback_location: use_instrument_path(@instrument)) + end - # Use callbacks to share common setup or constraints between actions. - def set_activity - @activity = Activity.find(params[:id]) - end + def set_instrument + return true if activity_params[:activity_type_id] + @instrument = Instrument.find_by_barcode!(activity_params[:instrument_barcode]) + rescue ActiveRecord::RecordNotFound => e + flash[:danger] = 'Instrument not found' + redirect_back(fallback_location: instruments_path) + end - # Never trust parameters from the scary internet, only allow the white list through. - def activity_params - params.require(:activity).permit(:activity_type_id, :kit_barcode, :instrument_barcode, :state) + def set_activity_type + if activity_params[:activity_type_id] + begin + @activity_type = ActivityType.find(activity_params[:activity_type_id]) + rescue ActiveRecord::RecordNotFound => e + flash[:danger] = 'Activity type not found' + redirect_back(fallback_location: instruments_path) and return + end + else + unless @instrument.compatible_with_kit?(@kit) + flash[:danger] = "Instrument not compatible with kit type '#{@kit.kit_type.name}'" + redirect_back(fallback_location: use_instrument_path(@instrument)) + end + @activity_type = @kit.kit_type.activity_type end + @activity_type + end + # Use callbacks to share common setup or constraints between actions. + def set_activity + @activity = Activity.find(params[:id]) + end + # Never trust parameters from the scary internet, only allow the white list through. + def activity_params + params.require(:activity).permit(:activity_type_id, :kit_barcode, :instrument_barcode, :state) + end end diff --git a/app/controllers/activity_types_controller.rb b/app/controllers/activity_types_controller.rb index b7cee56b..d71124a5 100644 --- a/app/controllers/activity_types_controller.rb +++ b/app/controllers/activity_types_controller.rb @@ -67,13 +67,14 @@ def destroy end private - # Use callbacks to share common setup or constraints between actions. - def set_activity_type - @activity_type = ActivityType.find(params[:id]) - end - # Never trust parameters from the scary internet, only allow the white list through. - def activity_type_params - params.require(:activity_type).permit(:name, :n3_definition, { :step_type_ids => [] }) - end + # Use callbacks to share common setup or constraints between actions. + def set_activity_type + @activity_type = ActivityType.find(params[:id]) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def activity_type_params + params.require(:activity_type).permit(:name, :n3_definition, { :step_type_ids => [] }) + end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0694b2ac..1cd8dfec 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,5 +1,4 @@ class ApplicationController < ActionController::Base - # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception @@ -21,9 +20,8 @@ def set_current_user @current_user = User.find_by(:token => session[:token]) unless @current_user # If I am logged in a different host, I lose the session in this one - session[:token]=nil + session[:token] = nil end end end - end diff --git a/app/controllers/asset_groups_controller.rb b/app/controllers/asset_groups_controller.rb index 1e40aeba..e7cb7a68 100644 --- a/app/controllers/asset_groups_controller.rb +++ b/app/controllers/asset_groups_controller.rb @@ -7,8 +7,6 @@ class AssetGroupsController < ApplicationController include ActivitiesHelper - - def show @assets = @asset_group.assets @@ -19,12 +17,11 @@ def show end end - def update @assets = @asset_group.assets head :ok - #render json: { asset_group: {assets: @asset_group.assets.map(&:uuid) }} + # render json: { asset_group: {assets: @asset_group.assets.map(&:uuid) }} end def upload @@ -44,37 +41,36 @@ def print private - def update_barcodes - perform_assets_update - - if @alerts - render json: { errors: @alerts } - end - end + def update_barcodes + perform_assets_update - def set_activity - # I need the activity to be able to know the step_types compatible to show. - @activity = Activity.find(params[:activity_id]) if params[:activity_id] + if @alerts + render json: { errors: @alerts } end + end - # Use callbacks to share common setup or constraints between actions. - def set_asset_group - @asset_group = AssetGroup.find(params[:id]) - end + def set_activity + # I need the activity to be able to know the step_types compatible to show. + @activity = Activity.find(params[:activity_id]) if params[:activity_id] + end - def perform_assets_update - @asset_group.update_attributes(assets: params_update_asset_group[:assets].filter_map do |uuid_or_barcode| - Asset.find_or_import_asset_with_barcode(uuid_or_barcode) - end.uniq) - end + # Use callbacks to share common setup or constraints between actions. + def set_asset_group + @asset_group = AssetGroup.find(params[:id]) + end - def show_alert(data) - @alerts = [] unless @alerts - @alerts.push(data) - end + def perform_assets_update + @asset_group.update_attributes(assets: params_update_asset_group[:assets].filter_map do |uuid_or_barcode| + Asset.find_or_import_asset_with_barcode(uuid_or_barcode) + end.uniq) + end - def params_update_asset_group - params.require(:asset_group).permit(:assets => []) - end + def show_alert(data) + @alerts = [] unless @alerts + @alerts.push(data) + end + def params_update_asset_group + params.require(:asset_group).permit(:assets => []) + end end diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index 92088a7d..96eb6220 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -1,5 +1,4 @@ class AssetsController < ApplicationController - before_action :set_asset, only: [:show, :edit, :update, :destroy, :print] before_action :set_queries, only: [:search, :print_search] @@ -15,7 +14,6 @@ def print respond_to do |format| format.html { redirect_to @asset, notice: 'Asset was printed.' } end - end def print_search @@ -52,14 +50,13 @@ def show_by_internal_id # GET /assets/1 # GET /assets/1.json def show - #@asset = Asset.find_by_uuid!(params[:uuid]) + # @asset = Asset.find_by_uuid!(params[:uuid]) respond_to do |format| format.html { render :show } format.n3 { render :show } end end - # GET /assets/new def new @asset = Asset.new @@ -89,7 +86,6 @@ def create # PATCH/PUT /assets/1.json def update respond_to do |format| - if @asset.update(asset_params) @asset.touch @@ -112,11 +108,9 @@ def destroy end end - private - - # Use callbacks to share common setup or constraints between actions. + # Use callbacks to share common setup or constraints between actions. def set_asset @asset = if TokenUtil::UUID_REGEXP.match(params[:id]) Asset.find_by(uuid: params[:id]) @@ -133,14 +127,14 @@ def valid_indexes params.keys.filter_map { |k| k.match(/^[pq](\d*)$/) }.map { |k| k[1] } end - def set_queries - @queries = valid_indexes.map do |val| - OpenStruct.new({ :predicate => params["p"+val], :object => params["o"+val] }) # rubocop:todo Style/OpenStructUse - end + def set_queries + @queries = valid_indexes.map do |val| + OpenStruct.new({ :predicate => params["p" + val], :object => params["o" + val] }) # rubocop:todo Style/OpenStructUse end + end - # Never trust parameters from the scary internet, only allow the white list through. - def asset_params - params.require(:asset).permit(:barcode) - end + # Never trust parameters from the scary internet, only allow the white list through. + def asset_params + params.require(:asset).permit(:barcode) + end end diff --git a/app/controllers/changes_controller.rb b/app/controllers/changes_controller.rb index d9cd631d..7a205d75 100644 --- a/app/controllers/changes_controller.rb +++ b/app/controllers/changes_controller.rb @@ -19,8 +19,7 @@ def create private - def params_changes - params.require(:changes).permit! - end - + def params_changes + params.require(:changes).permit! + end end diff --git a/app/controllers/instruments_controller.rb b/app/controllers/instruments_controller.rb index e869fdf0..497f9c3d 100644 --- a/app/controllers/instruments_controller.rb +++ b/app/controllers/instruments_controller.rb @@ -66,14 +66,14 @@ def destroy end private - # Use callbacks to share common setup or constraints between actions. - def set_instrument - @instrument = Instrument.find(params[:id]) - end - # Never trust parameters from the scary internet, only allow the white list through. - def instrument_params - params.require(:instrument).permit(:barcode, :name, { :activity_type_ids => [] }) - end + # Use callbacks to share common setup or constraints between actions. + def set_instrument + @instrument = Instrument.find(params[:id]) + end + # Never trust parameters from the scary internet, only allow the white list through. + def instrument_params + params.require(:instrument).permit(:barcode, :name, { :activity_type_ids => [] }) + end end diff --git a/app/controllers/kit_types_controller.rb b/app/controllers/kit_types_controller.rb index b09ae537..d564ae94 100644 --- a/app/controllers/kit_types_controller.rb +++ b/app/controllers/kit_types_controller.rb @@ -63,17 +63,18 @@ def destroy end private - # Use callbacks to share common setup or constraints between actions. - def set_kit_type - @kit_type = KitType.find(params[:id]) - end - def set_activity_types - @activity_types = ActivityType.all - end + # Use callbacks to share common setup or constraints between actions. + def set_kit_type + @kit_type = KitType.find(params[:id]) + end - # Never trust parameters from the scary internet, only allow the white list through. - def kit_type_params - params.require(:kit_type).permit(:name, :target_type, :activity_type_id, :abbreviation) - end + def set_activity_types + @activity_types = ActivityType.all + end + + # Never trust parameters from the scary internet, only allow the white list through. + def kit_type_params + params.require(:kit_type).permit(:name, :target_type, :activity_type_id, :abbreviation) + end end diff --git a/app/controllers/kits_controller.rb b/app/controllers/kits_controller.rb index a6d92468..6dd5def6 100644 --- a/app/controllers/kits_controller.rb +++ b/app/controllers/kits_controller.rb @@ -62,17 +62,18 @@ def destroy end private - # Use callbacks to share common setup or constraints between actions. - def set_kit - @kit = Kit.find(params[:id]) - end - def set_kit_types - @kit_types = KitType.all - end + # Use callbacks to share common setup or constraints between actions. + def set_kit + @kit = Kit.find(params[:id]) + end - # Never trust parameters from the scary internet, only allow the white list through. - def kit_params - params.require(:kit).permit(:barcode, :max_num_reactions, :num_reactions_performed, :kit_type_id) - end + def set_kit_types + @kit_types = KitType.all + end + + # Never trust parameters from the scary internet, only allow the white list through. + def kit_params + params.require(:kit).permit(:barcode, :max_num_reactions, :num_reactions_performed, :kit_type_id) + end end diff --git a/app/controllers/printers_controller.rb b/app/controllers/printers_controller.rb index 693658c1..b4055f96 100644 --- a/app/controllers/printers_controller.rb +++ b/app/controllers/printers_controller.rb @@ -62,13 +62,14 @@ def destroy end private - # Use callbacks to share common setup or constraints between actions. - def set_printer - @printer = Printer.find(params[:id]) - end - # Never trust parameters from the scary internet, only allow the white list through. - def printer_params - params.require(:printer).permit(:name, :printer_type, :default_printer) - end + # Use callbacks to share common setup or constraints between actions. + def set_printer + @printer = Printer.find(params[:id]) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def printer_params + params.require(:printer).permit(:name, :printer_type, :default_printer) + end end diff --git a/app/controllers/reracking_controller.rb b/app/controllers/reracking_controller.rb index 4876db91..e38a5f24 100644 --- a/app/controllers/reracking_controller.rb +++ b/app/controllers/reracking_controller.rb @@ -1,5 +1,4 @@ class RerackingController < ApplicationController - before_action :set_activity_type before_action :set_activity, :only => [:update, :show] @@ -7,9 +6,7 @@ def set_activity_type @activity_type = ActivityType.not_deprecated.where(name: 'Re-Racking').last end - def index @activity = Activity.new end - end diff --git a/app/controllers/samples_not_started_controller.rb b/app/controllers/samples_not_started_controller.rb index 799203bb..9dae765b 100644 --- a/app/controllers/samples_not_started_controller.rb +++ b/app/controllers/samples_not_started_controller.rb @@ -1,5 +1,4 @@ class SamplesNotStartedController < SamplesStatusController - private def get_assets_for_activity_type(activity_type) @@ -8,5 +7,4 @@ def get_assets_for_activity_type(activity_type) .preload(:facts) .paginate(pagination_params_for_activity_type(activity_type)) end - end diff --git a/app/controllers/samples_started_controller.rb b/app/controllers/samples_started_controller.rb index 986a11c9..edbd242f 100644 --- a/app/controllers/samples_started_controller.rb +++ b/app/controllers/samples_started_controller.rb @@ -1,5 +1,4 @@ class SamplesStartedController < SamplesStatusController - private def get_assets_for_activity_type(activity_type) @@ -11,5 +10,4 @@ def get_assets_for_activity_type(activity_type) .order(id: :desc) .paginate(pagination_params_for_activity_type(activity_type)) end - end diff --git a/app/controllers/samples_status_controller.rb b/app/controllers/samples_status_controller.rb index 572f5c13..96faaca4 100644 --- a/app/controllers/samples_status_controller.rb +++ b/app/controllers/samples_status_controller.rb @@ -11,7 +11,7 @@ def index private def pagination_params_for_activity_type(activity_type) - if samples_started_params[:activity_type_id].to_i==activity_type.id + if samples_started_params[:activity_type_id].to_i == activity_type.id { :page => samples_started_params[:page], :per_page => 5 } else { :page => 1, :per_page => 5 } @@ -27,7 +27,7 @@ def set_activity_type_selected end def set_activity_types - @activity_types = ActivityType.all.visible.sort { |a,b| a.name <=> b.name }.uniq + @activity_types = ActivityType.all.visible.sort { |a, b| a.name <=> b.name }.uniq end def set_assets_for_activity_types @@ -38,5 +38,4 @@ def set_assets_for_activity_types } end end - end diff --git a/app/controllers/step_types_controller.rb b/app/controllers/step_types_controller.rb index 5e80e96c..cc2407b9 100644 --- a/app/controllers/step_types_controller.rb +++ b/app/controllers/step_types_controller.rb @@ -29,7 +29,6 @@ def new def edit end - # POST /step_types # POST /step_types.json def create @@ -71,24 +70,24 @@ def destroy end private - # Use callbacks to share common setup or constraints between actions. - def set_step_type - @step_type = StepType.find(params[:id]) - end - def empty_options_set_to_nil(params) - params_copy = params.dup - if params - [:step_template, :connect_by, :step_action].each do |key| - params_copy[key] = nil if params[key] && params[key].empty? - end - end - params_copy - end + # Use callbacks to share common setup or constraints between actions. + def set_step_type + @step_type = StepType.find(params[:id]) + end - # Never trust parameters from the scary internet, only allow the white list through. - def step_type_params - params.require(:step_type).permit(:n3_definition,:name, :step_template, :connect_by, :for_reasoning, :step_action, :priority) + def empty_options_set_to_nil(params) + params_copy = params.dup + if params + [:step_template, :connect_by, :step_action].each do |key| + params_copy[key] = nil if params[key] && params[key].empty? + end end + params_copy + end + # Never trust parameters from the scary internet, only allow the white list through. + def step_type_params + params.require(:step_type).permit(:n3_definition, :name, :step_template, :connect_by, :for_reasoning, :step_action, :priority) + end end diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb index dc42825e..38e3e657 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -33,42 +33,41 @@ def update private - def event_for_step - "#{params_step[:event_name]}!" - end - - # Use callbacks to share common setup or constraints between actions. - def set_activity - @activity = Activity.find(params[:activity_id]) - end + def event_for_step + "#{params_step[:event_name]}!" + end - # Use callbacks to share common setup or constraints between actions. - def set_step - @step = Step.find(params[:id]) - end + # Use callbacks to share common setup or constraints between actions. + def set_activity + @activity = Activity.find(params[:activity_id]) + end - def set_asset_group - @asset_group = AssetGroup.find(params_step[:asset_group_id]) - end + # Use callbacks to share common setup or constraints between actions. + def set_step + @step = Step.find(params[:id]) + end - def set_step_type - @step_type = StepType.find(params_step[:step_type_id]) - end + def set_asset_group + @asset_group = AssetGroup.find(params_step[:asset_group_id]) + end - def set_printer_config - tube_printer = Printer.find_by(id: params_step[:tube_printer_id]) || nil - plate_printer = Printer.find_by(id: params_step[:plate_printer_id]) || nil - tube_rack_printer = Printer.find_by(id: params_step[:plate_printer_id]) || nil - @printer_config = { - 'Tube' => tube_printer.nil? ? "" : tube_printer.name, - 'Plate' => plate_printer.nil? ? "" : plate_printer.name, - 'TubeRack' => tube_rack_printer.nil? ? "" : tube_rack_printer.name - } - end + def set_step_type + @step_type = StepType.find(params_step[:step_type_id]) + end - def params_step - params.require(:step).permit(:step_type_id, :asset_group_id, :tube_printer_id, :plate_printer_id, - :event_name) - end + def set_printer_config + tube_printer = Printer.find_by(id: params_step[:tube_printer_id]) || nil + plate_printer = Printer.find_by(id: params_step[:plate_printer_id]) || nil + tube_rack_printer = Printer.find_by(id: params_step[:plate_printer_id]) || nil + @printer_config = { + 'Tube' => tube_printer.nil? ? "" : tube_printer.name, + 'Plate' => plate_printer.nil? ? "" : plate_printer.name, + 'TubeRack' => tube_rack_printer.nil? ? "" : tube_rack_printer.name + } + end + def params_step + params.require(:step).permit(:step_type_id, :asset_group_id, :tube_printer_id, :plate_printer_id, + :event_name) + end end diff --git a/app/controllers/uploaded_files_controller.rb b/app/controllers/uploaded_files_controller.rb index 672472b2..5e8927b4 100644 --- a/app/controllers/uploaded_files_controller.rb +++ b/app/controllers/uploaded_files_controller.rb @@ -4,14 +4,13 @@ class UploadedFilesController < ApplicationController def show respond_to do |format| format.bin { - send_data(@uploaded_file.data,filename: @uploaded_file.filename) + send_data(@uploaded_file.data, filename: @uploaded_file.filename) } format.html { render :show } format.n3 { render :show } end end - private def set_uploaded_file diff --git a/app/controllers/user_sessions_controller.rb b/app/controllers/user_sessions_controller.rb index 14b576d0..c03d7011 100644 --- a/app/controllers/user_sessions_controller.rb +++ b/app/controllers/user_sessions_controller.rb @@ -7,12 +7,11 @@ def create def destroy @current_user.clean_session if @current_user - session[:token]=nil + session[:token] = nil head :no_content end - private def user_session_params diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index bf73e007..8df0d715 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -67,13 +67,14 @@ def destroy end private - # Use callbacks to share common setup or constraints between actions. - def set_user - @user = User.find(params[:id]) - end - # Never trust parameters from the scary internet, only allow the white list through. - def user_params - params.require(:user).permit(:barcode, :username, :fullname, :role, :tube_printer_id, :plate_printer_id) - end + # Use callbacks to share common setup or constraints between actions. + def set_user + @user = User.find(params[:id]) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def user_params + params.require(:user).permit(:barcode, :username, :fullname, :role, :tube_printer_id, :plate_printer_id) + end end diff --git a/app/helpers/activities_helper.rb b/app/helpers/activities_helper.rb index de6706ec..bd6fae9a 100644 --- a/app/helpers/activities_helper.rb +++ b/app/helpers/activities_helper.rb @@ -1,24 +1,23 @@ require 'support_n3' module ActivitiesHelper - def ontology_json return @ontology if @ontology - ontology = File.new(Rails.root.to_s+'/app/assets/owls/root-ontology.ttl') - @ontology=SupportN3.ontology_to_json(ontology).to_json.html_safe + + ontology = File.new(Rails.root.to_s + '/app/assets/owls/root-ontology.ttl') + @ontology = SupportN3.ontology_to_json(ontology).to_json.html_safe end def step_types_data_for_step_types(activity, step_types) step_types.select { |st| st.step_template.blank? }.map do |st| - { - createStepUrl: Rails.application.routes.url_helpers.activity_steps_path(activity), - stepType: st, - name: st.name - } + { + createStepUrl: Rails.application.routes.url_helpers.activity_steps_path(activity), + stepType: st, + name: st.name + } end end - def step_types_for_asset_groups_data(activity, asset_group) step_types = activity.step_types_for(asset_group.assets) { @@ -30,6 +29,7 @@ def step_types_for_asset_groups_data(activity, asset_group) def step_types_control_data(activity) return {} if activity.running? + activity.owned_asset_groups.reduce({}) do |memo, asset_group| data_for_step_types = step_types_for_asset_groups_data(activity, asset_group) memo[asset_group.id] = data_for_step_types @@ -67,43 +67,42 @@ def operations_data(operations) operations.reduce([]) do |memo, fact| if occured_predicates.include?(fact.predicate) obj = memo.select { |f| f["predicate"] == fact.predicate }.first - obj["repeats"] = obj["repeats"] ? obj["repeats"]+1 : 0 + obj["repeats"] = obj["repeats"] ? obj["repeats"] + 1 : 0 next memo end elem = fact.object_asset if elem obj = { "object_asset" => { - uuid: elem.uuid, - barcode: elem.barcode, - id: elem.id, - info_line: elem.info_line - } }.merge(fact.attributes) + uuid: elem.uuid, + barcode: elem.barcode, + id: elem.id, + info_line: elem.info_line + } }.merge(fact.attributes) else obj = fact.attributes end - obj[:asset]=fact.asset.attributes + obj[:asset] = fact.asset.attributes memo.push(obj) memo end end - def facts_data(facts) occured_predicates = [] facts.reduce([]) do |memo, fact| if occured_predicates.include?(fact.predicate) obj = memo.select { |f| f["predicate"] == fact.predicate }.first - obj["repeats"] = obj["repeats"] ? obj["repeats"]+1 : 0 + obj["repeats"] = obj["repeats"] ? obj["repeats"] + 1 : 0 next memo end elem = fact.object_asset if elem obj = { "object_asset" => { - uuid: elem.uuid, - barcode: elem.barcode, - id: elem.id, - info_line: elem.info_line - } }.merge(fact.attributes) + uuid: elem.uuid, + barcode: elem.barcode, + id: elem.id, + info_line: elem.info_line + } }.merge(fact.attributes) else obj = fact.attributes end @@ -112,7 +111,6 @@ def facts_data(facts) end end - def asset_data(asset) asset.facts.reload { barcode: asset.barcode, uuid: asset.uuid, facts: facts_data(asset.facts) } @@ -140,7 +138,6 @@ def asset_groups_data(activity) end end - def step_type_templates_data_for_step_types(activity, step_types, asset_group) step_types.select { |s| !s.step_template.blank? }.map do |st| { @@ -148,7 +145,7 @@ def step_type_templates_data_for_step_types(activity, step_types, asset_group) createStepUrl: Rails.application.routes.url_helpers.activity_steps_path(activity), stepType: st, name: st.name, - id: "step-type-id-#{ rand(9999).to_s }-#{ st.id }" + id: "step-type-id-#{rand(9999).to_s}-#{st.id}" } end end @@ -170,5 +167,4 @@ def messages_for_activity(activity) { type: 'danger', msg: m.content.to_s.html_safe } end end - end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index c281134d..e53026d0 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -55,8 +55,8 @@ def object_for(fact) end def render_react_display_for_asset(asset) - data_asset_display = {}.tap { |o| o[asset.uuid]=data_asset_display(asset.facts) } - react_component('FactsSvg', { asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display }) + data_asset_display = {}.tap { |o| o[asset.uuid] = data_asset_display(asset.facts) } + react_component('FactsSvg', { asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display }) end def render_react_tooltip @@ -69,19 +69,21 @@ def facts_with_object_asset(facts) def object_with_facts(object) return nil if object.nil? + object.attributes.merge(facts: object.facts) end def render_react_display_and_facts_for_asset(asset) - data_asset_display = {}.tap { |o| o[asset.uuid]=data_asset_display(asset.facts) } - react_component('Facts', { asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display }) + data_asset_display = {}.tap { |o| o[asset.uuid] = data_asset_display(asset.facts) } + react_component('Facts', { asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display }) end def render_react_edit_asset(asset, readonly = false) - data_asset_display = {}.tap { |o| o[asset.uuid]=data_asset_display(asset.facts) } - react_component('FactsEditor', { - changesUrl: readonly ? nil : changes_url, - asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display }) + data_asset_display = {}.tap { |o| o[asset.uuid] = data_asset_display(asset.facts) } + react_component('FactsEditor', { + changesUrl: readonly ? nil : changes_url, + asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display + }) end def data_asset_display_for_plate(facts) @@ -108,12 +110,12 @@ def data_asset_display_for_tube(facts) aliquot_fact = facts.with_predicate('aliquotType').first if aliquot_fact css_classes = [(aliquot_fact.object || unknown_aliquot_type), is_facts_values].compact.join(' ') - url = ((aliquot_fact.class==Fact) ? asset_path(aliquot_fact.asset) : '') + url = ((aliquot_fact.class == Fact) ? asset_path(aliquot_fact.asset) : '') title = "#{aliquot_fact.asset.short_description}" else css_classes = is_facts_values - url='' - title='' + url = '' + title = '' end { aliquot: { @@ -124,6 +126,7 @@ def data_asset_display_for_tube(facts) def data_asset_display(facts) return data_asset_display_for_plate(facts) if facts.with_predicate('contains').count > 0 + data_asset_display_for_tube(facts) end @@ -148,5 +151,4 @@ def trigger_alerts "" end.join('\n').html_safe if @alerts end - end diff --git a/app/helpers/assets_helper.rb b/app/helpers/assets_helper.rb index 12f64acb..c9caf848 100644 --- a/app/helpers/assets_helper.rb +++ b/app/helpers/assets_helper.rb @@ -2,18 +2,18 @@ module AssetsHelper def condition_groups_init_for_asset(asset) obj = {} obj[asset.barcode] = { :template => 'templates/asset_facts' } - obj[asset.barcode][:facts]=asset.facts.map do |fact| - { - :cssClasses => '', - :name => asset.uuid, - :actionType => 'createAsset', - :predicate => fact.predicate, - :object_reference => fact.object_asset_id, - :object_label => fact.object_label, - :object => asset.object_value(fact) - } - end + obj[asset.barcode][:facts] = asset.facts.map do |fact| + { + :cssClasses => '', + :name => asset.uuid, + :actionType => 'createAsset', + :predicate => fact.predicate, + :object_reference => fact.object_asset_id, + :object_label => fact.object_label, + :object => asset.object_value(fact) + } + end obj - end + end end diff --git a/app/helpers/step_types_helper.rb b/app/helpers/step_types_helper.rb index a0f6a70f..79856601 100644 --- a/app/helpers/step_types_helper.rb +++ b/app/helpers/step_types_helper.rb @@ -16,7 +16,7 @@ def condition_groups_init_for_step_type(step_type) memo[name] = { :cardinality => condition_group.cardinality, :keepSelected => condition_group.keep_selected, - :facts => condition_group.conditions.map do |condition| + :facts => condition_group.conditions.map do |condition| { :cssClasses => fact_css_classes['checkFacts'], :name => name, @@ -30,21 +30,20 @@ def condition_groups_init_for_step_type(step_type) end agroups = step_type.actions.reduce(cgroups) do |memo, action| name = action.subject_condition_group.name || "a#{action.subject_condition_group.id}" - memo[name]={ + memo[name] = { :facts => [], :cardinality => action.subject_condition_group.cardinality, :keepSelected => action.subject_condition_group.keep_selected } unless memo[name] memo[name][:facts].push({ - :cssClasses => fact_css_classes[action.action_type], - :name => name, - :actionType => action.action_type, - :predicate => action.predicate, - :object => action.object - }) + :cssClasses => fact_css_classes[action.action_type], + :name => name, + :actionType => action.action_type, + :predicate => action.predicate, + :object => action.object + }) memo end agroups.to_json end - end diff --git a/app/models/action.rb b/app/models/action.rb index 741aa0ba..e882601a 100644 --- a/app/models/action.rb +++ b/app/models/action.rb @@ -34,9 +34,9 @@ def each_connected_asset(sources, destinations, wildcard_values = {}, &block) return sources.each do |s| destinations.each do |d| if (value_for[s.id] && value_for[d.id]) - yield s,d if (value_for[s.id] == value_for[d.id]) + yield s, d if (value_for[s.id] == value_for[d.id]) else - yield s,d + yield s, d end end end @@ -44,11 +44,11 @@ def each_connected_asset(sources, destinations, wildcard_values = {}, &block) end end if step_type.connect_by == 'position' - sources.zip(destinations).each { |s,d| yield s,d if d } + sources.zip(destinations).each { |s, d| yield s, d if d } else sources.each do |s| destinations.each do |d| - yield s,d + yield s, d end end end @@ -75,8 +75,7 @@ def run(asset_group, wildcard_values = {}) assets = num_assets_to_create(asset_group).times.map { Asset.new } updates.create_assets(assets) updates.add_assets([[asset_group, assets]]) - #asset_group.assets << assets - + # asset_group.assets << assets updates.create_asset_groups(["?#{subject_condition_group.name}"]) updates.add_assets([["?#{subject_condition_group.name}", assets]]) @@ -105,7 +104,7 @@ def run(asset_group, wildcard_values = {}) updates.remove_assets([[asset_group, sources(asset_group)]]) else each_connected_asset(sources(asset_group), destinations(asset_group), wildcard_values) do |source, destination| - if action_type=='addFacts' + if action_type == 'addFacts' updates.add(source, predicate, destination) elsif action_type == 'removeFacts' updates.remove_where(source, predicate, destination) @@ -116,9 +115,9 @@ def run(asset_group, wildcard_values = {}) end def num_assets_to_create(asset_group) - return asset_group.assets.count unless (subject_condition_group.cardinality) && (subject_condition_group.cardinality!=0) + return asset_group.assets.count unless (subject_condition_group.cardinality) && (subject_condition_group.cardinality != 0) + return subject_condition_group.cardinality - #return [[asset_group.assets.count, subject_condition_group.cardinality].min, 1].max + # return [[asset_group.assets.count, subject_condition_group.cardinality].min, 1].max end - end diff --git a/app/models/activities/background_tasks.rb b/app/models/activities/background_tasks.rb index 4238397e..01bdd60c 100644 --- a/app/models/activities/background_tasks.rb +++ b/app/models/activities/background_tasks.rb @@ -10,7 +10,6 @@ def initialize(step_type) def create!(params) @step_type.class_for_task_type.send(:create!, params.merge(step_type: @step_type)) end - end def background_tasks @@ -40,6 +39,5 @@ def create_connected_tasks(step, asset_group, printer_config = nil, user = nil) step.update_attributes(next_step: steps.first) [step, steps].flatten.compact end - end end diff --git a/app/models/activities/json_attributes.rb b/app/models/activities/json_attributes.rb index a641cce0..6ac7e2f1 100644 --- a/app/models/activities/json_attributes.rb +++ b/app/models/activities/json_attributes.rb @@ -1,14 +1,14 @@ module Activities::JsonAttributes def initial_json_attributes(current_user = nil) { - activity: { - id: id, - completed_at: completed_at, - activity_type_name: activity_type.name, - instrument_name: instrument ? (instrument.name || instrument.barcode) : nil, - kit_name: kit ? kit.barcode : nil, - selectedAssetGroup: owned_asset_groups.first.id - }, + activity: { + id: id, + completed_at: completed_at, + activity_type_name: activity_type.name, + instrument_name: instrument ? (instrument.name || instrument.barcode) : nil, + kit_name: kit ? kit.barcode : nil, + selectedAssetGroup: owned_asset_groups.first.id + }, tubePrinter: { optionsData: Printer.for_tube.map { |a| [a.name, a.id] }, defaultValue: current_user && current_user.tube_printer ? current_user.tube_printer.id : nil diff --git a/app/models/activities/state.rb b/app/models/activities/state.rb index aa0b857d..75039447 100644 --- a/app/models/activities/state.rb +++ b/app/models/activities/state.rb @@ -32,5 +32,4 @@ def in_progress! def editing? state == 'editing' end - end diff --git a/app/models/activities/steps_management.rb b/app/models/activities/steps_management.rb index 9974ba5f..98f230ff 100644 --- a/app/models/activities/steps_management.rb +++ b/app/models/activities/steps_management.rb @@ -1,11 +1,12 @@ module Activities::StepsManagement def active_step return nil unless steps.in_progress + steps.in_progress.first end def previous_steps - asset_group.assets.includes(:steps).map(&:steps).concat(steps).flatten.sort { |a,b| a.id <=> b.id }.uniq + asset_group.assets.includes(:steps).map(&:steps).concat(steps).flatten.sort { |a, b| a.id <=> b.id }.uniq end def assets @@ -27,5 +28,4 @@ def step_types_for(assets, required_assets = nil) def step_types_active step_types_for(asset_group.assets) end - -end \ No newline at end of file +end diff --git a/app/models/activities/tasks.rb b/app/models/activities/tasks.rb index 7b6bd05e..617c941b 100644 --- a/app/models/activities/tasks.rb +++ b/app/models/activities/tasks.rb @@ -1,6 +1,5 @@ module Activities module Tasks - def create_step(params) params[:step_type].class_for_task_type .create!( @@ -14,6 +13,5 @@ def create_step(params) step.run! end end - end end diff --git a/app/models/activities/websocket_events.rb b/app/models/activities/websocket_events.rb index ead73a5c..c450402d 100644 --- a/app/models/activities/websocket_events.rb +++ b/app/models/activities/websocket_events.rb @@ -37,15 +37,14 @@ def initial_websockets_attributes(attrs) def wss_event(opts = {}) _wss_event(opts) - #delay(queue: 'websockets')._wss_event(opts) + # delay(queue: 'websockets')._wss_event(opts) end def _wss_event(opts = {}) if Rails.configuration.redis_enabled && is_being_listened? data = websockets_attributes(json_attributes).merge(opts) - #debugger if data[:stepsFinished][0]['state']=='error' + # debugger if data[:stepsFinished][0]['state']=='error' send_wss_event(data) end end - end diff --git a/app/models/activity.rb b/app/models/activity.rb index e6ad48ce..6998cb54 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -37,7 +37,6 @@ class Activity < ApplicationRecord delegate :name, to: :instrument, prefix: true, allow_nil: true delegate :fullname, to: :last_user, prefix: true, allow_nil: true - # Called following state transition to finish # Broadcasts the activity to the ML warehouse def after_finish diff --git a/app/models/activity_type.rb b/app/models/activity_type.rb index 3c29ccbb..11347158 100644 --- a/app/models/activity_type.rb +++ b/app/models/activity_type.rb @@ -27,8 +27,9 @@ def create_activity(params) ActiveRecord::Base.transaction do group = AssetGroup.create activity = Activity.create({ - kit: params[:kit], instrument: params[:instrument], - activity_type: self, asset_group: group }) + kit: params[:kit], instrument: params[:instrument], + activity_type: self, asset_group: group + }) activities << activity group.update_attributes!(activity_owner: activity) end @@ -42,13 +43,12 @@ def available? def after_deprecate superceded_by.update_attributes( activities: superceded_by.activities | activities, - kit_types: superceded_by.kit_types | kit_types, + kit_types: superceded_by.kit_types | kit_types, instruments: superceded_by.instruments | instruments - ) + ) superceded_by.save! end - def compatible_with?(assets) condition_groups.any? { |c| c.compatible_with?(assets) } end diff --git a/app/models/asset.rb b/app/models/asset.rb index 1660e9a0..d086012f 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -32,7 +32,6 @@ def with_predicate(predicate) has_many :steps, through: :asset_groups has_many :activities_affected, -> { distinct }, through: :asset_groups, class_name: 'Activity', source: :activity_owner - def update_compatible_activity_type ActivityType.not_deprecated.all.each do |at| activity_types << at if at.compatible_with?(self) @@ -55,11 +54,11 @@ def update_compatible_activity_type } scope :not_started, ->() { - with_fact('is','NotStarted') + with_fact('is', 'NotStarted') } scope :started, ->() { - with_fact('is','Started') + with_fact('is', 'Started') } scope :for_printing, ->() { @@ -70,20 +69,20 @@ def update_compatible_activity_type queries.each_with_index.reduce(Asset) do |memo, list| query = list[0] index = list[1] - if query.predicate=='barcode' + if query.predicate == 'barcode' memo.where(barcode: query.object) else asset = Asset.where(barcode: query.object).first if asset memo.joins( "INNER JOIN facts AS facts#{index} ON facts#{index}.asset_id=assets.id" - ).where("facts#{index}.predicate" => query.predicate, - "facts#{index}.object_asset_id" => asset.id) + ).where("facts#{index}.predicate" => query.predicate, + "facts#{index}.object_asset_id" => asset.id) else memo.joins( "INNER JOIN facts AS facts#{index} ON facts#{index}.asset_id=assets.id" - ).where("facts#{index}.predicate" => query.predicate, - "facts#{index}.object" => query.object) + ).where("facts#{index}.predicate" => query.predicate, + "facts#{index}.object" => query.object) end end end @@ -135,28 +134,27 @@ def relation_id def build_barcode(index) self.barcode = SBCF::SangerBarcode.new({ - prefix: Rails.application.config.barcode_prefix, - number: index - }).human_barcode + prefix: Rails.application.config.barcode_prefix, + number: index + }).human_barcode end def generate_barcode save if barcode.nil? update_attributes({ - barcode: SBCF::SangerBarcode.new({ - prefix: Rails.application.config.barcode_prefix, - number: self.id - }).human_barcode - } - ) + barcode: SBCF::SangerBarcode.new({ + prefix: Rails.application.config.barcode_prefix, + number: self.id + }).human_barcode + }) end end def attrs_for_sequencescape(traversed_list = []) hash = facts.map do |fact| if fact.literal? - [fact.predicate, fact.object_value] + [fact.predicate, fact.object_value] else if traversed_list.include?(fact.object_value) [fact.predicate, fact.object_value.uuid] @@ -166,7 +164,7 @@ def attrs_for_sequencescape(traversed_list = []) end end end.reduce({}) do |memo, list| - predicate,object = list + predicate, object = list if memo[predicate] || memo[predicate.pluralize] # Updates name of list to pluralized name unless memo[predicate].kind_of? Array @@ -179,7 +177,7 @@ def attrs_for_sequencescape(traversed_list = []) end memo end - #return {:uuid => uuid, :barcode => { :prefix => 'SE', :number => 14 }} + # return {:uuid => uuid, :barcode => { :prefix => 'SE', :number => 14 }} hash end @@ -190,11 +188,12 @@ def study_and_barcode def barcode_sequencescaped unless barcode.match(/^\d+$/) return barcode.match(/\d+/)[0] if barcode.match(/\d+/) + return "" end ean13 = barcode.rjust(13, '0') - ean13.slice!(0,3) - ean13.slice!(ean13.length-3,3) + ean13.slice!(0, 3) + ean13.slice!(ean13.length - 3, 3) ean13.to_i end @@ -211,6 +210,7 @@ def study_name end end end + return '' end @@ -228,12 +228,13 @@ def barcode_formatted_for_printing def printable_object(username = 'unknown') return nil if barcode.nil? + if (kind_of_plate?) return { :label => { :barcode => barcode, :top_left => DateTime.now.strftime('%d/%b/%y'), - :top_right => info_line, #username, + :top_right => info_line, # username, :bottom_right => study_and_barcode, :bottom_left => barcode } @@ -245,8 +246,7 @@ def printable_object(username = 'unknown') :top_line => TokenUtil.human_barcode(barcode), :middle_line => kit_type, :bottom_line => info_line - } - } + } } end def kit_type @@ -256,7 +256,8 @@ def kit_type def position_value val = facts.filter_map(&:position).first return "" if val.nil? - "_#{(val.to_i+1).to_s}" + + "_#{(val.to_i + 1).to_s}" end def info_line @@ -268,6 +269,7 @@ def class_name if purposes_facts.count > 0 return purposes_facts.first.object end + return '' end @@ -276,10 +278,10 @@ def aliquot if purposes_facts.count > 0 return purposes_facts.first.object end + return '' end - def position_name_for_symphony str = first_value_for('location') [str[0], str[1..-1]].join(':') @@ -303,11 +305,12 @@ def self.class_type(facts) return 'Tube' if class_types.include?('Tube') return 'SampleTube' if class_types.include?('SampleTube') return facts.select { |f| f[:predicate] == 'a' }.first.object if facts.select { |f| f[:predicate] == 'a' }.first + return "" end def kind_of_plate? - (class_type=='Plate')||(class_type=='TubeRack') + (class_type == 'Plate') || (class_type == 'TubeRack') end def has_wells? @@ -318,7 +321,6 @@ def class_type Asset.class_type(facts) end - def contains_location?(location) facts.with_predicate('contains').any? do |f| f.object_asset.facts.with_predicate('location').map(&:object).include?(location) @@ -332,11 +334,10 @@ def assets_at_location(location) end def remove_from_parent(parent) - facts.with_predicate('parent').select { |f| f.object_asset==parent }.each(&:destroy) + facts.with_predicate('parent').select { |f| f.object_asset == parent }.each(&:destroy) facts.with_predicate('location').each(&:destroy) end - def duplicated_tubes_validation contained_assets = facts.with_predicate('contains').map(&:object_asset) duplicated = contained_assets.select do |element| @@ -352,21 +353,23 @@ def duplicated_tubes_validation def more_than_one_aliquot_type_validation if facts.with_predicate('contains').map(&:object_asset).map do |well| - well.facts.with_predicate('aliquotType').map(&:object) - end.flatten.uniq.count > 1 + well.facts.with_predicate('aliquotType').map(&:object) + end.flatten.uniq.count > 1 return ['More than one aliquot type in the same rack'] end + return [] end def barcode_type btypes = facts.with_predicate('barcodeType') return 'ean13' if btypes.empty? + btypes.first.object.downcase end def validate_rack_content - errors=[] + errors = [] errors.push(more_than_one_aliquot_type_validation) errors end diff --git a/app/models/asset_group.rb b/app/models/asset_group.rb index b604a195..4d6b093c 100644 --- a/app/models/asset_group.rb +++ b/app/models/asset_group.rb @@ -1,10 +1,9 @@ - class AssetGroup < ApplicationRecord include Uuidable has_many :asset_groups_assets, dependent: :destroy has_many :assets, through: :asset_groups_assets - #has_and_belongs_to_many :assets, ->() {distinct} + # has_and_belongs_to_many :assets, ->() {distinct} has_many :steps has_many :uploaded_files, through: :assets @@ -104,6 +103,7 @@ def select_barcodes(barcodes) if assets.select { |a| a.barcode == barcode }.empty? asset = Asset.find_or_import_asset_with_barcode(barcode) return false if asset.nil? + add_assets(asset) end end @@ -135,16 +135,17 @@ def clean_fact_group(groups) def assets_by_fact_group return [] unless assets - obj_type = Struct.new(:predicate,:object, :to_add_by, :to_remove_by, :object_asset_id) + + obj_type = Struct.new(:predicate, :object, :to_add_by, :to_remove_by, :object_asset_id) groups = assets.group_by do |a| - a.facts.sort do |f1,f2| + a.facts.sort do |f1, f2| # Canonical sort of facts f1.canonical_comparison_for_sorting(f2) end.map(&:as_json).map do |f| obj = f["object"] if f["object_asset_id"] - obj="?" + obj = "?" end obj_type.new(f["predicate"], obj, f["to_add_by"], f["to_remove_by"], nil) end.uniq @@ -152,5 +153,4 @@ def assets_by_fact_group clean_fact_group(groups) end - end diff --git a/app/models/assets/export.rb b/app/models/assets/export.rb index 3f52c7e8..21ee04e6 100644 --- a/app/models/assets/export.rb +++ b/app/models/assets/export.rb @@ -1,5 +1,5 @@ module Assets::Export - class DuplicateLocations < StandardError ; end + class DuplicateLocations < StandardError; end def update_sequencescape(_print_config, user, _step) FactChanges.new.tap do |updates| @@ -50,7 +50,7 @@ def mark_to_print(updates) def code39_barcode(instance) prefix = instance.barcode.prefix number = instance.barcode.number - SBCF::SangerBarcode.new(prefix:prefix, number:number).human_barcode + SBCF::SangerBarcode.new(prefix: prefix, number: number).human_barcode end def update_wells(instance, updates) @@ -100,8 +100,8 @@ def attributes_to_send def has_sample? has_predicate_with_value?('supplier_sample_name') || - has_relation_with_value?('sample_tube') || - has_predicate_with_value?('sample_uuid') + has_relation_with_value?('sample_tube') || + has_predicate_with_value?('sample_uuid') end def attributes_to_send_for_well(well) @@ -125,7 +125,7 @@ def attributes_to_send_for_well(well) memo[fact.predicate.to_sym] = TokenUtil.unpad_location(fact.object) end if (['aliquotType', 'sanger_sample_id', - 'sanger_sample_name', 'sample_uuid'].include?(fact.predicate)) + 'sanger_sample_name', 'sample_uuid'].include?(fact.predicate)) memo[fact.predicate.to_sym] = TokenUtil.unquote(fact.object) end memo diff --git a/app/models/assets/facts_management.rb b/app/models/assets/facts_management.rb index 1b2d3b1a..b59433a7 100644 --- a/app/models/assets/facts_management.rb +++ b/app/models/assets/facts_management.rb @@ -11,8 +11,6 @@ def self.included(klass) scope :with_predicate, ->(predicate) { joins(:facts).where(:facts => { :predicate => predicate }) } - - end end @@ -38,7 +36,7 @@ def has_fact?(fact) ((fact.predicate == f.predicate) && (fact.object_asset == f.object_asset) && (fact.to_add_by == f.to_add_by) && (fact.to_remove_by == f.to_remove_by)) else - other_conds=true + other_conds = true if fact.respond_to?(:to_add_by) other_conds = (fact.to_add_by == f.to_add_by) && (fact.to_remove_by == f.to_remove_by) end @@ -47,7 +45,6 @@ def has_fact?(fact) end end - def facts_to_s facts.each do |fact| render :partial => fact @@ -75,5 +72,4 @@ def facts_with_triples(triples) asset.facts.where(predicate: predicate, object_asset: object) end end - end diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 44a67cbc..8a2008dd 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -1,14 +1,12 @@ module Assets::Import - def self.included(base) base.send :include, InstanceMethods base.extend ClassMethods end - class RefreshSourceNotFoundAnymore < StandardError ; end + class RefreshSourceNotFoundAnymore < StandardError; end module InstanceMethods - def json_for_remote(remote_asset) distinct = remote_asset.attributes.to_json @@ -27,7 +25,7 @@ def json_for_remote(remote_asset) if listal listsa = listal.flatten.compact.map { |al| al.sample } if listsa - distinct+=listsa.compact.map(&:attributes).to_json + distinct += listsa.compact.map(&:attributes).to_json end end end @@ -40,7 +38,7 @@ def json_for_remote(remote_asset) if listal listsa = listal.flatten.compact.map { |al| al.sample } if listsa - distinct+=listsa.compact.map(&:attributes).to_json + distinct += listsa.compact.map(&:attributes).to_json end end end @@ -58,7 +56,7 @@ def json_for_remote(remote_asset) if listal listsa = listal.flatten.compact.map { |al| al.sample } if listsa - distinct+=listsa.compact.map(&:attributes).to_json + distinct += listsa.compact.map(&:attributes).to_json end end end @@ -107,7 +105,7 @@ def _process_refresh(remote_asset, fact_changes = nil) asset_group.touch ensure @import_step.update_attributes(state: 'error') unless @import_step.state == 'complete' - #@import_step.asset_group.touch if @import_step.asset_group + # @import_step.asset_group.touch if @import_step.asset_group end end @@ -127,6 +125,7 @@ def refresh(fact_changes = nil) if is_remote_asset? remote_asset = SequencescapeClient::find_by_uuid(uuid) raise RefreshSourceNotFoundAnymore unless remote_asset + if changed_remote?(remote_asset) unless is_refreshing_right_now? @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Refresh'), state: 'running') @@ -142,6 +141,7 @@ def refresh!(fact_changes = nil) @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Refresh!!'), state: 'running') remote_asset = SequencescapeClient::find_by_uuid(uuid) raise RefreshSourceNotFoundAnymore unless remote_asset + _process_refresh(remote_asset, fact_changes) end self @@ -161,11 +161,9 @@ def update_facts_from_remote(list, step = nil) facts << added add_operations([added].flatten, step) end - end module ClassMethods - def import_barcode(barcode) asset = nil @@ -185,7 +183,7 @@ def import_barcode(barcode) end def create_local_asset(barcode, updates) - asset=nil + asset = nil ActiveRecord::Base.transaction do asset = Asset.create!(:barcode => barcode) updates.add(asset, 'a', 'Tube') @@ -218,7 +216,6 @@ def find_or_import_asset_with_barcode(barcode) find_asset_with_barcode(barcode) || import_barcode(barcode) end - def update_asset_from_remote_asset(asset, remote_asset, fact_changes) fact_changes.tap do |updates| class_name = sequencescape_type_for_asset(remote_asset) @@ -257,7 +254,7 @@ def annotate_container(asset, remote_asset, fact_changes) end def sample_id_to_study_name(sample_id) - sample_id.gsub(/\d*$/,'').gsub('-', '') + sample_id.gsub(/\d*$/, '').gsub('-', '') end def get_study_uuid(study_name) @@ -336,8 +333,10 @@ def annotate_tubes(asset, remote_asset, fact_changes) def sequencescape_type_for_asset(remote_asset) return nil unless remote_asset.type + type = remote_asset.type.singularize.classify return 'SampleTube' if type == 'Tube' + return type end @@ -345,6 +344,5 @@ def keep_sync_with_sequencescape?(remote_asset) class_name = sequencescape_type_for_asset(remote_asset) (class_name != 'SampleTube') end - end end diff --git a/app/models/assets/traction_fields.rb b/app/models/assets/traction_fields.rb index 38826218..83a4115b 100644 --- a/app/models/assets/traction_fields.rb +++ b/app/models/assets/traction_fields.rb @@ -1,5 +1,4 @@ module Assets::TractionFields - def asset_type _get_values_for_predicate('a') end @@ -44,8 +43,9 @@ def _get_values_for_predicate(predicate) a.object_value_or_uuid end end - return list[0] if list.length==1 + return list[0] if list.length == 1 return nil if list.length == 0 + list end @@ -57,7 +57,7 @@ def fields end if memo[f.predicate] if memo[f.predicate].kind_of?(String) - memo[f.predicate]=[val] + memo[f.predicate] = [val] else memo[f.predicate].push(val) end diff --git a/app/models/concerns/deprecatable.rb b/app/models/concerns/deprecatable.rb index 9c9655fb..d379bbd7 100644 --- a/app/models/concerns/deprecatable.rb +++ b/app/models/concerns/deprecatable.rb @@ -4,8 +4,8 @@ module Deprecatable has_many :supercedes, :class_name => self.name, :foreign_key => :superceded_by_id belongs_to :superceded_by, :class_name => self.name, :foreign_key => :superceded_by_id - scope :visible, -> { where( :superceded_by_id => nil ) } - scope :not_deprecated, -> { where( :superceded_by_id => nil ) } + scope :visible, -> { where(:superceded_by_id => nil) } + scope :not_deprecated, -> { where(:superceded_by_id => nil) } end def deprecated? diff --git a/app/models/concerns/uuidable.rb b/app/models/concerns/uuidable.rb index f508dc5b..5ba27cab 100644 --- a/app/models/concerns/uuidable.rb +++ b/app/models/concerns/uuidable.rb @@ -9,5 +9,4 @@ module Uuidable def uuid self[:uuid] ||= SecureRandom.uuid end - end diff --git a/app/models/condition.rb b/app/models/condition.rb index 356d5be7..0e440015 100644 --- a/app/models/condition.rb +++ b/app/models/condition.rb @@ -14,7 +14,7 @@ def check_wildcard_condition(asset, wildcard_values = {}) else facts = asset.facts.with_predicate(predicate) end - return false if facts.count==0 + return false if facts.count == 0 return false unless facts.first.respond_to?(:object_value) @@ -80,6 +80,7 @@ def compatible_with?(asset, related_assets = [], checked_condition_groups = [], return true if is_runtime_evaluable_condition? return false if asset.nil? return check_wildcard_condition(asset, wildcard_values) if is_wildcard_condition? + asset.facts.any? do |fact| # Either objects are equal, or both of them are relations to something. We # do not check the relations values, because we consider them as wildcards @@ -88,7 +89,7 @@ def compatible_with?(asset, related_assets = [], checked_condition_groups = [], else cg = ConditionGroup.find(object_condition_group_id) check_related_condition_group(cg, fact, related_assets, - checked_condition_groups, wildcard_values) + checked_condition_groups, wildcard_values) end end end diff --git a/app/models/condition_group.rb b/app/models/condition_group.rb index 64cc764e..65918d08 100644 --- a/app/models/condition_group.rb +++ b/app/models/condition_group.rb @@ -18,6 +18,7 @@ def select_compatible_assets(assets, position = nil) def compatible_with?(assets, related_assets = [], checked_condition_groups = [], wildcard_values = {}) assets = [assets].flatten return true if is_wildcard? + if ((cardinality) && (cardinality > 0)) return false if assets.kind_of?(Array) && (assets.length > cardinality) end @@ -38,7 +39,7 @@ def runtime_conditions def runtime_conditions_compatible_with?(asset, related_asset) runtime_conditions.all? do |c| - c.runtime_compatible_with?(asset,related_asset) + c.runtime_compatible_with?(asset, related_asset) end end diff --git a/app/models/fact.rb b/app/models/fact.rb index 897b5a94..3b123d82 100644 --- a/app/models/fact.rb +++ b/app/models/fact.rb @@ -6,7 +6,7 @@ class Fact < ApplicationRecord scope :not_to_remove, ->() { where(:to_remove_by => nil) } scope :with_predicate, ->(predicate) { where(:predicate => predicate) } scope :with_ns_predicate, ->(namespace) { where(:ns_predicate => namespace) } - scope :with_fact, -> (predicate, object) { where(:predicate => predicate, :object => object) } + scope :with_fact, ->(predicate, object) { where(:predicate => predicate, :object => object) } scope :from_remote_asset, ->() { where(:is_remote? => true) } scope :created_before, ->(date) { date.nil? ? all : where('created_at < ?', date) } @@ -39,13 +39,12 @@ def canonical_comparison_for_sorting(f2) f1 = self if f1.predicate == f2.predicate obj1 = f1.object || '?' - obj1 = '?' unless f1["object_asset_id"].nil? + obj1 = '?' unless f1["object_asset_id"].nil? obj2 = f1.object || '?' - obj2 = '?' unless f2["object_asset_id"].nil? + obj2 = '?' unless f2["object_asset_id"].nil? (obj1 <=> obj2) else f1.predicate <=> f2.predicate end end - end diff --git a/app/models/instrument.rb b/app/models/instrument.rb index e168da51..42989916 100644 --- a/app/models/instrument.rb +++ b/app/models/instrument.rb @@ -7,6 +7,7 @@ def compatible_with_kit?(kit) kit, kit.kit_type, kit.kit_type.activity_type, - activity_types.include?(kit.kit_type.activity_type)].all? + activity_types.include?(kit.kit_type.activity_type) + ].all? end end diff --git a/app/models/label_template.rb b/app/models/label_template.rb index 4c289213..c2e4d55b 100644 --- a/app/models/label_template.rb +++ b/app/models/label_template.rb @@ -6,12 +6,13 @@ def self.for_type(type, barcodetype = 'ean13') type = { 'Plate' => ['TubeRack', 'Plate'], 'Tube' => ['Tube', 'SampleTube'] - }.select { |k,v| v.include?(type) }.first[0] + }.select { |k, v| v.include?(type) }.first[0] templates = where(:template_type => type) templates_by_barcodetype = templates.select { |t| t.name.include?(barcodetype) } return templates if templates_by_barcodetype.empty? + return templates_by_barcodetype end end diff --git a/app/models/operation.rb b/app/models/operation.rb index 84ecf876..d4a89bdc 100644 --- a/app/models/operation.rb +++ b/app/models/operation.rb @@ -7,10 +7,10 @@ class Operation < ApplicationRecord scope :for_presenting, ->() { includes(:asset, :action) } - #def action_type + # def action_type # return action.action_type if action # return attributes["action_type"] - #end + # end def object_value object || object_asset @@ -41,9 +41,9 @@ def generate_changes_for(option_name, updates = nil) elsif (type == :remove_facts) updates.remove_where(self.asset, self.predicate, object_value) elsif (type == :create_assets) - #asset = Asset.create(uuid: object) - #update_attributes(asset: asset) - #updates.create_assets([asset.uuid]) + # asset = Asset.create(uuid: object) + # update_attributes(asset: asset) + # updates.create_assets([asset.uuid]) updates.create_assets([object]) elsif (type == :delete_assets) updates.delete_assets([object]) @@ -58,5 +58,4 @@ def generate_changes_for(option_name, updates = nil) end updates end - end diff --git a/app/models/printables/group.rb b/app/models/printables/group.rb index 860d3372..6f00b599 100644 --- a/app/models/printables/group.rb +++ b/app/models/printables/group.rb @@ -23,11 +23,12 @@ def print_assets(assets, printer_config, user) info_for_template.each do |label_template, assets| body_print = assets.filter_map { |a| a.printable_object(user) }.reverse next if body_print.empty? + PMB::PrintJob.new( - printer_name:printer_name, - label_template_id: label_template.external_id, - labels:{ body: body_print } - ).save + printer_name: printer_name, + label_template_id: label_template.external_id, + labels: { body: body_print } + ).save end end end diff --git a/app/models/printables/instance.rb b/app/models/printables/instance.rb index fb0b2cc3..cf8342c3 100644 --- a/app/models/printables/instance.rb +++ b/app/models/printables/instance.rb @@ -5,12 +5,13 @@ def print(printer_config, user) if !printer_config raise 'No printer config provided' end + printer_name = printer_config[Printer.printer_type_for(class_type)] label_template = LabelTemplate.for_type(class_type, barcode_type).first PMB::PrintJob.new( - printer_name:printer_name, + printer_name: printer_name, label_template_id: label_template.external_id, - labels:{ body: body_print } + labels: { body: body_print } ).save end end diff --git a/app/models/printables/print_asset.rb b/app/models/printables/print_asset.rb index 005bc435..5e4ee855 100644 --- a/app/models/printables/print_asset.rb +++ b/app/models/printables/print_asset.rb @@ -6,10 +6,10 @@ def print_list(user, printer_config, barcodes) asset.facts << Fact.create(predicate: 'barcodeType', object: 'Code128') asset end - + asset_group = AssetGroup.create asset_group.assets << assets asset_group.save asset_group.print(printer_config, user.username) end -end \ No newline at end of file +end diff --git a/app/models/printer.rb b/app/models/printer.rb index 9ed2e827..033e9af8 100644 --- a/app/models/printer.rb +++ b/app/models/printer.rb @@ -13,6 +13,6 @@ def self.printer_type_for(type) { 'Plate' => ['TubeRack', 'Plate'], 'Tube' => ['Tube', 'SampleTube'] - }.select { |k,v| v.include?(type) }.first[0] + }.select { |k, v| v.include?(type) }.first[0] end end diff --git a/app/models/step.rb b/app/models/step.rb index bdf07938..7193f868 100644 --- a/app/models/step.rb +++ b/app/models/step.rb @@ -1,6 +1,4 @@ - class Step < ApplicationRecord - self.inheritance_column = :sti_type attr_accessor :wildcard_values @@ -11,7 +9,7 @@ class Step < ApplicationRecord belongs_to :user has_many :uploads has_many :operations - has_many :step_messages #, dependent: :destroy + has_many :step_messages # , dependent: :destroy has_many :assets, through: :asset_group has_many :assets_affected, -> { distinct }, through: :operations, class_name: 'Asset', source: :asset has_many :asset_groups_affected, -> { distinct }, through: :assets_affected, class_name: 'AssetGroup', source: :asset_groups @@ -22,7 +20,7 @@ class Step < ApplicationRecord serialize :printer_config scope :running_with_asset, ->(asset) { includes(:assets).where(asset_groups_assets: { asset_id: asset.id }, state: 'running') } - scope :for_assets, ->(assets) { joins(:asset_group => :assets).where(:asset_groups_assets => { :asset_id => assets }) } + scope :for_assets, ->(assets) { joins(:asset_group => :assets).where(:asset_groups_assets => { :asset_id => assets }) } scope :for_step_type, ->(step_type) { where(:step_type => step_type) } include Deprecatable @@ -39,12 +37,11 @@ class Step < ApplicationRecord def set_errors(errors) ActiveRecord::Base.transaction do - step_messages.each(&:destroy) - errors.each do |error| - step_messages.create(step_id: self.id, content: error) - end + step_messages.each(&:destroy) + errors.each do |error| + step_messages.create(step_id: self.id, content: error) + end end wss_event end - end diff --git a/app/models/step_type.rb b/app/models/step_type.rb index fc359078..91ec6e53 100644 --- a/app/models/step_type.rb +++ b/app/models/step_type.rb @@ -1,9 +1,8 @@ require 'support_n3' class StepType < ApplicationRecord - before_update :remove_previous_conditions - after_save :create_next_conditions #, :unless => :for_reasoning? + after_save :create_next_conditions # , :unless => :for_reasoning? after_update :touch_activities @@ -46,7 +45,6 @@ def all_step_templates return ["", "upload_file"] end - def valid_name_file(names) names.select { |l| l.match(/^[A-Za-z]/) } end @@ -76,28 +74,29 @@ def all_runners_files end def all_step_actions - [#all_background_steps_files, + [ # all_background_steps_files, all_inferences_files, - all_runners_files].flatten + all_runners_files + ].flatten end def task_type return 'background_step' if (actions.count > 0) || step_action.nil? return 'cwm' if step_action&.end_with?('.n3') + return 'runner' end def class_for_task_type - if task_type=='cwm' + if task_type == 'cwm' Steps::BackgroundTasks::Inference - elsif task_type=='runner' + elsif task_type == 'runner' Steps::BackgroundTasks::Runner else Step end end - def create_next_conditions unless n3_definition.nil? SupportN3::parse_string(n3_definition, {}, self) @@ -130,20 +129,20 @@ def condition_group_classification_for(assets, checked_condition_groups = [], wi related_assets = [] h = assets.to_h { |asset| [asset, condition_groups_for(asset, related_assets, [], wildcard_values)] } related_assets.each do |a| - h[a]= condition_groups_for(a, [], checked_condition_groups, wildcard_values) + h[a] = condition_groups_for(a, [], checked_condition_groups, wildcard_values) end h end def every_condition_group_satisfies_cardinality(classification) # http://stackoverflow.com/questions/10989259/swapping-keys-and-values-in-a-hash - inverter_classification = classification.each_with_object({}) do |(k,v),o| + inverter_classification = classification.each_with_object({}) do |(k, v), o| v.each do |cg| - (o[cg]||=[])<= inverter_classification[condition_group].length) end end @@ -155,12 +154,13 @@ def every_condition_group_has_at_least_one_asset?(classification, cgroups = nil) def every_asset_has_at_least_one_condition_group?(classification) (classification.values.all? do |condition_group| - ([condition_group].flatten.length>=1) + ([condition_group].flatten.length >= 1) end) end def every_required_asset_is_in_classification?(classification, required_assets) return true if required_assets.nil? + required_assets.all? { |asset| !classification[asset].empty? } end @@ -169,17 +169,18 @@ def compatible_with?(assets, required_assets = nil, checked_condition_groups = [ # Every asset has at least one condition group satisfied classification = condition_group_classification_for(assets, checked_condition_groups, wildcard_values) compatible = every_condition_group_satisfies_cardinality(classification) && - every_condition_group_has_at_least_one_asset?(classification) && - every_asset_has_at_least_one_condition_group?(classification) && - every_required_asset_is_in_classification?(classification, required_assets) + every_condition_group_has_at_least_one_asset?(classification) && + every_asset_has_at_least_one_condition_group?(classification) && + every_required_asset_is_in_classification?(classification, required_assets) return true if compatible + return false end def condition_groups_for(asset, related_assets = [], checked_condition_groups = [], wildcard_values = {}) condition_groups.select do |condition_group| condition_group.compatible_with?([asset].flatten, related_assets, checked_condition_groups, wildcard_values) - #condition_group.conditions_compatible_with?(asset, related_assets) + # condition_group.conditions_compatible_with?(asset, related_assets) end end @@ -197,20 +198,21 @@ def check_dependency_compatibility_for(asset, condition_group, assets) cg.conditions.select { |c| c.object_condition_group == condition_group }.count > 0 end return true if check_cgs.empty? + ancestors = assets.select { |a| a.facts.any? { |f| f.object_asset == asset } }.uniq return true if ancestors.empty? classification = classification_for(ancestors, check_cgs) compatible = every_condition_group_satisfies_cardinality(classification) && - every_condition_group_has_at_least_one_asset?(classification, check_cgs) && - every_asset_has_at_least_one_condition_group?(classification) + every_condition_group_has_at_least_one_asset?(classification, check_cgs) && + every_asset_has_at_least_one_condition_group?(classification) return true if compatible + return false end def to_n3 render :n3 end - end diff --git a/app/models/steps/background_tasks/inference.rb b/app/models/steps/background_tasks/inference.rb index 26347f43..cbc51b60 100644 --- a/app/models/steps/background_tasks/inference.rb +++ b/app/models/steps/background_tasks/inference.rb @@ -1,7 +1,6 @@ require 'inference_engines/cwm/step_execution' class Steps::BackgroundTasks::Inference < Step - def process inferences = InferenceEngines::Cwm::StepExecution.new( :step => self, @@ -11,5 +10,4 @@ def process ) inferences.run end - end diff --git a/app/models/steps/background_tasks/runner.rb b/app/models/steps/background_tasks/runner.rb index ef4eb654..69a806b9 100644 --- a/app/models/steps/background_tasks/runner.rb +++ b/app/models/steps/background_tasks/runner.rb @@ -1,7 +1,6 @@ require 'inference_engines/runner/step_execution' class Steps::BackgroundTasks::Runner < Step - def process runner = InferenceEngines::Runner::StepExecution.new( :step => self, @@ -11,5 +10,4 @@ def process ) runner.run end - end diff --git a/app/models/steps/cancellable.rb b/app/models/steps/cancellable.rb index c4b42ba8..6c198f08 100644 --- a/app/models/steps/cancellable.rb +++ b/app/models/steps/cancellable.rb @@ -28,11 +28,13 @@ def cancellable? def steps_newer_than_me return Step.none unless activity + activity.steps.newer_than(self) end def steps_older_than_me return Step.none unless activity + activity.steps.older_than(self) end @@ -50,7 +52,6 @@ def _remake_me end end - def _cancel_me_and_any_newer_completed_steps(change_state = true) changes = [ fact_changes_for_option(:cancel), @@ -89,5 +90,4 @@ def fact_changes_for_option(option_name) updates end end - end diff --git a/app/models/steps/compatible.rb b/app/models/steps/compatible.rb index df523afd..b8a92e00 100644 --- a/app/models/steps/compatible.rb +++ b/app/models/steps/compatible.rb @@ -1,8 +1,8 @@ module Steps::Compatible - def assets_compatible_with_step_type return true if asset_group.nil? - checked_condition_groups=[], @wildcard_values = {} + + checked_condition_groups = [], @wildcard_values = {} compatible = step_type.compatible_with?(asset_group_assets, nil, checked_condition_groups, wildcard_values) return compatible end @@ -10,5 +10,4 @@ def assets_compatible_with_step_type def asset_group_assets asset_group ? asset_group.assets : [] end - end diff --git a/app/models/steps/deprecatable.rb b/app/models/steps/deprecatable.rb index fccee9a7..98ea4c4b 100644 --- a/app/models/steps/deprecatable.rb +++ b/app/models/steps/deprecatable.rb @@ -6,12 +6,13 @@ def self.included(klass) end def following_step_ids - obj=self - list=[] + obj = self + list = [] loop do id = obj.next_step_id return list if id.nil? return list if list.include?(id) + list.push(id) obj = next_step end @@ -33,5 +34,4 @@ def remove_from_activity self.activity = nil save! end - end diff --git a/app/models/steps/job.rb b/app/models/steps/job.rb index 82af4a4c..2cd9aeb5 100644 --- a/app/models/steps/job.rb +++ b/app/models/steps/job.rb @@ -1,5 +1,4 @@ module Steps::Job - def create_job save_job(delay(queue: 'steps').perform_job) end @@ -12,7 +11,7 @@ def save_job(delayed_job) def clear_job self.job_id = nil - @error=nil + @error = nil save! end @@ -24,6 +23,7 @@ def save_error_output def output_error(exception) return output unless exception + [ output, exception && exception.message, Rails.backtrace_cleaner.clean(exception && exception.backtrace) @@ -50,5 +50,4 @@ def perform_job fail! end end - end diff --git a/app/models/steps/queueable_job.rb b/app/models/steps/queueable_job.rb index 275f10ed..4a68f397 100644 --- a/app/models/steps/queueable_job.rb +++ b/app/models/steps/queueable_job.rb @@ -1,5 +1,4 @@ module Steps::QueueableJob - def self.included(klass) klass.instance_eval do after_update :run_next_step, if: :can_run_next_step? @@ -29,5 +28,4 @@ def run_next_step def can_run_next_step? activity && activity.running? && completed? && next_step && !next_step.completed? && !next_step.running? end - end diff --git a/app/models/steps/retryable.rb b/app/models/steps/retryable.rb index 34049a78..59696bca 100644 --- a/app/models/steps/retryable.rb +++ b/app/models/steps/retryable.rb @@ -1,5 +1,4 @@ module Steps::Retryable - def on_retrying if ((state == 'retrying') && (state_was == 'error')) delay(queue: 'steps').on_retry diff --git a/app/models/steps/state.rb b/app/models/steps/state.rb index 2cc5675b..cb68f3f9 100644 --- a/app/models/steps/state.rb +++ b/app/models/steps/state.rb @@ -5,7 +5,6 @@ module Steps::State EVENT_REMAKE = 'remake' EVENT_CANCEL = 'cancel' - def self.included(klass) klass.instance_eval do scope :in_progress, ->() { where(:in_progress? => true) } @@ -23,10 +22,8 @@ def self.included(klass) scope :finished, ->() { includes(:operations, :step_type) } scope :in_activity, ->() { where.not(activity_id: nil) } - include AASM - aasm column: :state do state :pending, initial: true @@ -43,13 +40,13 @@ def self.included(klass) event :complete do transitions from: :cancelled, to: :complete - transitions from: [:running,:remaking], to: :complete, after: [ + transitions from: [:running, :remaking], to: :complete, after: [ :clear_job, :set_complete_timestamp! ] end event :cancelled do - transitions from: [:cancelling,:complete], to: :cancelled + transitions from: [:cancelling, :complete], to: :cancelled end event :run, guards: [:assets_compatible_with_step_type] do @@ -70,9 +67,9 @@ def self.included(klass) after: :remake_me_and_any_older_cancelled_steps end - event :continue, guards: [:assets_compatible_with_step_type] do + event :continue, guards: [:assets_compatible_with_step_type] do transitions from: :running, to: :running - transitions from: [:failed,:stopped,:pending], to: :running, after: [:continue_newer_steps, :run] + transitions from: [:failed, :stopped, :pending], to: :running, after: [:continue_newer_steps, :run] end event :stop do @@ -112,16 +109,16 @@ def processing? def is_processing_state?(state) return false if state.nil? + running? || cancelling? || remaking? end def active? running? || pending? - #((self.state == 'running') || (self.state.nil?)) + # ((self.state == 'running') || (self.state.nil?)) end def completed? complete? end - end diff --git a/app/models/steps/stoppable.rb b/app/models/steps/stoppable.rb index 456fd3d6..ae223049 100644 --- a/app/models/steps/stoppable.rb +++ b/app/models/steps/stoppable.rb @@ -16,5 +16,4 @@ def continue_newer_steps def stop_newer_steps activity.steps.newer_than(self).active.each(&:stop!) end - end diff --git a/app/models/steps/task.rb b/app/models/steps/task.rb index 95fe1d7d..6cb23dbf 100644 --- a/app/models/steps/task.rb +++ b/app/models/steps/task.rb @@ -43,6 +43,7 @@ def process def apply_changes(updates) reload return false if stopped? + updates.apply(self) true end diff --git a/app/models/steps/websocket_events.rb b/app/models/steps/websocket_events.rb index 84a60154..ac5b8ec8 100644 --- a/app/models/steps/websocket_events.rb +++ b/app/models/steps/websocket_events.rb @@ -1,8 +1,8 @@ module Steps::WebsocketEvents def self.included(klass) klass.instance_eval do - #after_update :unset_activity_running, if: :can_unset_activity_running? - #after_update :wss_event + # after_update :unset_activity_running, if: :can_unset_activity_running? + # after_update :wss_event end end @@ -18,5 +18,4 @@ def unset_activity_running def wss_event [activity].concat(activities_affected).compact.uniq.each(&:touch) end - end diff --git a/app/models/uploaded_file.rb b/app/models/uploaded_file.rb index eadadd19..c4b5bbcf 100644 --- a/app/models/uploaded_file.rb +++ b/app/models/uploaded_file.rb @@ -9,8 +9,9 @@ def step end def file_type(content_type) - return 'XML' if content_type=='text/xml' - return 'CSV' if content_type=='text/csv' + return 'XML' if content_type == 'text/xml' + return 'CSV' if content_type == 'text/csv' + return 'Unknown' end diff --git a/app/models/user.rb b/app/models/user.rb index 2dd1accf..454fc77c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -9,10 +9,10 @@ class User < ApplicationRecord def set_default_printers update_attributes( :tube_printer => Printer.for_tube.for_default.first, - ) if tube_printer.nil? + ) if tube_printer.nil? update_attributes( :plate_printer => Printer.for_plate.for_default.first, - ) if plate_printer.nil? + ) if plate_printer.nil? end def tube_printer_name @@ -43,6 +43,4 @@ def printer_config 'Plate' => plate_printer_name } end - - end diff --git a/app/resources/api/v1/asset_resource.rb b/app/resources/api/v1/asset_resource.rb index 57a1d3c2..68a9b190 100644 --- a/app/resources/api/v1/asset_resource.rb +++ b/app/resources/api/v1/asset_resource.rb @@ -3,7 +3,7 @@ module V1 class AssetResource < JSONAPI::Resource primary_key :uuid attributes :uuid, :asset_type, :barcode, :sample_uuid, :study_uuid, :pipeline, :library_type, - :estimate_of_gb_required, :number_of_smrt_cells, :cost_code, :species, :fields + :estimate_of_gb_required, :number_of_smrt_cells, :cost_code, :species, :fields filters :barcode end end diff --git a/app/views/printers/_printer.json.jbuilder b/app/views/printers/_printer.json.jbuilder index f805c0a2..c1d98cf5 100644 --- a/app/views/printers/_printer.json.jbuilder +++ b/app/views/printers/_printer.json.jbuilder @@ -1,2 +1,2 @@ json.extract! printer, :id, :created_at, :updated_at -json.url printer_url(printer, format: :json) \ No newline at end of file +json.url printer_url(printer, format: :json) diff --git a/app/views/printers/index.json.jbuilder b/app/views/printers/index.json.jbuilder index 6ae324a2..849a3b93 100644 --- a/app/views/printers/index.json.jbuilder +++ b/app/views/printers/index.json.jbuilder @@ -1 +1 @@ -json.array! @printers, partial: 'printers/printer', as: :printer \ No newline at end of file +json.array! @printers, partial: 'printers/printer', as: :printer diff --git a/app/views/printers/show.json.jbuilder b/app/views/printers/show.json.jbuilder index 9ac70ef3..0f6007b7 100644 --- a/app/views/printers/show.json.jbuilder +++ b/app/views/printers/show.json.jbuilder @@ -1 +1 @@ -json.partial! "printers/printer", printer: @printer \ No newline at end of file +json.partial! "printers/printer", printer: @printer diff --git a/app/views/users/index.json.jbuilder b/app/views/users/index.json.jbuilder index d6891e61..2faf5af0 100644 --- a/app/views/users/index.json.jbuilder +++ b/app/views/users/index.json.jbuilder @@ -1 +1 @@ -json.array! @users, partial: 'users/user', as: :user \ No newline at end of file +json.array! @users, partial: 'users/user', as: :user diff --git a/app/views/users/show.json.jbuilder b/app/views/users/show.json.jbuilder index a2e64e04..ff40bb96 100644 --- a/app/views/users/show.json.jbuilder +++ b/app/views/users/show.json.jbuilder @@ -1 +1 @@ -json.partial! "users/user", user: @user \ No newline at end of file +json.partial! "users/user", user: @user diff --git a/config/environments/development.rb b/config/environments/development.rb index 5486ac1b..e33f1b02 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -14,7 +14,7 @@ config.eager_load = true # Show full error reports - config.consider_all_requests_local = true + config.consider_all_requests_local = true # Enable/disable caching. By default caching is disabled. # Run rails dev:cache to toggle caching. @@ -67,7 +67,7 @@ # Raises error for missing translations # config.action_view.raise_on_missing_translations = true - config.pmb_uri = ENV.fetch('SE_PMB_URI','http://localhost:10000/v1') + config.pmb_uri = ENV.fetch('SE_PMB_URI', 'http://localhost:10000/v1') config.redis_url = ENV.fetch('SE_REDIS_URI', 'redis://127.0.0.1:6379') config.ss_uri = ENV.fetch('SE_SS_URI', 'http://localhost:3000/api/1/') config.ss_api_v2_uri = ENV.fetch('SE_SS_API_V2_URI', 'http://localhost:3000') @@ -75,7 +75,7 @@ config.searcher_name_by_barcode = 'Find assets by barcode' config.searcher_study_by_name = 'Find study by name' config.printing_disabled = true - config.redis_enabled=true + config.redis_enabled = true config.inference_engine = :default config.cwm_path = ENV.fetch('CWM_PATH', '') diff --git a/config/environments/production.rb b/config/environments/production.rb index ca2fc276..057804bd 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -49,11 +49,10 @@ config.time_zone = 'London' config.eager_load = true - # Raises error for missing translations # config.action_view.raise_on_missing_translations = true - config.pmb_uri = ENV.fetch('SE_PMB_URI','http://localhost:10000/v1') + config.pmb_uri = ENV.fetch('SE_PMB_URI', 'http://localhost:10000/v1') config.redis_url = ENV.fetch('SE_REDIS_URI', 'redis://127.0.0.1:6379') config.ss_uri = ENV.fetch('SE_SS_URI', 'http://localhost:3000/api/1/') config.ss_api_v2_uri = ENV.fetch('SE_SS_API_V2_URI', 'http://localhost:3000') @@ -62,14 +61,13 @@ config.searcher_name_by_barcode = 'Find assets by barcode' config.searcher_name_by_barcode = 'Find assets by barcode' - config.printing_enabled = ENV.fetch('PRINTING_ENABLED', '')=='true' + config.printing_enabled = ENV.fetch('PRINTING_ENABLED', '') == 'true' config.printing_disabled = !config.printing_enabled - config.redis_enabled=true + config.redis_enabled = true config.inference_engine = :default config.cwm_path = ENV.fetch('CWM_PATH', '') config.default_n3_resources_url = ENV.fetch('N3_RESOURCES_URL', '') config.enable_reasoning = true - end diff --git a/config/environments/test.rb b/config/environments/test.rb index 3c396126..1b9922e9 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -10,11 +10,10 @@ # Do not eager load code on boot. This avoids loading your whole application # just for the purpose of running a single test. If you are using a tool that # preloads Rails for running tests, you may have to set it to true. - #config.eager_load = false + # config.eager_load = false config.allow_concurrency = false config.eager_load = true - # Configure static file server for tests with Cache-Control for performance. config.public_file_server.enabled = true config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' } @@ -42,10 +41,9 @@ config.middleware.use RackSessionAccess::Middleware - # Raises error for missing translations # config.action_view.raise_on_missing_translations = true - config.pmb_uri = ENV.fetch('SE_PMB_URI','http://localhost:10000/v1') + config.pmb_uri = ENV.fetch('SE_PMB_URI', 'http://localhost:10000/v1') config.redis_url = ENV.fetch('SE_REDIS_URI', 'redis://127.0.0.1:6379') config.ss_uri = ENV.fetch('SE_SS_URI', 'http://localhost:3000/api/1/') config.ss_api_v2_uri = ENV.fetch('SE_SS_API_V2_URI', 'http://localhost:3000') diff --git a/config/initializers/inference_engine.rb b/config/initializers/inference_engine.rb index 30dc94a5..d82a7802 100644 --- a/config/initializers/inference_engine.rb +++ b/config/initializers/inference_engine.rb @@ -2,6 +2,7 @@ if Rails.configuration.inference_engine == :cwm raise 'Not found CWM' unless Rails.configuration.cwm_path + require 'inference_engines/cwm/step_execution' StepExecution = InferenceEngines::Cwm::StepExecution else diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index 51698dbf..80dc71bc 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,4 +1,4 @@ # Be sure to restart your server when you modify this file. -#Rails.application.config.session_store :active_record_store, key: '_samples_extraction_session' +# Rails.application.config.session_store :active_record_store, key: '_samples_extraction_session' Rails.application.config.session_store :cookie_store, key: '_samples_extraction_session' diff --git a/config/routes.rb b/config/routes.rb index 83c79305..edd9f7df 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,9 +1,7 @@ - require 'sass' require 'bootstrap-sass' Rails.application.routes.draw do - resources :printers resources :user_sessions do collection do @@ -22,7 +20,6 @@ get 'print' post 'upload', to: 'asset_groups#upload' end - end resources :activities do @@ -53,7 +50,7 @@ end root 'instruments#index' - #root 'activity_types#index' + # root 'activity_types#index' resources :samples_started resources :samples_not_started @@ -61,19 +58,16 @@ resources :reracking resources :uploaded_files, only: [:create, :show] - # Trying to make fonts work out in poltergeist get '/fonts/bootstrap/:name', to: redirect('/assets/bootstrap/%{name}') - namespace :api do namespace :v1 do jsonapi_resources :assets end end - #namespace :aker do + # namespace :aker do # resources :work_orders, only: [:create, :index] - #end - + # end end diff --git a/db/migrate/20160626224627_create_condition_groups.rb b/db/migrate/20160626224627_create_condition_groups.rb index 4d74b2fb..40f2140d 100644 --- a/db/migrate/20160626224627_create_condition_groups.rb +++ b/db/migrate/20160626224627_create_condition_groups.rb @@ -8,4 +8,3 @@ def change end end end - diff --git a/db/migrate/20160705084036_create_uploads.rb b/db/migrate/20160705084036_create_uploads.rb index fbf1ec10..9dfb20c0 100644 --- a/db/migrate/20160705084036_create_uploads.rb +++ b/db/migrate/20160705084036_create_uploads.rb @@ -3,7 +3,7 @@ def change create_table :uploads do |t| t.references :step, index: true, foreign_key: true t.references :activity, index: true, foreign_key: true - t.binary :data , :limit => 10.megabyte + t.binary :data, :limit => 10.megabyte t.string :filename t.string :content_type t.timestamps diff --git a/db/migrate/20170122173205_add_state_to_step.rb b/db/migrate/20170122173205_add_state_to_step.rb index 0a004bc4..49a6858b 100644 --- a/db/migrate/20170122173205_add_state_to_step.rb +++ b/db/migrate/20170122173205_add_state_to_step.rb @@ -2,6 +2,6 @@ class AddStateToStep < ActiveRecord::Migration def change ActiveRecord::Base.transaction do |t| add_column :steps, :state, :string - end + end end end diff --git a/db/migrate/20170128170039_add_namespace_to_fact_predicate.rb b/db/migrate/20170128170039_add_namespace_to_fact_predicate.rb index 2d465e69..d3f2f8f1 100644 --- a/db/migrate/20170128170039_add_namespace_to_fact_predicate.rb +++ b/db/migrate/20170128170039_add_namespace_to_fact_predicate.rb @@ -2,6 +2,6 @@ class AddNamespaceToFactPredicate < ActiveRecord::Migration def change ActiveRecord::Base.transaction do |t| add_column :facts, :ns_predicate, :string - end + end end end diff --git a/db/migrate/20170212120729_add_group_owned_to_activity.rb b/db/migrate/20170212120729_add_group_owned_to_activity.rb index 923f7c90..6053a060 100644 --- a/db/migrate/20170212120729_add_group_owned_to_activity.rb +++ b/db/migrate/20170212120729_add_group_owned_to_activity.rb @@ -1,6 +1,6 @@ class AddGroupOwnedToActivity < ActiveRecord::Migration def change - ActiveRecord::Base.transaction do + ActiveRecord::Base.transaction do add_column :asset_groups, :activity_owner_id, :integer add_column :asset_groups, :condition_group_id, :integer end diff --git a/db/migrate/20170608101740_remove_unneeded_tables.rb b/db/migrate/20170608101740_remove_unneeded_tables.rb index e4e3595d..d075ddda 100644 --- a/db/migrate/20170608101740_remove_unneeded_tables.rb +++ b/db/migrate/20170608101740_remove_unneeded_tables.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + class RemoveUnneededTables < ActiveRecord::Migration def change drop_table :asset_groups_steps diff --git a/db/migrate/20170917175535_add_from_remote_to_facts.rb b/db/migrate/20170917175535_add_from_remote_to_facts.rb index 00b295f1..15cd200d 100644 --- a/db/migrate/20170917175535_add_from_remote_to_facts.rb +++ b/db/migrate/20170917175535_add_from_remote_to_facts.rb @@ -1,8 +1,8 @@ class AddFromRemoteToFacts < ActiveRecord::Migration def change - ActiveRecord::Base.transaction do - add_column :facts, :is_remote?, :boolean, default: false - add_column :assets, :remote_digest, :string - end + ActiveRecord::Base.transaction do + add_column :facts, :is_remote?, :boolean, default: false + add_column :assets, :remote_digest, :string + end end end diff --git a/db/migrate/20171205163743_add_work_orders_table.rb b/db/migrate/20171205163743_add_work_orders_table.rb index 7a6496d3..133e11e1 100644 --- a/db/migrate/20171205163743_add_work_orders_table.rb +++ b/db/migrate/20171205163743_add_work_orders_table.rb @@ -4,6 +4,6 @@ def change t.integer :work_order_id, index: true, unique: true t.references :activity, index: true, foreign_key: true, unique: true t.timestamps null: false - end + end end end diff --git a/db/migrate/20171210183629_add_sti_to_step.rb b/db/migrate/20171210183629_add_sti_to_step.rb index 1bf11f3a..3f2240df 100644 --- a/db/migrate/20171210183629_add_sti_to_step.rb +++ b/db/migrate/20171210183629_add_sti_to_step.rb @@ -1,5 +1,5 @@ class AddStiToStep < ActiveRecord::Migration def change - add_column :steps, :sti_type, :string + add_column :steps, :sti_type, :string end end diff --git a/db/migrate/20180428131814_create_uploaded_files.rb b/db/migrate/20180428131814_create_uploaded_files.rb index ffee6053..539c20c8 100644 --- a/db/migrate/20180428131814_create_uploaded_files.rb +++ b/db/migrate/20180428131814_create_uploaded_files.rb @@ -1,12 +1,12 @@ class CreateUploadedFiles < ActiveRecord::Migration[5.1] def change create_table :uploaded_files, force: true do |t| - #t.references :asset_group, index: true, foreign_key: true + # t.references :asset_group, index: true, foreign_key: true t.integer :asset_id, index: true - t.binary :data , :limit => 10.megabyte + t.binary :data, :limit => 10.megabyte t.string :filename t.string :content_type - t.timestamps + t.timestamps end end end diff --git a/db/migrate/20190407165821_add_task_type_to_step_type.rb b/db/migrate/20190407165821_add_task_type_to_step_type.rb index 19a0aaac..133702da 100644 --- a/db/migrate/20190407165821_add_task_type_to_step_type.rb +++ b/db/migrate/20190407165821_add_task_type_to_step_type.rb @@ -1,5 +1,5 @@ class AddTaskTypeToStepType < ActiveRecord::Migration[5.1] def change - add_column :step_types, :task_type, :string, default: nil, null: true + add_column :step_types, :task_type, :string, default: nil, null: true end end diff --git a/db/migrate/20190407165921_migrate_reasoning_to_task_type.rb b/db/migrate/20190407165921_migrate_reasoning_to_task_type.rb index 66416677..669e29a9 100644 --- a/db/migrate/20190407165921_migrate_reasoning_to_task_type.rb +++ b/db/migrate/20190407165921_migrate_reasoning_to_task_type.rb @@ -1,5 +1,5 @@ class MigrateReasoningToTaskType < ActiveRecord::Migration[5.1] def change - #StepType.for_reasoning.update_all(task_type: 'cwm') + # StepType.for_reasoning.update_all(task_type: 'cwm') end end diff --git a/db/migrate/20190717130805_change_sti_type.rb b/db/migrate/20190717130805_change_sti_type.rb index 7a353ccb..8200608b 100644 --- a/db/migrate/20190717130805_change_sti_type.rb +++ b/db/migrate/20190717130805_change_sti_type.rb @@ -2,7 +2,6 @@ class ChangeStiType < ActiveRecord::Migration[5.1] def change ActiveRecord::Base.transaction do Step.where(sti_type: "Steps::BackgroundTasks::BackgroundTask").update_all(sti_type: 'Step') - end end end diff --git a/db/migrate/20200709123033_create_heron_activities_view.rb b/db/migrate/20200709123033_create_heron_activities_view.rb index 33c41e93..760b317f 100644 --- a/db/migrate/20200709123033_create_heron_activities_view.rb +++ b/db/migrate/20200709123033_create_heron_activities_view.rb @@ -48,7 +48,7 @@ def up 'CGAP Heron Extraction 200ul - 24ul', 'Heron R&D Extraction') SQL - ) + ) end def down diff --git a/db/seeds.rb b/db/seeds.rb index 89b85b19..eaf41de8 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -89,4 +89,4 @@ }] ].map { |l| StepType.create(name: l[0], step_action: l[1], n3_definition: l[2]) } -#reracking_activity_type.step_types << runners +# reracking_activity_type.step_types << runners diff --git a/db/views_schema.rb b/db/views_schema.rb index 799bd806..6f43b746 100644 --- a/db/views_schema.rb +++ b/db/views_schema.rb @@ -1,7 +1,7 @@ # This is an automatically generated file by rake:db:views:dump_schema require 'views_schema' ViewsSchema.create_view( -'heron_activities_view', -%Q{select ifnull(`supplier_name_fact`.`object`,`well_supplier_name_fact`.`object`) AS `Supplier sample name`,`input_asset`.`barcode` AS `Input barcode`,`output_asset`.`barcode` AS `Output barcode`,`activity_types`.`name` AS `Activity type`,`instruments`.`name` AS `Instrument`,`kits`.`barcode` AS `Kit barcode`,`kit_types`.`name` AS `Kit type`,`ac`.`completed_at` AS `Date`,`users`.`fullname` AS `User`,`ac`.`id` AS `_activity_id_` from (((((((((((`activities` `ac` left join `asset_groups_assets` `aga` on((`aga`.`asset_group_id` = `ac`.`asset_group_id`))) left join `assets` `output_asset` on((`output_asset`.`id` = `aga`.`asset_id`))) left join `activity_types` on((`ac`.`activity_type_id` = `activity_types`.`id`))) left join `kits` on((`ac`.`kit_id` = `kits`.`id`))) left join `kit_types` on((`kits`.`kit_type_id` = `kit_types`.`id`))) left join `instruments` on((`ac`.`instrument_id` = `instruments`.`id`))) left join `facts` `supplier_name_fact` on(((`supplier_name_fact`.`asset_id` = `output_asset`.`id`) and (`supplier_name_fact`.`predicate` = 'supplier_sample_name')))) left join `facts` `well_fact` on(((`well_fact`.`asset_id` = `output_asset`.`id`) and (`well_fact`.`predicate` = 'contains')))) left join `facts` `well_supplier_name_fact` on(((`well_supplier_name_fact`.`asset_id` = `well_fact`.`object_asset_id`) and (`well_supplier_name_fact`.`predicate` = 'supplier_sample_name')))) left join `assets` `input_asset` on((`input_asset`.`id` = (select `operations`.`object_asset_id` from (`operations` join `steps` on((`steps`.`id` = `operations`.`step_id`))) where ((`operations`.`predicate` = 'transferredFrom') and (`steps`.`activity_id` = `ac`.`id`) and (`operations`.`object_asset_id` is not null)) order by `operations`.`created_at`,`operations`.`id` limit 1)))) left join `users` on((`users`.`id` = (select `steps`.`user_id` from `steps` where ((`steps`.`activity_id` = `ac`.`id`) and (`steps`.`user_id` is not null)) order by `steps`.`created_at`,`steps`.`id` desc limit 1)))) where ((`ac`.`state` = 'finish') and ((`supplier_name_fact`.`id` is not null) or (`well_supplier_name_fact`.`id` is not null)) and (`activity_types`.`name` in ('CGAP Heron Extraction 500ul - 16ul','CGAP Heron Extraction 500ul - 24ul','Illumina Extraction','DNAP Heron Extraction 500ul - 24ul','CGAP Heron Extraction 200ul - 24ul','Heron R&D Extraction')))}, -algorithm: 'UNDEFINED', security: 'DEFINER' + 'heron_activities_view', + %Q{select ifnull(`supplier_name_fact`.`object`,`well_supplier_name_fact`.`object`) AS `Supplier sample name`,`input_asset`.`barcode` AS `Input barcode`,`output_asset`.`barcode` AS `Output barcode`,`activity_types`.`name` AS `Activity type`,`instruments`.`name` AS `Instrument`,`kits`.`barcode` AS `Kit barcode`,`kit_types`.`name` AS `Kit type`,`ac`.`completed_at` AS `Date`,`users`.`fullname` AS `User`,`ac`.`id` AS `_activity_id_` from (((((((((((`activities` `ac` left join `asset_groups_assets` `aga` on((`aga`.`asset_group_id` = `ac`.`asset_group_id`))) left join `assets` `output_asset` on((`output_asset`.`id` = `aga`.`asset_id`))) left join `activity_types` on((`ac`.`activity_type_id` = `activity_types`.`id`))) left join `kits` on((`ac`.`kit_id` = `kits`.`id`))) left join `kit_types` on((`kits`.`kit_type_id` = `kit_types`.`id`))) left join `instruments` on((`ac`.`instrument_id` = `instruments`.`id`))) left join `facts` `supplier_name_fact` on(((`supplier_name_fact`.`asset_id` = `output_asset`.`id`) and (`supplier_name_fact`.`predicate` = 'supplier_sample_name')))) left join `facts` `well_fact` on(((`well_fact`.`asset_id` = `output_asset`.`id`) and (`well_fact`.`predicate` = 'contains')))) left join `facts` `well_supplier_name_fact` on(((`well_supplier_name_fact`.`asset_id` = `well_fact`.`object_asset_id`) and (`well_supplier_name_fact`.`predicate` = 'supplier_sample_name')))) left join `assets` `input_asset` on((`input_asset`.`id` = (select `operations`.`object_asset_id` from (`operations` join `steps` on((`steps`.`id` = `operations`.`step_id`))) where ((`operations`.`predicate` = 'transferredFrom') and (`steps`.`activity_id` = `ac`.`id`) and (`operations`.`object_asset_id` is not null)) order by `operations`.`created_at`,`operations`.`id` limit 1)))) left join `users` on((`users`.`id` = (select `steps`.`user_id` from `steps` where ((`steps`.`activity_id` = `ac`.`id`) and (`steps`.`user_id` is not null)) order by `steps`.`created_at`,`steps`.`id` desc limit 1)))) where ((`ac`.`state` = 'finish') and ((`supplier_name_fact`.`id` is not null) or (`well_supplier_name_fact`.`id` is not null)) and (`activity_types`.`name` in ('CGAP Heron Extraction 500ul - 16ul','CGAP Heron Extraction 500ul - 24ul','Illumina Extraction','DNAP Heron Extraction 500ul - 24ul','CGAP Heron Extraction 200ul - 24ul','Heron R&D Extraction')))}, + algorithm: 'UNDEFINED', security: 'DEFINER' ) diff --git a/lib/actions/plate_transfer.rb b/lib/actions/plate_transfer.rb index 4704140a..63459528 100644 --- a/lib/actions/plate_transfer.rb +++ b/lib/actions/plate_transfer.rb @@ -2,7 +2,7 @@ module Actions module PlateTransfer def self.to_sequencescape_location(location) loc = location.match(/(\w)(0*)(\d*)/) - loc[1]+loc[3] + loc[1] + loc[3] end def self.ignored_predicates_for_existing_well @@ -16,6 +16,7 @@ def self.ignored_predicates_for_new_well def self.validate_plate_is_compatible_with_aliquot(updates, plate, aliquotType) aliquots = plate.facts.with_predicate('aliquotType').map(&:object).uniq return true if aliquots.empty? + if ((aliquots.size != 1) || (aliquots.first != aliquotType)) updates.set_errors( ["The plate #{plate.barcode} contains aliquot #{aliquots.first} which is not compatible with #{aliquotType}"] @@ -25,10 +26,10 @@ def self.validate_plate_is_compatible_with_aliquot(updates, plate, aliquotType) true end - def self.validate_tube_is_compatible_with_aliquot(updates, tube, aliquotType) aliquots = tube.facts.with_predicate('aliquotType').map(&:object).uniq return true if aliquots.empty? + if ((aliquots.size != 1) || (aliquots.first != aliquotType)) updates.set_errors( ["The tube #{tube.barcode} contains aliquot #{aliquots.first} which is not compatible with #{aliquotType}"] diff --git a/lib/actions/racking.rb b/lib/actions/racking.rb index b03dbebe..1b532f7c 100644 --- a/lib/actions/racking.rb +++ b/lib/actions/racking.rb @@ -14,21 +14,19 @@ def initialize(message = nil) def html_error_message(error_messages) ['
    ', error_messages.map do |msg| - ['
  • ',msg,'
  • '] + ['
  • ', msg, '
  • '] end, '
'].flatten.join end - end module Actions module Racking - DNA_STOCK_PLATE_PURPOSE = 'DNA Stock Plate' RNA_STOCK_PLATE_PURPOSE = 'RNA Stock Plate' STOCK_PLATE_PURPOSE = 'Stock Plate' DNA_ALIQUOT = 'DNA' RNA_ALIQUOT = 'RNA' - TUBE_TO_PLATE_TRANSFERRABLE_PROPERTIES = [:study_name,:aliquotType] + TUBE_TO_PLATE_TRANSFERRABLE_PROPERTIES = [:study_name, :aliquotType] ALIQUOT_PURPOSE = { DNA_ALIQUOT => DNA_STOCK_PLATE_PURPOSE, @@ -44,22 +42,21 @@ def rack_layout(asset_group) def rack_layout_creating_tubes(asset_group) content = selected_file(asset_group).data parser = Parsers::CsvLayout::CsvParser.new(content, { - barcode_parser: Parsers::CsvLayout::BarcodeCreatableParser - }) + barcode_parser: Parsers::CsvLayout::BarcodeCreatableParser + }) csv_parsing(asset_group, parser) end def rack_layout_any_barcode(asset_group) content = selected_file(asset_group).data parser = Parsers::CsvLayout::CsvParser.new(content, { - barcode_validator: Parsers::CsvLayout::Validators::AnyBarcodeValidator - }) + barcode_validator: Parsers::CsvLayout::Validators::AnyBarcodeValidator + }) csv_parsing(asset_group, parser) end # Support methods and classes - def clean_rack(rack) remove_facts(facts.with_predicate('contains')) end @@ -72,11 +69,12 @@ def reracking_tubes(rack, list_layout) def fact_changes_for_unrack_tubes(list_layout, destination_rack = nil) FactChanges.new.tap do |updates| - rerackGroup=nil + rerackGroup = nil previous_racks = [] tubes = list_layout.filter_map { |obj| obj[:asset] } return updates if tubes.empty? + tubes_ids = tubes.map(&:id) tubes_list = Asset.where(id: tubes_ids).includes(:facts) tubes_list.each_with_index do |tube, index| @@ -194,6 +192,7 @@ def fact_changes_for_rack_tubes(list_layout, rack) location = l[:location] tube = l[:asset] next unless tube + tubes.push(tube) updates.merge(put_tube_into_rack_position(tube, rack, location)) end @@ -215,7 +214,7 @@ def params_to_list_layout(params) def get_duplicates(list) list.reduce({}) do |memo, element| memo[element] = 0 unless memo[element] - memo[element]+=1 + memo[element] += 1 memo end.each_pair.select { |key, count| count > 1 } end @@ -230,7 +229,7 @@ def check_duplicates(params, error_messages, error_locations) end duplicated_assets.each do |barcode, count| - #error_locations.push(barcode) + # error_locations.push(barcode) error_messages.push("Asset #{barcode} is appearing #{count} times") end end @@ -259,11 +258,12 @@ def check_collisions(rack, list_layout, error_messages, error_locations) tube_location = tube.facts.with_predicate('location').first.object list_layout.each do |obj| next unless obj[:asset] + if (tube_location == obj[:location]) if (obj[:asset] != tube) error_messages.push( "Tube #{obj[:asset].barcode} cannot be put at location #{obj[:location]} because the tube #{tube.barcode || tube.uuid} is there" - ) + ) end end end @@ -271,11 +271,10 @@ def check_collisions(rack, list_layout, error_messages, error_locations) # Remember that the tubes needs to be always in a rack. They cannot be interchanged # in between racks error_messages.push( - "Missing tube!! Any tube already existing in the rack can't disappear from its defined layout without being reracked before. Tube #{tube.barcode || tube.uuid} should be present in the rack at location #{tube_location} but is missed from the rack." + "Missing tube!! Any tube already existing in the rack can't disappear from its defined layout without being reracked before. Tube #{tube.barcode || tube.uuid} should be present in the rack at location #{tube_location} but is missed from the rack." ) end end - end def selected_file(asset_group) @@ -310,23 +309,23 @@ def csv_parsing(asset_group, parser) unless error_messages.empty? raise InvalidDataParams, error_messages end + if parser.valid? updates = parser.parsed_changes.merge(reracking_tubes(asset, parser.layout)) error_messages.push(asset.validate_rack_content) raise InvalidDataParams, error_messages if error_messages.flatten.compact.count > 0 + return updates else raise InvalidDataParams, parser.error_list end end - def samples_symphony(step_type, params) rack = asset_group.assets.with_fact('a', 'TubeRack').first msgs = Parsers::Symphony.parse(params[:file].read, rack) raise InvalidDataParams, msgs if msgs.length > 0 end - end end diff --git a/lib/actions/tube_transfer.rb b/lib/actions/tube_transfer.rb index e1fdcb32..8d4cade7 100644 --- a/lib/actions/tube_transfer.rb +++ b/lib/actions/tube_transfer.rb @@ -9,11 +9,11 @@ def transfer_tubes(asset, modified_asset) end if (asset.has_predicate?('sample_tube')) updates.add(modified_asset, 'sample_tube', - asset.facts.with_predicate('sample_tube').first.object_asset) + asset.facts.with_predicate('sample_tube').first.object_asset) end if (asset.has_predicate?('study_name')) updates.add(modified_asset, 'study_name', - asset.facts.with_predicate('study_name').first.object) + asset.facts.with_predicate('study_name').first.object) end asset.facts.with_predicate('sanger_sample_id').each do |aliquot_fact| diff --git a/lib/changes_support/disjoint_list.rb b/lib/changes_support/disjoint_list.rb index 3b2d0245..bb035c2e 100644 --- a/lib/changes_support/disjoint_list.rb +++ b/lib/changes_support/disjoint_list.rb @@ -12,7 +12,7 @@ class ChangesSupport::DisjointList attr_accessor :list attr_reader :name - DISABLED_NAME="DISABLED" + DISABLED_NAME = "DISABLED" def initialize(list) @name = "object_id_#{object_id}" @@ -43,10 +43,10 @@ def store_for(element) def _store_for(unique_id) store_name = location_for_unique_id[unique_id] return nil if store_name.nil? || store_name == DISABLED_NAME + @disjoint_lists.select { |l| l.name == store_name }.first end - def enabled?(element) !store_for(element).nil? end @@ -125,6 +125,7 @@ def push(element) def add(element) return concat_disjoint_list(element) if element.kind_of?(ChangesSupport::DisjointList) + if enabled_in_other_list?(element) disable(element) elsif include?(element) @@ -139,7 +140,7 @@ def add(element) def sum_function_for(value) return value.hash # Value to create checksum and seed - #XXhash.xxh32(value, SEED_FOR_UNIQUE_IDS) + # XXhash.xxh32(value, SEED_FOR_UNIQUE_IDS) end def unique_id_for_element(element) @@ -168,6 +169,7 @@ def merge(disjoint_list) def enable(element) return if disabled?(element) + unique_id = unique_id_for_element(element) # Is not in any of the lists so we can add it if (element.kind_of?(Enumerable) && (!element.kind_of?(Hash))) @@ -175,7 +177,7 @@ def enable(element) else @list.push(element) end - @location_for_unique_id[unique_id]=name + @location_for_unique_id[unique_id] = name end def disable(element) @@ -189,7 +191,7 @@ def _synchronize_with_list(disjoint_list) unless (location_for_unique_id[key] == DISABLED_NAME) # If my disjoint lists do not have the element if location_for_unique_id[key].nil? - location_for_unique_id[key]=disjoint_list.location_for_unique_id[key] + location_for_unique_id[key] = disjoint_list.location_for_unique_id[key] if location_for_unique_id[key] == DISABLED_NAME _disable(key) end @@ -206,11 +208,12 @@ def _synchronize_with_list(disjoint_list) def _disable(unique_id) store = _store_for(unique_id) store.remove_from_raw_list_by_id(unique_id) if store - location_for_unique_id[unique_id]=DISABLED_NAME + location_for_unique_id[unique_id] = DISABLED_NAME end def _unique_id_for_element(element, deep = 0) - return sum_function_for(SecureRandom.uuid) if deep==MAX_DEEP_UNIQUE_ID + return sum_function_for(SecureRandom.uuid) if deep == MAX_DEEP_UNIQUE_ID + if element.kind_of?(String) sum_function_for(element) elsif (element.respond_to?(:uuid) && (!element.uuid.nil?)) @@ -223,10 +226,10 @@ def _unique_id_for_element(element, deep = 0) elsif (element.has_key?(:predicate)) _unique_id_for_fact(element) else - sum_function_for(element.keys.dup.concat(element.values.map { |val| _unique_id_for_element(val, deep+1) }).join) + sum_function_for(element.keys.dup.concat(element.values.map { |val| _unique_id_for_element(val, deep + 1) }).join) end elsif element.kind_of?(Enumerable) - sum_function_for(element.map { |o| _unique_id_for_element(o, deep+1) }.join) + sum_function_for(element.map { |o| _unique_id_for_element(o, deep + 1) }.join) else sum_function_for(element.to_s) end @@ -239,5 +242,4 @@ def _unique_id_for_fact(element) (element[:object] || element[:object_asset_id] || element[:object_asset].id || element[:object_asset].object_id) ].join('_')) end - end diff --git a/lib/changes_support/transaction_scope.rb b/lib/changes_support/transaction_scope.rb index 458c4e4b..b2b0044b 100644 --- a/lib/changes_support/transaction_scope.rb +++ b/lib/changes_support/transaction_scope.rb @@ -46,10 +46,10 @@ def _result_set_from_database(opts) # Filters out assets that do not complie to the conditions expressed in the opts anymore def _filter_removed_entries(opts) - if (@klass==Asset) + if (@klass == Asset) if @updates.to_h[:delete_assets] - selected_elements=result_set.to_a.select { |a| @updates.to_h[:delete_assets].include?(a.uuid) } - @result_set=result_set.to_a - selected_elements + selected_elements = result_set.to_a.select { |a| @updates.to_h[:delete_assets].include?(a.uuid) } + @result_set = result_set.to_a - selected_elements end if @updates.to_h[:remove_facts] if opts[:facts] @@ -58,13 +58,13 @@ def _filter_removed_entries(opts) object_asset = Asset.find(opts[:facts][:object_asset_id]) if opts[:facts][:object_asset_id] ( - ((triple[0]==element.uuid) && + ((triple[0] == element.uuid) && (opts[:facts][:predicate] == triple[1]) && (opts[:facts][:object] == triple[2])) || (object_asset.uuid == triple[2]) ) end end - @result_set=result_set.to_a - selected_elements + @result_set = result_set.to_a - selected_elements end end end @@ -72,7 +72,7 @@ def _filter_removed_entries(opts) def _append_added_entries(opts) selected_elements = _select_by(opts) - @result_set=result_set.to_a.concat(selected_elements) if selected_elements.length > 0 + @result_set = result_set.to_a.concat(selected_elements) if selected_elements.length > 0 end def where(opts) @@ -106,20 +106,21 @@ def _disjoint_list_for(type) def _join_condition(elem, default_fkey_name = nil) default_fkey_name ||= @klass.to_s.downcase.to_sym - rel={} + rel = {} rel[default_fkey_name] = elem rel end def _get_or_build_accessor(klass) return nil unless klass + @accessors ||= {} @accessors[klass] = ModelAccessor.new(klass, @updates) end def _select_by(opts) _disjoint_list_for(:create).select do |a| - opts.all? do |k,v| + opts.all? do |k, v| model_name = k.to_s.singularize.to_sym if (_disjoint_lists.has_key?(model_name) && (v.kind_of?(Hash))) class_name = model_name.to_s.classify.constantize @@ -128,13 +129,13 @@ def _select_by(opts) else k_id = k.to_s.concat("_id").to_sym if a.respond_to?(k) - a.send(k)==v + a.send(k) == v elsif (a.respond_to?(k_id) && (k_id != :object_id)) a.send(k_id) elsif (a.kind_of?(Hash) && a.has_key?(k)) - a[k]==v + a[k] == v elsif (a.kind_of?(Hash) && a.has_key?(k_id)) - a[k_id]==v.id + a[k_id] == v.id else false end @@ -146,8 +147,8 @@ def _select_by(opts) def transaction_scope(klass) raise 'Unsupported transaction scope class' unless klass == Asset + @transaction_scopes ||= {} @transaction_scopes[klass.to_s] ||= ModelAccessor.new(klass, self) end - end diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index 0f74a857..69d7dc6c 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -6,16 +6,15 @@ class FactChanges include ChangesSupport::TransactionScope attr_accessor :facts_to_destroy, :facts_to_add, :assets_to_create, :assets_to_destroy, - :assets_to_add, :assets_to_remove, :wildcards, :instances_from_uuid, - :asset_groups_to_create, :asset_groups_to_destroy, :errors_added, - :already_added_to_list, :instances_by_unique_id, - :facts_to_set_to_remote + :assets_to_add, :assets_to_remove, :wildcards, :instances_from_uuid, + :asset_groups_to_create, :asset_groups_to_destroy, :errors_added, + :already_added_to_list, :instances_by_unique_id, + :facts_to_set_to_remote attr_accessor :operations - def initialize(json = nil) - @assets_updated=[] + @assets_updated = [] reset parse_json(json) unless json.nil? end @@ -55,8 +54,8 @@ def asset_group_asset_to_h(asset_group_asset_str) memo[key] = [] unless memo[key] memo[key].push(o[:asset].uuid) memo - end.map do |k,v| - [k,v] + end.map do |k, v| + [k, v] end end @@ -88,7 +87,7 @@ def to_h end, add_assets: asset_group_asset_to_h(@assets_to_add), remove_assets: asset_group_asset_to_h(@assets_to_remove) - }.reject { |k,v| v.length == 0 } + }.reject { |k, v| v.length == 0 } end def to_json @@ -98,7 +97,7 @@ def to_json def parse_json(json) obj = json.is_a?(String) ? JSON.parse(json) : json.deep_stringify_keys ['set_errors', 'create_assets', 'create_asset_groups', 'delete_asset_groups', - 'remove_facts', 'add_facts', 'delete_assets', 'add_assets', 'remove_assets'].each do |action_type| + 'remove_facts', 'add_facts', 'delete_assets', 'add_assets', 'remove_assets'].each do |action_type| if obj[action_type] send(action_type, obj[action_type]) end @@ -118,21 +117,21 @@ def values_for_predicate(asset, predicate) end def _build_fact_attributes(s, p, o, options = {}) - t = [s,p,o, options] + t = [s, p, o, options] params = { asset: t[0], predicate: t[1], literal: !(t[2].kind_of?(Asset)) } params[:literal] ? params[:object] = t[2] : params[:object_asset] = t[2] params = params.merge(t[3]) if t[3] params end - def add(s,p,o, options = {}) + def add(s, p, o, options = {}) s = find_asset(s) - o = (options[:literal]==true) ? o : find_asset(o) + o = (options[:literal] == true) ? o : find_asset(o) fact = _build_fact_attributes(s, p, o, options) facts_to_add << fact if fact - #facts_to_add.push(track_object(params)) unless detected + # facts_to_add.push(track_object(params)) unless detected end def add_facts(listOfLists) @@ -145,8 +144,8 @@ def remove_facts(listOfLists) self end - def add_remote(s,p,o, options = {}) - add(s,p,o, options.merge({ is_remote?: true })) if (s && p && o) + def add_remote(s, p, o, options = {}) + add(s, p, o, options.merge({ is_remote?: true })) if (s && p && o) end def replace_remote(asset, p, o, options = {}) @@ -162,6 +161,7 @@ def replace_remote(asset, p, o, options = {}) def remove(f) return if f.nil? + if f.kind_of?(Enumerable) facts_to_destroy << f.map { |o| o.attributes.symbolize_keys } elsif f.kind_of?(Fact) @@ -180,7 +180,7 @@ def remove_where(subject, predicate, object) def merge_hash(h1, h2) h2.keys.each do |k| - h1[k]=h2[k] + h1[k] = h2[k] end h1 end @@ -188,7 +188,7 @@ def merge_hash(h1, h2) def merge(fact_changes) if (fact_changes) # To keep track of already added object after merging with another fact changes object - #_add_already_added_from_other_object(fact_changes) + # _add_already_added_from_other_object(fact_changes) errors_added.concat(fact_changes.errors_added) asset_groups_to_create.concat(fact_changes.asset_groups_to_create) assets_to_create.concat(fact_changes.assets_to_create) @@ -228,7 +228,8 @@ def apply(step, with_operations = true) def assets_updated return [] unless @operations - @assets_updated=Asset.where(id: @operations.pluck(:asset_id).uniq).distinct + + @assets_updated = Asset.where(id: @operations.pluck(:asset_id).uniq).distinct end def assets_for_printing @@ -245,7 +246,7 @@ def assets_for_printing end.filter_map(&:asset).uniq.map(&:uuid) ids_for_print = asset_ids.concat(ready_for_print_ids).flatten.uniq - @assets_for_printing=Asset.for_printing.where(uuid: ids_for_print) + @assets_for_printing = Asset.for_printing.where(uuid: ids_for_print) end def find_asset(asset_or_uuid) @@ -305,12 +306,12 @@ def wildcard_for_uuid(uuid) end def find_instance_from_uuid(klass, uuid) - found = klass.find_by(uuid:uuid) unless is_new_record?(uuid) + found = klass.find_by(uuid: uuid) unless is_new_record?(uuid) return found if found + instances_from_uuid[uuid] end - def validate_instances(instances) if instances.kind_of?(Array) instances.each { |a| raise StandardError, a if a.nil? } @@ -327,25 +328,25 @@ def set_errors(errors) def create_assets(assets) assets_to_create << validate_instances(build_assets(assets)) - #assets_to_create.concat(validate_instances(build_assets(assets))) + # assets_to_create.concat(validate_instances(build_assets(assets))) self end def create_asset_groups(asset_groups) asset_groups_to_create << validate_instances(build_asset_groups(asset_groups)) - #asset_groups_to_create.concat(validate_instances(build_asset_groups(asset_groups))).uniq! + # asset_groups_to_create.concat(validate_instances(build_asset_groups(asset_groups))).uniq! self end def delete_asset_groups(asset_groups) asset_groups_to_destroy << validate_instances(find_asset_groups(asset_groups)) - #asset_groups_to_destroy.concat(validate_instances(find_asset_groups(asset_groups))).uniq! + # asset_groups_to_destroy.concat(validate_instances(find_asset_groups(asset_groups))).uniq! self end def delete_assets(assets) assets_to_destroy << validate_instances(find_assets(assets)) - #assets_to_destroy.concat(validate_instances(find_assets(assets))).uniq! + # assets_to_destroy.concat(validate_instances(find_assets(assets))).uniq! self end @@ -360,8 +361,8 @@ def add_assets(list) end assets = validate_instances(find_assets(asset_ids)) assets_to_add << assets.map { |asset| { asset_group: asset_group, asset: asset } } - #add_to_list_keep_unique(assets.map{|asset| { asset_group: asset_group, asset: asset} }, :assets_to_add, :assets_to_remove) - #assets_to_add.concat(assets.map{|asset| { asset_group: asset_group, asset: asset} }) + # add_to_list_keep_unique(assets.map{|asset| { asset_group: asset_group, asset: asset} }, :assets_to_add, :assets_to_remove) + # assets_to_add.concat(assets.map{|asset| { asset_group: asset_group, asset: asset} }) end self end @@ -369,7 +370,7 @@ def add_assets(list) def remove_assets(list) list.each do |elem| if ((elem.length > 0) && elem[1].kind_of?(Array)) - asset_group = elem[0].nil? ? nil :validate_instances(find_asset_group(elem[0])) + asset_group = elem[0].nil? ? nil : validate_instances(find_asset_group(elem[0])) asset_ids = elem[1] else asset_group = nil @@ -377,8 +378,8 @@ def remove_assets(list) end assets = validate_instances(find_assets(asset_ids)) assets_to_remove << assets.map { |asset| { asset_group: asset_group, asset: asset } } - #add_to_list_keep_unique(assets.map{|asset| { asset_group: asset_group, asset: asset} }, :assets_to_remove, :assets_to_add) - #assets_to_remove.concat(assets.map{|asset| { asset_group: asset_group, asset: asset} }) + # add_to_list_keep_unique(assets.map{|asset| { asset_group: asset_group, asset: asset} }, :assets_to_remove, :assets_to_add) + # assets_to_remove.concat(assets.map{|asset| { asset_group: asset_group, asset: asset} }) end self end @@ -423,6 +424,7 @@ def _remove_assets(step, assets_to_remove, with_operations = true) def _create_assets(step, assets, with_operations = true) return unless assets + count = Asset.count + 1 assets = assets.each_with_index.map do |asset, barcode_index| _build_barcode(asset, count + barcode_index) @@ -458,6 +460,7 @@ def _detach_assets(step, assets, with_operations = true) def _create_asset_groups(step, asset_groups, with_operations = true) return unless asset_groups + asset_groups.each_with_index do |asset_group, index| asset_group.update_attributes( name: TokenUtil.to_asset_group_name(wildcard_for_uuid(asset_group.uuid)), @@ -483,7 +486,6 @@ def _create_facts(step, params_for_facts, with_operations = true) end end - def _remove_facts(step, facts_to_remove, with_operations = true) ids = [] modified_list = facts_to_remove.reduce([]) do |memo, data| @@ -491,10 +493,10 @@ def _remove_facts(step, facts_to_remove, with_operations = true) ids.push(data[:id]) elsif data[:object].kind_of? String elems = Fact.where(asset: data[:asset], predicate: data[:predicate], - object: data[:object]) + object: data[:object]) else elems = Fact.where(asset: data[:asset], predicate: data[:predicate], - object_asset: data[:object_asset]) + object_asset: data[:object_asset]) end memo.concat(elems) if elems memo @@ -514,13 +516,13 @@ def _asset_group_building_operations(action_type, step, asset_groups) def _asset_group_operations(action_type, step, asset_group_assets) asset_group_assets.map do |asset_group_asset, index| Operation.new(:action_type => action_type, :step => step, - :asset=> asset_group_asset.asset, object: asset_group_asset.asset_group.uuid) + :asset => asset_group_asset.asset, object: asset_group_asset.asset_group.uuid) end end def _asset_operations(action_type, step, assets) assets.map do |asset, index| - #refer = (action_type == 'deleteAsset' ? nil : asset) + # refer = (action_type == 'deleteAsset' ? nil : asset) Operation.new(:action_type => action_type, :step => step, object: asset.uuid) end end @@ -534,7 +536,7 @@ def _fact_operations(action_type, step, facts) operations = facts.map do |fact| modified_assets.push(fact.object_asset) if listening_to_predicate?(fact.predicate) Operation.new(:action_type => action_type, :step => step, - :asset=> fact.asset, :predicate => fact.predicate, :object => fact.object, object_asset: fact.object_asset) + :asset => fact.asset, :predicate => fact.predicate, :object => fact.object, object_asset: fact.object_asset) end modified_assets.flatten.compact.uniq.each(&:touch) @@ -548,7 +550,6 @@ def all_values_are_new_records(hash) end def _instance_builder_for_import(klass, params_list, &block) - instances = params_list.filter_map do |params_for_instance| unless (params_for_instance.kind_of?(klass)) if (all_values_are_new_records(params_for_instance) || @@ -582,5 +583,4 @@ def _instances_deletion(klass, instances, &block) klass.where(id: ids_to_remove).delete_all if ids_to_remove && !ids_to_remove.empty? operations end - end diff --git a/lib/inference_engines/cwm/step_execution.rb b/lib/inference_engines/cwm/step_execution.rb index fb2d3a35..bd6475a8 100644 --- a/lib/inference_engines/cwm/step_execution.rb +++ b/lib/inference_engines/cwm/step_execution.rb @@ -11,8 +11,8 @@ class StepExecution def initialize(params) @step = params[:step] @asset_group = params[:asset_group] - @original_assets= params[:original_assets] - @created_assets= params[:created_assets] + @original_assets = params[:original_assets] + @created_assets = params[:created_assets] @facts_to_destroy = params[:facts_to_destroy] @step_types = params[:step_types] || [@step.step_type] @@ -39,9 +39,9 @@ def generate_plan call_list = [ cmd = "#{Rails.configuration.cwm_path}/cwm", input_urls = [ - Rails.application.routes.url_helpers.asset_group_url(@asset_group.id)+".n3", + Rails.application.routes.url_helpers.asset_group_url(@asset_group.id) + ".n3", @step_types.map do |step_type| - Rails.application.routes.url_helpers.step_type_url(step_type.id)+".n3" + Rails.application.routes.url_helpers.step_type_url(step_type.id) + ".n3" end ], '--mode=r', @@ -59,7 +59,7 @@ def generate_plan content = stdout.read output = [line, content].join("\n") step.update_attributes(output: output) - unless thr.value==0 + unless thr.value == 0 raise "cwm execution failed\nCODE: #{thr.value}\nCMD: #{line}\nSTDOUT: #{content}\nSTDERR: #{stderror.read}\n" end end @@ -84,10 +84,8 @@ def export end updates.apply(step) - end - def fragment(k) SupportN3::fragment(k) end @@ -96,13 +94,14 @@ def add_facts(graphs) graphs.each do |quads| quads.map do |quad| asset = Asset.find_by!(:uuid => TokenUtil.uuid(fragment(quad[0]))) - add_quad_to_asset(quad,asset) + add_quad_to_asset(quad, asset) end end end def equal_quad_and_fact?(quad, fact) return false if fact.predicate != fragment(quad[1]) + object = fragment(quad[2]) if TokenUtil.is_uuid?(object) return true if fact.object_asset == Asset.find_by(:uuid => TokenUtil.uuid(object)) @@ -139,7 +138,7 @@ def create_asset(graphs) created_assets = {} graphs.each do |quads| quads.each do |quad| - created_assets[quad[0]] = [ Asset.create! ].flatten unless created_assets[quad[0]] + created_assets[quad[0]] = [Asset.create!].flatten unless created_assets[quad[0]] @step.asset_group.add_assets(created_assets[quad[0]]) created_assets[quad[0]].each do |asset| add_quad_to_asset(quad, asset, "createAsset") diff --git a/lib/inference_engines/default/step_execution.rb b/lib/inference_engines/default/step_execution.rb index df6da3a1..94f50b40 100644 --- a/lib/inference_engines/default/step_execution.rb +++ b/lib/inference_engines/default/step_execution.rb @@ -10,7 +10,6 @@ class StepExecution attr_accessor :asset_group attr_accessor :updates - def initialize(params) @step = params[:step] @asset_group = params[:asset_group] @@ -23,11 +22,11 @@ def compatible? end def executable_actions_sorted - step.step_type.actions.includes([:subject_condition_group, :object_condition_group]).sort do |a,b| + step.step_type.actions.includes([:subject_condition_group, :object_condition_group]).sort do |a, b| [:create_asset, :add_facts, :remove_facts, :delete_asset, :select_asset, :unselect_asset] - if a.action_type=='createAsset' + if a.action_type == 'createAsset' -1 - elsif b.action_type=='createAsset' + elsif b.action_type == 'createAsset' 1 else a.action_type <=> b.action_type @@ -35,7 +34,6 @@ def executable_actions_sorted end end - def unselect_assets_with_conditions(condition_groups, updates) condition_groups.each do |condition_group| unless condition_group.keep_selected @@ -71,7 +69,6 @@ def plan def apply updates.apply(step) end - end end end diff --git a/lib/inference_engines/runner/step_execution.rb b/lib/inference_engines/runner/step_execution.rb index b9f3620f..2b129841 100644 --- a/lib/inference_engines/runner/step_execution.rb +++ b/lib/inference_engines/runner/step_execution.rb @@ -13,13 +13,13 @@ class StepExecution include StepExecutionProcess attr_accessor :step, :asset_group, :original_assets, - :created_assets, :facts_to_destroy, :updates, :content + :created_assets, :facts_to_destroy, :updates, :content def initialize(params) @step = params[:step] @asset_group = params[:asset_group] - @original_assets= params[:original_assets] - @created_assets= params[:created_assets] + @original_assets = params[:original_assets] + @created_assets = params[:created_assets] @facts_to_destroy = params[:facts_to_destroy] @step_types = params[:step_types] || [@step.step_type] @@ -77,12 +77,12 @@ def generate_plan_from_external_process @content = stdout.read output = [line, content].join("\n") step.update_attributes(output: output) - unless thr.value==0 + unless thr.value == 0 raise "runner execution failed\nCODE: #{thr.value}\nCMD: #{line}\nSTDOUT: #{content}\nSTDERR: #{stderror.read}\n" end end - @updates=FactChanges.new(@content) + @updates = FactChanges.new(@content) end def plan @@ -108,10 +108,10 @@ def refresh def compatible? refresh return true if step.step_type.condition_groups.count == 0 + step.step_type.compatible_with?(@asset_group.assets) end - def add_facts(list) FactChanges.new.tap do |updates| list.each { |l| updates.add(l[0], l[1], l[2]) } @@ -140,7 +140,7 @@ def select_asset(uuids) FactChanges.new.tap do |updates| assets = uuids.map { |uuid| Asset.find_by(uuid: uuid) } updates.add_assets(@step.asset_group.id, uuids) - #@step.asset_group.add_assets(assets) + # @step.asset_group.add_assets(assets) end end @@ -148,18 +148,18 @@ def unselect_asset(uuids) FactChanges.new.tap do |updates| assets = uuids.map { |uuid| Asset.find_by(uuid: uuid) } updates.remove_assets(@step.asset_group.id, uuids) - #@step.asset_group.remove_assets(assets) + # @step.asset_group.remove_assets(assets) end end private def input_url - Rails.application.routes.url_helpers.asset_group_url(@asset_group.id)+".json" + Rails.application.routes.url_helpers.asset_group_url(@asset_group.id) + ".json" end def step_url - Rails.application.routes.url_helpers.step_url(@step.id)+".json" + Rails.application.routes.url_helpers.step_url(@step.id) + ".json" end end end diff --git a/lib/label_template_setup.rb b/lib/label_template_setup.rb index 586874fa..cd4869e7 100644 --- a/lib/label_template_setup.rb +++ b/lib/label_template_setup.rb @@ -1,7 +1,5 @@ class LabelTemplateSetup - module ClassMethods - def label_types @label_types ||= PMB::LabelType.all end @@ -29,10 +27,10 @@ def register_label_type(name, data) end end - def register_template(template_name,template_type) + def register_template(template_name, template_type) puts "Loading #{template_name}" type_id = label_type_id_for(template_type) - templates << LabelTemplateSetup.new(template_name,template_type, yield(template_name,type_id)) + templates << LabelTemplateSetup.new(template_name, template_type, yield(template_name, type_id)) end def find_or_register_each_template! @@ -40,13 +38,12 @@ def find_or_register_each_template! template.find_or_register! end end - end extend ClassMethods attr_reader :name, :hash, :template_type - def initialize(name,template_type, hash) + def initialize(name, template_type, hash) @name = name @template_type = template_type @hash = hash @@ -67,7 +64,8 @@ def find_or_register! def local_template return @local if @local - @local = LabelTemplate.find_by(name:name)||LabelTemplate.new(name:name, template_type:@template_type) + + @local = LabelTemplate.find_by(name: name) || LabelTemplate.new(name: name, template_type: @template_type) end def find_or_create_by_name! @@ -82,7 +80,7 @@ def find_or_create_by_name! end def template - @template||=PMB::LabelTemplate.new(hash) + @template ||= PMB::LabelTemplate.new(hash) end def create_remote! @@ -90,6 +88,4 @@ def create_remote! template.save template end - - end diff --git a/lib/label_templates/ss_plate.rb b/lib/label_templates/ss_plate.rb index 1fbf84d4..14a38cfd 100644 --- a/lib/label_templates/ss_plate.rb +++ b/lib/label_templates/ss_plate.rb @@ -3,42 +3,40 @@ # Label template currently defined for sqsc_96plate_label_template (20/Jan/2017) def bitmap_definition(attrs) - { horizontal_magnification:"05", - vertical_magnification:"1", - font:"G", - space_adjustment:"00", - rotational_angles:"00" - }.merge(attrs) + { horizontal_magnification: "05", + vertical_magnification: "1", + font: "G", + space_adjustment: "00", + rotational_angles: "00" }.merge(attrs) end def plate_barcode_definition(name, type_id, barcode_type) { name: name, label_type_id: type_id, # Plate - labels_attributes:[{ + labels_attributes: [{ name: 'label', - bitmaps_attributes:[ - bitmap_definition({ field_name:"top_left",x_origin:"0030",y_origin:"0035" }), - bitmap_definition({ field_name:"bottom_left",x_origin:"0030",y_origin:"0065" }), - bitmap_definition({ field_name:"top_right",x_origin:"0550",y_origin:"0035" }), - bitmap_definition({ field_name:"bottom_right",x_origin:"0550",y_origin:"0065" }), - bitmap_definition({ field_name:"top_far_right",x_origin:"0750",y_origin:"0035" }), - bitmap_definition({ field_name:"bottom_far_right",x_origin:"0750",y_origin:"0065" }), - bitmap_definition({ field_name:"label_counter_right",x_origin:"0890",y_origin:"0065",rotational_angles:"33" }) + bitmaps_attributes: [ + bitmap_definition({ field_name: "top_left", x_origin: "0030", y_origin: "0035" }), + bitmap_definition({ field_name: "bottom_left", x_origin: "0030", y_origin: "0065" }), + bitmap_definition({ field_name: "top_right", x_origin: "0550", y_origin: "0035" }), + bitmap_definition({ field_name: "bottom_right", x_origin: "0550", y_origin: "0065" }), + bitmap_definition({ field_name: "top_far_right", x_origin: "0750", y_origin: "0035" }), + bitmap_definition({ field_name: "bottom_far_right", x_origin: "0750", y_origin: "0065" }), + bitmap_definition({ field_name: "label_counter_right", x_origin: "0890", y_origin: "0065", rotational_angles: "33" }) ], - barcodes_attributes:[ - { field_name:"barcode", barcode_type: barcode_type,one_module_width:"02",height:"0070",rotational_angle:nil,one_cell_width:nil, - type_of_check_digit:"2",no_of_columns:nil,bar_height:nil,x_origin:"0200",y_origin:"0000", - } + barcodes_attributes: [ + { field_name: "barcode", barcode_type: barcode_type, one_module_width: "02", height: "0070", rotational_angle: nil, one_cell_width: nil, + type_of_check_digit: "2", no_of_columns: nil, bar_height: nil, x_origin: "0200", y_origin: "0000", } ] }] - } + } end -LabelTemplateSetup.register_template('se_ean13_96plate','Plate') do |name, type_id| +LabelTemplateSetup.register_template('se_ean13_96plate', 'Plate') do |name, type_id| plate_barcode_definition(name, type_id, "5") end -LabelTemplateSetup.register_template('se_code128_96plate','Plate') do |name, type_id| +LabelTemplateSetup.register_template('se_code128_96plate', 'Plate') do |name, type_id| plate_barcode_definition(name, type_id, "9") -end \ No newline at end of file +end diff --git a/lib/label_templates/ss_tube.rb b/lib/label_templates/ss_tube.rb index 5be624e5..06ade59d 100644 --- a/lib/label_templates/ss_tube.rb +++ b/lib/label_templates/ss_tube.rb @@ -5,39 +5,37 @@ def tube_barcode_definition(name, type_id, barcode_type) { name: name, - label_type_id: type_id, - labels_attributes:[{ + label_type_id: type_id, + labels_attributes: [{ name: 'label', - bitmaps_attributes:[ - { horizontal_magnification:"05",vertical_magnification:"05",font:"H",space_adjustment:"03",rotational_angles:"11", - x_origin:"0038",y_origin:"0210",field_name:"bottom_line" }, - { horizontal_magnification:"05",vertical_magnification:"05",font:"H",space_adjustment:"02",rotational_angles:"11", - x_origin:"0070",y_origin:"0210",field_name:"middle_line" }, - { horizontal_magnification:"05",vertical_magnification:"05",font:"H",space_adjustment:"02",rotational_angles:"11", - x_origin:"0120",y_origin:"0210",field_name:"top_line" }, - { horizontal_magnification:"05",vertical_magnification:"1",font:"G",space_adjustment:"00",rotational_angles:"00", - x_origin:"0240",y_origin:"0165",field_name:"round_label_top_line" }, - { horizontal_magnification:"05",vertical_magnification:"1",font:"G",space_adjustment:"00",rotational_angles:"00", - x_origin:"0220",y_origin:"0193",field_name:"round_label_bottom_line" } - ], - barcodes_attributes:[ - { barcode_type:"Q",one_module_width:"03",height:"0080",rotational_angle:"1",one_cell_width:"03", - type_of_check_digit:nil, - no_of_columns:nil,bar_height:nil,x_origin:"0300",y_origin:"0145",field_name:"barcode2d" }, - { barcode_type: barcode_type,one_module_width:"01",height:"0100",rotational_angle:nil, - one_cell_width:nil,type_of_check_digit:"2", - no_of_columns:nil,bar_height:nil,x_origin:"0043",y_origin:"0100",field_name:"barcode" } - ] - } - ] + bitmaps_attributes: [ + { horizontal_magnification: "05", vertical_magnification: "05", font: "H", space_adjustment: "03", rotational_angles: "11", + x_origin: "0038", y_origin: "0210", field_name: "bottom_line" }, + { horizontal_magnification: "05", vertical_magnification: "05", font: "H", space_adjustment: "02", rotational_angles: "11", + x_origin: "0070", y_origin: "0210", field_name: "middle_line" }, + { horizontal_magnification: "05", vertical_magnification: "05", font: "H", space_adjustment: "02", rotational_angles: "11", + x_origin: "0120", y_origin: "0210", field_name: "top_line" }, + { horizontal_magnification: "05", vertical_magnification: "1", font: "G", space_adjustment: "00", rotational_angles: "00", + x_origin: "0240", y_origin: "0165", field_name: "round_label_top_line" }, + { horizontal_magnification: "05", vertical_magnification: "1", font: "G", space_adjustment: "00", rotational_angles: "00", + x_origin: "0220", y_origin: "0193", field_name: "round_label_bottom_line" } + ], + barcodes_attributes: [ + { barcode_type: "Q", one_module_width: "03", height: "0080", rotational_angle: "1", one_cell_width: "03", + type_of_check_digit: nil, + no_of_columns: nil, bar_height: nil, x_origin: "0300", y_origin: "0145", field_name: "barcode2d" }, + { barcode_type: barcode_type, one_module_width: "01", height: "0100", rotational_angle: nil, + one_cell_width: nil, type_of_check_digit: "2", + no_of_columns: nil, bar_height: nil, x_origin: "0043", y_origin: "0100", field_name: "barcode" } + ] + }] } end - -LabelTemplateSetup.register_template('se_ean13_1dtube','Tube') do |name, type_id| +LabelTemplateSetup.register_template('se_ean13_1dtube', 'Tube') do |name, type_id| tube_barcode_definition(name, type_id, "5") end -LabelTemplateSetup.register_template('se_code128_1dtube','Tube') do |name, type_id| +LabelTemplateSetup.register_template('se_code128_1dtube', 'Tube') do |name, type_id| tube_barcode_definition(name, type_id, "9") -end \ No newline at end of file +end diff --git a/lib/label_types/plate.rb b/lib/label_types/plate.rb index c1d49035..baa0855d 100644 --- a/lib/label_types/plate.rb +++ b/lib/label_types/plate.rb @@ -1,13 +1,13 @@ require './lib/label_template_setup' LabelTemplateSetup.register_label_type("Plate", { - type: "label_types", - attributes: { - feed_value: "008", - fine_adjustment: "04", - pitch_length: "0110", - print_width: "0920", - print_length: "0080", - name: "Plate" - } -}) + type: "label_types", + attributes: { + feed_value: "008", + fine_adjustment: "04", + pitch_length: "0110", + print_width: "0920", + print_length: "0080", + name: "Plate" + } + }) diff --git a/lib/label_types/tube.rb b/lib/label_types/tube.rb index b4940820..ed58408e 100644 --- a/lib/label_types/tube.rb +++ b/lib/label_types/tube.rb @@ -1,14 +1,13 @@ require './lib/label_template_setup' -LabelTemplateSetup.register_label_type("Tube",{ - type:"label_types", - attributes:{ - feed_value:"008", - fine_adjustment:"10", - pitch_length:"0430", - print_width:"0300", - print_length:"0400", - name:"Tube" - } -}) - +LabelTemplateSetup.register_label_type("Tube", { + type: "label_types", + attributes: { + feed_value: "008", + fine_adjustment: "10", + pitch_length: "0430", + print_width: "0300", + print_length: "0400", + name: "Tube" + } + }) diff --git a/lib/parsers/csv_layout/barcode_creatable_parser.rb b/lib/parsers/csv_layout/barcode_creatable_parser.rb index 5d5c6102..d9db3f43 100644 --- a/lib/parsers/csv_layout/barcode_creatable_parser.rb +++ b/lib/parsers/csv_layout/barcode_creatable_parser.rb @@ -14,7 +14,7 @@ def asset @instance.generate_uuid! updater.create_assets([@instance]) updater.add(@instance, 'barcode', barcode) - updater.add(@instance , 'a', 'Tube') + updater.add(@instance, 'a', 'Tube') end @instance end diff --git a/lib/parsers/csv_layout/barcode_parser.rb b/lib/parsers/csv_layout/barcode_parser.rb index 5a12704e..2263ec00 100644 --- a/lib/parsers/csv_layout/barcode_parser.rb +++ b/lib/parsers/csv_layout/barcode_parser.rb @@ -4,7 +4,6 @@ module Parsers module CsvLayout class BarcodeParser - NO_READ_BARCODE = 'no read' include ActiveModel::Validations diff --git a/lib/parsers/csv_layout/csv_parser.rb b/lib/parsers/csv_layout/csv_parser.rb index 19cb137f..22a6badd 100644 --- a/lib/parsers/csv_layout/csv_parser.rb +++ b/lib/parsers/csv_layout/csv_parser.rb @@ -17,12 +17,12 @@ class CsvParser attr_reader :data, :parsed, :parsed_changes, :components, :line_parser DEFAULT_COMPONENTS = { - barcode_parser: Parsers::CsvLayout::BarcodeParser, - location_parser: Parsers::CsvLayout::LocationParser, - location_validator: Parsers::CsvLayout::Validators::LocationValidator, - barcode_validator: Parsers::CsvLayout::Validators::FluidxBarcodeValidator, - line_parser: Parsers::CsvLayout::LineParser, - line_reader: Parsers::CsvLayout::LineReader + barcode_parser: Parsers::CsvLayout::BarcodeParser, + location_parser: Parsers::CsvLayout::LocationParser, + location_validator: Parsers::CsvLayout::Validators::LocationValidator, + barcode_validator: Parsers::CsvLayout::Validators::FluidxBarcodeValidator, + line_parser: Parsers::CsvLayout::LineParser, + line_reader: Parsers::CsvLayout::LineReader } def initialize(str, component_defs = {}) @@ -94,7 +94,6 @@ def duplicated(sym) (!element.nil?) && (all_elems.count(element) > 1) end.uniq.compact end - end end end diff --git a/lib/parsers/csv_layout/line_reader.rb b/lib/parsers/csv_layout/line_reader.rb index a2083bb0..fe464177 100644 --- a/lib/parsers/csv_layout/line_reader.rb +++ b/lib/parsers/csv_layout/line_reader.rb @@ -2,8 +2,7 @@ module Parsers module CsvLayout class LineReader - - BOM_HEADER="\xEF\xBB\xBF" + BOM_HEADER = "\xEF\xBB\xBF" def initialize(input) @input = input @@ -26,7 +25,6 @@ def clean_bom(str) def csv_convert(str) CSV.new(str).to_a end - end end end diff --git a/lib/parsers/csv_layout/location_parser.rb b/lib/parsers/csv_layout/location_parser.rb index 1362b445..f4da98a2 100644 --- a/lib/parsers/csv_layout/location_parser.rb +++ b/lib/parsers/csv_layout/location_parser.rb @@ -25,7 +25,6 @@ def parse(line) @location = nil end end - end end end diff --git a/lib/parsers/csv_metadata/csv_parser.rb b/lib/parsers/csv_metadata/csv_parser.rb index 48feef96..1829e880 100644 --- a/lib/parsers/csv_metadata/csv_parser.rb +++ b/lib/parsers/csv_metadata/csv_parser.rb @@ -14,7 +14,6 @@ class CsvParser attr_accessor :headers_parser attr_reader :data, :parsed, :parsed_changes, :components, :line_parser - DEFAULT_COMPONENTS = { headers_parser: Parsers::CsvMetadata::HeadersParser, data_parser: Parsers::CsvMetadata::DataParser, @@ -67,7 +66,6 @@ def validate_parsed_data errors.add(:base, "The csv contains some errors") end end - end end end diff --git a/lib/parsers/csv_metadata/headers_parser.rb b/lib/parsers/csv_metadata/headers_parser.rb index 9ee53444..0c1487c3 100644 --- a/lib/parsers/csv_metadata/headers_parser.rb +++ b/lib/parsers/csv_metadata/headers_parser.rb @@ -19,7 +19,7 @@ def initialize(line, parser) end def _parse(line) - @headers=line.map { |header| header.strip } + @headers = line.map { |header| header.strip } end end end diff --git a/lib/parsers/csv_metadata/line_parser.rb b/lib/parsers/csv_metadata/line_parser.rb index 1ab2cbba..d32a99bb 100644 --- a/lib/parsers/csv_metadata/line_parser.rb +++ b/lib/parsers/csv_metadata/line_parser.rb @@ -9,7 +9,7 @@ class LineParser def initialize(input_reader, parser) @parser = parser @parsed_content = [] - @parsed=false + @parsed = false @input_reader = input_reader end @@ -55,7 +55,7 @@ def parse memo.push(num_line: num_line, data_parser: data_parser) end end - num_line = num_line+1 + num_line = num_line + 1 memo end @parsed = true diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index e4e2aea2..4da597f3 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -1,20 +1,20 @@ -#This file is part of SEQUENCESCAPE is distributed under the terms of GNU General Public License version 1 or later; -#Please refer to the LICENSE and README files for information on licensing and authorship of this file. -#Copyright (C) 2007-2011 Genome Research Ltd. +# This file is part of SEQUENCESCAPE is distributed under the terms of GNU General Public License version 1 or later; +# Please refer to the LICENSE and README files for information on licensing and authorship of this file. +# Copyright (C) 2007-2011 Genome Research Ltd. require 'sequencescape-api' require 'sequencescape' require 'sequencescape_client_v2' class SequencescapeClient - @purposes=nil + @purposes = nil def self.api_connection_options { - :namespace => 'SamplesExtraction', - :url => Rails.configuration.ss_uri, + :namespace => 'SamplesExtraction', + :url => Rails.configuration.ss_uri, :authorisation => Rails.configuration.ss_authorisation, - :read_timeout => 60 + :read_timeout => 60 } end @@ -35,7 +35,7 @@ def self.update_extraction_attributes(instance, attrs, username = 'test') end def self.purpose_by_name(name) - client.plate_purpose.all.select { |p| p.name===name }.first + client.plate_purpose.all.select { |p| p.name === name }.first end def self.create_plate(purpose_name, attrs) diff --git a/lib/sequencescape_client_v2.rb b/lib/sequencescape_client_v2.rb index fca7777d..a0876b18 100644 --- a/lib/sequencescape_client_v2.rb +++ b/lib/sequencescape_client_v2.rb @@ -1,7 +1,6 @@ require "faraday" module SequencescapeClientV2 - class SequencescapeClientV2::Model < JsonApiClient::Resource # set the api base url in an abstract base class self.site = "#{Rails.configuration.ss_api_v2_uri}/api/v2/" diff --git a/lib/step_execution_process.rb b/lib/step_execution_process.rb index 9c01014c..e17bc24d 100644 --- a/lib/step_execution_process.rb +++ b/lib/step_execution_process.rb @@ -1,6 +1,7 @@ module StepExecutionProcess def run return false unless compatible? + plan step.reload if step.stopped? @@ -9,6 +10,4 @@ def run apply end end - end - diff --git a/lib/support_n3.rb b/lib/support_n3.rb index 03cc466f..fe5deab7 100644 --- a/lib/support_n3.rb +++ b/lib/support_n3.rb @@ -1,36 +1,35 @@ module SupportN3 - def self.ontology_to_json(ontology_file) reading_instance = nil data = {} definitions = {} inheritance = {} ontology = RDF::N3::Reader.new(ontology_file, { - validate: false, - canonicalize: false, - }).quads.reduce({}) do |memo, quad| + validate: false, + canonicalize: false, + }).quads.reduce({}) do |memo, quad| subject = quad[0].pname predicate = quad[1].pname object = quad[2].to_s if reading_instance != subject if (data["rdfs:label"]) - memo[data["rdfs:label"]]=data - definitions[reading_instance]=data["rdfs:label"] + memo[data["rdfs:label"]] = data + definitions[reading_instance] = data["rdfs:label"] end - data={ uri: subject } + data = { uri: subject } reading_instance = subject end if (predicate == "rdfs:subClassOf") - inheritance[subject]=[subject] unless inheritance[subject] + inheritance[subject] = [subject] unless inheritance[subject] inheritance[subject].push(object) end if (predicate == "http://purl.org/dc/elements/1.1/description") predicate = "description" end - data[predicate]=object + data[predicate] = object memo end @@ -59,7 +58,6 @@ def self.ontology_to_json(ontology_file) ontology end - def self.parse_string(input, options = {}, step_type = nil) options = { validate: false, @@ -76,7 +74,7 @@ def self.parse_file(file_path) end def self.fragment(k) - k.try(:fragment) || (k.try(:name) || k).to_s.gsub(/.*#/,'') + k.try(:fragment) || (k.try(:name) || k).to_s.gsub(/.*#/, '') end def self.build_asset(name, create_assets = true, created_assets = []) @@ -96,14 +94,13 @@ def self.is_literal?(element, quads) element.literal? || quads.select { |q| q[0] == element }.count == 0 end - def self.load_step_actions(content, options = {}) options = { validate: false, canonicalize: false, }.merge(options) - #puts content + # puts content open_resource = RDF::N3::Reader.new(content, options) quads = open_resource.quads quads.reduce({}) do |memo, quad| @@ -116,22 +113,21 @@ def self.load_step_actions(content, options = {}) end end - def self.subgraph(node, quads) - quads.select { |q| q[3]==node } + quads.select { |q| q[3] == node } end - def self.create_fact(quad, quads, create_assets = true, created_assets = []) asset = build_asset(SupportN3::fragment(quad[0]), create_assets, created_assets) if is_literal?(quad[2], quads) asset.facts << Fact.create( :predicate => SupportN3::fragment(quad[1]), - :object => SupportN3::fragment(quad[2])) + :object => SupportN3::fragment(quad[2]) + ) else related_asset = build_asset(SupportN3::fragment(quad[2]), create_assets, created_assets) asset.facts << Fact.create(:predicate => SupportN3::fragment(quad[1]), - :object_asset => related_asset, :literal => false) + :object_asset => related_asset, :literal => false) end asset end @@ -163,13 +159,13 @@ class RuleGraphAccessor attr_reader :step_type def self.rules(quads) - quads.select { |quad| fragment(quad[1])=='implies' } + quads.select { |quad| fragment(quad[1]) == 'implies' } end def self.parse_rules(quads, enforce_step_type = nil) self.activity_type = nil deprecate_class_by_name(ActivityType, activity_type_name(quads), activity_type(quads)) do |old_instances| - RuleGraphAccessor.rules(quads).each do |k,p,v,g| + RuleGraphAccessor.rules(quads).each do |k, p, v, g| accessor = RuleGraphAccessor.new(enforce_step_type, quads, k, v) accessor.execute end @@ -197,7 +193,7 @@ def initialize(step_type, quads, graph_conditions, graph_consequences) @graph_conditions = graph_conditions @graph_consequences = graph_consequences @c_groups = {} - @c_groups_cardinalities={} + @c_groups_cardinalities = {} @step_type = step_type || StepType.create(:name => name_for_step_type) self.class.deprecate_class_by_name(StepType, name_for_step_type, @step_type) do @@ -219,10 +215,10 @@ def actions end def sort_created_assets_first(list) - list.sort do |a,b| - if fragment(a[1])=='createAsset' + list.sort do |a, b| + if fragment(a[1]) == 'createAsset' -1 - elsif fragment(b[1])=='createAsset' + elsif fragment(b[1]) == 'createAsset' 1 else fragment(a[1]) <=> fragment(b[1]) @@ -231,23 +227,21 @@ def sort_created_assets_first(list) end def fragment(k) - k.try(:fragment) || (k.try(:name) || k).to_s.gsub(/.*#/,'').gsub(/_[0-9][0-9][0-9][0-9][0-9][0-9].*$/,'') + k.try(:fragment) || (k.try(:name) || k).to_s.gsub(/.*#/, '').gsub(/_[0-9][0-9][0-9][0-9][0-9][0-9].*$/, '') end def self.fragment(k) - k.try(:fragment) || (k.try(:name) || k).to_s.gsub(/.*#/,'').gsub(/_[0-9][0-9][0-9][0-9][0-9][0-9].*$/,'') + k.try(:fragment) || (k.try(:name) || k).to_s.gsub(/.*#/, '').gsub(/_[0-9][0-9][0-9][0-9][0-9][0-9].*$/, '') end - def condition_group_for(node) c_groups[fragment(node)] end def store_condition_group(condition_group) - c_groups[condition_group.name]=condition_group + c_groups[condition_group.name] = condition_group end - def find_or_create_condition_group_for(node, params) if condition_group_for(node) condition_group_for(node) @@ -260,7 +254,7 @@ def find_or_create_condition_group_for(node, params) def keep_selected_list actions.select { |quad| fragment(quad[1]) == 'unselectAsset' }.map do |q| if q[2].class == RDF::Node - fragment(@quads.select { |k,p,v,g| g==q[2] }.flatten[0]) + fragment(@quads.select { |k, p, v, g| g == q[2] }.flatten[0]) else fragment(q[2]) end @@ -280,32 +274,32 @@ def update_condition_group(condition_group, p, v) else # or we add the new condition object_condition_group = condition_group_for(v) - #if (!object_condition_group.nil? && object_condition_group.conditions.empty? && (fragment(v)[0] != '_')) + # if (!object_condition_group.nil? && object_condition_group.conditions.empty? && (fragment(v)[0] != '_')) # object_condition_group = nil - #end + # end Condition.create({ :predicate => fragment(p), :object => fragment(v), - :condition_group_id => condition_group.id, :object_condition_group => object_condition_group }) + :condition_group_id => condition_group.id, :object_condition_group => object_condition_group }) end end def is_wildcard?(v) - (fragment(v)[0]==('_')) + (fragment(v)[0] == ('_')) end def build_condition_groups # Left side of the rule - conditions.each do |k,p,v,g| + conditions.each do |k, p, v, g| # Finds the condition group (or creates it) condition_group = find_or_create_condition_group_for(k, - { :step_type => @step_type, - :keep_selected => check_keep_selected_asset(k) }) + { :step_type => @step_type, + :keep_selected => check_keep_selected_asset(k) }) end cgr = [] - conditions.each do |k,p,v,g| + conditions.each do |k, p, v, g| if is_wildcard?(v) vcgroup = find_or_create_condition_group_for(v, - { :step_type => @step_type, - :keep_selected => check_keep_selected_asset(v) }) + { :step_type => @step_type, + :keep_selected => check_keep_selected_asset(v) }) cgr.push(condition_group_for(v)) end # After reading all condition groups we will be able to recognize @@ -372,7 +366,6 @@ def step_action fragment(value) unless value.nil? end - def execute build_condition_groups build_actions @@ -380,10 +373,10 @@ def execute def build_actions # Right side of the rule - actions.each do |k,p,v,g| + actions.each do |k, p, v, g| action = fragment(p) unless v.literal? - @quads.select { |quad| quad.last == v }.each do |k,p,v,g| + @quads.select { |quad| quad.last == v }.each do |k, p, v, g| # Updates cardinality for the condition group if fragment(p) == 'maxCardinality' @c_groups_cardinalities[fragment(k)] = fragment(v) @@ -397,7 +390,7 @@ def build_actions # side of the rules if @c_groups[fragment(k)].nil? @c_groups[fragment(k)] = ConditionGroup.create({ :cardinality => @c_groups_cardinalities[fragment(k)], - :name => fragment(k), :keep_selected => check_keep_selected_asset(fragment(k)) }) + :name => fragment(k), :keep_selected => check_keep_selected_asset(fragment(k)) }) end # Creates condition groups from the objects of the actions side object_condition_group_id = nil @@ -407,21 +400,21 @@ def build_actions if v.class.name == 'RDF::Query::Variable' if c_groups[fragment(v)].nil? c_groups[fragment(v)] = ConditionGroup.create(:cardinality => @c_groups_cardinalities[fragment(v)], - :name=> fragment(v), :keep_selected => check_keep_selected_asset(fragment(v))) + :name => fragment(v), :keep_selected => check_keep_selected_asset(fragment(v))) end object_condition_group_id = c_groups[fragment(v)].id end end Action.create({ :action_type => action, :predicate => fragment(p), - :object => fragment(v), - :step_type_id => @step_type.id, - :subject_condition_group_id => @c_groups[fragment(k)].id, - :object_condition_group_id => object_condition_group_id - }) - if (action=='unselectAsset') + :object => fragment(v), + :step_type_id => @step_type.id, + :subject_condition_group_id => @c_groups[fragment(k)].id, + :object_condition_group_id => object_condition_group_id }) + if (action == 'unselectAsset') Condition.create({ - :predicate => fragment(p), :object => fragment(v), - :condition_group_id => @c_groups[fragment(k)].id }) + :predicate => fragment(p), :object => fragment(v), + :condition_group_id => @c_groups[fragment(k)].id + }) end end end diff --git a/lib/tasks/setup_templates.rake b/lib/tasks/setup_templates.rake index 4afc27d9..4d538605 100644 --- a/lib/tasks/setup_templates.rake +++ b/lib/tasks/setup_templates.rake @@ -1,4 +1,3 @@ - namespace :label_templates do desc "Find or register label templates in print-my-barcode" task setup: :environment do @@ -10,4 +9,3 @@ namespace :label_templates do LabelTemplateSetup.find_or_register_each_template! end end - diff --git a/lib/token_util.rb b/lib/token_util.rb index b5cedfad..e66e6dbf 100644 --- a/lib/token_util.rb +++ b/lib/token_util.rb @@ -15,22 +15,26 @@ def self.invalid_barcode?(barcode) def self.machine_barcode?(barcode) return false if invalid_barcode?(barcode) + barcode.to_s.match?(MACHINE_BARCODE) end def self.human_barcode?(barcode) return false if invalid_barcode?(barcode) + # If we change the next line, we should change it to check the regexp !machine_barcode?(barcode) end def self.machine_barcode(barcode) return SBCF::SangerBarcode.from_human(barcode).machine_barcode.to_s if human_barcode?(barcode) + barcode.to_s end def self.human_barcode(barcode) return SBCF::SangerBarcode.from_machine(barcode).human_barcode.to_s if machine_barcode?(barcode) + barcode.to_s end @@ -40,6 +44,7 @@ def self.is_uuid?(str) def self.quote_if_uuid(str) return quote(str) if is_uuid?(str) + return str end @@ -61,43 +66,49 @@ def self.kind_of_asset_id?(str) def self.to_asset_group_name(wildcard) return wildcard if wildcard.nil? + wildcard.gsub('?', '') end def self.generate_positions(letters, columns) - size=letters.size * columns.size + size = letters.size * columns.size location_for_position = size.times.map do |i| - "#{letters[(i%letters.length).floor]}#{pad((columns[(i/letters.length).floor]).to_s,'0',2)}" + "#{letters[(i % letters.length).floor]}#{pad((columns[(i / letters.length).floor]).to_s, '0', 2)}" end end - def self.pad(str,chr,size) - "#{(size-str.size).times.map { chr }.join}#{str}" + def self.pad(str, chr, size) + "#{(size - str.size).times.map { chr }.join}#{str}" end def self.unpad_location(location) return location unless location + loc = location.match(/(\w)(0*)(\d*)/) - loc[1]+loc[3] + loc[1] + loc[3] end def self.pad_location(location) return location unless location + parts = location.match(LOCATION_REGEXP) return nil if parts.length == 0 + letter = parts[1] number = parts[2] - number = TokenUtil.pad(number,"0",2) unless number.length == 2 + number = TokenUtil.pad(number, "0", 2) unless number.length == 2 "#{letter}#{number}" end def self.quote(str) return str unless str + "\"#{str}\"" end def self.unquote(str) return str unless str - str.gsub(/\"/,"") + + str.gsub(/\"/, "") end end diff --git a/script/aliquot_type_inference.rb b/script/aliquot_type_inference.rb index 98c4d974..acfcf2aa 100644 --- a/script/aliquot_type_inference.rb +++ b/script/aliquot_type_inference.rb @@ -4,6 +4,7 @@ class AliquotTypeInference def initialize(params) @asset_group = params[:asset_group] end + # rubocop:todo Naming/MethodName def _CODE %Q{ @@ -16,6 +17,7 @@ def _CODE } } end + def assets_compatible_with_step_type asset_group.assets.with_predicate('aliquotType').select { |a| a.has_predicate?('contains') } end @@ -29,8 +31,8 @@ def process if assets_compatible_with_step_type.count > 0 assets_compatible_with_step_type.each do |asset| unless asset.facts.with_predicate('contains').map(&:object_asset).any? do |o| - o.has_predicate?('aliquotType') - end + o.has_predicate?('aliquotType') + end asset.facts.with_predicate('contains').map(&:object_asset).each do |o| if o.has_predicate?('sample_tube') updates.add(o, 'aliquotType', aliquot_type_fact(asset).object) @@ -50,6 +52,7 @@ def out(val) end return unless ARGV.any? { |s| s.match(".json") } + args = ARGV[0] out({}) unless args diff --git a/script/claim_uuids.rb b/script/claim_uuids.rb index b2db7869..fab8478d 100644 --- a/script/claim_uuids.rb +++ b/script/claim_uuids.rb @@ -6,7 +6,7 @@ module ClaimUuids def orphan_receptacles(stock_plate_ss) stock_plate_ss.wells.map do |well| list = well.aliquots.first.sample.receptacles.select { |w| w.plate.nil? } - if list.length>1 + if list.length > 1 puts "The plate #{stock_plate_ss.barcode} has more than one orphan for the well #{well.id}" end list @@ -51,5 +51,4 @@ def process_list(list) link_missing_wells(pre_extracted_plate, stock_plate) end end - -end \ No newline at end of file +end diff --git a/script/container_inferences.rb b/script/container_inferences.rb index 0985b13a..456ed532 100644 --- a/script/container_inferences.rb +++ b/script/container_inferences.rb @@ -5,7 +5,6 @@ def initialize(params) @asset_group = params[:asset_group] end - def containers asset_group.assets.joins(%Q{ INNER JOIN facts as plate_facts on plate_facts.asset_id=assets.id AND plate_facts.predicate='contains' @@ -17,6 +16,7 @@ def containers def purpose_for_aliquot(aliquot) return 'DNA Stock Plate' if aliquot == 'DNA' return 'RNA Stock Plate' if aliquot == 'RNA' + return 'Stock Plate' end @@ -25,6 +25,7 @@ def study_name_for(asset) f.object_asset.facts.with_predicate('study_name').map(&:object) end.flatten.compact.uniq return "" if list.count > 1 + return list.first end @@ -33,6 +34,7 @@ def purpose_for(asset) f.object_asset.facts.with_predicate('aliquotType').map(&:object) end.flatten.compact.uniq return "" if list.count > 1 + return purpose_for_aliquot(list.first) end @@ -46,7 +48,6 @@ def process end end end - end def out(val) @@ -63,4 +64,3 @@ def out(val) asset_group_id = matches[1] asset_group = AssetGroup.find(asset_group_id) out(ContainerInferences.new(asset_group: asset_group).process) - diff --git a/script/purpose_name_inference.rb b/script/purpose_name_inference.rb index 88b429de..8b74a252 100644 --- a/script/purpose_name_inference.rb +++ b/script/purpose_name_inference.rb @@ -48,6 +48,7 @@ def containers def purpose_for_aliquot(aliquot) return 'DNA Stock Plate' if aliquot == 'DNA' return 'RNA Stock Plate' if aliquot == 'RNA' + return 'Stock Plate' end @@ -56,6 +57,7 @@ def purpose_for(asset) f.object_asset.facts.with_predicate('aliquotType').map(&:object) end.flatten.compact.uniq return "" if list.count > 1 + return purpose_for_aliquot(list.first) end @@ -68,7 +70,6 @@ def process end end end - end def out(val) diff --git a/script/recreate_steptypes.rb b/script/recreate_steptypes.rb index 5c59c3e4..04e6f4e6 100755 --- a/script/recreate_steptypes.rb +++ b/script/recreate_steptypes.rb @@ -53,7 +53,7 @@ { ?p :a :TubeRack .}=>{}. }] ].map { |l| - s=StepType.find_by(name: l[0]) - s2=StepType.create(name: l[0], step_action: l[1], for_reasoning: true, n3_definition: l[2]) + s = StepType.find_by(name: l[0]) + s2 = StepType.create(name: l[0], step_action: l[1], for_reasoning: true, n3_definition: l[2]) s.deprecate_with(s) } diff --git a/script/remove_duplicates.rb b/script/remove_duplicates.rb index 8e27df09..3023627c 100644 --- a/script/remove_duplicates.rb +++ b/script/remove_duplicates.rb @@ -1,6 +1,6 @@ def remove_duplicates(plate) ActiveRecord::Base.transaction do - #wells = plate.facts.where(predicate: 'contains').map(&:object_asset) + # wells = plate.facts.where(predicate: 'contains').map(&:object_asset) wells.each do |well| location = well.facts.where(predicate: 'location').last parent = well.facts.where(predicate: 'parent').last diff --git a/script/runners/create_12_tubes.rb b/script/runners/create_12_tubes.rb index f2913acf..bb23fc27 100755 --- a/script/runners/create_12_tubes.rb +++ b/script/runners/create_12_tubes.rb @@ -1,5 +1,6 @@ return unless ARGV.any? { |s| s.match(".json") } -TOTAL_NUMBER=12 + +TOTAL_NUMBER = 12 tubes = TOTAL_NUMBER.times.map { |i| "?p#{i}" } samples = TOTAL_NUMBER.times.map { |i| "?q#{i}" } @@ -15,9 +16,9 @@ f7 = tubes.each_with_index.map { |t, i| [t, 'volume', 100] } all_assets = tubes + samples -obj= { +obj = { create_assets: all_assets, - add_facts: [f1,f2,f3,f4,f5,f6,f7].reduce([]) { |memo, facts| memo.concat(facts) }, + add_facts: [f1, f2, f3, f4, f5, f6, f7].reduce([]) { |memo, facts| memo.concat(facts) }, add_assets: [tubes] }.to_json diff --git a/script/runners/create_file.rb b/script/runners/create_file.rb index 3cfda02f..0dd33a41 100755 --- a/script/runners/create_file.rb +++ b/script/runners/create_file.rb @@ -2,12 +2,12 @@ require 'csv' require 'rest_client' -NUM_BARCODES=96 +NUM_BARCODES = 96 num = 0 barcodes = [] while (num < NUM_BARCODES) do - number=(rand*999999).floor.to_s - barcode = ["FR"].concat((6-number.length).times.map { "0" }).concat([number]).join + number = (rand * 999999).floor.to_s + barcode = ["FR"].concat((6 - number.length).times.map { "0" }).concat([number]).join found = Asset.find_by(barcode: barcode) unless found barcodes.push(barcode) @@ -19,7 +19,7 @@ letters = ("A".."H").to_a columns = (1..12).to_a location_for_position = NUM_BARCODES.times.map do |i| - "#{letters[(i/columns.length).floor]}#{(columns[i%columns.length]).to_s}" + "#{letters[(i / columns.length).floor]}#{(columns[i % columns.length]).to_s}" end temp_file = Tempfile.new diff --git a/script/runners/create_layout.rb b/script/runners/create_layout.rb index 65a512ac..9a9ab6c1 100755 --- a/script/runners/create_layout.rb +++ b/script/runners/create_layout.rb @@ -2,12 +2,12 @@ require 'csv' require 'rest_client' -NUM_BARCODES=96 +NUM_BARCODES = 96 num = 0 barcodes = [] while (num < NUM_BARCODES) do - number=(rand*999999).floor.to_s - barcode = ["FR"].concat((6-number.length).times.map { "0" }).concat([number]).join + number = (rand * 999999).floor.to_s + barcode = ["FR"].concat((6 - number.length).times.map { "0" }).concat([number]).join found = Asset.find_by(barcode: barcode) unless found barcodes.push(barcode) @@ -19,7 +19,7 @@ letters = ("A".."H").to_a columns = (1..12).to_a location_for_position = NUM_BARCODES.times.map do |i| - "#{letters[(i/columns.length).floor]}#{(columns[i%columns.length]).to_s}" + "#{letters[(i / columns.length).floor]}#{(columns[i % columns.length]).to_s}" end temp_file = Tempfile.new @@ -32,6 +32,6 @@ file = UploadedFile.create(filename: "_temp.csv", data: temp_file.read) asset = file.build_asset(content_type: "csv") -data= { add_assets: [[nil, [asset.uuid] ]] } +data = { add_assets: [[nil, [asset.uuid]]] } puts data.to_json diff --git a/script/runners/create_stamped_plate.rb b/script/runners/create_stamped_plate.rb index 0fb475cc..190db3e2 100644 --- a/script/runners/create_stamped_plate.rb +++ b/script/runners/create_stamped_plate.rb @@ -26,7 +26,6 @@ def process Actions::PlateTransfer.transfer_plates(source_plate, "?stampedPlate", updates) end end - end return unless ARGV.any? { |s| s.match(".json") } @@ -35,4 +34,3 @@ def process asset_group_id = args.match(/(\d*)\.json/)[1] asset_group = AssetGroup.find(asset_group_id) puts CreateStampedPlate.new(asset_group: asset_group).process.to_json - diff --git a/script/runners/full_rack_generator.rb b/script/runners/full_rack_generator.rb index aa8add61..3d17fd6e 100644 --- a/script/runners/full_rack_generator.rb +++ b/script/runners/full_rack_generator.rb @@ -16,7 +16,7 @@ letters = ("A".."H").to_a columns = (1..12).to_a location_for_position = 96.times.map do |i| - "#{letters[(i/columns.length).floor]}#{(columns[i%columns.length]).to_s}" + "#{letters[(i / columns.length).floor]}#{(columns[i % columns.length]).to_s}" end facts_to_add = (location_for_position - locations_with_tube).reduce([]) do |memo, location| diff --git a/script/runners/load_metadata.rb b/script/runners/load_metadata.rb index edf44cd6..9ef0f591 100644 --- a/script/runners/load_metadata.rb +++ b/script/runners/load_metadata.rb @@ -18,6 +18,7 @@ def find_asset(line_parsed) facts = parent.facts.where(predicate: 'contains', object_asset_id: Fact.where(predicate: 'location', object: line_parsed['location']).select(:asset_id)) raise 'More than one asset found' if facts.count > 1 + return facts.first.object_asset else Asset.find_by!(barcode: line_parsed['barcode']) @@ -25,7 +26,7 @@ def find_asset(line_parsed) end def filter_unneeded_data(line_parsed) - line_parsed.reject { |k,v| k=='location' || k=='barcode' } + line_parsed.reject { |k, v| k == 'location' || k == 'barcode' } end def metadata_updates(asset_group) @@ -45,7 +46,6 @@ def metadata_updates(asset_group) end end - def process FactChanges.new.tap do |updates| if assets_compatible_with_step_type.count > 0 @@ -70,5 +70,5 @@ def process rescue InvalidDataParams => e puts ({ set_errors: e.errors }.to_json) rescue StandardError => e - puts ({ set_errors: ['Unknown error while parsing file'+e.backtrace.to_s] }.to_json) + puts ({ set_errors: ['Unknown error while parsing file' + e.backtrace.to_s] }.to_json) end diff --git a/script/runners/move_barcodes_from_tube_rack_to_plate.rb b/script/runners/move_barcodes_from_tube_rack_to_plate.rb index e61d55ae..58656081 100644 --- a/script/runners/move_barcodes_from_tube_rack_to_plate.rb +++ b/script/runners/move_barcodes_from_tube_rack_to_plate.rb @@ -1,4 +1,3 @@ - # # This rule applies the barcodes from a rack into a plate # { # ?plate se:a Plate . @@ -22,7 +21,6 @@ class MoveBarcodesFromTubeRackToPlate attr_reader :asset_group - def initialize(params) @asset_group = params[:asset_group] end @@ -31,7 +29,6 @@ def assets_compatible_with_step_type [plate, tube_rack].flatten.compact.count > 0 end - def plate asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'Plate').count > 0 }.first end @@ -49,7 +46,7 @@ def well_at_location(asset, location) location_facts = w.facts.where(predicate: 'location') if (location_facts.count == 1) location_fact = location_facts.first - (TokenUtil.pad_location(location_fact.object) == TokenUtil.pad_location(location)) + (TokenUtil.pad_location(location_fact.object) == TokenUtil.pad_location(location)) end end.first end @@ -66,12 +63,12 @@ def process if assets_compatible_with_step_type traverse_wells(tube_rack) do |well_from_tube_rack, location| well_from_plate = well_at_location(plate, location) - barcode = well_from_tube_rack.barcode + barcode = well_from_tube_rack.barcode updates.remove_where(well_from_tube_rack, 'barcode', barcode) updates.add(well_from_tube_rack, 'previousBarcode', barcode) updates.add(well_from_tube_rack, 'appliedBarcodeTo', well_from_plate) - well_from_tube_rack.update_attributes(barcode: nil) - well_from_plate.update_attributes(barcode: barcode) + well_from_tube_rack.update_attributes(barcode: nil) + well_from_plate.update_attributes(barcode: barcode) updates.add(well_from_plate, 'barcode', barcode) end @@ -82,7 +79,6 @@ def process end end - args = ARGV[0] asset_group_id = args.match(/(\d*)\.json/)[1] asset_group = AssetGroup.find(asset_group_id) @@ -95,6 +91,5 @@ def process JSON.parse(json) puts json rescue StandardError => e - puts ({ set_errors: ['Unknown error while applying barcodes'+e.backtrace.to_s] }.to_json) + puts ({ set_errors: ['Unknown error while applying barcodes' + e.backtrace.to_s] }.to_json) end - diff --git a/script/runners/print_barcodes.rb b/script/runners/print_barcodes.rb index 6e754222..bc264c16 100644 --- a/script/runners/print_barcodes.rb +++ b/script/runners/print_barcodes.rb @@ -34,7 +34,6 @@ def process end end end - end return unless ARGV.any? { |s| s.match(".json") } diff --git a/script/runners/put_tubes_into_rack_by_column_order.rb b/script/runners/put_tubes_into_rack_by_column_order.rb index 840a3977..9a27c65f 100644 --- a/script/runners/put_tubes_into_rack_by_column_order.rb +++ b/script/runners/put_tubes_into_rack_by_column_order.rb @@ -6,8 +6,6 @@ updates = FactChanges.new - - args = ARGV[0] out({}) unless args matches = args.match(/(\d*)\.json/) diff --git a/script/runners/rack_layout.rb b/script/runners/rack_layout.rb index 6bebf87b..9a201467 100644 --- a/script/runners/rack_layout.rb +++ b/script/runners/rack_layout.rb @@ -13,7 +13,6 @@ def assets_compatible_with_step_type asset_group.uploaded_files end - def process FactChanges.new.tap do |updates| if assets_compatible_with_step_type.count > 0 @@ -37,5 +36,5 @@ def process rescue InvalidDataParams => e puts ({ set_errors: e.errors }.to_json) rescue StandardError => e - puts ({ set_errors: ['Unknown error while parsing file'+e] }.to_json) + puts ({ set_errors: ['Unknown error while parsing file' + e] }.to_json) end diff --git a/script/runners/rack_layout_any_barcode.rb b/script/runners/rack_layout_any_barcode.rb index 39583a28..ecaf3ca9 100644 --- a/script/runners/rack_layout_any_barcode.rb +++ b/script/runners/rack_layout_any_barcode.rb @@ -13,7 +13,6 @@ def assets_compatible_with_step_type asset_group.uploaded_files end - def process FactChanges.new.tap do |updates| if assets_compatible_with_step_type.count > 0 @@ -38,6 +37,5 @@ def process rescue InvalidDataParams => e puts ({ set_errors: e.errors }.to_json) rescue StandardError => e - - puts ({ set_errors: ['Unknown error while parsing file'+e.to_json+e.backtrace.join] }.to_json) + puts ({ set_errors: ['Unknown error while parsing file' + e.to_json + e.backtrace.join] }.to_json) end diff --git a/script/runners/transfer_plate_to_plate.rb b/script/runners/transfer_plate_to_plate.rb index 67589421..096d260e 100644 --- a/script/runners/transfer_plate_to_plate.rb +++ b/script/runners/transfer_plate_to_plate.rb @@ -1,14 +1,13 @@ require 'actions/plate_transfer' # Stamps an Asset (plate or tube rack) to another Asset -# In the step type config, there should be: +#  In the step type config, there should be: # A condition group, with name set (e.g. 'p') # A new asset, with addFacts 'transferredFrom:p', where 'p' is the name of above group # The new asset should also have the type specified, by adding fact 'a:Plate' or 'a:TubeRack' # If the new asset is destined for export for Sequencescape... # ...add fact 'barcodeType:NoBarcode', and Samples Extraction won't create a barcode class TransferPlateToPlate - attr_reader :asset_group def initialize(params) @@ -17,7 +16,6 @@ def initialize(params) # rubocop:todo Naming/MethodName def _CODE - end # rubocop:enable Naming/MethodName @@ -34,7 +32,6 @@ def _CODE # } . # - def assets_compatible_with_step_type asset_group.assets.with_predicate('transferredFrom').count > 0 end diff --git a/script/runners/transfer_samples.rb b/script/runners/transfer_samples.rb index a45b4f52..4f038fb3 100644 --- a/script/runners/transfer_samples.rb +++ b/script/runners/transfer_samples.rb @@ -45,7 +45,6 @@ def process end end end - end return unless ARGV.any? { |s| s.match(".json") } diff --git a/script/runners/transfer_tubes_to_tube_rack_by_position.rb b/script/runners/transfer_tubes_to_tube_rack_by_position.rb index a6857636..7e73a37f 100644 --- a/script/runners/transfer_tubes_to_tube_rack_by_position.rb +++ b/script/runners/transfer_tubes_to_tube_rack_by_position.rb @@ -31,7 +31,7 @@ def asset_group_for_execution end def location_to_pos(location, max_row = 8) - ((location[1..-1].to_i - 1) * max_row)+ (location[0].ord - 'A'.ord); + ((location[1..-1].to_i - 1) * max_row) + (location[0].ord - 'A'.ord); end def wells_for(rack) @@ -137,7 +137,6 @@ def process end end end - end return unless ARGV.any? { |s| s.match(".json") } diff --git a/script/runners/update_sequencescape.rb b/script/runners/update_sequencescape.rb index 844e1efd..5fb345e5 100644 --- a/script/runners/update_sequencescape.rb +++ b/script/runners/update_sequencescape.rb @@ -54,4 +54,3 @@ def out(val) asset_group = AssetGroup.find(asset_group_id) step = Step.find(step_id) out(UpdateSequencescape.new(asset_group: asset_group, step: step).process) - diff --git a/script/study_name_inference.rb b/script/study_name_inference.rb index c0baffb1..43a73d88 100644 --- a/script/study_name_inference.rb +++ b/script/study_name_inference.rb @@ -31,6 +31,7 @@ def study_name_for(asset) f.object_asset.facts.with_predicate('study_name').map(&:object) end.flatten.compact.uniq return "" if list.count > 1 + return list.first end @@ -43,7 +44,6 @@ def process end end end - end return unless ARGV.any? { |s| s.match(".json") } diff --git a/script/tasks/runners/aliquot_type_inference.rb b/script/tasks/runners/aliquot_type_inference.rb index 0cb51349..4fd41259 100755 --- a/script/tasks/runners/aliquot_type_inference.rb +++ b/script/tasks/runners/aliquot_type_inference.rb @@ -4,6 +4,7 @@ class AliquotTypeInference def initialize(params) @asset_group = params[:asset_group] end + # rubocop:todo Naming/MethodName def _CODE %Q{ @@ -31,8 +32,8 @@ def process if assets_compatible_with_step_type.count > 0 assets_compatible_with_step_type.each do |asset| unless asset.facts.with_predicate('contains').map(&:object_asset).any? do |o| - o.has_predicate?('aliquotType') - end + o.has_predicate?('aliquotType') + end asset.facts.with_predicate('contains').map(&:object_asset).each do |o| if o.has_predicate?('sample_tube') updates.add(o, 'aliquotType', aliquot_type_fact(asset).object) diff --git a/script/test2.rb b/script/test2.rb index 66d376e2..08d05772 100644 --- a/script/test2.rb +++ b/script/test2.rb @@ -1,5 +1,3 @@ - - obj = { create_assets: ["?p"], create_asset_groups: ["?Eduardo Martin"], diff --git a/spec/concerns/deprecatable_spec.rb b/spec/concerns/deprecatable_spec.rb index fa5c045d..2f8a1ad3 100644 --- a/spec/concerns/deprecatable_spec.rb +++ b/spec/concerns/deprecatable_spec.rb @@ -5,7 +5,6 @@ def build_instance FactoryBot.create(model.to_s.underscore.to_sym) end - let(:model) { described_class } it "deprecates all the instances of the class with the same name" do @@ -19,7 +18,7 @@ def build_instance deprecatable_list.each { |old| old.deprecate_with(active_instance) } expect(model.visible.count).to eq(1) - expect(model.all.count).to eq(deprecatable_list.count+1) + expect(model.all.count).to eq(deprecatable_list.count + 1) expect(model.visible.first).to eq(active_instance) end -end \ No newline at end of file +end diff --git a/spec/controllers/activities_controller_spec.rb b/spec/controllers/activities_controller_spec.rb index dd7c2c1c..b54c1118 100644 --- a/spec/controllers/activities_controller_spec.rb +++ b/spec/controllers/activities_controller_spec.rb @@ -13,7 +13,6 @@ @kit_type = FactoryBot.create :kit_type, :activity_type => @activity_type @kit = FactoryBot.create :kit, { :kit_type => @kit_type } @instrument = FactoryBot.create :instrument - end context "when updating an activity" do @@ -21,7 +20,7 @@ @activity = @kit.kit_type.activity_type.create_activity({ kit: @kit, instrument: @instrument }) end it 'can finish the activity' do - post :update, params: { id: @activity.id, activity: { state: 'finish' } } + post :update, params: { id: @activity.id, activity: { state: 'finish' } } @activity.reload expect(@activity.state).to eq('finish') end @@ -29,7 +28,7 @@ context "when scanning a new kit" do context 'when the kit does not exist' do let(:subject) { - post :create, params: { activity: { :kit_barcode => '11850', :instrument_barcode => @instrument.barcode } } + post :create, params: { activity: { :kit_barcode => '11850', :instrument_barcode => @instrument.barcode } } } it 'fails creating the activity' do count = @kit.kit_type.activity_type.activities.count @@ -45,7 +44,7 @@ context 'when the kit exists' do context 'when the instrument does not support the activity type' do let(:subject) { - post :create, params: { activity: { :kit_barcode => @kit.barcode, :instrument_barcode => @instrument.barcode } } + post :create, params: { activity: { :kit_barcode => @kit.barcode, :instrument_barcode => @instrument.barcode } } } it 'fails creating the activity' do count = @kit.kit_type.activity_type.activities.count @@ -64,7 +63,7 @@ end it "creates a new activity" do count = @kit.kit_type.activity_type.activities.count - post :create, params: { activity: { :kit_barcode => @kit.barcode, :instrument_barcode => @instrument.barcode } } + post :create, params: { activity: { :kit_barcode => @kit.barcode, :instrument_barcode => @instrument.barcode } } @kit.kit_type.activity_type.activities.reload assert_equal @kit.kit_type.activity_type.activities.count, count + 1 assert_equal @activity_type.activities.count, count + 1 diff --git a/spec/controllers/activity_types_controller_spec.rb b/spec/controllers/activity_types_controller_spec.rb index 003a83e2..ae98fbc4 100644 --- a/spec/controllers/activity_types_controller_spec.rb +++ b/spec/controllers/activity_types_controller_spec.rb @@ -17,19 +17,19 @@ it "should create activity_type" do expect { - post :create, params: { activity_type: @activity_type.attributes } + post :create, params: { activity_type: @activity_type.attributes } }.to change { ActivityType.count }.by(1) assert_redirected_to activity_type_path(assigns(:activity_type)) end it "should show activity_type" do - get :show, params: { id: @activity_type } + get :show, params: { id: @activity_type } assert_response :success end it "should get edit" do - get :edit, params: { id: @activity_type } + get :edit, params: { id: @activity_type } assert_response :success end @@ -40,8 +40,8 @@ it "should destroy activity_type" do expect { - delete :destroy, params: { id: @activity_type } - }.to change { ActivityType.count }.by(-1) + delete :destroy, params: { id: @activity_type } + }.to change { ActivityType.count }.by(-1) assert_redirected_to activity_types_path end diff --git a/spec/controllers/asset_groups_controller_spec.rb b/spec/controllers/asset_groups_controller_spec.rb index 64c51aa6..469c739d 100644 --- a/spec/controllers/asset_groups_controller_spec.rb +++ b/spec/controllers/asset_groups_controller_spec.rb @@ -8,8 +8,6 @@ let(:activity_type) { create :activity_type } let(:activity) { create :activity, { activity_type: activity_type, asset_group: asset_group } } - - context '#upload' do let(:file) { fixture_file_upload('test/data/layout.csv', 'text/csv') } @@ -31,7 +29,6 @@ end context "adding a new asset to the asset group" do - let(:barcode) { generate :barcode } let(:asset) { create :asset, barcode: barcode } @@ -40,7 +37,7 @@ it "add the new asset to the group" do expect { post :update, params: { :asset_group => { :assets => [asset.uuid] }, - :id => asset_group.id, :activity_id => activity.id } + :id => asset_group.id, :activity_id => activity.id } }.to change { asset_group.assets.count }.by(1) end end @@ -48,7 +45,7 @@ it "add the new asset to the group" do expect { post :update, params: { :asset_group => { :assets => [asset.barcode] }, - :id => asset_group.id, :activity_id => activity.id } + :id => asset_group.id, :activity_id => activity.id } }.to change { asset_group.assets.count }.by(1) end end @@ -65,12 +62,11 @@ end context "when it is in Sequencescape" do - context 'finding by uuid' do it "retrieves the asset from Sequencescape" do expect { post :update, params: { :asset_group => { :assets => [uuid] }, - :id => asset_group.id, :activity_id => activity.id } + :id => asset_group.id, :activity_id => activity.id } }.to change { asset_group.assets.count }.by(1) end end @@ -79,17 +75,16 @@ it "retrieves the asset from Sequencescape" do expect { post :update, params: { :asset_group => { :assets => [barcode] }, - :id => asset_group.id, :activity_id => activity.id } + :id => asset_group.id, :activity_id => activity.id } }.to change { asset_group.assets.count }.by(1) end end end context "when it is not in Sequencescape" do - it 'does not retrieve anything' do post :update, params: { :asset_group => { :assets => [SecureRandom.uuid] }, - :id => asset_group.id, :activity_id => activity.id } + :id => asset_group.id, :activity_id => activity.id } expect(asset_group.assets.count).to eq(0) end end @@ -101,8 +96,8 @@ expect { post :update, params: { :asset_group => { :assets => [creatable_barcode] - }, - :id => asset_group.id, :activity_id => activity.id } + }, + :id => asset_group.id, :activity_id => activity.id } }.to change { asset_group.assets.count }.by(1) end end diff --git a/spec/controllers/assets_controller_spec.rb b/spec/controllers/assets_controller_spec.rb index 804e527a..bc809ed0 100644 --- a/spec/controllers/assets_controller_spec.rb +++ b/spec/controllers/assets_controller_spec.rb @@ -52,7 +52,7 @@ post :print_search, params: { p0: 'barcode', o0: 'S1234' }, xhr: true expect(assigns(:assets).to_a).to eq(search.to_a) - expect(mocked_group).to have_received(:print).with({ "Plate"=>'Pum', "Tube"=>'Pim' }, 'test') + expect(mocked_group).to have_received(:print).with({ "Plate" => 'Pum', "Tube" => 'Pim' }, 'test') end end end diff --git a/spec/controllers/instruments_controller_spec.rb b/spec/controllers/instruments_controller_spec.rb index 9eb51eca..935edff8 100644 --- a/spec/controllers/instruments_controller_spec.rb +++ b/spec/controllers/instruments_controller_spec.rb @@ -22,30 +22,30 @@ it "should create instrument" do expect { - post :create, params: { instrument: @instrument.attributes } + post :create, params: { instrument: @instrument.attributes } }.to change { Instrument.count }.by(1) assert_redirected_to instrument_path(assigns(:instrument)) end it "should show instrument" do - get :show, params: { id: @instrument } + get :show, params: { id: @instrument } assert_response :success end it "should get edit" do - get :edit, params: { id: @instrument } + get :edit, params: { id: @instrument } assert_response :success end it "should update instrument" do - patch :update, params: { id: @instrument, instrument: @instrument.attributes } + patch :update, params: { id: @instrument, instrument: @instrument.attributes } assert_redirected_to instrument_path(assigns(:instrument)) end it "should destroy instrument" do expect { - delete :destroy, params: { id: @instrument } + delete :destroy, params: { id: @instrument } }.to change { Instrument.count }.by(-1) assert_redirected_to instruments_path diff --git a/spec/controllers/kit_types_controller_spec.rb b/spec/controllers/kit_types_controller_spec.rb index f833d66e..d500b48f 100644 --- a/spec/controllers/kit_types_controller_spec.rb +++ b/spec/controllers/kit_types_controller_spec.rb @@ -30,7 +30,7 @@ end it "should get edit" do - get :edit, params: { id: @kit_type } + get :edit, params: { id: @kit_type } assert_response :success end @@ -41,9 +41,9 @@ it "should destroy kit_type" do expect { - delete :destroy, params: { id: @kit_type } + delete :destroy, params: { id: @kit_type } }.to change { KitType.count }.by(-1) - + assert_redirected_to kit_types_path end end diff --git a/spec/controllers/kits_controller_spec.rb b/spec/controllers/kits_controller_spec.rb index 34a120d9..f338a124 100644 --- a/spec/controllers/kits_controller_spec.rb +++ b/spec/controllers/kits_controller_spec.rb @@ -19,30 +19,30 @@ it "should create kit" do expect { post :create, params: { kit: @kit.attributes } - }.to change { Kit.count }.by(1) + }.to change { Kit.count }.by(1) assert_redirected_to kit_path(assigns(:kit)) end it "should show kit" do - get :show, params:{ id: @kit } + get :show, params: { id: @kit } assert_response :success end it "should get edit" do - get :edit, params:{ id: @kit } + get :edit, params: { id: @kit } assert_response :success end it "should update kit" do - patch :update, params:{ id: @kit, kit: @kit.attributes } + patch :update, params: { id: @kit, kit: @kit.attributes } assert_redirected_to kit_path(assigns(:kit)) end it "should destroy kit" do expect { delete :destroy, params: { id: @kit } - }.to change { Kit.count }.by(-1) + }.to change { Kit.count }.by(-1) assert_redirected_to kits_path end diff --git a/spec/controllers/printers_controller_spec.rb b/spec/controllers/printers_controller_spec.rb index cea6884e..289907ae 100644 --- a/spec/controllers/printers_controller_spec.rb +++ b/spec/controllers/printers_controller_spec.rb @@ -17,10 +17,10 @@ it "should create printer" do expect { - post :create, params: { printer: @printer.attributes } - }.to change { - Printer.count - }.by(1) + post :create, params: { printer: @printer.attributes } + }.to change { + Printer.count + }.by(1) assert_redirected_to printer_path(assigns(:printer)) end @@ -36,14 +36,14 @@ end it "should update printer" do - patch :update, params: { id: @printer, printer: @printer.attributes } + patch :update, params: { id: @printer, printer: @printer.attributes } assert_redirected_to printer_path(assigns(:printer)) end it "should destroy printer" do expect { delete :destroy, params: { id: @printer } - }.to change { Printer.count }.by(-1) + }.to change { Printer.count }.by(-1) assert_redirected_to printers_path end diff --git a/spec/controllers/step_types_controller_spec.rb b/spec/controllers/step_types_controller_spec.rb index 7c7e999e..2e8adb70 100644 --- a/spec/controllers/step_types_controller_spec.rb +++ b/spec/controllers/step_types_controller_spec.rb @@ -18,25 +18,25 @@ it "should create step_type" do expect { post :create, params: { step_type: { :name => 'Test' } } - }.to change { - StepType.count - }.by(1) + }.to change { + StepType.count + }.by(1) assert_redirected_to step_type_url(StepType.last) end it "should show step_type" do - get :show, params:{ id: @step_type } + get :show, params: { id: @step_type } assert_response :success end it "should get edit" do - get :show, params:{ id: @step_type } + get :show, params: { id: @step_type } assert_response :success end it "should update step_type" do - patch :update, params: { id: @step_type, step_type: @step_type.attributes } + patch :update, params: { id: @step_type, step_type: @step_type.attributes } assert_redirected_to step_type_url(@step_type) end @@ -53,9 +53,9 @@ it "should destroy step_type" do expect { delete :destroy, params: { id: @step_type } - }.to change { - StepType.count - }.by(-1) + }.to change { + StepType.count + }.by(-1) assert_redirected_to step_types_url end @@ -71,8 +71,5 @@ post :create, params: params expect(response.redirect?).to eq(true) end - end - end - diff --git a/spec/controllers/steps_controller_spec.rb b/spec/controllers/steps_controller_spec.rb index c5d43992..8645fbe2 100644 --- a/spec/controllers/steps_controller_spec.rb +++ b/spec/controllers/steps_controller_spec.rb @@ -26,16 +26,16 @@ let(:plate_printer) { create :printer, name: 'plates' } it 'stores the printer_config provided as parameter' do post :create, params: { - activity_id: activity.id, step: { - asset_group_id: asset_group.id, step_type_id: step_type.id, - tube_printer_id: tube_printer.id, plate_printer_id: plate_printer.id - } + activity_id: activity.id, step: { + asset_group_id: asset_group.id, step_type_id: step_type.id, + tube_printer_id: tube_printer.id, plate_printer_id: plate_printer.id } + } expect(Step.last.printer_config).to eq({ - "Tube" => tube_printer.name, - "Plate" => plate_printer.name, - "TubeRack" => plate_printer.name - }) + "Tube" => tube_printer.name, + "Plate" => plate_printer.name, + "TubeRack" => plate_printer.name + }) end end end @@ -54,9 +54,11 @@ end context 'when a step is running' do - let(:step) { create :step, - activity: activity, - asset_group: asset_group, step_type: step_type } + let(:step) { + create :step, + activity: activity, + asset_group: asset_group, step_type: step_type + } let(:run_step) { # We want to simulate that during a running process a 'stop' event is received so we @@ -83,7 +85,6 @@ expect(step.stopped?).to eq(true) end context 'when the step performed some changes before stopping' do - it 'cancels all changes that were produced during running' do step_id = step.id allow_any_instance_of(Step).to receive(:process) do @@ -102,7 +103,5 @@ end end end - end - end diff --git a/spec/inferences_helper.rb b/spec/inferences_helper.rb index ffb9bf65..6384b7f0 100644 --- a/spec/inferences_helper.rb +++ b/spec/inferences_helper.rb @@ -3,10 +3,11 @@ def assets_equal?(expected, obtained) return false if expected.nil? || obtained.nil? [[expected, obtained], - [obtained, expected]].all? do |expected_assets, obtained_assets| + [obtained, expected]].all? do |expected_assets, obtained_assets| expected_assets.all? do |expected_asset| obtained_assets.any? do |obtained_asset| next if expected_asset.name != obtained_asset.name + obtained_asset.facts.reload.all? do |obtained_asset_fact| expected_asset.facts.reload.any? do |expected_asset_fact| val = (obtained_asset_fact.predicate == expected_asset_fact.predicate) @@ -23,11 +24,11 @@ def assets_equal?(expected, obtained) end def assets_to_n3(assets) - "\n"+assets.map do |asset| + "\n" + assets.map do |asset| asset.facts.map do |fact| - ":#{asset.name}\t:#{fact.predicate}\t#{fact.object_asset.nil? ? fact.object: ':'+fact.object_asset.name} ." + ":#{asset.name}\t:#{fact.predicate}\t#{fact.object_asset.nil? ? fact.object : ':' + fact.object_asset.name} ." end - end.flatten.sort.join("\n")+"\n" + end.flatten.sort.join("\n") + "\n" end def assets_are_equal(expected_assets, obtained_assets) @@ -44,6 +45,7 @@ def build_step(rule, input_facts, options = {}) input_assets = SupportN3::parse_facts(input_facts, {}, false) reload_assets(input_assets) fail if input_assets.nil? + asset_group = FactoryBot.create(:asset_group, { :assets => input_assets }) user = FactoryBot.create :user, username: 'test' @@ -92,7 +94,6 @@ def check_inference(rule, input_facts, output_facts) comparison = compare_n3_output(expected_n3, obtained_n3) expect(comparison).to eq(true), "expected #{expected_n3}, obtained #{obtained_n3}" end - end include InferencesHelper diff --git a/spec/integration/inference_spec.rb b/spec/integration/inference_spec.rb index f9d69712..e47fa219 100644 --- a/spec/integration/inference_spec.rb +++ b/spec/integration/inference_spec.rb @@ -7,7 +7,6 @@ def cwm_engine? end RSpec.describe "Inference" do - describe '#inference' do describe '#parse_facts' do it 'creates assets from a N3 definition', :testcreation => true do @@ -20,23 +19,23 @@ def cwm_engine? obtained_assets = SupportN3::parse_facts(code) f1 = [ - FactoryBot.create(:fact, { :predicate => 'name', :object => 'a name' }), - FactoryBot.create(:fact, { :predicate => 'volume', :object => '17' })] + FactoryBot.create(:fact, { :predicate => 'name', :object => 'a name' }), + FactoryBot.create(:fact, { :predicate => 'volume', :object => '17' }) + ] tube2 = FactoryBot.create(:asset, :name => 'tube2', :facts => f1) f2 = [ FactoryBot.create(:fact, { :predicate => 'relates', :object_asset => tube2 }) ] - tube1 = FactoryBot.create(:asset, :name => 'tube1', :facts=> f2) + tube1 = FactoryBot.create(:asset, :name => 'tube1', :facts => f2) tube3 = FactoryBot.create(:asset) f3 = [ FactoryBot.create(:fact, { :predicate => 'relates', :object_asset => tube2 }) ] tube4 = FactoryBot.create(:asset, :name => 'tube4', - :facts => f3 - ) + :facts => f3) f4 = [FactoryBot.create(:fact, { :predicate => 'volume', :object => '17' })] tube5 = FactoryBot.create(:asset, :name => 'tube2', - :facts => f4) + :facts => f4) obtained_assets.each do |t| t.reload @@ -48,13 +47,12 @@ def cwm_engine? assets_are_different([tube3, tube2], obtained_assets) assets_are_different([tube4, tube2], obtained_assets) assets_are_different([tube1, tube5], obtained_assets) - assets_are_equal([tube2,tube1], [tube1, tube2]) + assets_are_equal([tube2, tube1], [tube1, tube2]) assets_are_equal([tube1, tube1, tube2], [tube1, tube2]) end end - describe '#inferences' do before do # TODO @@ -80,6 +78,5 @@ def cwm_engine? end end end - end end diff --git a/spec/integration/inferences_data.rb b/spec/integration/inferences_data.rb index 816ac5e9..39c015b7 100644 --- a/spec/integration/inferences_data.rb +++ b/spec/integration/inferences_data.rb @@ -1,28 +1,28 @@ def inferences_data -[ - { - :it => %Q{keeps elements the way they are when there is no changes}, - :rule => %Q{ { ?x :t ?_y .} => { :step :addFacts {?x :t ?_y .}. }. }, - :inputs => %Q{ :a :t "1" . }, - :outputs => %Q{ :a :t "1" .} - }, + [ + { + :it => %Q{keeps elements the way they are when there is no changes}, + :rule => %Q{ { ?x :t ?_y .} => { :step :addFacts {?x :t ?_y .}. }. }, + :inputs => %Q{ :a :t "1" . }, + :outputs => %Q{ :a :t "1" .} + }, - { - :it => %Q{keeps elements the way they are when there is no changes}, - :rule => %Q{ { ?x :t ?_y .} => { :step :addFacts {?x :t ?_y .}. }. }, - :inputs => %Q{ :a :t "1" . :b :t "2".}, - :outputs => %Q{ :a :t "1" . :b :t "2".} - }, + { + :it => %Q{keeps elements the way they are when there is no changes}, + :rule => %Q{ { ?x :t ?_y .} => { :step :addFacts {?x :t ?_y .}. }. }, + :inputs => %Q{ :a :t "1" . :b :t "2".}, + :outputs => %Q{ :a :t "1" . :b :t "2".} + }, - { - :it => %Q{keeps elements the way they are when there is no changes}, - :rule => %Q{ { ?x :relation_r ?_y .} => { :step :addFacts { ?x :relation_r ?_y . }. }. }, - :inputs => %Q{ :a :relation_r """1""" . :b :relation_r :a .}, - :outputs => %Q{ :a :relation_r """1""" . :b :relation_r :a .} - }, - { - :it => %Q{relates elements with wildcard and with literal}, - :rule => %Q{ + { + :it => %Q{keeps elements the way they are when there is no changes}, + :rule => %Q{ { ?x :relation_r ?_y .} => { :step :addFacts { ?x :relation_r ?_y . }. }. }, + :inputs => %Q{ :a :relation_r """1""" . :b :relation_r :a .}, + :outputs => %Q{ :a :relation_r """1""" . :b :relation_r :a .} + }, + { + :it => %Q{relates elements with wildcard and with literal}, + :rule => %Q{ { ?x :s """1""" . ?y :t ?_val . @@ -31,14 +31,14 @@ def inferences_data } }, - :inputs => %Q{ + :inputs => %Q{ :tube1 :s """1""" . :tube2 :t """2""" . :tube3 :s """1""" . :tube4 :t """2""" . }, - :outputs => %Q{ + :outputs => %Q{ :tube1 :s """1""" . :tube1 :val """2""" . :tube2 :t """2""" . @@ -47,10 +47,10 @@ def inferences_data :tube3 :val """2""" . :tube4 :t """2""" . } -}, -{ - :it => %Q{relates elements with wildcard}, - :rule => %Q{ + }, + { + :it => %Q{relates elements with wildcard}, + :rule => %Q{ { ?x :t ?_pos . ?y :t ?_pos . @@ -58,14 +58,14 @@ def inferences_data :step :addFacts {?x :relates_with ?y }. } }, - :inputs => %Q{ + :inputs => %Q{ :tube1 :t """1""" . :tube2 :t """2""" . :tube3 :t """1""" . :tube4 :t """2""" . }, - :outputs => %Q{ + :outputs => %Q{ :tube1 :t """1""" . :tube2 :t """2""" . :tube3 :t """1""" . @@ -80,11 +80,11 @@ def inferences_data :tube4 :relates_with :tube4 . } -}, -{ - :it => %Q{relates elements with relation}, - :tags => :testing, - :rule => %Q{ + }, + { + :it => %Q{relates elements with relation}, + :tags => :testing, + :rule => %Q{ { ?x :a "TubeA" . ?x :transfer ?y . @@ -93,24 +93,24 @@ def inferences_data :step :addFacts { ?y :transferredFrom ?x . }. } }, - :inputs => %Q{ + :inputs => %Q{ :tube1 :a "TubeA" . :tube1 :transfer :tube2 . :tube2 :a "TubeB" . }, - :outputs => %Q{ + :outputs => %Q{ :tube1 :a """TubeA""" . :tube2 :a """TubeB""" . :tube1 :transfer :tube2 . :tube2 :transferredFrom :tube1 . } -}, - { - :it => %Q{set the value if the destination does not have the value}, - :unless => :cwm_engine?, - :rule => %Q{ + }, + { + :it => %Q{set the value if the destination does not have the value}, + :unless => :cwm_engine?, + :rule => %Q{ { ?x :a :Tube . ?y :a :Tube . @@ -121,23 +121,23 @@ def inferences_data :step :addFacts {?y :aliquotType ?_aliquot .}. }. }, - :inputs => %Q{ + :inputs => %Q{ :tube1 :a :Tube . :tube1 :transfer :tube2 . :tube2 :a :Tube . :tube1 :aliquotType "DNA" . }, - :outputs => %Q{ + :outputs => %Q{ :tube1 :a :Tube . :tube1 :transfer :tube2 . :tube2 :a :Tube . :tube1 :aliquotType "DNA" . :tube2 :aliquotType "DNA" . } - }, - { - :it => %Q{only set the value if the destination does not have the value already}, - :rule => %Q{ + }, + { + :it => %Q{only set the value if the destination does not have the value already}, + :rule => %Q{ { ?x :a :Tube . ?y :a :Tube . @@ -148,25 +148,25 @@ def inferences_data :step :addFacts {?y :aliquotType ?_aliquot .}. }. }, - :inputs => %Q{ + :inputs => %Q{ :tube1 :a :Tube . :tube1 :transfer :tube2 . :tube2 :a :Tube . :tube1 :aliquotType """DNA""" . :tube2 :aliquotType """RNA""" . }, - :outputs => %Q{ + :outputs => %Q{ :tube1 :a :Tube . :tube1 :transfer :tube2 . :tube2 :a :Tube . :tube1 :aliquotType """DNA""" . :tube2 :aliquotType """RNA""" . } - }, - { - :it => %Q{transfer between plates}, - :unless => :cwm_engine?, - :rule => %Q{ + }, + { + :it => %Q{transfer between plates}, + :unless => :cwm_engine?, + :rule => %Q{ { ?plate :a :Plate . ?plate2 :a :Plate . @@ -184,7 +184,7 @@ def inferences_data :step :addFacts {?tube1 :transfer ?tube2 .}. }. }, - :inputs => %Q{ + :inputs => %Q{ :plate1 :a :Plate . :plate2 :a :Plate . :tube1 :a :Tube . @@ -199,7 +199,7 @@ def inferences_data :tube3 :location "D9" . :plate1 :contains :tube3 . }, - :outputs => %Q{ + :outputs => %Q{ :plate1 :a :Plate . :plate2 :a :Plate . :tube1 :a :Tube . @@ -216,11 +216,11 @@ def inferences_data :tube1 :transfer :tube2 . } - }, + }, - { - :xit => %Q{perform math operations}, - :rule => %Q{ + { + :xit => %Q{perform math operations}, + :rule => %Q{ { ?plate :a :Plate . @@ -235,7 +235,7 @@ def inferences_data :step :addFacts {?aliquot :currentVolume ?newVolume .}. }. }, - :inputs => %Q{ + :inputs => %Q{ :plate1 :a """Plate""" . :well1 :a """Well""" . @@ -244,7 +244,7 @@ def inferences_data :aliquot1 :currentVolume """20""". }, - :outputs => %Q{ + :outputs => %Q{ :plate1 :a """Plate""" . :well1 :a """Well""" . @@ -252,10 +252,10 @@ def inferences_data :aliquot1 :a :Aliquot . :aliquot1 :currentVolume """30""". } - }, - { - :it => 'moves the value of a wildcard using a relation between two cgroups', - :rule => %Q{ + }, + { + :it => 'moves the value of a wildcard using a relation between two cgroups', + :rule => %Q{ { ?tube :is "Tube" . ?tube :location ?_position . @@ -268,7 +268,7 @@ def inferences_data :step :addFacts {?rack :location ?_position .} . } }, - :inputs => %Q{ + :inputs => %Q{ :tube1 :is "Tube" , :Full ; :location "1". :tube2 :is "Tube" , :Full ; :location "2". :tube3 :is "Tube" , :Full ; :location "3". @@ -283,7 +283,7 @@ def inferences_data :rack4 :is "Rack" , :Full ; :contains :tube4 ; :position "4" ; :relates :tube4 . :rack5 :is "Rack" , :Full ; :contains :tube5 ; :position "5" ; :relates :tube5 . }, - :outputs => %Q{ + :outputs => %Q{ :tube1 :is "Tube" , :Full ; :location "1". :tube2 :is "Tube" , :Full ; :location "2". :tube3 :is "Tube" , :Full ; :location "3". @@ -298,10 +298,10 @@ def inferences_data :rack4 :is "Rack" , "TubeRack" , :Full ; :contains :tube4 ; :position "4" ; :relates :tube4 ; :location "4" . :rack5 :is "Rack" , "TubeRack" , :Full ; :contains :tube5 ; :position "5" ; :relates :tube5 ; :location "5" . } - }, - { - :it => 'Bug 1: Not transferring tube contents to tube rack', - :rule => %Q{ + }, + { + :it => 'Bug 1: Not transferring tube contents to tube rack', + :rule => %Q{ { ?tuberack :a :TubeRack . ?tuberack :layout :Complete . @@ -309,7 +309,7 @@ def inferences_data ?tube :sanger_sample_id ?_sample . } => { :step :addFacts {?tube :transferToTubeRackByPosition ?tuberack . } . } . }, - :inputs => %Q{ + :inputs => %Q{ :tube :a "Tube" . :tube :aliquotType "RNA" . :tube :is "Used" . @@ -323,7 +323,7 @@ def inferences_data :tubeRack :contains :tube2 . :tubeRack :contains :tube3 . :tubeRack :layout "Complete" . }, - :outputs => %Q{ + :outputs => %Q{ :tube :transferToTubeRackByPosition :tubeRack . :tube :a "Tube" . :tube :aliquotType "RNA" . @@ -339,20 +339,20 @@ def inferences_data :tubeRack :contains :tube3 . :tubeRack :layout "Complete" . } - }, - { - :it => 'creates new assets from scratch', - :rule => %Q{ + }, + { + :it => 'creates new assets from scratch', + :rule => %Q{ {?p :maxCardinality "1" .} => { :step :createAsset {?p :a :Tube . ?p :uuid "tube" .} } . }, - :inputs => %Q{}, - :outputs => %Q{ + :inputs => %Q{}, + :outputs => %Q{ :tube :a :Tube . :tube :uuid "tube" . } - } + } -] + ] end diff --git a/spec/lib/actions/plate_transfer_spec.rb b/spec/lib/actions/plate_transfer_spec.rb index 26196b8b..f1ea741c 100644 --- a/spec/lib/actions/plate_transfer_spec.rb +++ b/spec/lib/actions/plate_transfer_spec.rb @@ -9,7 +9,7 @@ tube = create(:asset, barcode: '1234') source.facts << create(:fact, predicate: 'contains', object_asset: tube) destination = create :asset - updates = Actions::PlateTransfer.transfer_plates(source,destination) + updates = Actions::PlateTransfer.transfer_plates(source, destination) expect(updates.to_h[:add_facts].select { |t| t[1] == 'barcode' }.length).to eq(0) end it 'copies facts from source wells to destination wells' do @@ -29,11 +29,11 @@ well2.facts << create(:fact, predicate: 'concentration', object: '1.3') destination = create :asset - updates = Actions::PlateTransfer.transfer_plates(source,destination) - expect(updates.to_h[:add_facts].select { |t| t[1]=='location' }.map { |t| t[2] }).to eq(["A01", "B01"]) - expect(updates.to_h[:add_facts].select { |t| t[1]=='concentration' }.map { |t| t[2] }).to eq(["1.3"]) - expect(updates.to_h[:add_facts].select { |t| t[1]=='sample_common_name' }.map { |t| t[2] }).to eq(["species"]) - expect(updates.to_h[:add_facts].select { |t| t[1]=='a' }.map { |t| t[2] }).to eq(["Well", "Well"]) + updates = Actions::PlateTransfer.transfer_plates(source, destination) + expect(updates.to_h[:add_facts].select { |t| t[1] == 'location' }.map { |t| t[2] }).to eq(["A01", "B01"]) + expect(updates.to_h[:add_facts].select { |t| t[1] == 'concentration' }.map { |t| t[2] }).to eq(["1.3"]) + expect(updates.to_h[:add_facts].select { |t| t[1] == 'sample_common_name' }.map { |t| t[2] }).to eq(["species"]) + expect(updates.to_h[:add_facts].select { |t| t[1] == 'a' }.map { |t| t[2] }).to eq(["Well", "Well"]) end it 'can copy facts with uuid values' do source = create :asset @@ -43,7 +43,7 @@ well.facts << create(:fact, predicate: 'study', object: SecureRandom.uuid, literal: true) destination = create :asset - updates = Actions::PlateTransfer.transfer_plates(source,destination) + updates = Actions::PlateTransfer.transfer_plates(source, destination) expect(updates.to_h[:set_errors].nil?).to eq(true) end it 'copies the aliquot type of the plate into the wells' do @@ -59,7 +59,7 @@ updates = Actions::PlateTransfer.transfer_plates(source, destination, updates) created_well = updates.to_h[:add_facts].select { |t| (t[1] == 'location') }.first[0] - expect(updates.to_h[:add_facts].select { |t| (t[0]==created_well) && (t[1]=='aliquotType') }.first[2]).to eq('DNA') + expect(updates.to_h[:add_facts].select { |t| (t[0] == created_well) && (t[1] == 'aliquotType') }.first[2]).to eq('DNA') end it 'does not copy ignored predicates' do source = create :asset @@ -76,7 +76,7 @@ updates = Actions::PlateTransfer.transfer_plates(source, destination, FactChanges.new) expect(updates.to_h[:add_facts].select { |t| (t[1] == 'pushedTo') }.length).to eq(0) - expect(updates.to_h[:add_facts].select { |t| (t[1] == 'location') }.length>0).to eq(true) + expect(updates.to_h[:add_facts].select { |t| (t[1] == 'location') }.length > 0).to eq(true) end end end diff --git a/spec/lib/actions/racking_spec.rb b/spec/lib/actions/racking_spec.rb index 933c97dc..8797c6c7 100644 --- a/spec/lib/actions/racking_spec.rb +++ b/spec/lib/actions/racking_spec.rb @@ -3,16 +3,18 @@ RSpec.describe Actions::Racking do let(:content) { File.read('test/data/layout.csv') } - let(:file) { create(:uploaded_file, data: content ) } + let(:file) { create(:uploaded_file, data: content) } let(:activity) { create(:activity) } let(:asset_group) { create(:asset_group, assets: [asset]) } let(:fact) { create(:fact, predicate: 'a', object: 'TubeRack') } let(:asset) { create :asset, uploaded_file: file, facts: [fact] } let(:step_type) { create(:step_type, condition_groups: [condition_group]) } - let(:step) { create :step, - activity: activity, - state: Step::STATE_RUNNING, - asset_group: asset_group, step_type: step_type } + let(:step) { + create :step, + activity: activity, + state: Step::STATE_RUNNING, + asset_group: asset_group, step_type: step_type + } let(:condition) { create(:condition, predicate: fact.predicate, object: fact.object) } let(:condition_group) { create(:condition_group, conditions: [condition]) } @@ -107,13 +109,10 @@ def add_empty_slots(content, num_empty, start_pos = 0) end end end - end - end end - describe '#fact_changes_for_rack_when_unracking_tubes' do before do @tubes = 15.times.map do |line| @@ -130,7 +129,7 @@ def add_empty_slots(content, num_empty, start_pos = 0) end updates = fact_changes_for_rack_when_unracking_tubes(asset, @tubes) expect(updates.to_h[:remove_facts].select do |triple| - triple[1]=='study_name' + triple[1] == 'study_name' end.map { |triple| triple[2] }.sort).to eq(['STDY1', 'STDY2']) end @@ -139,7 +138,7 @@ def add_empty_slots(content, num_empty, start_pos = 0) @tubes.first.facts << create(:fact, predicate: 'aliquotType', object: 'DNA') updates = fact_changes_for_rack_when_unracking_tubes(asset, @tubes) expect(updates.to_h[:remove_facts].select do |triple| - triple[1]=='purpose' + triple[1] == 'purpose' end.map { |triple| triple[2] }.sort).to eq(['DNA Stock Plate']) end @@ -154,12 +153,11 @@ def add_empty_slots(content, num_empty, start_pos = 0) updates = fact_changes_for_rack_when_unracking_tubes(asset, tubes2) expect(updates.to_h[:remove_facts].select do |triple| - triple[1]=='study_name' + triple[1] == 'study_name' end.map { |triple| triple[2] }.sort).to eq(['STDY1']) end end - describe '#fact_changes_for_rack_when_racking_tubes' do before do @tubes = 15.times.map do |line| @@ -174,7 +172,7 @@ def add_empty_slots(content, num_empty, start_pos = 0) updates = fact_changes_for_rack_when_racking_tubes(asset, @tubes) expect(updates.to_h[:add_facts].select do |triple| - triple[1]=='study_name' + triple[1] == 'study_name' end.map { |triple| triple[2] }.sort).to eq(['STDY1', 'STDY2']) end it 'generates the DNA stock plate purpose' do @@ -183,7 +181,7 @@ def add_empty_slots(content, num_empty, start_pos = 0) end updates = fact_changes_for_rack_when_racking_tubes(asset, @tubes) expect(updates.to_h[:add_facts].select do |triple| - triple[1]=='purpose' + triple[1] == 'purpose' end.first[2]).to eq('DNA Stock Plate') end it 'generates the RNA stock plate purpose' do @@ -192,7 +190,7 @@ def add_empty_slots(content, num_empty, start_pos = 0) end updates = fact_changes_for_rack_when_racking_tubes(asset, @tubes) expect(updates.to_h[:add_facts].select do |triple| - triple[1]=='purpose' + triple[1] == 'purpose' end.first[2]).to eq('RNA Stock Plate') end end @@ -212,5 +210,4 @@ def add_empty_slots(content, num_empty, start_pos = 0) let(:method) { :rack_layout_creating_tubes } it_behaves_like('rack_layout') end - end diff --git a/spec/lib/actions/tube_transfer_spec.rb b/spec/lib/actions/tube_transfer_spec.rb index 86671f86..43fe5ba5 100644 --- a/spec/lib/actions/tube_transfer_spec.rb +++ b/spec/lib/actions/tube_transfer_spec.rb @@ -15,12 +15,11 @@ end it 'transfers study_uuid' do updates = transfer_tubes(source, destination) - expect(updates.to_h[:add_facts].select { |t| t[1]=='study_uuid' }.first[2]).to eq(quoted_study_uuid) + expect(updates.to_h[:add_facts].select { |t| t[1] == 'study_uuid' }.first[2]).to eq(quoted_study_uuid) end it 'transfers common name' do updates = transfer_tubes(source, destination) - expect(updates.to_h[:add_facts].select { |t| t[1]=='sample_common_name' }.first[2]).to eq(common_name) + expect(updates.to_h[:add_facts].select { |t| t[1] == 'sample_common_name' }.first[2]).to eq(common_name) end - end end diff --git a/spec/lib/changes_support/disjoint_list_spec.rb b/spec/lib/changes_support/disjoint_list_spec.rb index 5fa570f4..8d399f3b 100644 --- a/spec/lib/changes_support/disjoint_list_spec.rb +++ b/spec/lib/changes_support/disjoint_list_spec.rb @@ -2,11 +2,10 @@ require 'changes_support/disjoint_list' RSpec.describe 'ChangesSupport::DisjointList' do - describe '#initialize' do it 'adds the elements of the list and caches info' do - list = ChangesSupport::DisjointList.new([1,2,3]) - expect(list.to_a).to eq([1,2,3]) + list = ChangesSupport::DisjointList.new([1, 2, 3]) + expect(list.to_a).to eq([1, 2, 3]) end end @@ -33,7 +32,7 @@ expect(list.unique_id_for_element("abcdef")).to eq(list.unique_id_for_element("abcdef")) end it 'can generate an id for arrays' do - expect(list.unique_id_for_element(["1","2","3"])).to eq(list.unique_id_for_element([1,2,3])) + expect(list.unique_id_for_element(["1", "2", "3"])).to eq(list.unique_id_for_element([1, 2, 3])) end it 'can generate an id for hash' do expect(list.unique_id_for_element({ a: 1, b: 2, c: 3 })).to eq(list.unique_id_for_element({ a: "1", b: "2", c: "3" })) @@ -76,28 +75,27 @@ expect { list.unique_id_for_element(obj) }.not_to raise_error end it 'generates same id for facts when using id or object reference' do - asset=create :asset + asset = create :asset asset2 = create :asset - somepredicate='relation' - ob1={ asset: asset, predicate: somepredicate, object_asset: asset2 } - ob2={ id: 123, asset_id: asset.id, predicate: somepredicate, object_asset_id: asset2.id } + somepredicate = 'relation' + ob1 = { asset: asset, predicate: somepredicate, object_asset: asset2 } + ob2 = { id: 123, asset_id: asset.id, predicate: somepredicate, object_asset_id: asset2.id } expect(list.unique_id_for_element(ob1)).to eq(list.unique_id_for_element(ob2)) end it 'generates different ids for facts using instances not in database' do - asset=build :asset + asset = build :asset asset2 = build :asset asset3 = build :asset - somepredicate='relation' + somepredicate = 'relation' - ob1={ asset: asset, predicate: somepredicate, object_asset: asset2 } - ob2={ asset: asset2, predicate: somepredicate, object_asset: asset } - ob3={ asset: asset, predicate: somepredicate, object_asset: asset3 } - ob4={ asset: asset, predicate: somepredicate, object_asset: asset } + ob1 = { asset: asset, predicate: somepredicate, object_asset: asset2 } + ob2 = { asset: asset2, predicate: somepredicate, object_asset: asset } + ob3 = { asset: asset, predicate: somepredicate, object_asset: asset3 } + ob4 = { asset: asset, predicate: somepredicate, object_asset: asset } expect(list.unique_id_for_element(ob1)).not_to eq(list.unique_id_for_element(ob2)) expect(list.unique_id_for_element(ob1)).not_to eq(list.unique_id_for_element(ob3)) expect(list.unique_id_for_element(ob1)).not_to eq(list.unique_id_for_element(ob4)) - end it 'generates different ids for different instances' do asset = build :asset @@ -124,14 +122,14 @@ expect { list.add(elem) }.to change { list.to_a.length }.by(1) - .and change { list.length }.by(1) + .and change { list.length }.by(1) expect(list.to_a).to eq([elem]) end it 'stores the position in the common hash' do expect { list.add(elem) }.to change { list.store_for(elem) }.from(nil).to(list) - .and change { list2.store_for(elem) }.from(nil).to(list) + .and change { list2.store_for(elem) }.from(nil).to(list) end it 'does not add the element again if it is already present' do list.add(elem) @@ -139,7 +137,7 @@ expect { list.add(elem) }.to change { list.to_a.length }.by(0) - .and change { list.length }.by(0) + .and change { list.length }.by(0) expect(list.to_a).to eq([elem]) end it 'disables the element from the list if is added to another disjoint list' do @@ -154,7 +152,7 @@ context 'with a group of disjoint lists' do let(:lists) { - l=5.times.map { ChangesSupport::DisjointList.new([]) } + l = 5.times.map { ChangesSupport::DisjointList.new([]) } l[0].add_disjoint_list(l[1]) l[0].add_disjoint_list(l[2]) l[0].add_disjoint_list(l[3]) @@ -175,13 +173,13 @@ end it 'disables lists in another list' do - lists[0] << [1,2,3,4,5] + lists[0] << [1, 2, 3, 4, 5] lists[1] << [] lists[2] << [] lists[3] << [] - lists[4] << [6,7,8,9] + lists[4] << [6, 7, 8, 9] - lists[2] << [1,2,3,4,5,6,7,8,9] + lists[2] << [1, 2, 3, 4, 5, 6, 7, 8, 9] expect(lists[0].to_a).to eq([]) expect(lists[1].to_a).to eq([]) expect(lists[2].to_a).to eq([]) @@ -225,7 +223,7 @@ list.add(elem) expect(list.length).to eq(1) expect { list.remove(elem) }.to change { list.length }.by(-1) - .and change { list.store_for(elem) }.from(list).to(nil) + .and change { list.store_for(elem) }.from(list).to(nil) expect(list.to_a).to eq([]) end end @@ -237,8 +235,8 @@ let(:list3) { ChangesSupport::DisjointList.new([]) } it 'adds the list to the disjoint lists' do - expect { list.add_disjoint_list(list2) }.to change { list.disjoint_lists }.from([list]).to([list,list2]) - .and change { list2.disjoint_lists }.from([list2]).to([list,list2]) + expect { list.add_disjoint_list(list2) }.to change { list.disjoint_lists }.from([list]).to([list, list2]) + .and change { list2.disjoint_lists }.from([list2]).to([list, list2]) end it 'sets up a shared list of disjoint lists for all added instances' do @@ -246,7 +244,7 @@ expect(list.disjoint_lists).to be(list2.disjoint_lists) list3 = ChangesSupport::DisjointList.new([]) - expect { list3.add_disjoint_list(list2) }.to change { list.disjoint_lists }.from([list,list2]).to([list3,list,list2]) + expect { list3.add_disjoint_list(list2) }.to change { list.disjoint_lists }.from([list, list2]).to([list3, list, list2]) end it 'sets up a common list of locations for all added instances' do @@ -300,7 +298,6 @@ let(:list2) { ChangesSupport::DisjointList.new(facts_to_destroy) } - context 'with mutual disjoint' do before do disjoint1.add_disjoint_list(disjoint2) @@ -321,7 +318,7 @@ d1.merge(d2).merge(d3) - expect(d1.to_a).to eq([1,2,3]) + expect(d1.to_a).to eq([1, 2, 3]) end it 'merges from different objects that have mutual disjoint' do @@ -339,16 +336,16 @@ d1.merge(d2).merge(d3) - expect(d1.to_a).to eq([1,2,3]) + expect(d1.to_a).to eq([1, 2, 3]) end it 'can disable elements with every merge' do - d1 = ChangesSupport::DisjointList.new([1,2,3]) + d1 = ChangesSupport::DisjointList.new([1, 2, 3]) d2 = ChangesSupport::DisjointList.new([4]) d3 = ChangesSupport::DisjointList.new([5]) o1 = ChangesSupport::DisjointList.new([]) - o2 = ChangesSupport::DisjointList.new([1,2]) + o2 = ChangesSupport::DisjointList.new([1, 2]) o3 = ChangesSupport::DisjointList.new([3]) d1.add_disjoint_list(o1) @@ -357,17 +354,16 @@ d1.merge(d2).merge(d3) - expect(d1.to_a).to eq([4,5]) - + expect(d1.to_a).to eq([4, 5]) end it 'does not re-enable elements after merge' do - d1 = ChangesSupport::DisjointList.new([1,2,3]) + d1 = ChangesSupport::DisjointList.new([1, 2, 3]) d2 = ChangesSupport::DisjointList.new([4]) - d3 = ChangesSupport::DisjointList.new([1,2]) + d3 = ChangesSupport::DisjointList.new([1, 2]) o1 = ChangesSupport::DisjointList.new([]) - o2 = ChangesSupport::DisjointList.new([1,2]) + o2 = ChangesSupport::DisjointList.new([1, 2]) o3 = ChangesSupport::DisjointList.new([3]) d1.add_disjoint_list(o1) @@ -375,7 +371,7 @@ d3.add_disjoint_list(o3) d1.merge(d2) - expect(d1.to_a).to eq([3,4]) + expect(d1.to_a).to eq([3, 4]) d1.merge(d3) expect(d1.to_a).to eq([4]) end @@ -394,9 +390,11 @@ context 'when merging a chain of objects' do let(:winners) { 6.times.map { ChangesSupport::DisjointList.new([]) } } let(:losers) { 6.times.map { ChangesSupport::DisjointList.new([]) } } - let(:list) { winners.zip(losers).map { |l| - l[0].add_disjoint_list(l[1]) - { winner: l[0], loser: l[1] }} + let(:list) { + winners.zip(losers).map { |l| + l[0].add_disjoint_list(l[1]) + { winner: l[0], loser: l[1] } + } } it 'keeps track of all restrictions until the final list' do @@ -418,7 +416,6 @@ memo end expect(winners.to_a.sort).to eq(['Manchester City']) - end end end @@ -439,10 +436,10 @@ disjoint1 << ['green', 'red', 'white'] disjoint3 << ['blue', 'red', 'white'] expect { disjoint1.merge(disjoint3) }.to change { - disjoint1.to_a.sort}.from(['green', 'red', 'white']).to(["blue", "green", "red", "white"]) + disjoint1.to_a.sort + }.from(['green', 'red', 'white']).to(["blue", "green", "red", "white"]) end - it 'merges the information of disjoint lists keeping duplicates unique' do disjoint1 << ['green', 'yellow'] disjoint2 << ['paris', 'london', 'rome'] @@ -465,7 +462,6 @@ disjoint1 << 'rome' expect(disjoint1.to_a).to eq(['athens']) end - end end end diff --git a/spec/lib/changes_support/transaction_scope_spec.rb b/spec/lib/changes_support/transaction_scope_spec.rb index f0297059..6f2510ad 100644 --- a/spec/lib/changes_support/transaction_scope_spec.rb +++ b/spec/lib/changes_support/transaction_scope_spec.rb @@ -60,8 +60,8 @@ asset3.facts << create(:fact, predicate: 'is', object: 'Empty') asset3.facts << create(:fact, predicate: 'a', object: 'Tube') expect(accessor.joins(:facts).where(facts: { predicate: 'a', object: 'Tube' }).map(&:uuid)).to eq([ - asset1.uuid, asset3.uuid - ]) + asset1.uuid, asset3.uuid + ]) end end context 'when the condition are met both in the Changes and in the database' do diff --git a/spec/lib/fact_changes_spec.rb b/spec/lib/fact_changes_spec.rb index 2b66f901..bc57ff50 100644 --- a/spec/lib/fact_changes_spec.rb +++ b/spec/lib/fact_changes_spec.rb @@ -114,14 +114,14 @@ it 'loads added assets' do asset = Asset.create group = AssetGroup.create - json = { add_assets: [[group.uuid, [asset.uuid] ]] }.to_json + json = { add_assets: [[group.uuid, [asset.uuid]]] }.to_json expect(updates.parse_json(json)).to eq(true) expect(updates.assets_to_add.length).to eq(1) end it 'loads removed assets' do asset = Asset.create group = AssetGroup.create - json = { remove_assets: [[group.uuid, [asset.uuid] ]] }.to_json + json = { remove_assets: [[group.uuid, [asset.uuid]]] }.to_json expect(updates.parse_json(json)).to eq(true) expect(updates.assets_to_remove.length).to eq(1) end @@ -177,13 +177,13 @@ asset = Asset.create group = AssetGroup.create updates.add_assets([[group, [asset]]]) - expect(updates.to_h).to include(add_assets: [[group.uuid, [asset.uuid] ]]) + expect(updates.to_h).to include(add_assets: [[group.uuid, [asset.uuid]]]) end it 'adds removed assets from the group in the hash' do asset = Asset.create group = AssetGroup.create updates.remove_assets([[group, [asset]]]) - expect(updates.to_h).to include(remove_assets: [[group.uuid, [asset.uuid] ]]) + expect(updates.to_h).to include(remove_assets: [[group.uuid, [asset.uuid]]]) end it 'adds facts to the hash' do asset = Asset.create @@ -220,20 +220,20 @@ expect { updates1.apply(step) }.to change { asset1.facts.count }.by(1) - .and change { Operation.count }.by(1) + .and change { Operation.count }.by(1) end it 'applies a new added relation' do updates1.add(asset1, relation, asset2) expect { updates1.apply(step) }.to change { asset1.facts.count }.by(1) - .and change { Operation.count }.by(1) + .and change { Operation.count }.by(1) end it 'is able to add facts to assets created before' do updates1.create_assets(['?p']) updates1.add('?p', property, value) expect { updates1.apply(step) }.to change { Asset.count }.by(1) - .and change { Fact.count }.by(1) + .and change { Fact.count }.by(1) end end context 'with add_remote' do @@ -242,7 +242,7 @@ expect { updates1.apply(step) }.to change { asset1.facts.count }.by(1) - .and change { Operation.count }.by(1) + .and change { Operation.count }.by(1) expect(asset1.facts.first.is_remote?).to eq(true) end @@ -253,7 +253,7 @@ expect { updates1.apply(step) }.to change { asset1.facts.count }.by(1) - .and change { Operation.count }.by(1) + .and change { Operation.count }.by(1) expect(asset1.facts.count).to eq(1) expect(asset1.facts.first.is_remote?).to eq(true) end @@ -267,7 +267,7 @@ expect { updates1.apply(step) }.to change { asset1.facts.count }.by(0) - .and change { Operation.count }.by(2) + .and change { Operation.count }.by(2) asset1.facts.reload expect(asset1.facts.count).to eq(1) @@ -281,7 +281,7 @@ expect { updates1.apply(step) }.to change { asset1.facts.count }.by(-1) - .and change { Operation.count }.by(1) + .and change { Operation.count }.by(1) end end @@ -296,7 +296,7 @@ expect { updates1.apply(step) }.to change { asset1.facts.count }.by(-2) - .and change { Operation.count }.by(2) + .and change { Operation.count }.by(2) end end @@ -304,7 +304,7 @@ it 'creates the assets provided' do updates1.create_assets(["?p", "?q", "?r"]) expect { updates1.apply(step) }.to change { Asset.count }.by(3) - .and change { Operation.count }.by(3) + .and change { Operation.count }.by(3) end end @@ -322,11 +322,11 @@ end it 'removes the facts for the assets' do expect { updates1.apply(step) }.to change { asset3.facts.count }.by(-1) - .and change { asset4.facts.count }.by(-1) + .and change { asset4.facts.count }.by(-1) end it 'detaches the assets from any groups' do expect { updates1.apply(step) }.to change { asset3.asset_groups.count }.by(-1) - .and change { asset4.asset_groups.count }.by(-1) + .and change { asset4.asset_groups.count }.by(-1) end end @@ -337,7 +337,7 @@ it 'adds the assets to the asset group' do updates1.add_assets([[asset_group, [asset1.uuid, asset2.uuid]]]) expect { updates1.apply(step) }.to change { asset_group.assets.count }.by(2) - .and change { Operation.count }.by(2) + .and change { Operation.count }.by(2) end end @@ -349,10 +349,9 @@ asset_group.assets << [asset1, asset2] updates1.remove_assets([[asset_group, [asset1.uuid, asset2.uuid]]]) expect { updates1.apply(step) }.to change { asset_group.assets.count }.by(-2) - .and change { Operation.count }.by(2) + .and change { Operation.count }.by(2) end end - end describe '#add' do it 'raises error if we use a wildcard not created before' do @@ -517,7 +516,6 @@ expect(updates1.values_for_predicate(asset, 'description')).to eq(['green', 'tall']) end - end describe '#create_assets' do @@ -532,7 +530,6 @@ it 'does not raise error when referring to an asset not referred before' do expect { updates1.create_assets([SecureRandom.uuid]) }.not_to raise_error end - end describe '#create_asset_groups' do @@ -547,10 +544,8 @@ it 'does not raise error when referring to an asset not referred before' do expect { updates1.create_asset_groups([SecureRandom.uuid]) }.not_to raise_error end - end - describe '#delete_assets' do let(:asset1) { Asset.create(uuid: SecureRandom.uuid) } let(:asset2) { Asset.create(uuid: SecureRandom.uuid) } @@ -600,7 +595,6 @@ it 'raises error when referring to an asset group not referred before ' do expect { updates1.add_assets([[SecureRandom.uuid, [asset1.uuid, asset2.uuid]]]) }.to raise_error(StandardError) end - end describe '#remove_assets' do @@ -618,10 +612,8 @@ it 'raises error when referring to an asset group not referred before ' do expect { updates1.remove_assets([[SecureRandom.uuid, [asset1.uuid, asset2.uuid]]]) }.to raise_error(StandardError) end - end - describe '#merge' do it 'returns another FactChanges object' do expect(updates1.merge(updates2).kind_of?(FactChanges)).to eq(true) @@ -630,14 +622,14 @@ asset = create :asset fact = create(:fact, predicate: 'p', object: 'v') fact2 = create(:fact, predicate: 'p2', object: 'v2') - asset.facts< 'FR'+(11200002 + i).to_s - }) + :barcode => 'FR' + (11200002 + i).to_s + }) end end @@ -63,22 +64,20 @@ expect(@csv).to be_valid end it 'detects tube duplication' do - asset1 = create :asset, barcode: 'FR000001' - content = "A01,#{asset1.barcode}\nB01,#{asset1.barcode}" - csv = Parsers::CsvLayout::CsvParser.new(content) - expect(csv).not_to be_valid - expect(csv.error_list.length).to eq(1) + asset1 = create :asset, barcode: 'FR000001' + content = "A01,#{asset1.barcode}\nB01,#{asset1.barcode}" + csv = Parsers::CsvLayout::CsvParser.new(content) + expect(csv).not_to be_valid + expect(csv.error_list.length).to eq(1) end it 'detects location duplication' do - asset1 = create :asset, barcode: 'FR000001' - asset2 = create :asset, barcode: 'FR000002' - content = "A01,#{asset1.barcode}\nA01,#{asset2.barcode}" - csv = Parsers::CsvLayout::CsvParser.new(content) - expect(csv).not_to be_valid - expect(csv.error_list.length).to eq(1) + asset1 = create :asset, barcode: 'FR000001' + asset2 = create :asset, barcode: 'FR000002' + content = "A01,#{asset1.barcode}\nA01,#{asset2.barcode}" + csv = Parsers::CsvLayout::CsvParser.new(content) + expect(csv).not_to be_valid + expect(csv.error_list.length).to eq(1) end end end - end - diff --git a/spec/lib/parsers/csv_layout/line_parser_spec.rb b/spec/lib/parsers/csv_layout/line_parser_spec.rb index 1df5913a..d259a5fd 100644 --- a/spec/lib/parsers/csv_layout/line_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/line_parser_spec.rb @@ -6,15 +6,14 @@ require 'parsers/csv_layout/validators/location_validator' RSpec.describe Parsers::CsvLayout::LineParser do - let(:main_parser) { main = double('parser') allow(main).to receive(:components).and_return({ - location_validator: Parsers::CsvLayout::Validators::LocationValidator, - barcode_validator: Parsers::CsvLayout::Validators::AnyBarcodeValidator, - barcode_parser: Parsers::CsvLayout::BarcodeParser, - location_parser: Parsers::CsvLayout::LocationParser - }) + location_validator: Parsers::CsvLayout::Validators::LocationValidator, + barcode_validator: Parsers::CsvLayout::Validators::AnyBarcodeValidator, + barcode_parser: Parsers::CsvLayout::BarcodeParser, + location_parser: Parsers::CsvLayout::LocationParser + }) main } let(:input_reader) { @@ -41,54 +40,54 @@ context '#parsed_data' do it 'returns the number of lines at input' do - @input = [["A1","F1234"],["A2","F5678"]] + @input = [["A1", "F1234"], ["A2", "F5678"]] expect(parser).to be_valid expect(parser.parsed_data.length).to eq(@input.length) end it 'returns the parsed input' do - @input = [["A1","F1234"],["A2","F5678"]] + @input = [["A1", "F1234"], ["A2", "F5678"]] expect(parser).to be_valid expect(parser.parsed_data).to eq([ - { location: "A01", asset: @asset1 }, - { location: "A02", asset: @asset2 } - ]) + { location: "A01", asset: @asset1 }, + { location: "A02", asset: @asset2 } + ]) end it 'filters empty lines' do - @input = [["A1","F1234"],[],["A2","F5678"]] + @input = [["A1", "F1234"], [], ["A2", "F5678"]] expect(parser).to be_valid expect(parser.parsed_data).to eq([ - { location: "A01", asset: @asset1 }, - { location: "A02", asset: @asset2 } - ]) + { location: "A01", asset: @asset1 }, + { location: "A02", asset: @asset2 } + ]) end it 'filters nil lines' do - @input = [["A1","F1234"],nil,["A2","F5678"]] + @input = [["A1", "F1234"], nil, ["A2", "F5678"]] expect(parser).to be_valid expect(parser.parsed_data).to eq([ - { location: "A01", asset: @asset1 }, - { location: "A02", asset: @asset2 } - ]) + { location: "A01", asset: @asset1 }, + { location: "A02", asset: @asset2 } + ]) end it 'filters nil empty lines' do - @input = [["A1","F1234"],[nil, nil],["A2","F5678"]] + @input = [["A1", "F1234"], [nil, nil], ["A2", "F5678"]] expect(parser).to be_valid expect(parser.parsed_data).to eq([ - { location: "A01", asset: @asset1 }, - { location: "A02", asset: @asset2 } - ]) + { location: "A01", asset: @asset1 }, + { location: "A02", asset: @asset2 } + ]) end it 'filters no read barcodes' do - @input = [["A1","F1234"],["B01", "No read"],["A2","F5678"]] + @input = [["A1", "F1234"], ["B01", "No read"], ["A2", "F5678"]] expect(parser).to be_valid expect(parser.parsed_data).to eq([ - { location: "A01", asset: @asset1 }, - { location: "A02", asset: @asset2 } - ]) + { location: "A01", asset: @asset1 }, + { location: "A02", asset: @asset2 } + ]) end end context 'when the a location is not valid' do before do - @input = [["A111","F1234"],["B01", "No read"],["A2","F5678"]] + @input = [["A111", "F1234"], ["B01", "No read"], ["A2", "F5678"]] end it 'is invalid' do parser.valid? diff --git a/spec/lib/parsers/csv_layout/line_reader_spec.rb b/spec/lib/parsers/csv_layout/line_reader_spec.rb index 26ed4250..b04ed4af 100644 --- a/spec/lib/parsers/csv_layout/line_reader_spec.rb +++ b/spec/lib/parsers/csv_layout/line_reader_spec.rb @@ -3,7 +3,7 @@ RSpec.describe Parsers::CsvLayout::LineReader do let(:parserClass) { Parsers::CsvLayout::LineReader } - let(:result) { [["A01","1234"],["B01", "4567"],["C01","8901"]] } + let(:result) { [["A01", "1234"], ["B01", "4567"], ["C01", "8901"]] } it 'recognises line feed for new line' do expect(parserClass.new("A01,1234\nB01,4567\nC01,8901").lines).to eq(result) expect(parserClass.new("A01,1234\nB01,4567\nC01,8901\n").lines).to eq(result) diff --git a/spec/lib/parsers/csv_layout/location_parser_spec.rb b/spec/lib/parsers/csv_layout/location_parser_spec.rb index 14a24c2e..ea64615a 100644 --- a/spec/lib/parsers/csv_layout/location_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/location_parser_spec.rb @@ -2,14 +2,13 @@ require 'parsers/csv_layout/location_parser' require 'parsers/csv_layout/validators/location_validator' - RSpec.describe Parsers::CsvLayout::LocationParser do let(:main_parser) { main = double('parser') allow(main).to receive(:add_error) allow(main).to receive(:components).and_return({ - location_validator: Parsers::CsvLayout::Validators::LocationValidator - }) + location_validator: Parsers::CsvLayout::Validators::LocationValidator + }) main } let(:barcode) { '1234' } @@ -24,26 +23,25 @@ expect(parser.location).to eq(location) end it 'chomps empty spaces before and after the location' do - parser = Parsers::CsvLayout::LocationParser.new([" A01 "," F1234 "], main_parser) + parser = Parsers::CsvLayout::LocationParser.new([" A01 ", " F1234 "], main_parser) expect(parser.location).to eq("A01") end end it 'can parse a line' do - expect(Parsers::CsvLayout::LocationParser.new(["A01","F123456"], main_parser).location).to eq("A01") + expect(Parsers::CsvLayout::LocationParser.new(["A01", "F123456"], main_parser).location).to eq("A01") end it 'can pad the location' do - expect(Parsers::CsvLayout::LocationParser.new(["A1","F123456"], main_parser).location).to eq("A01") + expect(Parsers::CsvLayout::LocationParser.new(["A1", "F123456"], main_parser).location).to eq("A01") end it 'validates when the location is right' do - parser = Parsers::CsvLayout::LocationParser.new(["A1","F123456"], main_parser) + parser = Parsers::CsvLayout::LocationParser.new(["A1", "F123456"], main_parser) expect(parser).to be_valid end it 'does not validate when the location is wrong' do - parser = Parsers::CsvLayout::LocationParser.new(["A111","F123456"], main_parser) + parser = Parsers::CsvLayout::LocationParser.new(["A111", "F123456"], main_parser) expect(parser).to be_invalid end - end diff --git a/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb b/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb index 4b6a3db7..14991e00 100644 --- a/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb +++ b/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb @@ -24,6 +24,4 @@ instance.barcode = '' expect(instance).to be_invalid end - end - diff --git a/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb b/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb index 7ffb005b..49c3c847 100644 --- a/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb +++ b/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' require 'parsers/csv_layout/validators/location_validator' - RSpec.describe Parsers::CsvLayout::Validators::LocationValidator do let(:klass) { Class.new { @@ -28,5 +27,4 @@ instance.location = '' expect(instance).to be_invalid end - end diff --git a/spec/lib/parsers/csv_metadata/csv_parser_spec.rb b/spec/lib/parsers/csv_metadata/csv_parser_spec.rb index 7a865c5d..8208ac63 100644 --- a/spec/lib/parsers/csv_metadata/csv_parser_spec.rb +++ b/spec/lib/parsers/csv_metadata/csv_parser_spec.rb @@ -7,15 +7,16 @@ require 'parsers/csv_layout/validators/location_validator' RSpec.describe Parsers::CsvMetadata::CsvParser do - describe "parses a metadata file" do let(:activity) { create(:activity) } let(:asset_group) { create(:asset_group) } let(:step_type) { create(:step_type) } - let(:step) { create :step, - activity: activity, - state: Step::STATE_RUNNING, - asset_group: asset_group, step_type: step_type } + let(:step) { + create :step, + activity: activity, + state: Step::STATE_RUNNING, + asset_group: asset_group, step_type: step_type + } setup do allow(Asset).to receive(:find_or_import_asset_with_barcode) do |barcode| @@ -25,8 +26,8 @@ @content = File.read('test/data/metadata.csv') @assets = 96.times.map do |i| FactoryBot.create(:asset, { - :barcode => 'FR'+(11200002 + i).to_s - }) + :barcode => 'FR' + (11200002 + i).to_s + }) end end @@ -41,11 +42,11 @@ @csv = Parsers::CsvMetadata::CsvParser.new(@content) expect(@csv.metadata.length).to eq(96) expect(@csv.metadata[0]).to eq({ - 'barcode' => 'DN1001001', 'location' => 'A01', 'data1' => '111', 'data2'=> '444' - }) + 'barcode' => 'DN1001001', 'location' => 'A01', 'data1' => '111', 'data2' => '444' + }) expect(@csv.metadata[95]).to eq({ - 'barcode' => 'DN1001001', 'location' => 'H12', 'data1' => '123', 'data2'=> '456' - }) + 'barcode' => 'DN1001001', 'location' => 'H12', 'data1' => '123', 'data2' => '456' + }) end end @@ -57,4 +58,3 @@ end end end - diff --git a/spec/lib/support_n3_spec.rb b/spec/lib/support_n3_spec.rb index db829623..8ade1863 100644 --- a/spec/lib/support_n3_spec.rb +++ b/spec/lib/support_n3_spec.rb @@ -1,19 +1,18 @@ require 'rails_helper' require 'support_n3' -def assert_equal(a,b) +def assert_equal(a, b) expect(a).to eq(b) end RSpec.describe SupportN3 do - def validates_parsed(obj) obj.each do |class_instance, instances_list| compare_total = class_instance.send(:count) if class_instance != Action assert_equal instances_list.length, compare_total class_instance.send(:all).each_with_index do |instance, i| - instances_list[i].each do |k,v| + instances_list[i].each do |k, v| expect(v).to eq(instance.send(k)) end end @@ -85,13 +84,14 @@ def validates_rule_with(parsed_obj) describe "with rules that remove facts" do it '{?x :a :Tube .} => { :step :removeFacts {?x :has :RNA .}.}.' do validates_rule_with({ - ConditionGroup => [{ :name => 'x', - :step_type => @step_type, :cardinality => nil, - :keep_selected => true }], - Condition => [{ :predicate => 'a', :object => 'Tube' }], - Action => [{ :action_type => 'removeFacts', - :predicate => 'has', :object => 'RNA', - :object_condition_group_id => nil, :step_type_id => @step_type.id }] }) + ConditionGroup => [{ :name => 'x', + :step_type => @step_type, :cardinality => nil, + :keep_selected => true }], + Condition => [{ :predicate => 'a', :object => 'Tube' }], + Action => [{ :action_type => 'removeFacts', + :predicate => 'has', :object => 'RNA', + :object_condition_group_id => nil, :step_type_id => @step_type.id }] + }) assert_equal ConditionGroup.first, Condition.first.condition_group assert_equal ConditionGroup.first, Action.first.subject_condition_group end @@ -100,16 +100,18 @@ def validates_rule_with(parsed_obj) describe "with rules that create new assets" do it '{?z :has :Content .} => {:step :createAsset {?y :a :Rack .}.}.' do validates_rule_with({ - ConditionGroup => [ - { :name => 'z',:step_type => @step_type, :cardinality => nil, - :keep_selected => true }, - { :name => 'y',:step_type => nil, :cardinality => nil, - :keep_selected => true }], - Condition => [{ :predicate => 'has', :object => 'Content' }], - Action => [{ :action_type => 'createAsset', - :predicate => 'a', :object => 'Rack', - :object_condition_group => nil, - :step_type_id => @step_type.id }] }) + ConditionGroup => [ + { :name => 'z', :step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'y', :step_type => nil, :cardinality => nil, + :keep_selected => true } + ], + Condition => [{ :predicate => 'has', :object => 'Content' }], + Action => [{ :action_type => 'createAsset', + :predicate => 'a', :object => 'Rack', + :object_condition_group => nil, + :step_type_id => @step_type.id }] + }) z = ConditionGroup.find_by_name('z') y = ConditionGroup.find_by_name('y') @@ -121,14 +123,16 @@ def validates_rule_with(parsed_obj) describe "with rules that check cardinality" do it '{?a :maxCardinality """96""" . ?a :is :Tube . }=>{ :step :addFacts {?a :has :Capacity .}.}.' do validates_rule_with({ - ConditionGroup => [ - { :name => 'a',:step_type => @step_type, :cardinality => 96, - :keep_selected => true }], - Condition => [{ :predicate => 'is', :object => 'Tube' }], - Action => [{ :action_type => 'addFacts', - :predicate => 'has', :object => 'Capacity', - :object_condition_group => nil, - :step_type_id => @step_type.id }] }) + ConditionGroup => [ + { :name => 'a', :step_type => @step_type, :cardinality => 96, + :keep_selected => true } + ], + Condition => [{ :predicate => 'is', :object => 'Tube' }], + Action => [{ :action_type => 'addFacts', + :predicate => 'has', :object => 'Capacity', + :object_condition_group => nil, + :step_type_id => @step_type.id }] + }) a = ConditionGroup.find_by_name('a') assert_equal a, Action.first.subject_condition_group assert_equal a, Condition.first.condition_group @@ -138,71 +142,72 @@ def validates_rule_with(parsed_obj) describe "with rules that unselect assets" do it '{?a :is :Tube . }=>{ :step :unselectAsset ?a . :step :addFacts {?a :is :Full.}.}.' do validates_rule_with({ - ConditionGroup => [ - { :name => 'a',:step_type => @step_type, :cardinality => nil, - :keep_selected => false }], - Condition => [{ :predicate => 'is', :object => 'Tube' }], - Action => [{ :action_type => 'addFacts', - :predicate => 'is', :object => 'Full', - :object_condition_group => nil, - :step_type_id => @step_type.id } - ] }) + ConditionGroup => [ + { :name => 'a', :step_type => @step_type, :cardinality => nil, + :keep_selected => false } + ], + Condition => [{ :predicate => 'is', :object => 'Tube' }], + Action => [{ :action_type => 'addFacts', + :predicate => 'is', :object => 'Full', + :object_condition_group => nil, + :step_type_id => @step_type.id }] + }) a = ConditionGroup.find_by_name('a') assert_equal a, Action.first.subject_condition_group end it '{?a :is :Tube . }=>{ :step :unselectAsset {?b :is :Tube.}.}.' do validates_rule_with({ - ConditionGroup => [ - { :name => 'a',:step_type => @step_type, :cardinality => nil, - :keep_selected => true }, - { :name => 'b',:step_type => nil, :cardinality => nil, - :keep_selected => false }], - Condition => [{ :predicate => 'is', :object => 'Tube' }, - { :predicate => 'is', :object => 'Tube' }], - Action => [{ :action_type => 'unselectAsset', - :predicate => 'is', :object => 'Tube', - :object_condition_group => nil, - :step_type_id => @step_type.id } - ] }) + ConditionGroup => [ + { :name => 'a', :step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'b', :step_type => nil, :cardinality => nil, + :keep_selected => false } + ], + Condition => [{ :predicate => 'is', :object => 'Tube' }, + { :predicate => 'is', :object => 'Tube' }], + Action => [{ :action_type => 'unselectAsset', + :predicate => 'is', :object => 'Tube', + :object_condition_group => nil, + :step_type_id => @step_type.id }] + }) assert_equal Action.first.subject_condition_group, ConditionGroup.last end end describe "with rules that create a relation between two matches" do - it '{?p :is :Tube . ?q :maxCardinality """1""".} => {:step :createAsset {?q :a :Plate.}.}.' do validates_rule_with({ - ConditionGroup => [{ :name => 'p',:step_type => @step_type, - :cardinality => nil, :keep_selected => true }, - { :name => 'q', :step_type => nil, - :cardinality => 1, :keep_selected => true }], - Condition => [{ :predicate => 'is', :object=> 'Tube' }], - Action => [{ :action_type => 'createAsset', - :predicate => 'a', - :step_type_id => @step_type.id, - :object => 'Plate' }] - }) - p= ConditionGroup.find_by_name('p') - q= ConditionGroup.find_by_name('q') + ConditionGroup => [{ :name => 'p', :step_type => @step_type, + :cardinality => nil, :keep_selected => true }, + { :name => 'q', :step_type => nil, + :cardinality => 1, :keep_selected => true }], + Condition => [{ :predicate => 'is', :object => 'Tube' }], + Action => [{ :action_type => 'createAsset', + :predicate => 'a', + :step_type_id => @step_type.id, + :object => 'Plate' }] + }) + p = ConditionGroup.find_by_name('p') + q = ConditionGroup.find_by_name('q') assert_equal q, Action.first.subject_condition_group end it '{?p :is :Tube . ?q :is :TubeRack.} => {:step :addFacts {?p :transferTo ?q.}.}.' do validates_rule_with({ - ConditionGroup => [{ :name => 'p',:step_type => @step_type, - :cardinality => nil, :keep_selected => true }, - { :name => 'q', :step_type => @step_type, - :cardinality => nil, :keep_selected => true }], - Condition => [{ :predicate => 'is', :object=> 'Tube' }, - { :predicate => 'is', :object => 'TubeRack' }], - Action => [{ :action_type => 'addFacts', - :predicate => 'transferTo', - :step_type_id => @step_type.id, - :object => 'q' }] - }) - p= ConditionGroup.find_by_name('p') - q= ConditionGroup.find_by_name('q') + ConditionGroup => [{ :name => 'p', :step_type => @step_type, + :cardinality => nil, :keep_selected => true }, + { :name => 'q', :step_type => @step_type, + :cardinality => nil, :keep_selected => true }], + Condition => [{ :predicate => 'is', :object => 'Tube' }, + { :predicate => 'is', :object => 'TubeRack' }], + Action => [{ :action_type => 'addFacts', + :predicate => 'transferTo', + :step_type_id => @step_type.id, + :object => 'q' }] + }) + p = ConditionGroup.find_by_name('p') + q = ConditionGroup.find_by_name('q') assert_equal p, Action.first.subject_condition_group assert_equal q, Action.first.object_condition_group end @@ -212,52 +217,53 @@ def validates_rule_with(parsed_obj) ?rack :maxCardinality """1""". } .}.' do validates_rule_with({ - ConditionGroup => [ - { :name => 'p',:step_type => @step_type, :cardinality => nil, - :keep_selected => true }, - { :name => 'rack',:step_type => nil, :cardinality => 1, - :keep_selected => true }], - Condition => [ - { :predicate => 'is', :object => 'Tube2D' } - ], - Action => [{ :action_type => 'createAsset', - :predicate => 'is', :object => 'TubeRack', - :object_condition_group => nil, - :step_type_id => @step_type.id }, - { :action_type => 'addFacts', - :predicate => 'inRack', :object => 'rack', - :step_type_id => @step_type.id } - ] }) + ConditionGroup => [ + { :name => 'p', :step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'rack', :step_type => nil, :cardinality => 1, + :keep_selected => true } + ], + Condition => [ + { :predicate => 'is', :object => 'Tube2D' } + ], + Action => [{ :action_type => 'createAsset', + :predicate => 'is', :object => 'TubeRack', + :object_condition_group => nil, + :step_type_id => @step_type.id }, + { :action_type => 'addFacts', + :predicate => 'inRack', :object => 'rack', + :step_type_id => @step_type.id }] + }) - p = ConditionGroup.find_by_name('p') - q = ConditionGroup.find_by_name('rack') - ac = Action.find_by_action_type('createAsset') - af = Action.find_by_action_type('addFacts') - assert_equal q, ac.subject_condition_group - assert_equal p, af.subject_condition_group - assert_equal q, af.object_condition_group + p = ConditionGroup.find_by_name('p') + q = ConditionGroup.find_by_name('rack') + ac = Action.find_by_action_type('createAsset') + af = Action.find_by_action_type('addFacts') + assert_equal q, ac.subject_condition_group + assert_equal p, af.subject_condition_group + assert_equal q, af.object_condition_group end end describe 'with rules that match for relations between variables' do it '{?q :is :Tube . ?q :has :DNA. ?p :is :Rack . ?p :contains ?q . } => {:step :addFacts { ?p :has :DNA . }}.' do validates_rule_with({ - ConditionGroup => [ - { :name => 'q', :step_type => @step_type, :cardinality => nil, - :keep_selected => true }, - { :name => 'p', :step_type => @step_type, :cardinality => nil, - :keep_selected => true } - ], - Condition => [ - { :predicate => 'is', :object => 'Tube' }, - { :predicate => 'has', :object => 'DNA' }, - { :predicate => 'is', :object => 'Rack' }, - { :predicate => 'contains', :object => 'q' } - ], - Action => [ - { :action_type => 'addFacts', :predicate => 'has', :object => 'DNA' } - ] - }) + ConditionGroup => [ + { :name => 'q', :step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'p', :step_type => @step_type, :cardinality => nil, + :keep_selected => true } + ], + Condition => [ + { :predicate => 'is', :object => 'Tube' }, + { :predicate => 'has', :object => 'DNA' }, + { :predicate => 'is', :object => 'Rack' }, + { :predicate => 'contains', :object => 'q' } + ], + Action => [ + { :action_type => 'addFacts', :predicate => 'has', :object => 'DNA' } + ] + }) p = ConditionGroup.find_by_name('p') q = ConditionGroup.find_by_name('q') expect(p.conditions.select do |c| @@ -281,47 +287,45 @@ def validates_rule_with(parsed_obj) ':step :addFacts { ?d :is :Processed .}. ' \ '} .' do validates_rule_with({ - ConditionGroup => [ - { :name => 'a', :step_type => @step_type, :cardinality => nil, - :keep_selected => true }, - { :name => 'b', :step_type => @step_type, :cardinality => nil, - :keep_selected => true }, - { :name => 'c', :step_type => @step_type, :cardinality => nil, - :keep_selected => true }, - { :name => 'd', :step_type => @step_type, :cardinality => nil, - :keep_selected => true } - ], - Condition => [ - { :predicate => 'is', :object => 'A' }, - { :predicate => 'transfer' }, - { :predicate => 'is', :object => 'B' }, - { :predicate => 'transfer' }, - { :predicate => 'is', :object => 'C' }, - { :predicate => 'transfer' }, - { :predicate => 'is', :object => 'D' }, - { :predicate => 'transfer' } - ], - Action => [ - { :action_type => 'addFacts', :predicate => 'is', :object => 'Processed' }, - { :action_type => 'addFacts', :predicate => 'is', :object => 'Processed' }, - { :action_type => 'addFacts', :predicate => 'is', :object => 'Processed' }, - { :action_type => 'addFacts', :predicate => 'is', :object => 'Processed' } - ] - }) + ConditionGroup => [ + { :name => 'a', :step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'b', :step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'c', :step_type => @step_type, :cardinality => nil, + :keep_selected => true }, + { :name => 'd', :step_type => @step_type, :cardinality => nil, + :keep_selected => true } + ], + Condition => [ + { :predicate => 'is', :object => 'A' }, + { :predicate => 'transfer' }, + { :predicate => 'is', :object => 'B' }, + { :predicate => 'transfer' }, + { :predicate => 'is', :object => 'C' }, + { :predicate => 'transfer' }, + { :predicate => 'is', :object => 'D' }, + { :predicate => 'transfer' } + ], + Action => [ + { :action_type => 'addFacts', :predicate => 'is', :object => 'Processed' }, + { :action_type => 'addFacts', :predicate => 'is', :object => 'Processed' }, + { :action_type => 'addFacts', :predicate => 'is', :object => 'Processed' }, + { :action_type => 'addFacts', :predicate => 'is', :object => 'Processed' } + ] + }) a = ConditionGroup.find_by_name('a') b = ConditionGroup.find_by_name('b') c = ConditionGroup.find_by_name('c') d = ConditionGroup.find_by_name('d') - - [a,b,c,d].zip([b,c,d,a]).each do |p,q| + [a, b, c, d].zip([b, c, d, a]).each do |p, q| expect(p.conditions.select do |c| c.predicate == 'transfer' end.first.object_condition_group_id).to eq(q.id) end end - end end @@ -330,16 +334,17 @@ def validates_rule_with(parsed_obj) validate_all_rules(' { ?a :location ?_l . ?a :status :Done . ?a :name """My name""". ?b :location ?_l . ?b :status :Done .} => - {:step :addFacts { ?a :repeatedLocation ?_l .}}.',{ - ConditionGroup =>[{ :name => 'a' }, { :name => 'b' }, { :name => '_l' }], - Condition => [ - { :predicate => 'location' }, - { :predicate => 'status', :object => 'Done', :object_condition_group_id => nil }, - { :predicate => 'name', :object_condition_group_id => nil }, - { :predicate => 'location' }, - { :predicate => 'status', :object => 'Done', :object_condition_group_id => nil } - ], - Action => [{ :action_type => 'addFacts', :predicate => 'repeatedLocation' }] }) + {:step :addFacts { ?a :repeatedLocation ?_l .}}.', { + ConditionGroup => [{ :name => 'a' }, { :name => 'b' }, { :name => '_l' }], + Condition => [ + { :predicate => 'location' }, + { :predicate => 'status', :object => 'Done', :object_condition_group_id => nil }, + { :predicate => 'name', :object_condition_group_id => nil }, + { :predicate => 'location' }, + { :predicate => 'status', :object => 'Done', :object_condition_group_id => nil } + ], + Action => [{ :action_type => 'addFacts', :predicate => 'repeatedLocation' }] + }) l = ConditionGroup.find_by_name('_l') a = ConditionGroup.find_by_name('a') b = ConditionGroup.find_by_name('b') @@ -356,23 +361,23 @@ def validates_rule_with(parsed_obj) it 'updates the step type created with the supplied name' do validate_all_rules(' {?p :is :M .}=>{:step :addFacts {?p :is :G.}. :step :stepTypeName """A"""}. - {?p :is :G .}=>{:step :addFacts {?p :is :M.}.}.',{ + {?p :is :G .}=>{:step :addFacts {?p :is :M.}.}.', { ConditionGroup => [ { :name => 'p', - :cardinality => nil, :keep_selected => true }, + :cardinality => nil, :keep_selected => true }, { :name => 'p', :cardinality => nil, :keep_selected => true } - ], + ], StepType => [{ :name => 'A' }, {}], - Condition => [{ :predicate => 'is', :object=> 'M' }, - { :predicate => 'is', :object => 'G' }], + Condition => [{ :predicate => 'is', :object => 'M' }, + { :predicate => 'is', :object => 'G' }], Action => [{ :action_type => 'addFacts', - :predicate => 'is', - :object => 'G' }, + :predicate => 'is', + :object => 'G' }, { :action_type => 'addFacts', - :predicate => 'is', - :object => 'M' }] - }) + :predicate => 'is', + :object => 'M' }] + }) expect(ConditionGroup.first.step_type).to eq(StepType.first) expect(ConditionGroup.last.step_type).to eq(StepType.last) end @@ -380,26 +385,26 @@ def validates_rule_with(parsed_obj) it 'applies cardinality to the right condition group of the right step' do validate_all_rules(' {?p :is :M . ?p :maxCardinality """1""".}=>{:step :createAsset {?q :is :M.}.}. - {?p :is :G . ?p :maxCardinality """2""".}=>{:step :createAsset {?q :is :G.}.}.',{ + {?p :is :G . ?p :maxCardinality """2""".}=>{:step :createAsset {?q :is :G.}.}.', { ConditionGroup => [ { :name => 'p', - :cardinality => 1, :keep_selected => true }, + :cardinality => 1, :keep_selected => true }, { :name => 'q', - :cardinality => nil, :keep_selected => true }, + :cardinality => nil, :keep_selected => true }, { :name => 'p', :cardinality => 2, :keep_selected => true }, { :name => 'q', - :cardinality => nil, :keep_selected => true } - ], - Condition => [{ :predicate => 'is', :object=> 'M' }, - { :predicate => 'is', :object => 'G' }], + :cardinality => nil, :keep_selected => true } + ], + Condition => [{ :predicate => 'is', :object => 'M' }, + { :predicate => 'is', :object => 'G' }], Action => [{ :action_type => 'createAsset', - :predicate => 'is', - :object => 'M' }, + :predicate => 'is', + :object => 'M' }, { :action_type => 'createAsset', - :predicate => 'is', - :object => 'G' }] - }) + :predicate => 'is', + :object => 'G' }] + }) expect(StepType.all.count).to eq(2) expect(StepType.first.condition_groups.count).to eq(1) expect(StepType.last.condition_groups.count).to eq(1) @@ -413,26 +418,26 @@ def validates_rule_with(parsed_obj) it 'applies unselectAsset to the right condition group of the right step' do validate_all_rules(' {?p :is :M .}=>{:step :createAsset {?q :is :M.}. :step :unselectAsset ?q .}. - {?p :is :G .}=>{:step :createAsset {?q :is :G.}. :step :unselectAsset ?p .}.',{ + {?p :is :G .}=>{:step :createAsset {?q :is :G.}. :step :unselectAsset ?p .}.', { ConditionGroup => [ { :name => 'p', - :cardinality => nil, :keep_selected => true }, + :cardinality => nil, :keep_selected => true }, { :name => 'q', - :cardinality => nil, :keep_selected => false }, + :cardinality => nil, :keep_selected => false }, { :name => 'p', :cardinality => nil, :keep_selected => false }, { :name => 'q', - :cardinality => nil, :keep_selected => true } - ], - Condition => [{ :predicate => 'is', :object=> 'M' }, - { :predicate => 'is', :object => 'G' }], + :cardinality => nil, :keep_selected => true } + ], + Condition => [{ :predicate => 'is', :object => 'M' }, + { :predicate => 'is', :object => 'G' }], Action => [{ :action_type => 'createAsset', - :predicate => 'is', - :object => 'M' }, + :predicate => 'is', + :object => 'M' }, { :action_type => 'createAsset', - :predicate => 'is', - :object => 'G' }] - }) + :predicate => 'is', + :object => 'G' }] + }) expect(StepType.all.count).to eq(2) expect(StepType.first.condition_groups.count).to eq(1) expect(StepType.last.condition_groups.count).to eq(1) @@ -442,6 +447,5 @@ def validates_rule_with(parsed_obj) expect(StepType.last.condition_groups.first.keep_selected).to eq(false) expect(StepType.last.actions.first.subject_condition_group.keep_selected).to eq(true) end - end end diff --git a/spec/models/action_spec.rb b/spec/models/action_spec.rb index 85fffff7..d333b29a 100644 --- a/spec/models/action_spec.rb +++ b/spec/models/action_spec.rb @@ -1,29 +1,32 @@ require 'rails_helper' RSpec.describe Action, type: :model do context '#each_connected_asset' do + let(:action) { + create(:action, step_type: step_type, + predicate: 'some verb', action_type: 'something') + } - let(:action) { create(:action, step_type: step_type, - predicate: 'some verb', action_type: 'something') } - shared_examples 'a connector by position' do - let(:step_type) { create(:step_type, - connect_by: 'position')} + let(:step_type) { + create(:step_type, + connect_by: 'position') + } it 'yields sources and destination' do - i=0 - action.each_connected_asset(sources, destinations) do |a,b| - expect([a,b]).to eq(pairs_by_position[i]) - i=i+1 - end + i = 0 + action.each_connected_asset(sources, destinations) do |a, b| + expect([a, b]).to eq(pairs_by_position[i]) + i = i + 1 + end end end shared_examples 'a connector of all to all' do let(:step_type) { create(:step_type) } it 'yields sources and destination' do - i=0 - action.each_connected_asset(sources, destinations) do |a,b| - expect([a,b]).to eq(pairs[i]) - i=i+1 - end + i = 0 + action.each_connected_asset(sources, destinations) do |a, b| + expect([a, b]).to eq(pairs[i]) + i = i + 1 + end end end @@ -31,37 +34,43 @@ let(:sources) { [:a, :b, :c] } let(:destinations) { [:alpha, :beta, :gamma] } let(:pairs_by_position) { [[:a, :alpha], [:b, :beta], [:c, :gamma]] } - let(:pairs) { [ - [:a, :alpha], [:a, :beta], [:a, :gamma], - [:b, :alpha], [:b, :beta], [:b, :gamma], - [:c, :alpha], [:c, :beta], [:c, :gamma] - ]} + let(:pairs) { + [ + [:a, :alpha], [:a, :beta], [:a, :gamma], + [:b, :alpha], [:b, :beta], [:b, :gamma], + [:c, :alpha], [:c, :beta], [:c, :gamma] + ] + } it_behaves_like 'a connector by position' - it_behaves_like 'a connector of all to all' + it_behaves_like 'a connector of all to all' end context 'when there are less sources than destinations' do let(:sources) { [:a, :b] } let(:destinations) { [:alpha, :beta, :gamma] } let(:pairs_by_position) { [[:a, :alpha], [:b, :beta]] } - let(:pairs) { [ - [:a, :alpha], [:a, :beta], [:a, :gamma], - [:b, :alpha], [:b, :beta], [:b, :gamma] - ]} + let(:pairs) { + [ + [:a, :alpha], [:a, :beta], [:a, :gamma], + [:b, :alpha], [:b, :beta], [:b, :gamma] + ] + } it_behaves_like 'a connector by position' - it_behaves_like 'a connector of all to all' + it_behaves_like 'a connector of all to all' end context 'when there are less destinations than sources' do let(:sources) { [:a, :b, :c] } let(:destinations) { [:alpha, :beta] } let(:pairs_by_position) { [[:a, :alpha], [:b, :beta]] } - let(:pairs) { [ - [:a, :alpha], [:a, :beta], - [:b, :alpha], [:b, :beta], - [:c, :alpha], [:c, :beta] - ]} + let(:pairs) { + [ + [:a, :alpha], [:a, :beta], + [:b, :alpha], [:b, :beta], + [:c, :alpha], [:c, :beta] + ] + } it_behaves_like 'a connector by position' - it_behaves_like 'a connector of all to all' + it_behaves_like 'a connector of all to all' end end end diff --git a/spec/models/activities/background_tasks_spec.rb b/spec/models/activities/background_tasks_spec.rb index 4e57b9b8..525273a1 100644 --- a/spec/models/activities/background_tasks_spec.rb +++ b/spec/models/activities/background_tasks_spec.rb @@ -5,6 +5,7 @@ class DummyBackgroundStep def self.create!(params) @instance = FactoryBot.create(:step, params) end + def self.update_attributes!(params) @instance.update_attributes!(params) end @@ -25,8 +26,8 @@ def self.update_attributes!(params) activity.create_background_steps(list_of_tasks, {}) steps = Step.all steps.each_with_index do |s, idx| - if ((idx+1) < steps.count) - expect(s.next_step).to eq(steps[idx+1]) + if ((idx + 1) < steps.count) + expect(s.next_step).to eq(steps[idx + 1]) end end end @@ -51,7 +52,6 @@ def self.update_attributes!(params) end context '#background_tasks' do - it 'returns the list of inference tasks sorted by priority' do step_types = 5.times.each_with_index.map { |i| create :step_type } reasoning_step_types = 4.times.each_with_index.map { |i| create :step_type, { for_reasoning: true, priority: i } } diff --git a/spec/models/activities/steps_management_spec.rb b/spec/models/activities/steps_management_spec.rb index 961a0e88..43bb2118 100644 --- a/spec/models/activities/steps_management_spec.rb +++ b/spec/models/activities/steps_management_spec.rb @@ -1,24 +1,26 @@ require 'rails_helper' RSpec.describe 'Activities::StepsManagement' do context "with an activity configuration" do - let(:asset) { create :asset, { - barcode: '1', - facts: [ - ['is_a', 'Tube'], - ['is_a', 'ReceptionTube'], - ['aliquotType', 'DNA'] - ].map do |a,b| - create :fact, { :predicate => a, :object => b } - end + let(:asset) { + create :asset, { + barcode: '1', + facts: [ + ['is_a', 'Tube'], + ['is_a', 'ReceptionTube'], + ['aliquotType', 'DNA'] + ].map do |a, b| + create :fact, { :predicate => a, :object => b } + end } } - let(:step_type) { create :step_type, name: 'Step B', - condition_groups: [ - create(:condition_group, conditions: [ - create(:condition, { predicate: 'is_a', object: 'ReceptionTube' }), - create(:condition, { predicate: 'aliquotType', object: 'DNA' }) - ]) - ] + let(:step_type) { + create :step_type, name: 'Step B', + condition_groups: [ + create(:condition_group, conditions: [ + create(:condition, { predicate: 'is_a', object: 'ReceptionTube' }), + create(:condition, { predicate: 'aliquotType', object: 'DNA' }) + ]) + ] } let(:step_type2) { create :step_type, name: 'Step A' } let(:activity_type) { create :activity_type, step_types: [step_type, step_type2] } diff --git a/spec/models/activity_type_spec.rb b/spec/models/activity_type_spec.rb index c18c58ee..afce1169 100644 --- a/spec/models/activity_type_spec.rb +++ b/spec/models/activity_type_spec.rb @@ -2,4 +2,4 @@ describe ActivityType do it_behaves_like "deprecatable" -end \ No newline at end of file +end diff --git a/spec/models/asset_group_spec.rb b/spec/models/asset_group_spec.rb index 96cd0ddf..075e9de1 100644 --- a/spec/models/asset_group_spec.rb +++ b/spec/models/asset_group_spec.rb @@ -24,4 +24,3 @@ end end end - diff --git a/spec/models/asset_spec.rb b/spec/models/asset_spec.rb index a4532e91..fa1a10af 100644 --- a/spec/models/asset_spec.rb +++ b/spec/models/asset_spec.rb @@ -30,7 +30,7 @@ let(:asset) { create(:asset) } it 'returns true when the asset has a barcode format of machine barcode' do asset.facts << create(:fact, predicate: 'barcodeFormat', object: 'machine_barcode', - literal: true) + literal: true) expect(asset.print_machine_barcode?).to be_truthy end it 'returns false when the asset does not have a setting' do @@ -51,7 +51,7 @@ context 'when machine barcode has been selected' do before do asset.facts << create(:fact, predicate: 'barcodeFormat', object: 'machine_barcode', - literal: true) + literal: true) end context 'when we can generate the machine barcode' do it 'returns the machine barcode' do @@ -89,7 +89,7 @@ context 'when machine barcode has been selected' do before do asset.facts << create(:fact, predicate: 'barcodeFormat', - object: 'machine_barcode', literal: true) + object: 'machine_barcode', literal: true) end it 'prints the human barcode in the top line' do expect(asset.printable_object[:label][:top_line]).to eq(human_barcode) diff --git a/spec/models/assets/export_spec.rb b/spec/models/assets/export_spec.rb index 7952b1c7..b87270ce 100644 --- a/spec/models/assets/export_spec.rb +++ b/spec/models/assets/export_spec.rb @@ -29,9 +29,9 @@ expect(asset.attributes_to_send_for_well(well1)).to eq({ sample_uuid: TokenUtil.unquote(uuid) }) expect(asset.attributes_to_send_for_well(well2)).to eq({ - sample_tube_uuid: sample_tube.uuid, - sanger_sample_name: 'name1' - }) + sample_tube_uuid: sample_tube.uuid, + sanger_sample_name: 'name1' + }) end it 'generates an attribute object for a well' do @@ -60,10 +60,11 @@ @rack1 = Asset.find_by(uuid: 'rack1') expect(@rack1.attributes_to_send).to eq([ - { sample_tube_uuid: "s1", location: "A1" }, - { sample_tube_uuid: "s2", location: "B1" }, - { sample_tube_uuid: "s3", location: "C1" }, - { sample_tube_uuid: "s4", location: "D1" }]) + { sample_tube_uuid: "s1", location: "A1" }, + { sample_tube_uuid: "s2", location: "B1" }, + { sample_tube_uuid: "s3", location: "C1" }, + { sample_tube_uuid: "s4", location: "D1" } + ]) end end @@ -99,7 +100,7 @@ let(:step_type) { create :step_type } let(:step) { create :step, step_type: step_type, state: Step::STATE_RUNNING } let(:user) { create :user, username: 'test' } - let(:print_config) { { "Plate"=>'Pum', "Tube"=>'Pim' } } + let(:print_config) { { "Plate" => 'Pum', "Tube" => 'Pim' } } let(:plate) { build_remote_plate } let(:asset) { create :asset } @@ -153,10 +154,11 @@ @assets = SupportN3::parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') expect(@rack2.attributes_to_send).to eq([ - { sample_tube_uuid: "s1", location: "A1" }, - { sample_tube_uuid: "s2", location: "B1" }, - { sample_tube_uuid: "s3", location: "C1" }, - { sample_tube_uuid: "s4", location: "D1" }]) + { sample_tube_uuid: "s1", location: "A1" }, + { sample_tube_uuid: "s2", location: "B1" }, + { sample_tube_uuid: "s3", location: "C1" }, + { sample_tube_uuid: "s4", location: "D1" } + ]) end it 'generates the attributes when the locations are not duplicated' do @@ -184,10 +186,11 @@ @assets = SupportN3::parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') expect(@rack2.attributes_to_send).to eq([ - { sample_tube_uuid: "s1", location: "A1" }, - { sample_tube_uuid: "s2", location: "B1" }, - { sample_tube_uuid: "s3", location: "C1" }, - { sample_tube_uuid: "s4", location: "D1" }]) + { sample_tube_uuid: "s1", location: "A1" }, + { sample_tube_uuid: "s2", location: "B1" }, + { sample_tube_uuid: "s3", location: "C1" }, + { sample_tube_uuid: "s4", location: "D1" } + ]) end it 'fails when trying to generate attributes when the locations are duplicated' do @@ -241,9 +244,10 @@ @assets = SupportN3::parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') expect(@rack2.attributes_to_send).to eq([ - { sample_tube_uuid: "s1", location: "A1" }, - { sample_tube_uuid: "s2", location: "B1" }, - { sample_tube_uuid: "s4", location: "D1" }]) + { sample_tube_uuid: "s1", location: "A1" }, + { sample_tube_uuid: "s2", location: "B1" }, + { sample_tube_uuid: "s4", location: "D1" } + ]) end end end diff --git a/spec/models/assets/facts_management_spec.rb b/spec/models/assets/facts_management_spec.rb index 9de0ee1d..372bd325 100644 --- a/spec/models/assets/facts_management_spec.rb +++ b/spec/models/assets/facts_management_spec.rb @@ -1,6 +1,5 @@ require 'rails_helper' RSpec.describe Assets::FactsManagement do - context '#first_value_for' do it 'returns the first object value for an asset predicate' do asset = create :asset @@ -31,6 +30,5 @@ expect(asset.first_value_for('contains')).to eq(nil) end - end end diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 9ab1b045..2fb20073 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -2,7 +2,7 @@ require 'remote_assets_helper' RSpec.describe 'Assets::Import' do - include RemoteAssetsHelper + include RemoteAssetsHelper context '#refresh!' do let(:asset) { create :asset } @@ -160,10 +160,10 @@ it 'should store the study uuid in a safe format' do @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) expected_study_uuid = if @remote_asset.respond_to?(:wells) - @remote_asset.wells.first.aliquots.first.study.uuid - else - @remote_asset.racked_tubes.first.tube.aliquots.first.study.uuid - end + @remote_asset.wells.first.aliquots.first.study.uuid + else + @remote_asset.racked_tubes.first.tube.aliquots.first.study.uuid + end @asset.facts.reload asset_study_uuid = @asset.facts.where(predicate: 'study_uuid').first.object @@ -175,7 +175,7 @@ expect(Asset.count).to eq(0) Asset.find_or_import_asset_with_barcode(@barcode_asset) - expect(Asset.count>0).to eq(true) + expect(Asset.count > 0).to eq(true) end end @@ -249,18 +249,18 @@ tubes_with_info = tubes.select { |t| t.facts.where(predicate: 'supplier_sample_name').count > 0 } locations_with_info = tubes_with_info.map { |t| t.facts.with_predicate('location').first.object } - expect(locations_with_info).to eq(['C1','D1']) + expect(locations_with_info).to eq(['C1', 'D1']) end end context '#find_or_import_asset_with_barcode' do - context 'when importing an asset that does not exist' do - setup do - allow(SequencescapeClient).to receive(:get_remote_asset).and_return(nil) + context 'when importing an asset that does not exist' do + setup do + allow(SequencescapeClient).to receive(:get_remote_asset).and_return(nil) end - it 'should return nil' do - expect(Asset.find_or_import_asset_with_barcode('NOT_FOUND')).to eq(nil) + it 'should return nil' do + expect(Asset.find_or_import_asset_with_barcode('NOT_FOUND')).to eq(nil) end it 'should not create a new asset' do @@ -270,22 +270,22 @@ end end - context 'when importing a local asset' do - setup do - @barcode_asset = generate(:barcode) - @asset = Asset.create!(barcode: @barcode_asset) + context 'when importing a local asset' do + setup do + @barcode_asset = generate(:barcode) + @asset = Asset.create!(barcode: @barcode_asset) end - it 'should return the local asset when looking by its barcode' do - expect(Asset.find_or_import_asset_with_barcode(@barcode_asset)).to eq(@asset) + it 'should return the local asset when looking by its barcode' do + expect(Asset.find_or_import_asset_with_barcode(@barcode_asset)).to eq(@asset) end - it 'should return the local asset when looking by its uuid' do - expect(Asset.find_or_import_asset_with_barcode(@asset.uuid)).to eq(@asset) - end + it 'should return the local asset when looking by its uuid' do + expect(Asset.find_or_import_asset_with_barcode(@asset.uuid)).to eq(@asset) + end end - context 'when importing a remote asset' do + context 'when importing a remote asset' do let(:SequencescapeClient) { double('sequencescape_client') } context 'when the asset is a tube' do @@ -301,9 +301,8 @@ setup do sample_no_supplier_name = build_remote_sample( sample_metadata: double('sample_metadata', - supplier_name: nil, - sample_common_name: 'species' - ) + supplier_name: nil, + sample_common_name: 'species') ) @remote_tube_asset_without_supplier = build_remote_tube( barcode: generate(:barcode), @@ -349,13 +348,13 @@ build_remote_sample(sample_metadata: nil))]), build_remote_well('B1', aliquots: [build_remote_aliquot(sample: build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: nil)))]), + sample_common_name: 'species', supplier_name: nil)))]), build_remote_well('C1', aliquots: [build_remote_aliquot(sample: build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: 'a supplier name')))]), + sample_common_name: 'species', supplier_name: 'a supplier name')))]), build_remote_well('D1', aliquots: [build_remote_aliquot(sample: build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: 'a supplier name')))]) + sample_common_name: 'species', supplier_name: 'a supplier name')))]) ] @remote_asset_without_supplier = build_remote_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_asset_without_supplier) @@ -366,7 +365,7 @@ context 'when the plate does not have aliquots in its wells' do setup do - wells = ['A1','B1'].map { |l| build_remote_well(l, aliquots: []) } + wells = ['A1', 'B1'].map { |l| build_remote_well(l, aliquots: []) } @remote_asset_without_aliquots = build_remote_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_asset_without_aliquots) end @@ -374,13 +373,13 @@ it 'creates the wells with the same uuid as in the remote asset' do @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_aliquots.barcode) wells = @asset.facts.with_predicate('contains').map(&:object_asset) - expect(wells.zip(@remote_asset_without_aliquots.wells).all? { |w,w2| w.uuid == w2.uuid }).to eq(true) + expect(wells.zip(@remote_asset_without_aliquots.wells).all? { |w, w2| w.uuid == w2.uuid }).to eq(true) end end context 'when the plate does not have samples in its wells' do setup do - wells = ['A1','B1'].map { |l| build_remote_well(l, aliquots: [build_remote_aliquot(sample: nil)]) } + wells = ['A1', 'B1'].map { |l| build_remote_well(l, aliquots: [build_remote_aliquot(sample: nil)]) } @remote_asset_without_samples = build_remote_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_asset_without_samples) end @@ -388,7 +387,7 @@ it 'creates the wells with the same uuid as in the remote asset' do @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_samples.barcode) wells = @asset.facts.with_predicate('contains').map(&:object_asset) - expect(wells.zip(@remote_asset_without_samples.wells).all? { |w,w2| w.uuid == w2.uuid }).to eq(true) + expect(wells.zip(@remote_asset_without_samples.wells).all? { |w, w2| w.uuid == w2.uuid }).to eq(true) end end end @@ -410,13 +409,13 @@ build_remote_sample(sample_metadata: nil))])), build_remote_racked_tube('B1', build_remote_tube(aliquots: [build_remote_aliquot(sample: build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: nil)))])), + sample_common_name: 'species', supplier_name: nil)))])), build_remote_racked_tube('C1', build_remote_tube(aliquots: [build_remote_aliquot(sample: build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: 'a supplier name')))])), + sample_common_name: 'species', supplier_name: 'a supplier name')))])), build_remote_racked_tube('D1', build_remote_tube(aliquots: [build_remote_aliquot(sample: build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: 'a supplier name')))])) + sample_common_name: 'species', supplier_name: 'a supplier name')))])) ] @remote_asset_without_supplier = build_remote_tube_rack(barcode: generate(:barcode), racked_tubes: racked_tubes) stub_client_with_asset(SequencescapeClient, @remote_asset_without_supplier) @@ -425,6 +424,6 @@ it_behaves_like 'a partial import of samples' end end - end + end end end diff --git a/spec/models/assets/traction_fields_spec.rb b/spec/models/assets/traction_fields_spec.rb index 112230ef..0e8ee330 100644 --- a/spec/models/assets/traction_fields_spec.rb +++ b/spec/models/assets/traction_fields_spec.rb @@ -33,5 +33,4 @@ let(:method) { :study_uuid } it_behaves_like 'a method that converts from quoted to unquoted uuid' end - end diff --git a/spec/models/condition_spec.rb b/spec/models/condition_spec.rb index 7a786433..16e767af 100644 --- a/spec/models/condition_spec.rb +++ b/spec/models/condition_spec.rb @@ -6,10 +6,11 @@ setup do @wildcard = FactoryBot.create(:condition_group) @cond = FactoryBot.create(:condition, { - :predicate => 'aliquotType', :object_condition_group => @wildcard }) + :predicate => 'aliquotType', :object_condition_group => @wildcard + }) @fact = FactoryBot.create(:fact, { - :predicate => 'aliquotType', :object => 'DNA' - }) + :predicate => 'aliquotType', :object => 'DNA' + }) @asset = FactoryBot.create(:asset, { :facts => [@fact] }) end @@ -19,7 +20,7 @@ end describe 'wildcard creation on compatible_with()' do - #assets, required_assets=nil, checked_condition_groups=[], wildcard_values={}) + # assets, required_assets=nil, checked_condition_groups=[], wildcard_values={}) setup do @assets = 5.times.map do |i| facts = [ @@ -37,7 +38,7 @@ aliquot = ((i % 2) == 0) ? 'DNA' : 'RNA' facts.push(FactoryBot.create(:fact, { :predicate => 'aliquotType', :object => aliquot })) FactoryBot.create(:asset, :facts => facts) - end + end @rack = FactoryBot.create :asset @rack.facts << (FactoryBot.create(:fact, { :predicate => 'a', :object => 'Rack' })) @rack.facts << (@wells.map { |well| FactoryBot.create(:fact, { :predicate => 'contains', :object_asset => well }) }) @@ -69,16 +70,14 @@ @asset_group = FactoryBot.create(:asset_group, :assets => @assets) @step = FactoryBot.create(:step, { :step_type => @step_type, :asset_group => @asset_group }) - { 210=>{ 1737=>["DNA"], 1738=>["RNA"], - 1739=>["DNA"], 1740=>["RNA"], 1741=>["DNA"], - 1742=>["DNA"], 1743=>["RNA"], 1744=>["DNA"], - 1745=>["RNA"], 1746=>["DNA"] }, - 211=>{ 1737=>["DNA"], - 1738=>["RNA"], 1739=>["DNA"], 1740=>["RNA"], - 1741=>["DNA"], 1742=>["DNA"], 1743=>["RNA"], - 1744=>["DNA"], 1745=>["RNA"], 1746=>["DNA"] } } - + { 210 => { 1737 => ["DNA"], 1738 => ["RNA"], + 1739 => ["DNA"], 1740 => ["RNA"], 1741 => ["DNA"], + 1742 => ["DNA"], 1743 => ["RNA"], 1744 => ["DNA"], + 1745 => ["RNA"], 1746 => ["DNA"] }, + 211 => { 1737 => ["DNA"], + 1738 => ["RNA"], 1739 => ["DNA"], 1740 => ["RNA"], + 1741 => ["DNA"], 1742 => ["DNA"], 1743 => ["RNA"], + 1744 => ["DNA"], 1745 => ["RNA"], 1746 => ["DNA"] } } end - - end -end \ No newline at end of file + end +end diff --git a/spec/models/fact_spec.rb b/spec/models/fact_spec.rb index ce4e283a..10b00a6c 100644 --- a/spec/models/fact_spec.rb +++ b/spec/models/fact_spec.rb @@ -22,5 +22,4 @@ expect(fact).not_to be_valid end end - end diff --git a/spec/models/step_execution_spec.rb b/spec/models/step_execution_spec.rb index db87b34e..74ad0e87 100644 --- a/spec/models/step_execution_spec.rb +++ b/spec/models/step_execution_spec.rb @@ -2,9 +2,8 @@ require 'support_n3' RSpec.describe Condition, type: :model do - describe 'wildcard creation on compatible_with()' do - #assets, required_assets=nil, checked_condition_groups=[], wildcard_values={}) + # assets, required_assets=nil, checked_condition_groups=[], wildcard_values={}) setup do @assets = 5.times.map do |i| facts = [ @@ -58,20 +57,19 @@ @step = Step.create(step_type: @step_type, asset_group: @asset_group, wildcard_values: wildcards, state: Step::STATE_RUNNING) @step_execution = StepExecution.new({ - :step => @step, - :asset_group => @asset_group, :created_assets => created_assets }) + :step => @step, + :asset_group => @asset_group, :created_assets => created_assets + }) @step_execution.run - { 210=>{ 1737=>["DNA"], 1738=>["RNA"], - 1739=>["DNA"], 1740=>["RNA"], 1741=>["DNA"], - 1742=>["DNA"], 1743=>["RNA"], 1744=>["DNA"], - 1745=>["RNA"], 1746=>["DNA"] }, - 211=>{ 1737=>["DNA"], - 1738=>["RNA"], 1739=>["DNA"], 1740=>["RNA"], - 1741=>["DNA"], 1742=>["DNA"], 1743=>["RNA"], - 1744=>["DNA"], 1745=>["RNA"], 1746=>["DNA"] } } - + { 210 => { 1737 => ["DNA"], 1738 => ["RNA"], + 1739 => ["DNA"], 1740 => ["RNA"], 1741 => ["DNA"], + 1742 => ["DNA"], 1743 => ["RNA"], 1744 => ["DNA"], + 1745 => ["RNA"], 1746 => ["DNA"] }, + 211 => { 1737 => ["DNA"], + 1738 => ["RNA"], 1739 => ["DNA"], 1740 => ["RNA"], + 1741 => ["DNA"], 1742 => ["DNA"], 1743 => ["RNA"], + 1744 => ["DNA"], 1745 => ["RNA"], 1746 => ["DNA"] } } end - end end diff --git a/spec/models/step_spec.rb b/spec/models/step_spec.rb index 3825696e..0632bdf2 100644 --- a/spec/models/step_spec.rb +++ b/spec/models/step_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -def assert_equal(a,b) +def assert_equal(a, b) expect(a).to eq(b) end @@ -9,7 +9,6 @@ def cwm_engine? end RSpec.describe Step, type: :model do - let(:activity) { create :activity } let(:user) { create :user, username: 'test' } before do @@ -22,41 +21,41 @@ def build_instance def create_step step = FactoryBot.create(:step, { - activity: activity, - step_type: @step_type, - asset_group: @asset_group, - user: user - }) + activity: activity, + step_type: @step_type, + asset_group: @asset_group, + user: user + }) step.run! step end def run_step_type(step_type, asset_group) step = create(:step, { - activity: activity, - step_type: step_type, - asset_group: asset_group, - user: user - }) + activity: activity, + step_type: step_type, + asset_group: asset_group, + user: user + }) step.run! step end def create_asset(type) create(:asset, facts: [ - create(:fact, predicate: 'a', object: type) - ]) + create(:fact, predicate: 'a', object: type) + ]) end def create_action_for_creating_asset(asset_type) cg3 = create(:condition_group, name: 'my_new_asset') create(:action, action_type: 'createAsset', - predicate: 'a', subject_condition_group: cg3, object: asset_type) + predicate: 'a', subject_condition_group: cg3, object: asset_type) end def create_action_for_connecting_condition_groups(predicate, cg1, cg2) create(:action, action_type: 'addFacts', - predicate: predicate, subject_condition_group: cg1, object_condition_group: cg2) + predicate: predicate, subject_condition_group: cg1, object_condition_group: cg2) end def create_condition_to_select_asset_type(asset_type) @@ -67,15 +66,13 @@ def create_condition_group_to_select_asset_type(asset_type, name = nil) create(:condition_group, name: name, conditions: [create_condition_to_select_asset_type(asset_type)]) end - - def create_assets(num, type) num.times.map { create_asset(type) } end describe '#create' do context 'when creating a step with a specific printer config' do - let(:printer_data_config) { { "Tube"=>"1234", "Plate"=>"6789" } } + let(:printer_data_config) { { "Tube" => "1234", "Plate" => "6789" } } it 'stores the printer config in the database' do s = create(:step, printer_config: printer_data_config) s2 = Step.find_by(id: s.id) @@ -88,22 +85,28 @@ def create_assets(num, type) setup do @step_type = FactoryBot.create :step_type - @cg1 = FactoryBot.create(:condition_group,{ :name => 'p' }) - @cg1.conditions << FactoryBot.create(:condition,{ - :predicate => 'is', :object => 'Tube' }) - @cg2 = FactoryBot.create(:condition_group,{ :name => 'q' }) - @cg2.conditions << FactoryBot.create(:condition,{ - :predicate => 'is', :object => 'Rack' }) + @cg1 = FactoryBot.create(:condition_group, { :name => 'p' }) + @cg1.conditions << FactoryBot.create(:condition, { + :predicate => 'is', :object => 'Tube' + }) + @cg2 = FactoryBot.create(:condition_group, { :name => 'q' }) + @cg2.conditions << FactoryBot.create(:condition, { + :predicate => 'is', :object => 'Rack' + }) @step_type.condition_groups << @cg1 @step_type.condition_groups << @cg2 - @tubes = 7.times.map { |i| FactoryBot.create(:asset, { :facts =>[ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ] })} - @racks = 5.times.map { |i| FactoryBot.create(:asset, { :facts =>[ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ] })} + @tubes = 7.times.map { |i| + FactoryBot.create(:asset, { :facts => [ + FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') + ] }) + } + @racks = 5.times.map { |i| + FactoryBot.create(:asset, { :facts => [ + FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') + ] }) + } @assets = [@tubes, @racks].flatten @asset_group = FactoryBot.create(:asset_group, { :assets => @assets }) end @@ -113,17 +116,18 @@ def create_assets(num, type) @cg1.update_attributes(:cardinality => 1) expect { @step = create_step - }.to raise_error(AASM::InvalidTransition) + }.to raise_error(AASM::InvalidTransition) end end describe 'with related assets in conditions' do setup do @cg2.conditions << FactoryBot.create(:condition, { - :predicate => 'contains', :object_condition_group_id => @cg1.id }) + :predicate => 'contains', :object_condition_group_id => @cg1.id + }) @action = FactoryBot.create(:action, { :action_type => 'addFacts', - :predicate => 'is', :object => 'TubeRack', :subject_condition_group => @cg2 }) + :predicate => 'is', :object => 'TubeRack', :subject_condition_group => @cg2 }) @step_type.actions << @action @racks.each_with_index do |r, i| @@ -147,7 +151,7 @@ def create_assets(num, type) setup do @wildcard = FactoryBot.create :condition_group condition = FactoryBot.create :condition, { :predicate => 'position', - :object_condition_group => @wildcard } + :object_condition_group => @wildcard } @cg2.conditions << condition end @@ -166,16 +170,15 @@ def create_assets(num, type) end expect(Operation.all.count).to eq(0) end - end describe 'when the wildcard conditions are met' do setup do @racks.each_with_index do |rack, idx| rack.facts << FactoryBot.create(:fact, { - :predicate => 'position', - :object => idx.to_s - }) + :predicate => 'position', + :object => idx.to_s + }) end end @@ -196,9 +199,8 @@ def create_assets(num, type) previous_num = @asset_group.assets.count @action = FactoryBot.create(:action, { :action_type => 'addFacts', - :predicate => 'value', :object_condition_group => @wildcard, - :subject_condition_group => @cg2 - }) + :predicate => 'value', :object_condition_group => @wildcard, + :subject_condition_group => @cg2 }) @step_type.actions << @action @step = create_step @@ -208,36 +210,34 @@ def create_assets(num, type) @racks.each_with_index do |rack, pos| assert_equal true, rack.has_literal?('value', pos.to_s) end - expect(Operation.all.count).to eq(2*@racks.count) + expect(Operation.all.count).to eq(2 * @racks.count) end it 'uses the value of the condition group to relate different groups' do # ?x :t ?pos . ?y :v ?pos . => ?x :relates ?y . - previous_num = @asset_group.assets.count @cg1.conditions << FactoryBot.create(:condition, { :predicate => 'location', - :object_condition_group => @wildcard }) + :object_condition_group => @wildcard }) @cg2.conditions << FactoryBot.create(:condition, { :predicate => 'location', - :object_condition_group => @wildcard }) + :object_condition_group => @wildcard }) @action = FactoryBot.create(:action, { :action_type => 'addFacts', - :predicate => 'relates', :object_condition_group => @cg1, - :subject_condition_group => @cg2 - }) + :predicate => 'relates', :object_condition_group => @cg1, + :subject_condition_group => @cg2 }) @step_type.actions << @action @tubes.each_with_index do |tube, idx| tube.facts << FactoryBot.create(:fact, { - :predicate => 'location', - :object => idx.to_s - }) + :predicate => 'location', + :object => idx.to_s + }) end @racks.each_with_index do |rack, idx| rack.facts << FactoryBot.create(:fact, { - :predicate => 'location', - :object => idx.to_s - }) + :predicate => 'location', + :object => idx.to_s + }) end @step = create_step @@ -246,18 +246,16 @@ def create_assets(num, type) @tubes.each(&:reload) @tubes.each_with_index do |tube, pos| - assert_equal true, tube.facts.with_predicate('relates').count==0 + assert_equal true, tube.facts.with_predicate('relates').count == 0 end @racks.each_with_index do |rack, pos| - assert_equal true, rack.facts.with_predicate('relates').count!=0 + assert_equal true, rack.facts.with_predicate('relates').count != 0 end @racks.zip(@tubes).each do |list| - rack,tube = list[0],list[1] + rack, tube = list[0], list[1] assert_equal tube, rack.facts.with_predicate('relates').first.object_asset end - end - end end end @@ -266,15 +264,15 @@ def create_assets(num, type) setup do @cg3 = FactoryBot.create(:condition_group, { :name => 'r' }) @cg3.conditions << FactoryBot.create(:condition, { - :predicate => 'is', :object => 'NewTube' - }) + :predicate => 'is', :object => 'NewTube' + }) @action = FactoryBot.create(:action, { :action_type => 'createAsset', - :predicate => 'is', :object => 'NewTube', :subject_condition_group => @cg3 }) + :predicate => 'is', :object => 'NewTube', :subject_condition_group => @cg3 }) if cwm_engine? @action2 = FactoryBot.create(:action, { :action_type => 'createAsset', - :predicate => 'createdBy', :object_condition_group => @cg1, :subject_condition_group => @cg3 }) + :predicate => 'createdBy', :object_condition_group => @cg1, :subject_condition_group => @cg3 }) @action3 = FactoryBot.create(:action, { :action_type => 'createAsset', - :predicate => 'createdBy', :object_condition_group => @cg2, :subject_condition_group => @cg3 }) + :predicate => 'createdBy', :object_condition_group => @cg2, :subject_condition_group => @cg3 }) @step_type.actions << [@action, @action2, @action3] else @@ -289,15 +287,15 @@ def create_assets(num, type) @asset_group.reload assets_created = Asset.with_fact('is', 'NewTube') expect(previous_num).not_to eq(@asset_group.assets.count) - #expect(assets_created.length).to eq(previous_num) + # expect(assets_created.length).to eq(previous_num) if cwm_engine? expect(assets_created.length).to eq(@tubes.count * @racks.count) - expect(Operation.all.count).to eq(assets_created.count*3) + expect(Operation.all.count).to eq(assets_created.count * 3) else expect(assets_created.length).to eq(previous_num) - expect(Operation.all.select { |o| o.action_type=='createAssets' }.count).to eq(assets_created.count) + expect(Operation.all.select { |o| o.action_type == 'createAssets' }.count).to eq(assets_created.count) end - expect(assets_created.length+previous_num).to eq(@asset_group.assets.count) + expect(assets_created.length + previous_num).to eq(@asset_group.assets.count) end unless cwm_engine? @@ -310,9 +308,9 @@ def create_assets(num, type) assets_created = Asset.with_fact('is', 'NewTube') expect(previous_num).not_to eq(@asset_group.assets.count) expect(assets_created.length).to eq(6) - expect(assets_created.length+previous_num).to eq(@asset_group.assets.count) + expect(assets_created.length + previous_num).to eq(@asset_group.assets.count) - expect(Operation.all.select { |o| o.action_type=='createAssets' }.count).to eq(assets_created.count) + expect(Operation.all.select { |o| o.action_type == 'createAssets' }.count).to eq(assets_created.count) end it 'cardinality does not restrict the number of assets created when it is over the number of inputs' do @@ -325,16 +323,16 @@ def create_assets(num, type) assets_created = Asset.with_fact('is', 'NewTube') expect(previous_num).not_to eq(@asset_group.assets.count) expect(assets_created.length).to eq(cardinality) - #expect(assets_created.length+previous_num).to eq(@asset_group.assets.count) + # expect(assets_created.length+previous_num).to eq(@asset_group.assets.count) - expect(Operation.all.select { |o| o.action_type=='createAssets' }.count).to eq(assets_created.count) + expect(Operation.all.select { |o| o.action_type == 'createAssets' }.count).to eq(assets_created.count) end end it 'adds facts to all the assets created' do previous_num = @asset_group.assets.count action = FactoryBot.create(:action, { :action_type => 'createAsset', - :predicate => 'has', :object => "MoreData", :subject_condition_group => @cg3 }) + :predicate => 'has', :object => "MoreData", :subject_condition_group => @cg3 }) @step_type.actions << action @step = create_step @@ -346,30 +344,30 @@ def create_assets(num, type) expect(previous_num).not_to eq(@asset_group.assets.count) if cwm_engine? expect(assets_created.length).to eq(@tubes.count * @racks.count) - expect(Operation.all.count).to eq(4*assets_created.count) + expect(Operation.all.count).to eq(4 * assets_created.count) else expect(assets_created.length).to eq(previous_num) end - expect(assets_created.length+previous_num).to eq(@asset_group.assets.count) + expect(assets_created.length + previous_num).to eq(@asset_group.assets.count) end it 'is able to execute addFacts and createFacts referring to the same condition group' do previous_num = @asset_group.assets.count action = FactoryBot.create(:action, { :action_type => 'addFacts', - :predicate => 'has', :object => 'MoreData', :subject_condition_group => @cg3 }) + :predicate => 'has', :object => 'MoreData', :subject_condition_group => @cg3 }) @step_type.actions << action @step = create_step - expect(@asset_group.assets.count).to eq(previous_num*2) - expect(Operation.all.select { |o| o.action_type == 'addFacts' }.count).to eq(2*previous_num) + expect(@asset_group.assets.count).to eq(previous_num * 2) + expect(Operation.all.select { |o| o.action_type == 'addFacts' }.count).to eq(2 * previous_num) end describe 'with overlapping assets' do setup do @tubes_and_racks = 7.times.map do FactoryBot.create(:asset, { :facts => [ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') - ] }) + FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') + ] }) end @asset_group.assets << @tubes_and_racks end @@ -387,24 +385,20 @@ def create_assets(num, type) # Its 3 actions for each asset created, but the 'createdBy' relations with the # asset themselves wont happen twice (this is the case only for the @tubes_and_racks # overlapped assets), so its 7 - total_operations = (assets_created.count*3) - @tubes_and_racks.count + total_operations = (assets_created.count * 3) - @tubes_and_racks.count expect(Operation.all.count).to eq(total_operations) else expect(assets_created.length).to eq(previous_num) end - expect(assets_created.length+previous_num).to eq(@asset_group.assets.count) - + expect(assets_created.length + previous_num).to eq(@asset_group.assets.count) end end - - - end describe 'with unselectAsset action type' do setup do @action = FactoryBot.create(:action, { :action_type => 'addFacts', - :predicate => 'is', :object => 'Empty', :subject_condition_group => @cg1 }) + :predicate => 'is', :object => 'Empty', :subject_condition_group => @cg1 }) @step_type.actions << @action end @@ -421,16 +415,16 @@ def create_assets(num, type) assert_equal false, @tubes.any? { |tube| @asset_group.assets.include?(tube) } - #expect(Operation.all.count).to eq(@tubes.length) + # expect(Operation.all.count).to eq(@tubes.length) end describe 'with overlapping assets' do setup do @tubes_and_racks = 7.times.map do FactoryBot.create(:asset, { :facts => [ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') - ] }) + FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') + ] }) end @asset_group.assets << @tubes_and_racks end @@ -450,8 +444,6 @@ def create_assets(num, type) assert_equal false, [@tubes, @tubes_and_racks].flatten.all? { |tube| @asset_group.assets.include?(tube) } end end - - end describe 'when using different values of connect_by' do @@ -481,7 +473,7 @@ def create_assets(num, type) s = run_step_type(step_type, asset_group) origins.each(&:reload) destinations.each(&:reload) - transfers = origins.map(&:facts).map { |facts| facts.with_predicate('transfer') }.flatten.sort do |a,b| + transfers = origins.map(&:facts).map { |facts| facts.with_predicate('transfer') }.flatten.sort do |a, b| if (a.asset.id == b.asset.id) (a.object_asset.id <=> b.object_asset.id) else @@ -495,14 +487,18 @@ def create_assets(num, type) end context 'when the destinations exist upfront' do - let(:condition_groups) { [ - create_condition_group_to_select_asset_type('Tube'), - create_condition_group_to_select_asset_type('Rack') - ] } - let(:actions) { [ - create_action_for_connecting_condition_groups('transfer', - condition_groups.first, condition_groups.last) - ] } + let(:condition_groups) { + [ + create_condition_group_to_select_asset_type('Tube'), + create_condition_group_to_select_asset_type('Rack') + ] + } + let(:actions) { + [ + create_action_for_connecting_condition_groups('transfer', + condition_groups.first, condition_groups.last) + ] + } let(:targets) { destinations } context 'when there are more destinations than origins' do let(:origins) { create_assets(5, 'Tube') } @@ -530,19 +526,22 @@ def create_assets(num, type) end context 'when the destinations are going to be created during the execution' do - let(:condition_groups) { [ - create_condition_group_to_select_asset_type('Tube') - ] } + let(:condition_groups) { + [ + create_condition_group_to_select_asset_type('Tube') + ] + } let(:action_for_creating_rack) { create_action_for_creating_asset('Rack') } - let(:actions) { [ - create_action_for_connecting_condition_groups('transfer', - condition_groups.first, - action_for_creating_rack.subject_condition_group - ), - action_for_creating_rack - ] } + let(:actions) { + [ + create_action_for_connecting_condition_groups('transfer', + condition_groups.first, + action_for_creating_rack.subject_condition_group), + action_for_creating_rack + ] + } let(:origins) { create_assets(5, 'Tube') } let(:targets) { [] } @@ -558,7 +557,7 @@ def create_assets(num, type) describe 'with one action' do setup do @action = FactoryBot.create(:action, { :action_type => 'addFacts', - :predicate => 'is', :object => 'Empty', :subject_condition_group => @cg1 }) + :predicate => 'is', :object => 'Empty', :subject_condition_group => @cg1 }) @step_type.actions << @action end @@ -593,11 +592,11 @@ def create_assets(num, type) @racks.each do |rack| assert_equal true, @tubes.first.has_fact?(build(:fact, predicate: @action.predicate, - object_asset_id: rack.id)) + object_asset_id: rack.id)) end assert_equal false, @tubes.last.has_fact?(build(:fact, predicate: @action.predicate, - object_asset_id: @racks.first.id)) + object_asset_id: @racks.first.id)) expect(Operation.all.count).to eq(@racks.length) end @@ -612,10 +611,10 @@ def create_assets(num, type) @tubes.each do |tube| assert_equal true, tube.has_fact?(build(:fact, predicate: @action.predicate, - object_asset_id: @racks.first.id)) + object_asset_id: @racks.first.id)) end assert_equal false, @tubes.first.has_fact?(build(:fact, predicate: @action.predicate, - object_asset_id: @racks.last.id)) + object_asset_id: @racks.last.id)) expect(Operation.all.count).to eq(@tubes.length) end @@ -630,7 +629,7 @@ def create_assets(num, type) @racks.each(&:reload) assert_equal true, @tubes.first.has_fact?(build(:fact, predicate: @action.predicate, - object_asset_id: @racks.first.id)) + object_asset_id: @racks.first.id)) expect(Operation.all.count).to eq(1) end @@ -645,24 +644,24 @@ def create_assets(num, type) @tubes.each do |tube| @racks.each do |rack| assert_equal true, tube.has_fact?(build(:fact, predicate: @action.predicate, - object_asset_id: rack.id)) + object_asset_id: rack.id)) end end - expect(Operation.all.count).to eq(@racks.length*@tubes.length) + expect(Operation.all.count).to eq(@racks.length * @tubes.length) end describe 'with overlapping assets' do setup do @tubes_and_racks = 7.times.map do FactoryBot.create(:asset, { :facts => [ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') - ] }) + FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') + ] }) end @asset_group.assets << @tubes_and_racks end - it 'connects overlapped assets with themselves as consequence of the condition', :last=> true do + it 'connects overlapped assets with themselves as consequence of the condition', :last => true do @asset_group.assets.reload @step = create_step @@ -672,25 +671,23 @@ def create_assets(num, type) @tubes_and_racks.each(&:reload) [@tubes, @tubes_and_racks].flatten.each do |tube| - [@racks, @tubes_and_racks].flatten.each do |rack| + [@racks, @tubes_and_racks].flatten.each do |rack| assert_equal true, tube.has_fact?(build(:fact, predicate: @action.predicate, - object_asset_id: rack.id)) + object_asset_id: rack.id)) end end - expect(Operation.all.count).to eq((@racks.length+@tubes_and_racks.length)*(@tubes.length+@tubes_and_racks.length)) + expect(Operation.all.count).to eq((@racks.length + @tubes_and_racks.length) * (@tubes.length + @tubes_and_racks.length)) end end - end end - describe 'with several actions' do setup do @action = FactoryBot.create(:action, { :action_type => 'addFacts', - :predicate => 'is', :object => 'Empty' }) + :predicate => 'is', :object => 'Empty' }) @action2 = FactoryBot.create(:action, { :action_type => 'addFacts', - :predicate => 'is', :object => 'Red' }) + :predicate => 'is', :object => 'Red' }) @step_type.actions << @action @step_type.actions << @action2 @@ -714,7 +711,7 @@ def create_assets(num, type) assert_equal false, asset.has_fact?(@action2) end - expect(Operation.all.count).to eq(2*@tubes.length) + expect(Operation.all.count).to eq(2 * @tubes.length) end end @@ -736,11 +733,9 @@ def create_assets(num, type) assert_equal false, asset.has_fact?(@action) assert_equal true, asset.has_fact?(@action2) end - expect(Operation.all.count).to eq(@racks.length+@tubes.length) + expect(Operation.all.count).to eq(@racks.length + @tubes.length) end end - - end end @@ -748,7 +743,7 @@ def create_assets(num, type) describe 'with one action' do setup do @action = FactoryBot.create(:action, { :action_type => 'removeFacts', - :predicate => 'is', :object => 'Tube', :subject_condition_group => @cg1 }) + :predicate => 'is', :object => 'Tube', :subject_condition_group => @cg1 }) @step_type.actions << @action end @@ -773,16 +768,17 @@ def create_assets(num, type) setup do # Something like removeFact(?tube :relatesTo ?rack) @action = FactoryBot.create(:action, { :action_type => 'removeFacts', - :predicate => 'relatesTo', :subject_condition_group => @cg1, - :object_condition_group => @cg2 }) + :predicate => 'relatesTo', :subject_condition_group => @cg1, + :object_condition_group => @cg2 }) @step_type.actions << @action end it 'removes the link between both assets' do @tubes.first.facts << FactoryBot.create(:fact, { - :predicate => 'relatesTo', :object => @racks.first.relation_id, - :object_asset => @racks.first, - :literal => false }) + :predicate => 'relatesTo', :object => @racks.first.relation_id, + :object_asset => @racks.first, + :literal => false + }) assert_equal 1, @tubes.first.facts.select { |f| f.predicate == 'relatesTo' }.length @@ -799,9 +795,10 @@ def create_assets(num, type) @tubes.each do |tube| @racks.each do |rack| tube.facts << FactoryBot.create(:fact, { - :predicate => 'relatesTo', :object => rack.relation_id, - :object_asset => rack, - :literal => false }) + :predicate => 'relatesTo', :object => rack.relation_id, + :object_asset => rack, + :literal => false + }) end end @@ -809,7 +806,7 @@ def create_assets(num, type) @racks.each(&:reload) @tubes.each do |tube| - assert_equal true, (tube.facts.select { |f| f.predicate == 'relatesTo' }.length>0) + assert_equal true, (tube.facts.select { |f| f.predicate == 'relatesTo' }.length > 0) end create_step @@ -820,33 +817,35 @@ def create_assets(num, type) @tubes.each do |tube| assert_equal 0, tube.facts.select { |f| f.predicate == 'relatesTo' }.length end - expect(Operation.all.count).to eq(@racks.length*@tubes.length) + expect(Operation.all.count).to eq(@racks.length * @tubes.length) end it 'removes the link just between the matched assets', :last => true do @tubes.each do |tube| tube.facts << FactoryBot.create(:fact, { - :predicate => 'relatesTo', :object => @tubes.first.relation_id, - :object_asset => @racks.first, - :literal => false }) + :predicate => 'relatesTo', :object => @tubes.first.relation_id, + :object_asset => @racks.first, + :literal => false + }) end @racks.each do |rack| rack.facts << FactoryBot.create(:fact, { - :predicate => 'relatesTo', :object => @racks.first.relation_id, - :object_asset => @racks.first, - :literal => false }) + :predicate => 'relatesTo', :object => @racks.first.relation_id, + :object_asset => @racks.first, + :literal => false + }) end @tubes.each(&:reload) @racks.each(&:reload) @tubes.each do |tube| - assert_equal true, (tube.facts.select { |f| f.predicate == 'relatesTo' }.length>0) + assert_equal true, (tube.facts.select { |f| f.predicate == 'relatesTo' }.length > 0) end @racks.each do |rack| - assert_equal true, (rack.facts.select { |f| f.predicate == 'relatesTo' }.length>0) + assert_equal true, (rack.facts.select { |f| f.predicate == 'relatesTo' }.length > 0) end create_step @@ -864,15 +863,14 @@ def create_assets(num, type) expect(Operation.all.count).to eq(@tubes.length) end - end end describe 'with several actions' do setup do @action = FactoryBot.create(:action, { :action_type => 'removeFacts', - :predicate => 'is', :object => 'Tube' }) + :predicate => 'is', :object => 'Tube' }) @action2 = FactoryBot.create(:action, { :action_type => 'removeFacts', - :predicate => 'is', :object => 'Full' }) + :predicate => 'is', :object => 'Full' }) @step_type.actions << @action @step_type.actions << @action2 @@ -905,7 +903,7 @@ def create_assets(num, type) assert_equal false, asset.has_fact?(@action) assert_equal true, asset.has_fact?(@action2) end - expect(Operation.all.count).to eq(2*@tubes.length) + expect(Operation.all.count).to eq(2 * @tubes.length) end end @@ -939,14 +937,10 @@ def create_assets(num, type) assert_equal false, asset.has_fact?(@action) assert_equal false, asset.has_fact?(@action2) end - expect(Operation.all.count).to eq(@tubes.length+@racks.length) + expect(Operation.all.count).to eq(@tubes.length + @racks.length) end end - end end - end - - end diff --git a/spec/models/step_type_spec.rb b/spec/models/step_type_spec.rb index a9d67469..f0a24f28 100644 --- a/spec/models/step_type_spec.rb +++ b/spec/models/step_type_spec.rb @@ -1,11 +1,10 @@ require 'rails_helper' require 'spec_helper' -def assert_equal(a,b) +def assert_equal(a, b) expect(a).to eq(b) end - RSpec.describe StepType, type: :model do it_behaves_like "deprecatable" @@ -16,8 +15,8 @@ def assert_equal(a,b) create :step_type, for_reasoning: true create :step_type, name: 'Not background', for_reasoning: false, priority: 5000 create :step_type, name: 'Third', for_reasoning: true, priority: 10 - create :step_type, name: 'First', for_reasoning: true , priority: 1000 - create :step_type, name: 'Second', for_reasoning: true , priority: 50 + create :step_type, name: 'First', for_reasoning: true, priority: 1000 + create :step_type, name: 'Second', for_reasoning: true, priority: 50 expect(StepType.all.for_reasoning.first.name).to eq('First') expect(StepType.all.for_reasoning[1].name).to eq('Second') @@ -62,14 +61,15 @@ def assert_equal(a,b) describe '#compatible_with' do setup do - @step_type=FactoryBot.create :step_type - @cg1=FactoryBot.create(:condition_group, { :name => 'p' }) + @step_type = FactoryBot.create :step_type + @cg1 = FactoryBot.create(:condition_group, { :name => 'p' }) @step_type.condition_groups << @cg1 @cg1.conditions << FactoryBot.create(:condition, { - :predicate => 'is', :object => 'Tube' }) + :predicate => 'is', :object => 'Tube' + }) @cg1.conditions << FactoryBot.create(:condition, { - :predicate => 'is', :object => 'Full' }) - + :predicate => 'is', :object => 'Full' + }) @asset = FactoryBot.create :asset end @@ -116,10 +116,12 @@ def assert_equal(a,b) describe "with special configuration" do describe "related with cardinality" do setup do - @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ + @assets = 5.times.map { |i| + FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ] }} + ] } + } end it 'is compatible with any number of assets with no cardinality check' do @@ -142,38 +144,38 @@ def assert_equal(a,b) @cg1.cardinality = 4 assert_equal false, @step_type.compatible_with?(@assets) end - end - end end describe 'matching more than one asset' do describe 'for the same condition group' do setup do - @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ + @assets = 5.times.map { |i| + FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ] }} + ] } + } end it 'is compatible if all the assets match all the conditions of the rule' do @assets.first.facts << FactoryBot.create(:fact, - :predicate => 'has', :object => 'DNA') + :predicate => 'has', :object => 'DNA') assert_equal true, @step_type.compatible_with?(@assets) end it 'is not compatible if any of the assets do not match any the conditions of the rule' do @assets << FactoryBot.create(:asset, { :facts => [ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Empty') - ] }) + FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Empty') + ] }) assert_equal false, @step_type.compatible_with?(@assets) end it 'is not compatible if any of the assets do not match all the conditions of the rule' do @assets << FactoryBot.create(:asset, { :facts => [ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Empty') - ] }) + FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Empty') + ] }) assert_equal false, @step_type.compatible_with?(@assets) end end @@ -182,24 +184,28 @@ def assert_equal(a,b) setup do @cg2 = FactoryBot.create(:condition_group, { :name => 'q' }) @cg2.conditions << FactoryBot.create(:condition, { - :predicate => 'is', - :object => 'Rack' - }) + :predicate => 'is', + :object => 'Rack' + }) @step_type.condition_groups << @cg2 - @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ] }} - - @racks = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), - ] }} + @assets = 5.times.map { |i| + FactoryBot.create :asset, { :facts => [ + FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') + ] } + } + + @racks = 5.times.map { |i| + FactoryBot.create :asset, { :facts => [ + FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), + ] } + } end it 'is compatible with both condition groups when cardinality was set for one of them' do - racks = @racks.slice(0,3) + racks = @racks.slice(0, 3) @cg2.cardinality = 3 assert_equal true, @step_type.compatible_with?([@assets, racks].flatten) @@ -221,7 +227,7 @@ def assert_equal(a,b) a.facts << FactoryBot.create(:fact, { :predicate => 'a', :object => 'b' }) b = FactoryBot.create :asset b.facts << FactoryBot.create(:fact, { :predicate => 'c', :object => 'd' }) - assert_equal false, @step_type.compatible_with?([a,b].flatten) + assert_equal false, @step_type.compatible_with?([a, b].flatten) end it 'is not compatible if any of the condition groups is partially matched by any of the assets' do @@ -233,14 +239,13 @@ def assert_equal(a,b) it 'is compatible with overlapped assets' do @tubes_and_racks = 7.times.map do FactoryBot.create(:asset, { :facts => [ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') - ] }) + FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') + ] }) end assert_equal true, @step_type.compatible_with?([@assets, @racks, @tubes_and_racks].flatten) end - end end end @@ -249,41 +254,53 @@ def assert_equal(a,b) setup do @cg2 = FactoryBot.create(:condition_group, {}) @cg2.conditions << FactoryBot.create(:condition, { - :predicate => 'is', :object => 'Rack' }) + :predicate => 'is', :object => 'Rack' + }) @step_type.condition_groups << @cg2 @cg1.conditions << FactoryBot.create(:condition, { - :predicate => 'inRack', :object => 'q', - :object_condition_group_id => @cg2.id }) + :predicate => 'inRack', :object => 'q', + :object_condition_group_id => @cg2.id + }) - @racks = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ + @racks = 5.times.map { |i| + FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack') - ] }} + ] } + } - @bad_racks = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ + @bad_racks = 5.times.map { |i| + FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack') - ] }} + ] } + } - @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ + @assets = 5.times.map { |i| + FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), FactoryBot.create(:fact, :predicate => 'inRack', :object_asset_id => @racks[i].id) - ] }} + ] } + } end it 'is compatible with condition groups that have relations with elements included in the asset group' do assert_equal true, @step_type.compatible_with?([@assets, @racks].flatten) end it 'is not compatible when the relation is not matching the conditions required' do - @bad_racks = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ - FactoryBot.create(:fact, :predicate => 'is', :object => 'BadRack') - ] }} - - @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), - FactoryBot.create(:fact, :predicate => 'inRack', :object_asset_id => @bad_racks[i].id) - ] }} + @bad_racks = 5.times.map { |i| + FactoryBot.create :asset, { :facts => [ + FactoryBot.create(:fact, :predicate => 'is', :object => 'BadRack') + ] } + } + + @assets = 5.times.map { |i| + FactoryBot.create :asset, { :facts => [ + FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), + FactoryBot.create(:fact, :predicate => 'inRack', :object_asset_id => @bad_racks[i].id) + ] } + } assert_equal false, @step_type.compatible_with?([@assets, @bad_racks].flatten) end it 'is compatible with condition groups that have relations with elements outside the asset group' do @@ -294,16 +311,18 @@ def assert_equal(a,b) setup do @cg2 = FactoryBot.create(:condition_group, {}) @cg1.conditions << FactoryBot.create(:condition, { - :predicate => 'position', - :object_condition_group_id => @cg2.id }) + :predicate => 'position', + :object_condition_group_id => @cg2.id + }) end it 'is compatible with any literal when met the other conditions' do - - @assets = 5.times.map { |i| FactoryBot.create :asset, { :facts => [ - FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), - FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), - FactoryBot.create(:fact, :predicate => 'position', :object => i) - ] }} + @assets = 5.times.map { |i| + FactoryBot.create :asset, { :facts => [ + FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), + FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), + FactoryBot.create(:fact, :predicate => 'position', :object => i) + ] } + } assert_equal true, @step_type.compatible_with?([@assets].flatten) end end diff --git a/spec/models/steps/background_tasks/inference_spec.rb b/spec/models/steps/background_tasks/inference_spec.rb index c2606721..00ceee9a 100644 --- a/spec/models/steps/background_tasks/inference_spec.rb +++ b/spec/models/steps/background_tasks/inference_spec.rb @@ -24,30 +24,30 @@ }.to change { inference.output.nil? }.to(false) end end - context 'when there is no error' do - before do - allow(execution).to receive(:run) - end + context 'when there is no error' do + before do + allow(execution).to receive(:run) + end - it 'changes the status to complete' do - inference.run! - expect(inference.state).to eq('complete') - end + it 'changes the status to complete' do + inference.run! + expect(inference.state).to eq('complete') + end - it 'executes the rest of next steps' do - inferences = 5.times.map { create :inference, activity: activity } - inferences.reverse.reduce(nil) do |memo, step| - id = (memo && memo.id) || nil - step.update_attributes(next_step_id: id) - # Step is modified by the accumulator. This is actually shown as a - # 'good' pattern on the Lint/UnmodifiedReduceAccumulator documentation - # so surprised its complaining here. - step # rubocop:disable Lint/UnmodifiedReduceAccumulator - end - inferences.first.run! - inferences.each(&:reload) - inferences.each { |i| expect(i.state).to eq('complete') } - end - end + it 'executes the rest of next steps' do + inferences = 5.times.map { create :inference, activity: activity } + inferences.reverse.reduce(nil) do |memo, step| + id = (memo && memo.id) || nil + step.update_attributes(next_step_id: id) + # Step is modified by the accumulator. This is actually shown as a + # 'good' pattern on the Lint/UnmodifiedReduceAccumulator documentation + # so surprised its complaining here. + step # rubocop:disable Lint/UnmodifiedReduceAccumulator + end + inferences.first.run! + inferences.each(&:reload) + inferences.each { |i| expect(i.state).to eq('complete') } + end + end end end diff --git a/spec/models/steps/cancellable_spec.rb b/spec/models/steps/cancellable_spec.rb index 6482a1a0..0e12d8a8 100644 --- a/spec/models/steps/cancellable_spec.rb +++ b/spec/models/steps/cancellable_spec.rb @@ -66,5 +66,4 @@ @steps.each(&:reload) expect(@steps.any? { |s| s.cancelled? }).to eq(false) end - end diff --git a/spec/models/steps/queueable_job_spec.rb b/spec/models/steps/queueable_job_spec.rb index 730589e0..a17e91b9 100644 --- a/spec/models/steps/queueable_job_spec.rb +++ b/spec/models/steps/queueable_job_spec.rb @@ -1,30 +1,27 @@ require 'rails_helper' RSpec.describe "Steps::QueuableJob" do - let(:activity) { create :activity } let(:step_type) { create :step_type } let(:asset_group) { create :asset_group } let(:user) { create :user, username: 'test' } - def build_instance_with_activity step = create(:step, { - activity: activity, - step_type: step_type, - asset_group: asset_group, - user: user - }) + activity: activity, + step_type: step_type, + asset_group: asset_group, + user: user + }) end context 'when a background step is completed' do - let(:step) { build_instance_with_activity } context 'when there was an error in its execution' do before do allow(step).to receive(:process) do raise StandardError - #step.update_attributes(state: 'error') + # step.update_attributes(state: 'error') end end context 'when it has a next step configured' do @@ -53,7 +50,6 @@ def build_instance_with_activity expect(my_steps.last).not_to have_received(:process) end end - end context 'when the step is still in progress and has a next step' do let(:another_step) { build_instance_with_activity } @@ -181,5 +177,4 @@ def mock_step_completion(s, state) end end end - end diff --git a/spec/models/steps/state_spec.rb b/spec/models/steps/state_spec.rb index 9ac2b176..fd576dba 100644 --- a/spec/models/steps/state_spec.rb +++ b/spec/models/steps/state_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' RSpec.describe Steps::State do - let(:activity) { create :activity } let(:step_type) { create :step_type } let(:job) { double('a job', id: 'an id') } @@ -15,7 +14,7 @@ before do allow(step).to receive(:create_job).and_return(job) end - let(:step) { create :step, state: Step::STATE_PENDING, activity: activity, step_type: step_type } + let(:step) { create :step, state: Step::STATE_PENDING, activity: activity, step_type: step_type } it 'can transition to run' do expect(step).to transition_from(:pending).to(:running).on_event(:run) expect(step).to transition_from(:failed).to(:running).on_event(:run) @@ -97,7 +96,6 @@ end end - context 'when changing state to complete' do let(:step) { create :step, state: Step::STATE_RUNNING, activity: activity, step_type: step_type } it 'sets the timestamp for finished_at' do @@ -113,4 +111,3 @@ end end end - diff --git a/spec/models/steps/stoppable_spec.rb b/spec/models/steps/stoppable_spec.rb index 982b3012..59c90893 100644 --- a/spec/models/steps/stoppable_spec.rb +++ b/spec/models/steps/stoppable_spec.rb @@ -24,7 +24,6 @@ steps.each(&:reload) } - context 'but the step was already completed before' do let(:previous_state) { Step::STATE_COMPLETE } before do diff --git a/spec/models/steps/task_spec.rb b/spec/models/steps/task_spec.rb index c9dea0cd..a848c7db 100644 --- a/spec/models/steps/task_spec.rb +++ b/spec/models/steps/task_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' describe Steps::Task do - let(:user) { create :user, username: 'test' } let(:printer_config) { { @@ -19,24 +18,23 @@ def create_instance(step_type, activity, group) create(:step, step_type: step_type, activity: activity, asset_group: group, user: user, printer_config: printer_config) end - #it_behaves_like 'background task' + # it_behaves_like 'background task' context 'a background task with some changes defined' do let(:step_type) { create(:step_type, - step_action: step_action, - condition_groups: [cg], - actions: [ - create(:action, action_type: 'createAsset', predicate: 'a', object: 'Tube', - subject_condition_group: cg2) - ] - ) + step_action: step_action, + condition_groups: [cg], + actions: [ + create(:action, action_type: 'createAsset', predicate: 'a', object: 'Tube', + subject_condition_group: cg2) + ]) } - let(:cg) { create :condition_group, conditions: [ create(:condition, predicate: 'a', object: 'Plate')] } + let(:cg) { create :condition_group, conditions: [create(:condition, predicate: 'a', object: 'Plate')] } let(:cg2) { create :condition_group } let(:group) { create :asset_group, assets: [asset] } let(:activity) { create :activity } - let(:asset) { create :asset, facts: [ create(:fact, predicate: 'a', object: 'Plate')] } + let(:asset) { create :asset, facts: [create(:fact, predicate: 'a', object: 'Plate')] } context 'when the step type does not have a step action' do let(:step_action) { nil } diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 1d9a0fd9..2dde1434 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -29,7 +29,6 @@ Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } Dir[Rails.root.join('spec/shared_examples/*.rb')].each { |f| require f } - RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_path = "#{::Rails.root}/spec/fixtures" @@ -60,5 +59,4 @@ config.filter_rails_from_backtrace! # arbitrary gems may also be filtered via: # config.filter_gems_from_backtrace("gem name") - end diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index 9df15804..6a1a94c7 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -1,94 +1,94 @@ module RemoteAssetsHelper - def build_remote_plate(opts = {}) - purpose = double('purpose', name: 'A purpose') - obj = { - uuid: SecureRandom.uuid, - wells: [build_remote_well('A1'), build_remote_well('A4')], - purpose: purpose, - type: 'plates' - }.merge(opts) - - my_double = double('remote_asset', obj) - allow(my_double).to receive(:attributes).and_return(obj) - allow(my_double).to receive(:class).and_return(Sequencescape::Plate) - - my_double - end - - def build_remote_well(location, opts = {}) - double('well', { aliquots: [build_remote_aliquot], location: location, position: { "name" => location }, uuid: SecureRandom.uuid }.merge(opts)) - end - - def build_remote_tube_rack(opts = {}) - purpose = double('purpose', name: 'A purpose') - obj = { - uuid: SecureRandom.uuid, - racked_tubes: [build_remote_racked_tube('A1'), build_remote_racked_tube('A4')], - purpose: purpose, - type: 'tube_racks' - }.merge(opts) - - my_double = double('remote_asset', obj) - allow(my_double).to receive(:attributes).and_return(obj) - - my_double - end - - def build_remote_racked_tube(coordinate, tube = nil) - obj = { - coordinate: coordinate, - tube: tube || build_remote_tube - } - - my_double = double('racked_tube', obj) - end - - def build_remote_tube(opts = {}) - purpose = double('purpose', name: 'A purpose') - obj = { - uuid: SecureRandom.uuid, - type: 'tubes', - plate_purpose: purpose, - aliquots: [build_remote_aliquot], - labware_barcode: { 'human_barcode' => 'test' } - }.merge(opts) - my_double = double('remote_asset', obj) - - allow(my_double).to receive(:attributes).and_return(obj) - allow(my_double).to receive(:class).and_return(Sequencescape::Tube) - - my_double - end - - def build_remote_aliquot(opts = {}) - double('aliquot', { sample: build_remote_sample, study: build_study }.merge(opts)) - end - - def build_study(opts = {}) - double('study', { name: 'STDY', uuid: SecureRandom.uuid }) - end - - def build_remote_sample(opts = {}) - attrs_for_sample = { - sanger_sample_id: 'TEST-123', - name: 'a sample name', - sample_metadata: double('sample_metadata', { supplier_name: 'a supplier', sample_common_name: 'species' }), - #sanger: double('sanger', { sample_id: 'TEST-123', name: 'a sample name'}), - uuid: SecureRandom.uuid, - #supplier: double('supplier', {sample_name: 'a supplier'}), - updated_at: Time.now.to_s - }.merge(opts) - - sample = double('sample', attrs_for_sample) - allow(sample).to receive(:attributes).and_return(attrs_for_sample) - sample - end - - def stub_client_with_asset(double, asset) - type = (asset.class==Sequencescape::Plate) ? :plate : :tube - allow(double).to receive(:find_by_uuid).with(asset.uuid).and_return(asset) - allow(double).to receive(:get_remote_asset) { nil } - allow(double).to receive(:get_remote_asset).with(asset.barcode).and_return(asset) - allow(double).to receive(:get_remote_asset).with(asset.uuid).and_return(asset) - end + def build_remote_plate(opts = {}) + purpose = double('purpose', name: 'A purpose') + obj = { + uuid: SecureRandom.uuid, + wells: [build_remote_well('A1'), build_remote_well('A4')], + purpose: purpose, + type: 'plates' + }.merge(opts) + + my_double = double('remote_asset', obj) + allow(my_double).to receive(:attributes).and_return(obj) + allow(my_double).to receive(:class).and_return(Sequencescape::Plate) + + my_double + end + + def build_remote_well(location, opts = {}) + double('well', { aliquots: [build_remote_aliquot], location: location, position: { "name" => location }, uuid: SecureRandom.uuid }.merge(opts)) + end + + def build_remote_tube_rack(opts = {}) + purpose = double('purpose', name: 'A purpose') + obj = { + uuid: SecureRandom.uuid, + racked_tubes: [build_remote_racked_tube('A1'), build_remote_racked_tube('A4')], + purpose: purpose, + type: 'tube_racks' + }.merge(opts) + + my_double = double('remote_asset', obj) + allow(my_double).to receive(:attributes).and_return(obj) + + my_double + end + + def build_remote_racked_tube(coordinate, tube = nil) + obj = { + coordinate: coordinate, + tube: tube || build_remote_tube + } + + my_double = double('racked_tube', obj) + end + + def build_remote_tube(opts = {}) + purpose = double('purpose', name: 'A purpose') + obj = { + uuid: SecureRandom.uuid, + type: 'tubes', + plate_purpose: purpose, + aliquots: [build_remote_aliquot], + labware_barcode: { 'human_barcode' => 'test' } + }.merge(opts) + my_double = double('remote_asset', obj) + + allow(my_double).to receive(:attributes).and_return(obj) + allow(my_double).to receive(:class).and_return(Sequencescape::Tube) + + my_double + end + + def build_remote_aliquot(opts = {}) + double('aliquot', { sample: build_remote_sample, study: build_study }.merge(opts)) + end + + def build_study(opts = {}) + double('study', { name: 'STDY', uuid: SecureRandom.uuid }) + end + + def build_remote_sample(opts = {}) + attrs_for_sample = { + sanger_sample_id: 'TEST-123', + name: 'a sample name', + sample_metadata: double('sample_metadata', { supplier_name: 'a supplier', sample_common_name: 'species' }), + # sanger: double('sanger', { sample_id: 'TEST-123', name: 'a sample name'}), + uuid: SecureRandom.uuid, + # supplier: double('supplier', {sample_name: 'a supplier'}), + updated_at: Time.now.to_s + }.merge(opts) + + sample = double('sample', attrs_for_sample) + allow(sample).to receive(:attributes).and_return(attrs_for_sample) + sample + end + + def stub_client_with_asset(double, asset) + type = (asset.class == Sequencescape::Plate) ? :plate : :tube + allow(double).to receive(:find_by_uuid).with(asset.uuid).and_return(asset) + allow(double).to receive(:get_remote_asset) { nil } + allow(double).to receive(:get_remote_asset).with(asset.barcode).and_return(asset) + allow(double).to receive(:get_remote_asset).with(asset.uuid).and_return(asset) + end end diff --git a/spec/requests/api/v1/assets_spec.rb b/spec/requests/api/v1/assets_spec.rb index 2497c8e6..6f83a4f6 100644 --- a/spec/requests/api/v1/assets_spec.rb +++ b/spec/requests/api/v1/assets_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' RSpec.describe 'Api::V1::Sets', type: :request do - let(:headers) do { "Content-Type" => "application/vnd.api+json", @@ -12,6 +11,7 @@ def key_for_attribute(attr_key) # Because some Traction attributes has been stored with a different predicate in extraction return :sample_common_name if attr_key == :species + return attr_key end @@ -46,9 +46,7 @@ def key_for_attribute(attr_key) end describe 'Assets' do - describe 'GET' do - before do get api_v1_asset_path(asset.uuid), headers: { 'Content-Type': "application/vnd.api+json", @@ -66,12 +64,10 @@ def key_for_attribute(attr_key) it_behaves_like 'a response with the required fields for Traction' end - end describe 'filtering' do context 'when filtering by barcode' do - let!(:sets) do [ create(:asset, barcode: 'B01'), @@ -95,5 +91,4 @@ def key_for_attribute(attr_key) it_behaves_like 'a response with the required fields for Traction' end end - end diff --git a/spec/script/runners/load_metadata_spec.rb b/spec/script/runners/load_metadata_spec.rb index f343792c..8a661ec5 100644 --- a/spec/script/runners/load_metadata_spec.rb +++ b/spec/script/runners/load_metadata_spec.rb @@ -1,11 +1,11 @@ require 'rails_helper' -require Rails.root.to_s+'/script/runners/load_metadata' +require Rails.root.to_s + '/script/runners/load_metadata' require 'parsers/csv_metadata/csv_parser' RSpec.describe 'LoadMetadata' do let(:content) { File.read('test/data/metadata.csv') } - let(:file) { create(:uploaded_file, data: content ) } + let(:file) { create(:uploaded_file, data: content) } let(:file_asset) { create :asset, uploaded_file: file } let(:positions) { TokenUtil.generate_positions(('A'..'H').to_a, ('1'..'12').to_a) } @@ -17,12 +17,14 @@ asset end } - let(:rack) { create(:asset, - barcode: 'DN1001001', - facts: [ - create(:fact, predicate: 'a', object: 'TubeRack'), - wells.map { |w| create(:fact, predicate: 'contains', object_asset_id: w.id) } - ].flatten)} + let(:rack) { + create(:asset, + barcode: 'DN1001001', + facts: [ + create(:fact, predicate: 'a', object: 'TubeRack'), + wells.map { |w| create(:fact, predicate: 'contains', object_asset_id: w.id) } + ].flatten) + } let(:instance) { LoadMetadata.new(asset_group: group) } @@ -30,7 +32,7 @@ let(:group) { create(:asset_group, assets: [rack, file_asset].flatten) } let(:added_triples) { instance.process.to_h[:add_facts] } it 'generates the number of changes for the specified assets in the file' do - expect(added_triples.length).to eq(96*2) + expect(added_triples.length).to eq(96 * 2) end it 'adds the right set of properties' do predicates = added_triples.map { |l| l[1] }.uniq diff --git a/spec/script/runners/transfer_plate_to_plate_spec.rb b/spec/script/runners/transfer_plate_to_plate_spec.rb index 014e46cd..82fbd271 100644 --- a/spec/script/runners/transfer_plate_to_plate_spec.rb +++ b/spec/script/runners/transfer_plate_to_plate_spec.rb @@ -1,24 +1,24 @@ require 'rails_helper' -require Rails.root.to_s+'/script/runners/transfer_plate_to_plate' +require Rails.root.to_s + '/script/runners/transfer_plate_to_plate' RSpec.describe 'TransferPlateToPlate' do let(:sample_tube) { create(:asset) } def create_wells 5.times.each_with_index.map do |i| create(:asset, facts: [ - create(:fact, predicate: 'a', object: 'Well'), - create(:fact, predicate: 'location', object: "A0#{i+1}") - ]) + create(:fact, predicate: 'a', object: 'Well'), + create(:fact, predicate: 'location', object: "A0#{i + 1}") + ]) end end + def create_rack create(:asset, facts: [ create(:fact, predicate: 'a', object: 'TubeRack'), create_wells.map { |w| create(:fact, predicate: 'contains', object_asset_id: w.id, literal: false) } - ].flatten) + ].flatten) end - let(:instance) { TransferPlateToPlate.new(asset_group: group) } @@ -35,7 +35,6 @@ def create_rack end context 'when transferring between two plates' do - before do source_rack.facts << create(:fact, predicate: 'transfer', object_asset_id: destination_rack.id) destination_rack.facts << create(:fact, predicate: 'transferredFrom', object_asset_id: source_rack.id) @@ -45,7 +44,6 @@ def create_rack let(:destination_wells) { destination_rack.facts.with_predicate('contains').map(&:object_asset) } context 'when the destination is an empty rack' do - before do source_wells.each_with_index do |w, i| w.facts << create(:fact, predicate: 'sample_id', object: "Sample #{i}") @@ -56,7 +54,7 @@ def create_rack added_facts = instance.process.to_h[:add_facts] destination_well_uuids = added_facts.select { |triple| triple[1] == 'contains' }.map { |t| t[2] } added_samples = added_facts.select { |triple| triple[1] == 'sample_id' }.map { |triple| [triple[0], triple[2]] } - expect(added_samples).to eq(destination_well_uuids.each_with_index.map { |uuid,i| [uuid, "Sample #{i}"] }) + expect(added_samples).to eq(destination_well_uuids.each_with_index.map { |uuid, i| [uuid, "Sample #{i}"] }) added_sample_tubes = added_facts.select { |triple| triple[1] == 'sample_tube' }.map { |triple| [triple[0], triple[2]] } expect(added_sample_tubes).to eq(destination_well_uuids.map { |uuid| [uuid, sample_tube.uuid] }) end @@ -88,7 +86,7 @@ def create_rack it 'transfers the contents of all wells' do added_facts = instance.process.to_h[:add_facts] added_samples = added_facts.select { |triple| triple[1] == 'sample_id' }.map { |triple| [triple[0], triple[2]] } - expect(added_samples).to eq(destination_wells.each_with_index.map { |w,i| [w.uuid, "Sample #{i}"] }) + expect(added_samples).to eq(destination_wells.each_with_index.map { |w, i| [w.uuid, "Sample #{i}"] }) added_sample_tubes = added_facts.select { |triple| triple[1] == 'sample_tube' }.map { |triple| [triple[0], triple[2]] } expect(added_sample_tubes).to eq(destination_wells.map { |w| [w.uuid, sample_tube.uuid] }) end diff --git a/spec/script/runners/transfer_samples_spec.rb b/spec/script/runners/transfer_samples_spec.rb index 58932239..014a8925 100644 --- a/spec/script/runners/transfer_samples_spec.rb +++ b/spec/script/runners/transfer_samples_spec.rb @@ -1,14 +1,16 @@ require 'rails_helper' -require Rails.root.to_s+'/script/runners/transfer_samples' +require Rails.root.to_s + '/script/runners/transfer_samples' RSpec.describe 'TransferSamples' do let(:sample) { create(:asset, facts: [create(:fact, predicate: 'sample_name', object: 'sample1')]) } let(:sources) { - 5.times.map { create(:asset, facts: [ - create(:fact, predicate: 'a', object: 'Tube'), - create(:fact, predicate: 'study_name', object: 'Study 1'), - create(:fact, predicate: 'sample_tube', object_asset_id: sample.id) - ]) } + 5.times.map { + create(:asset, facts: [ + create(:fact, predicate: 'a', object: 'Tube'), + create(:fact, predicate: 'study_name', object: 'Study 1'), + create(:fact, predicate: 'sample_tube', object_asset_id: sample.id) + ]) + } } let(:destinations) { 5.times.map { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } @@ -50,7 +52,7 @@ context 'when the assets are related by a transfer' do before do - sources.zip(destinations).each do |s,d| + sources.zip(destinations).each do |s, d| s.facts << create(:fact, predicate: 'transfer', object_asset_id: d.id) end end @@ -76,7 +78,7 @@ context 'when only sources are in the group' do let(:group) { create(:asset_group, assets: sources) } before do - sources.zip(destinations).each do |s,d| + sources.zip(destinations).each do |s, d| s.facts << create(:fact, predicate: 'transfer', object_asset_id: d.id) end end @@ -85,11 +87,10 @@ context 'when only destinations are in the group' do let(:group) { create(:asset_group, assets: destinations) } before do - destinations.zip(sources).each do |d,s| + destinations.zip(sources).each do |d, s| d.facts << create(:fact, predicate: 'transferredFrom', object_asset_id: s.id) end end it_behaves_like 'transfers all facts from source to destination' end end - diff --git a/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb b/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb index 33813ce2..e91e2ad4 100644 --- a/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb +++ b/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb @@ -1,21 +1,22 @@ require 'rails_helper' -require Rails.root.to_s+'/script/runners/transfer_tubes_to_tube_rack_by_position' - +require Rails.root.to_s + '/script/runners/transfer_tubes_to_tube_rack_by_position' RSpec.describe 'TransferTubesToTubeRackByPosition' do let(:wells) { 5.times.each_with_index.map do |i| create(:asset, facts: [ - create(:fact, predicate: 'a', object: 'Well'), - create(:fact, predicate: 'location', object: "A0#{i}") - ]) + create(:fact, predicate: 'a', object: 'Well'), + create(:fact, predicate: 'location', object: "A0#{i}") + ]) end } - let(:rack) { create(:asset, facts: [ - create(:fact, predicate: 'a', object: 'TubeRack'), - wells.map { |w| create(:fact, predicate: 'contains', object_asset_id: w.id) } - ].flatten)} + let(:rack) { + create(:asset, facts: [ + create(:fact, predicate: 'a', object: 'TubeRack'), + wells.map { |w| create(:fact, predicate: 'contains', object_asset_id: w.id) } + ].flatten) + } let(:tubes) { 5.times.map { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } } @@ -103,7 +104,7 @@ let(:aliquot) { aliquot_dna } it 'will set up a DNA Stock plate purpose' do added_facts = instance.process.to_h[:add_facts] - purposes = added_facts.select { |triple| triple[1]=='purpose' } + purposes = added_facts.select { |triple| triple[1] == 'purpose' } expect(purposes.size).to eq(1) expect(purposes.first[0]).to eq(rack.uuid) expect(purposes.first[2]).to eq("DNA Stock Plate") @@ -113,7 +114,7 @@ let(:aliquot) { aliquot_rna } it 'will set up an RNA Stock plate purpose' do added_facts = instance.process.to_h[:add_facts] - purposes = added_facts.select { |triple| triple[1]=='purpose' } + purposes = added_facts.select { |triple| triple[1] == 'purpose' } expect(purposes.size).to eq(1) expect(purposes.first[0]).to eq(rack.uuid) expect(purposes.first[2]).to eq("RNA Stock Plate") @@ -144,7 +145,6 @@ end end - context 'when some of the tubes were already in the rack' do before do wells.last.facts << create(:fact, predicate: 'transferredFrom', object_asset_id: tubes.last.id) @@ -159,8 +159,8 @@ wells.first.facts << create(:fact, predicate: 'transferredFrom', object_asset_id: tubes.first.id) end it 'starts transferring after the last occupied well of the rack' do - rest_tubes = tubes.slice(1,tubes.length) - rest_wells = wells.slice(1,wells.length) + rest_tubes = tubes.slice(1, tubes.length) + rest_wells = wells.slice(1, wells.length) group.update_attributes(assets: [rest_tubes, rack].flatten) added_facts = instance.process.to_h[:add_facts] @@ -168,7 +168,6 @@ transfers = added_facts.select { |triple| triple[1] == 'transfer' }.map { |triple| [triple[0], triple[2]] } expect(rest_tubes.map(&:uuid).zip(rest_wells.map(&:uuid))).to eq(transfers) end - end context 'when there are no more space left in the rack' do let(:tubes) { diff --git a/spec/shared_examples/background_step.rb b/spec/shared_examples/background_step.rb index 9bd82239..df9e127b 100644 --- a/spec/shared_examples/background_step.rb +++ b/spec/shared_examples/background_step.rb @@ -1,7 +1,6 @@ require 'rails_helper' require 'spec_helper' shared_examples_for 'background task' do - it_behaves_like "queueable job" context '#Background task' do @@ -77,7 +76,6 @@ expect(step.output).to include('boom!') end end - end end end diff --git a/test/factories/barcode_creatable.rb b/test/factories/barcode_creatable.rb index d48253c5..552c042a 100644 --- a/test/factories/barcode_creatable.rb +++ b/test/factories/barcode_creatable.rb @@ -4,6 +4,6 @@ end sequence :barcode_creatable do |n| - SBCF::SangerBarcode.new(prefix:'FF',number: n).human_barcode + SBCF::SangerBarcode.new(prefix: 'FF', number: n).human_barcode end end diff --git a/test/factories/instruments.rb b/test/factories/instruments.rb index a00329eb..2ea3e13a 100644 --- a/test/factories/instruments.rb +++ b/test/factories/instruments.rb @@ -1,5 +1,5 @@ FactoryBot.define do factory :instrument do - barcode { FactoryBot.generate :barcode } + barcode { FactoryBot.generate :barcode } end end diff --git a/test/factories/kits.rb b/test/factories/kits.rb index a272fe66..a7857f81 100644 --- a/test/factories/kits.rb +++ b/test/factories/kits.rb @@ -1,6 +1,5 @@ FactoryBot.define do factory :kit do - barcode { FactoryBot.generate :barcode } + barcode { FactoryBot.generate :barcode } end - end diff --git a/test/factories/steps.rb b/test/factories/steps.rb index 4222c099..9353dd54 100644 --- a/test/factories/steps.rb +++ b/test/factories/steps.rb @@ -4,6 +4,4 @@ factory :background_task, :class => 'Steps::BackgroundTasks::BackgroundTask' do step_type { create :step_type } end - - end diff --git a/test/factories/users.rb b/test/factories/users.rb index cc935769..80422446 100644 --- a/test/factories/users.rb +++ b/test/factories/users.rb @@ -1,10 +1,9 @@ FactoryBot.define do - factory :user_with_barcode, :class => User do + factory :user_with_barcode, :class => User do barcode { FactoryBot.generate :barcode } end - factory :user, :class => User do + factory :user, :class => User do barcode { FactoryBot.generate :barcode } end - end diff --git a/test/test_helper.rb b/test/test_helper.rb index 35f02270..f844c53a 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -5,7 +5,7 @@ class ActiveSupport::TestCase # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. - #fixtures :all + # fixtures :all include FactoryBot::Syntax::Methods # Add more helper methods to be used by all tests here... From ac3778c65c79ea82304b321f910778edea23dd05 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 18 Mar 2022 16:48:28 +0000 Subject: [PATCH 111/303] Remove unneeded array creation --- app/channels/activity_channel.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/channels/activity_channel.rb b/app/channels/activity_channel.rb index dca9bb58..a892b215 100644 --- a/app/channels/activity_channel.rb +++ b/app/channels/activity_channel.rb @@ -32,8 +32,6 @@ def process_asset_group(strong_params) assets = strong_params[:assets] if asset_group && assets begin - received_list = [] - received_list = assets.filter_map do |uuid_or_barcode| Asset.find_or_import_asset_with_barcode(uuid_or_barcode) end From eb36b65ec7ea3bb53c577443b5b5a74ee07697e6 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 18 Mar 2022 16:49:59 +0000 Subject: [PATCH 112/303] Remove commented out code --- app/controllers/assets_controller.rb | 1 - app/models/operation.rb | 8 -------- 2 files changed, 9 deletions(-) diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index 96eb6220..e232d769 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -50,7 +50,6 @@ def show_by_internal_id # GET /assets/1 # GET /assets/1.json def show - # @asset = Asset.find_by_uuid!(params[:uuid]) respond_to do |format| format.html { render :show } format.n3 { render :show } diff --git a/app/models/operation.rb b/app/models/operation.rb index d4a89bdc..ef0e1b19 100644 --- a/app/models/operation.rb +++ b/app/models/operation.rb @@ -7,11 +7,6 @@ class Operation < ApplicationRecord scope :for_presenting, ->() { includes(:asset, :action) } - # def action_type - # return action.action_type if action - # return attributes["action_type"] - # end - def object_value object || object_asset end @@ -41,9 +36,6 @@ def generate_changes_for(option_name, updates = nil) elsif (type == :remove_facts) updates.remove_where(self.asset, self.predicate, object_value) elsif (type == :create_assets) - # asset = Asset.create(uuid: object) - # update_attributes(asset: asset) - # updates.create_assets([asset.uuid]) updates.create_assets([object]) elsif (type == :delete_assets) updates.delete_assets([object]) From 5f5776802968609e76ee45850bfd743e6bfcfbb3 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 18 Mar 2022 16:55:28 +0000 Subject: [PATCH 113/303] Used instance doubles Instance doubles verify that the method exists on the actual object, improving robustness of specs. --- .../barcode_creatable_parser_spec.rb | 16 ++++---- .../parsers/csv_layout/barcode_parser_spec.rb | 41 ++++++++++--------- .../parsers/csv_layout/line_parser_spec.rb | 19 ++++----- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb b/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb index eb3b2062..97d58bef 100644 --- a/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb @@ -9,15 +9,13 @@ Asset.find_by(barcode: barcode) end end - let(:main_parser) { - main = double('parser') - allow(main).to receive(:add_error) - allow(main).to receive(:parsed_changes).and_return(FactChanges.new) - allow(main).to receive(:components).and_return({ - barcode_validator: ValidatorSuccess - }) - main - } + + let(:main_parser) do + instance_double(Parsers::CsvLayout::CsvParser, + parsed_changes: FactChanges.new, + components: { barcode_validator: ValidatorSuccess }) + end + class ValidatorSuccess < ActiveModel::Validator def validate(record) true diff --git a/spec/lib/parsers/csv_layout/barcode_parser_spec.rb b/spec/lib/parsers/csv_layout/barcode_parser_spec.rb index 606dc38c..8491a7d5 100644 --- a/spec/lib/parsers/csv_layout/barcode_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/barcode_parser_spec.rb @@ -9,20 +9,29 @@ Asset.find_by(barcode: barcode) end end - let(:main_parser) { - main = double('parser') - allow(main).to receive(:add_error) - allow(main).to receive(:components).and_return({ - barcode_validator: ValidatorSuccess - }) - main - } - class ValidatorSuccess < ActiveModel::Validator - def validate(record) - true + + let(:success_validator) do + Class.new(ActiveModel::Validator) do + def validate(record) + true + end end end + let(:reject_validator) do + Class.new(ActiveModel::Validator) do + def validate(record) + record.errors.add(:barcode, 'There was an error') + false + end + end + end + + let(:main_parser) do + instance_double(Parsers::CsvLayout::CsvParser, + components: { barcode_validator: success_validator }) + end + let(:barcode) { '1234' } let(:location) { 'A10' } let(:input) { [location, barcode] } @@ -62,17 +71,11 @@ def validate(record) create :asset, barcode: barcode end - class ValidatorReject < ActiveModel::Validator - def validate(record) - record.errors.add(:barcode, 'There was an error') - false - end - end let(:parser) { Parsers::CsvLayout::BarcodeParser.new(input, main_parser) } context 'when the validator accepts the input' do before do allow(main_parser).to receive(:components).and_return({ - barcode_validator: ValidatorSuccess + barcode_validator: success_validator }) end it 'validates the instance' do @@ -82,7 +85,7 @@ def validate(record) context 'when the validator rejects the input' do before do allow(main_parser).to receive(:components).and_return({ - barcode_validator: ValidatorReject + barcode_validator: reject_validator }) end diff --git a/spec/lib/parsers/csv_layout/line_parser_spec.rb b/spec/lib/parsers/csv_layout/line_parser_spec.rb index d259a5fd..06eb2105 100644 --- a/spec/lib/parsers/csv_layout/line_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/line_parser_spec.rb @@ -6,16 +6,15 @@ require 'parsers/csv_layout/validators/location_validator' RSpec.describe Parsers::CsvLayout::LineParser do - let(:main_parser) { - main = double('parser') - allow(main).to receive(:components).and_return({ - location_validator: Parsers::CsvLayout::Validators::LocationValidator, - barcode_validator: Parsers::CsvLayout::Validators::AnyBarcodeValidator, - barcode_parser: Parsers::CsvLayout::BarcodeParser, - location_parser: Parsers::CsvLayout::LocationParser - }) - main - } + let(:main_parser) do + instance_double(Parsers::CsvLayout::CsvParser, + components: { + location_validator: Parsers::CsvLayout::Validators::LocationValidator, + barcode_validator: Parsers::CsvLayout::Validators::AnyBarcodeValidator, + barcode_parser: Parsers::CsvLayout::BarcodeParser, + location_parser: Parsers::CsvLayout::LocationParser + }) + end let(:input_reader) { reader = double('reader') allow(reader).to receive(:lines).and_return(@input) From 62bc3826e2b8dcc804f184f36e01d3a5dcf56621 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 18 Mar 2022 16:56:53 +0000 Subject: [PATCH 114/303] Simplify duplicated method uniq! returns the duplicated errors, and while it mutates the original array, here we created it moments ago with the pluck. --- lib/parsers/csv_layout/csv_parser.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/parsers/csv_layout/csv_parser.rb b/lib/parsers/csv_layout/csv_parser.rb index 22a6badd..cb76ac77 100644 --- a/lib/parsers/csv_layout/csv_parser.rb +++ b/lib/parsers/csv_layout/csv_parser.rb @@ -89,10 +89,7 @@ def validate_location_duplication end def duplicated(sym) - all_elems = layout.map { |obj| obj[sym] } - all_elems.select do |element| - (!element.nil?) && (all_elems.count(element) > 1) - end.uniq.compact + layout.pluck(sym).compact.uniq! || [] end end end From f60e9549cdf00d5b9b150e4447e04c5b4a2cd7ec Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 18 Mar 2022 16:58:20 +0000 Subject: [PATCH 115/303] USe describe not context for identifying methods --- spec/lib/parsers/csv_layout/line_parser_spec.rb | 2 +- spec/models/assets/import_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/lib/parsers/csv_layout/line_parser_spec.rb b/spec/lib/parsers/csv_layout/line_parser_spec.rb index 06eb2105..cb6498b5 100644 --- a/spec/lib/parsers/csv_layout/line_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/line_parser_spec.rb @@ -30,7 +30,7 @@ end end - context '#initialize' do + describe '#initialize' do it 'can be initialized' do @input = [["A1", @asset1.barcode]] expect { parser }.not_to raise_error diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 2fb20073..28a6d9e6 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -253,7 +253,7 @@ end end - context '#find_or_import_asset_with_barcode' do + describe '#find_or_import_asset_with_barcode' do context 'when importing an asset that does not exist' do setup do allow(SequencescapeClient).to receive(:get_remote_asset).and_return(nil) From 6555304b65ed89da95862df99e7487d7897bbef1 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 08:49:26 +0000 Subject: [PATCH 116/303] Add labware to V2 Client --- lib/sequencescape_client_v2.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/sequencescape_client_v2.rb b/lib/sequencescape_client_v2.rb index a0876b18..090d6d53 100644 --- a/lib/sequencescape_client_v2.rb +++ b/lib/sequencescape_client_v2.rb @@ -9,6 +9,13 @@ class SequencescapeClientV2::Model < JsonApiClient::Resource class SequencescapeClientV2::Asset < SequencescapeClientV2::Model end + class SequencescapeClientV2::Labware < SequencescapeClientV2::Model + # The plural of labware is labware + def self.table_name + 'labware' + end + end + class SequencescapeClientV2::Plate < SequencescapeClientV2::Model has_many :wells has_many :studies, through: :well From 712ca9054c0af6fd54ff98f74b45b2cfdef922f6 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 08:53:11 +0000 Subject: [PATCH 117/303] DRY out SCV parsing - Move shared behaviour into rack layout - There is further scope to remove asset_group as a method argument, as it should be an instance variable, however I need to make sure this is used consistently. --- lib/actions/racking.rb | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/actions/racking.rb b/lib/actions/racking.rb index 1b532f7c..33767a2f 100644 --- a/lib/actions/racking.rb +++ b/lib/actions/racking.rb @@ -34,25 +34,17 @@ module Racking } # Actions - def rack_layout(asset_group) + def rack_layout(asset_group, options = {}) content = selected_file(asset_group).data - csv_parsing(asset_group, Parsers::CsvLayout::CsvParser.new(content)) + csv_parsing(asset_group, Parsers::CsvLayout::CsvParser.new(content, options)) end def rack_layout_creating_tubes(asset_group) - content = selected_file(asset_group).data - parser = Parsers::CsvLayout::CsvParser.new(content, { - barcode_parser: Parsers::CsvLayout::BarcodeCreatableParser - }) - csv_parsing(asset_group, parser) + rack_layout(asset_group, barcode_parser: Parsers::CsvLayout::BarcodeCreatableParser) end def rack_layout_any_barcode(asset_group) - content = selected_file(asset_group).data - parser = Parsers::CsvLayout::CsvParser.new(content, { - barcode_validator: Parsers::CsvLayout::Validators::AnyBarcodeValidator - }) - csv_parsing(asset_group, parser) + rack_layout(asset_group, barcode_validator: Parsers::CsvLayout::Validators::AnyBarcodeValidator) end # Support methods and classes From 068a3e0694120580f059564663b36cb16901f809 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 08:57:20 +0000 Subject: [PATCH 118/303] Refine spec files - We don't need to set up a double for SequncescapeClient - Use RSpec change expectations --- spec/models/assets/import_spec.rb | 6 +----- spec/remote_assets_helper.rb | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 28a6d9e6..be8144f2 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -264,9 +264,7 @@ end it 'should not create a new asset' do - expect(Asset.all.count).to eq(0) - Asset.find_or_import_asset_with_barcode('NOT_FOUND') - expect(Asset.all.count).to eq(0) + expect { Asset.find_or_import_asset_with_barcode('NOT_FOUND') }.not_to change(Asset, :count) end end @@ -286,8 +284,6 @@ end context 'when importing a remote asset' do - let(:SequencescapeClient) { double('sequencescape_client') } - context 'when the asset is a tube' do setup do @remote_asset = build_remote_tube(barcode: generate(:barcode)) diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index 6a1a94c7..1e90142e 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -85,7 +85,6 @@ def build_remote_sample(opts = {}) end def stub_client_with_asset(double, asset) - type = (asset.class == Sequencescape::Plate) ? :plate : :tube allow(double).to receive(:find_by_uuid).with(asset.uuid).and_return(asset) allow(double).to receive(:get_remote_asset) { nil } allow(double).to receive(:get_remote_asset).with(asset.barcode).and_return(asset) From 61c6e65dca5d35c1886c7cee9d91baf1f5efd5ef Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 08:58:27 +0000 Subject: [PATCH 119/303] Libe parser enumerates barcodes --- lib/parsers/csv_layout/line_parser.rb | 6 ++++++ spec/lib/parsers/csv_layout/line_parser_spec.rb | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/parsers/csv_layout/line_parser.rb b/lib/parsers/csv_layout/line_parser.rb index 8305effd..179368f4 100644 --- a/lib/parsers/csv_layout/line_parser.rb +++ b/lib/parsers/csv_layout/line_parser.rb @@ -40,6 +40,12 @@ def parsed_content @parsed_content ||= parse end + def barcodes + parsed_content.filter_map do |line| + line[:barcode_parser].barcode + end.uniq + end + protected def validate_parsed_content diff --git a/spec/lib/parsers/csv_layout/line_parser_spec.rb b/spec/lib/parsers/csv_layout/line_parser_spec.rb index cb6498b5..446d088c 100644 --- a/spec/lib/parsers/csv_layout/line_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/line_parser_spec.rb @@ -37,7 +37,14 @@ end end - context '#parsed_data' do + describe '#barcodes' do + it 'returns a list of barcodes' do + @input = [["A1", "F1234"], ["A2", "F5678"]] + expect(parser.barcodes).to eq ['F1234', 'F5678'] + end + end + + describe '#parsed_data' do it 'returns the number of lines at input' do @input = [["A1", "F1234"], ["A2", "F5678"]] expect(parser).to be_valid From f2d076d1298c31f67a0e1372e339ea96533dab6c Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 08:59:45 +0000 Subject: [PATCH 120/303] Remove commented out code --- lib/fact_changes.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index 69d7dc6c..08a2fe1f 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -328,25 +328,21 @@ def set_errors(errors) def create_assets(assets) assets_to_create << validate_instances(build_assets(assets)) - # assets_to_create.concat(validate_instances(build_assets(assets))) self end def create_asset_groups(asset_groups) asset_groups_to_create << validate_instances(build_asset_groups(asset_groups)) - # asset_groups_to_create.concat(validate_instances(build_asset_groups(asset_groups))).uniq! self end def delete_asset_groups(asset_groups) asset_groups_to_destroy << validate_instances(find_asset_groups(asset_groups)) - # asset_groups_to_destroy.concat(validate_instances(find_asset_groups(asset_groups))).uniq! self end def delete_assets(assets) assets_to_destroy << validate_instances(find_assets(assets)) - # assets_to_destroy.concat(validate_instances(find_assets(assets))).uniq! self end @@ -361,8 +357,6 @@ def add_assets(list) end assets = validate_instances(find_assets(asset_ids)) assets_to_add << assets.map { |asset| { asset_group: asset_group, asset: asset } } - # add_to_list_keep_unique(assets.map{|asset| { asset_group: asset_group, asset: asset} }, :assets_to_add, :assets_to_remove) - # assets_to_add.concat(assets.map{|asset| { asset_group: asset_group, asset: asset} }) end self end @@ -378,8 +372,6 @@ def remove_assets(list) end assets = validate_instances(find_assets(asset_ids)) assets_to_remove << assets.map { |asset| { asset_group: asset_group, asset: asset } } - # add_to_list_keep_unique(assets.map{|asset| { asset_group: asset_group, asset: asset} }, :assets_to_remove, :assets_to_add) - # assets_to_remove.concat(assets.map{|asset| { asset_group: asset_group, asset: asset} }) end self end From b72119248b690e235f87d97245f3015279a52d8b Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 09:04:07 +0000 Subject: [PATCH 121/303] CSV parse handles asset lookup By moving asset lookup to the CSV parse we allow us to move to using a cache of all assets looked up in bulk --- .../csv_layout/barcode_creatable_parser.rb | 21 ++++++++++++------- lib/parsers/csv_layout/barcode_parser.rb | 2 +- lib/parsers/csv_layout/csv_parser.rb | 4 ++++ .../barcode_creatable_parser_spec.rb | 2 +- .../parsers/csv_layout/barcode_parser_spec.rb | 2 +- .../parsers/csv_layout/line_parser_spec.rb | 2 +- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/parsers/csv_layout/barcode_creatable_parser.rb b/lib/parsers/csv_layout/barcode_creatable_parser.rb index d9db3f43..57f6eca9 100644 --- a/lib/parsers/csv_layout/barcode_creatable_parser.rb +++ b/lib/parsers/csv_layout/barcode_creatable_parser.rb @@ -8,14 +8,19 @@ def updater end def asset - @instance ||= Asset.find_or_import_asset_with_barcode(barcode) - unless @instance - @instance = Asset.new(barcode: barcode) - @instance.generate_uuid! - updater.create_assets([@instance]) - updater.add(@instance, 'barcode', barcode) - updater.add(@instance, 'a', 'Tube') - end + @instance ||= @parser.find_or_import_asset_with_barcode(barcode) + + return @instance if @instance + + # In reality I don't think we ever get here, as Asset.find_or_import_asset_with_barcode + # will actually create assets for valid fluidx barcodes, and this is only used + # in that context. However, this is definitely the more sensible way of handling this. + + @instance = Asset.new(barcode: barcode) + @instance.generate_uuid! + updater.create_assets([@instance]) + updater.add(@instance, 'barcode', barcode) + updater.add(@instance, 'a', 'Tube') @instance end end diff --git a/lib/parsers/csv_layout/barcode_parser.rb b/lib/parsers/csv_layout/barcode_parser.rb index 2263ec00..76f6eef4 100644 --- a/lib/parsers/csv_layout/barcode_parser.rb +++ b/lib/parsers/csv_layout/barcode_parser.rb @@ -29,7 +29,7 @@ def no_read_barcode? end def asset - Asset.find_or_import_asset_with_barcode(barcode) + @parser.find_or_import_asset_with_barcode(barcode) end def barcode? diff --git a/lib/parsers/csv_layout/csv_parser.rb b/lib/parsers/csv_layout/csv_parser.rb index cb76ac77..7116b93f 100644 --- a/lib/parsers/csv_layout/csv_parser.rb +++ b/lib/parsers/csv_layout/csv_parser.rb @@ -57,6 +57,10 @@ def error_list self_error_list.concat(line_parser.error_list) end + def find_or_import_asset_with_barcode(barcode) + Asset.find_or_import_asset_with_barcode(barcode) + end + protected def validate_parsed_data diff --git a/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb b/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb index 97d58bef..5b1ff271 100644 --- a/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb @@ -5,7 +5,7 @@ RSpec.describe Parsers::CsvLayout::BarcodeCreatableParser do before do - allow(Asset).to receive(:find_or_import_asset_with_barcode) do |barcode| + allow(main_parser).to receive(:find_or_import_asset_with_barcode) do |barcode| Asset.find_by(barcode: barcode) end end diff --git a/spec/lib/parsers/csv_layout/barcode_parser_spec.rb b/spec/lib/parsers/csv_layout/barcode_parser_spec.rb index 8491a7d5..bcc9522f 100644 --- a/spec/lib/parsers/csv_layout/barcode_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/barcode_parser_spec.rb @@ -5,7 +5,7 @@ RSpec.describe Parsers::CsvLayout::BarcodeParser do before do - allow(Asset).to receive(:find_or_import_asset_with_barcode) do |barcode| + allow(main_parser).to receive(:find_or_import_asset_with_barcode) do |barcode| Asset.find_by(barcode: barcode) end end diff --git a/spec/lib/parsers/csv_layout/line_parser_spec.rb b/spec/lib/parsers/csv_layout/line_parser_spec.rb index 446d088c..ef4ae041 100644 --- a/spec/lib/parsers/csv_layout/line_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/line_parser_spec.rb @@ -25,7 +25,7 @@ before do @asset1 = create :asset, barcode: 'F1234' @asset2 = create :asset, barcode: 'F5678' - allow(Asset).to receive(:find_or_import_asset_with_barcode) do |barcode| + allow(main_parser).to receive(:find_or_import_asset_with_barcode) do |barcode| Asset.find_by(barcode: barcode) end end From 6d3acb1bd40c4ba56fd6458a866291bff7b96b02 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 09:06:46 +0000 Subject: [PATCH 122/303] Single pass on parse data with filter_map --- lib/parsers/csv_layout/line_parser.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/parsers/csv_layout/line_parser.rb b/lib/parsers/csv_layout/line_parser.rb index 179368f4..a6d46aca 100644 --- a/lib/parsers/csv_layout/line_parser.rb +++ b/lib/parsers/csv_layout/line_parser.rb @@ -12,7 +12,9 @@ def initialize(input_reader, parser) def parsed_data if valid? - parsed_content.select { |e| !e[:barcode_parser].no_read_barcode? }.map do |entry| + parsed_content.filter_map do |entry| + next if entry[:barcode_parser].no_read_barcode? + { location: entry[:location_parser].location, asset: entry[:barcode_parser].asset From 73c96d702523c5d843f9a817cda4d702e66fd9c1 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 09:11:16 +0000 Subject: [PATCH 123/303] Remove unused optional parameter THe opts param was not used in the method itself, and not included in any calls to this method (unless we have some fancy metaprograming going on I missed) --- lib/sequencescape_client.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 4da597f3..67340623 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -62,7 +62,7 @@ def self.get_remote_asset(barcode) find_by(barcode: barcode) end - def self.find_by_uuid(uuid, opts = nil) + def self.find_by_uuid(uuid) find_by(uuid: uuid) end From 3cde0310fe211db26d6a5f081ea41bc47b9d8bd4 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 09:12:25 +0000 Subject: [PATCH 124/303] Remove redundant validation --- lib/parsers/csv_layout/barcode_parser.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/parsers/csv_layout/barcode_parser.rb b/lib/parsers/csv_layout/barcode_parser.rb index 76f6eef4..e7b4266c 100644 --- a/lib/parsers/csv_layout/barcode_parser.rb +++ b/lib/parsers/csv_layout/barcode_parser.rb @@ -9,7 +9,6 @@ class BarcodeParser include ActiveModel::Validations validates :asset, presence: { message: "Cannot find the barcode" }, if: :barcode? - validates :barcode, presence: true validate :validations def validations From 3fed45e553fc336cfbd8e0c9207e9c4019059f40 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 09:14:08 +0000 Subject: [PATCH 125/303] Freeze strings and remove unecessary imports --- lib/parsers/csv_layout/barcode_parser.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/parsers/csv_layout/barcode_parser.rb b/lib/parsers/csv_layout/barcode_parser.rb index e7b4266c..d3793a74 100644 --- a/lib/parsers/csv_layout/barcode_parser.rb +++ b/lib/parsers/csv_layout/barcode_parser.rb @@ -1,5 +1,4 @@ -require 'parsers/csv_layout/validators/any_barcode_validator' -require 'parsers/csv_layout/validators/fluidx_barcode_validator' +# frozen_string_literal: true module Parsers module CsvLayout From 4e8d6f97304aaee107747cb3e08947418639d449 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 11:34:34 +0000 Subject: [PATCH 126/303] Avoid passing round instance variable Asset group is already an instance variable so lets avoid passing it around. --- .../rack_layout_creating_tubes.rb | 2 +- lib/actions/racking.rb | 18 ++++---- script/runners/rack_layout.rb | 2 +- script/runners/rack_layout_any_barcode.rb | 2 +- script/runners/rack_layout_creating_tubes.rb | 43 ------------------- spec/lib/actions/racking_spec.rb | 23 ++++++++-- 6 files changed, 31 insertions(+), 59 deletions(-) delete mode 100644 script/runners/rack_layout_creating_tubes.rb diff --git a/app/step_planners/step_planner/rack_layout_creating_tubes.rb b/app/step_planners/step_planner/rack_layout_creating_tubes.rb index 7740c297..de232ba2 100644 --- a/app/step_planners/step_planner/rack_layout_creating_tubes.rb +++ b/app/step_planners/step_planner/rack_layout_creating_tubes.rb @@ -20,7 +20,7 @@ def assets_compatible_with_step_type def process FactChanges.new.tap do |updates| if assets_compatible_with_step_type.any? - updates.merge(rack_layout_creating_tubes(@asset_group)) + updates.merge(rack_layout_creating_tubes) updates.remove_assets([[asset_group.uploaded_files.first.asset.uuid]]) end end diff --git a/lib/actions/racking.rb b/lib/actions/racking.rb index 33767a2f..160fd8b1 100644 --- a/lib/actions/racking.rb +++ b/lib/actions/racking.rb @@ -34,17 +34,17 @@ module Racking } # Actions - def rack_layout(asset_group, options = {}) - content = selected_file(asset_group).data - csv_parsing(asset_group, Parsers::CsvLayout::CsvParser.new(content, options)) + def rack_layout(options = {}) + content = selected_file.data + csv_parsing(Parsers::CsvLayout::CsvParser.new(content, options)) end - def rack_layout_creating_tubes(asset_group) - rack_layout(asset_group, barcode_parser: Parsers::CsvLayout::BarcodeCreatableParser) + def rack_layout_creating_tubes + rack_layout(barcode_parser: Parsers::CsvLayout::BarcodeCreatableParser) end - def rack_layout_any_barcode(asset_group) - rack_layout(asset_group, barcode_validator: Parsers::CsvLayout::Validators::AnyBarcodeValidator) + def rack_layout_any_barcode + rack_layout(barcode_validator: Parsers::CsvLayout::Validators::AnyBarcodeValidator) end # Support methods and classes @@ -269,11 +269,11 @@ def check_collisions(rack, list_layout, error_messages, error_locations) end end - def selected_file(asset_group) + def selected_file asset_group.uploaded_files.first end - def csv_parsing(asset_group, parser) + def csv_parsing(parser) error_messages = [] error_locations = [] diff --git a/script/runners/rack_layout.rb b/script/runners/rack_layout.rb index 9a201467..70caeeaa 100644 --- a/script/runners/rack_layout.rb +++ b/script/runners/rack_layout.rb @@ -16,7 +16,7 @@ def assets_compatible_with_step_type def process FactChanges.new.tap do |updates| if assets_compatible_with_step_type.count > 0 - updates.merge(rack_layout(@asset_group)) + updates.merge(rack_layout) end end end diff --git a/script/runners/rack_layout_any_barcode.rb b/script/runners/rack_layout_any_barcode.rb index ecaf3ca9..f0acacce 100644 --- a/script/runners/rack_layout_any_barcode.rb +++ b/script/runners/rack_layout_any_barcode.rb @@ -16,7 +16,7 @@ def assets_compatible_with_step_type def process FactChanges.new.tap do |updates| if assets_compatible_with_step_type.count > 0 - updates.merge(rack_layout_any_barcode(@asset_group)) + updates.merge(rack_layout_any_barcode) updates.remove_assets([[asset_group.uploaded_files.first.asset.uuid]]) end end diff --git a/script/runners/rack_layout_creating_tubes.rb b/script/runners/rack_layout_creating_tubes.rb deleted file mode 100644 index c048b4d6..00000000 --- a/script/runners/rack_layout_creating_tubes.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -require 'actions/racking' - -class RackLayoutCreatingTubes - attr_reader :asset_group - - include Actions::Racking - - def initialize(params) - @asset_group = params[:asset_group] - end - - def assets_compatible_with_step_type - asset_group.uploaded_files - end - - def process - FactChanges.new.tap do |updates| - if assets_compatible_with_step_type.any? - updates.merge(rack_layout_creating_tubes(@asset_group)) - updates.remove_assets([[asset_group.uploaded_files.first.asset.uuid]]) - end - end - end -end - -return unless ARGV.any? { |s| s.match('.json') } - -args = ARGV[0] -asset_group_id = args.match(/(\d*)\.json/)[1] -asset_group = AssetGroup.find(asset_group_id) - -begin - updates = RackLayoutCreatingTubes.new(asset_group: asset_group).process - json = updates.to_json - JSON.parse(json) - puts json -rescue InvalidDataParams => e - puts({ set_errors: e.errors }.to_json) -rescue StandardError => e - puts({ set_errors: ['Unknown error while parsing file' + e.to_json + e.backtrace.join] }.to_json) -end diff --git a/spec/lib/actions/racking_spec.rb b/spec/lib/actions/racking_spec.rb index 8797c6c7..45b80fc6 100644 --- a/spec/lib/actions/racking_spec.rb +++ b/spec/lib/actions/racking_spec.rb @@ -18,7 +18,18 @@ let(:condition) { create(:condition, predicate: fact.predicate, object: fact.object) } let(:condition_group) { create(:condition_group, conditions: [condition]) } + let(:racking_class) do + Class.new do + include Actions::Racking + attr_reader :asset_group + def initialize(asset_group) + @asset_group = asset_group + end + end + end + + # @todo Use racking_class exclusively include Actions::Racking setup do @@ -31,7 +42,7 @@ describe "when linking it with an asset" do it 'adds the facts to the asset' do expect(asset.facts.count).to eq(1) - updates = send(method, asset_group) + updates = send(method) updates.apply(step) asset.facts.reload @@ -46,8 +57,10 @@ describe 'with links with previous parents' do let(:actual_parent) { create(:asset, uploaded_file: file, facts: [fact]) } + it 'removes links with the previous parents' do - send(method, asset_group).apply(step) + asset_group + send(method).apply(step) asset.facts.reload assets = asset.facts.with_predicate('contains').map(&:object_asset) expect(assets.count).to eq(96) @@ -58,12 +71,14 @@ end asset_group = AssetGroup.create(assets: [actual_parent]) + another_step = Step.new( activity: activity, asset_group: asset_group, step_type: step_type, state: Step::STATE_RUNNING ) - send(method, asset_group).apply(another_step) + + racking_class.new(asset_group).send(method).apply(another_step) assets = asset.reload.facts.with_predicate('contains').map(&:object_asset) expect(assets.count).to eq(0) @@ -96,7 +111,7 @@ def add_empty_slots(content, num_empty, start_pos = 0) it 'adds the new facts to the asset and removes the old ones' do expect(asset.facts.count).to eq(1) - send(method, asset_group).apply(step) + send(method).apply(step) asset.facts.reload assets = asset.facts.with_predicate('contains').map(&:object_asset) From 59cbb9396f772f77e4e9e42254c68b63829d4dff Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 14:44:32 +0000 Subject: [PATCH 127/303] Add simplecov for test coverage --- Gemfile | 1 + Gemfile.lock | 8 ++++++++ spec/rails_helper.rb | 2 +- spec/spec_helper.rb | 13 ++++++++----- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index f55424d5..58b16db5 100644 --- a/Gemfile +++ b/Gemfile @@ -72,6 +72,7 @@ group :test do gem 'factory_bot_rails' gem 'rspec-rails' gem 'shoulda-matchers' + gem 'simplecov', require: false gem 'rails-controller-testing' gem 'database_cleaner' gem 'json-schema' diff --git a/Gemfile.lock b/Gemfile.lock index 39916609..12d1efe9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -108,6 +108,7 @@ GEM activerecord (>= 3.0, < 8.0) delayed_job (>= 3.0, < 5) diff-lcs (1.5.0) + docile (1.4.0) domain_name (0.5.20180417) unf (>= 0.0.5, < 1.0.0) dropzonejs-rails (0.8.4) @@ -344,6 +345,12 @@ GEM set (1.0.2) shoulda-matchers (5.1.0) activesupport (>= 5.2.0) + simplecov (0.21.2) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.4) sorted_set (1.0.3) rbtree set (~> 1.0) @@ -458,6 +465,7 @@ DEPENDENCIES sdoc sequencescape-client-api shoulda-matchers + simplecov spring sprockets-rails turbolinks diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 2dde1434..b44a5cf3 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,9 +1,9 @@ # This file is copied to spec/ when you run 'rails generate rspec:install' ENV['RAILS_ENV'] ||= 'test' +require 'spec_helper' require File.expand_path('../../config/environment', __FILE__) # Prevent database truncation if the environment is production abort("The Rails environment is running in production mode!") if Rails.env.production? -require 'spec_helper' require 'rspec/rails' # Add additional requires below this line. Rails is not loaded until this point! diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 37324f72..ce600bce 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,6 @@ +require 'simplecov' +SimpleCov.start + # This file was generated by the `rails generate rspec:install` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # The generated `.rspec` file contains `--require spec_helper` which will cause @@ -54,6 +57,11 @@ Warren.handler.disable! end + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + # The settings below are suggested to provide a good initial experience # with RSpec, but feel free to customize to your heart's content. =begin @@ -86,11 +94,6 @@ config.default_formatter = 'doc' end - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing # the seed, which is printed after each run. From da3464e5f09ff5ce928b65fc62e512193b025f94 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 22 Mar 2022 14:48:22 +0000 Subject: [PATCH 128/303] Remove unused code Trying to clear up this file a little bit before working with it. --- app/models/assets/import.rb | 98 ++++++++++--------------------------- 1 file changed, 25 insertions(+), 73 deletions(-) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 8a2008dd..2e08c0d1 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -80,47 +80,10 @@ def assets_to_refresh end].flatten end - def get_import_step - @import_step - end - - def _process_refresh(remote_asset, fact_changes = nil) - fact_changes ||= FactChanges.new - asset_group = AssetGroup.new - @import_step.update_attributes(asset_group: asset_group) - - begin - fact_changes.tap do |updates| - asset_group.update_attributes(assets: assets_to_refresh) - - # Removes previous state - assets_to_refresh.each do |asset| - updates.remove(asset.facts.from_remote_asset) - end - - # Loads new state - self.class.update_asset_from_remote_asset(self, remote_asset, updates) - end.apply(@import_step) - @import_step.update_attributes(state: 'complete') - asset_group.touch - ensure - @import_step.update_attributes(state: 'error') unless @import_step.state == 'complete' - # @import_step.asset_group.touch if @import_step.asset_group - end - end - def is_refreshing_right_now? Step.running_with_asset(self).count > 0 end - def type_of_asset_for_sequencescape - if ((facts.with_predicate('a').first) && ["Tube", "SampleTube"].include?(facts.with_predicate('a').first.object)) - :tube - else - :plate - end - end - def refresh(fact_changes = nil) if is_remote_asset? remote_asset = SequencescapeClient::find_by_uuid(uuid) @@ -151,15 +114,30 @@ def is_remote_asset? facts.from_remote_asset.count > 0 end - def update_facts_from_remote(list, step = nil) - step = step || @import_step - list = [list].flatten - added = list.map do |f| - f.assign_attributes(:is_remote? => true) - f + private + + def _process_refresh(remote_asset, fact_changes) + fact_changes ||= FactChanges.new + asset_group = AssetGroup.new + @import_step.update(asset_group: asset_group) + + begin + fact_changes.tap do |updates| + asset_group.update(assets: assets_to_refresh) + + # Removes previous state + assets_to_refresh.each do |asset| + updates.remove(asset.facts.from_remote_asset) + end + + # Loads new state + self.class.update_asset_from_remote_asset(self, remote_asset, updates) + end.apply(@import_step) + @import_step.update(state: 'complete') + asset_group.touch + ensure + @import_step.update(state: 'error') unless @import_step.state == 'complete' end - facts << added - add_operations([added].flatten, step) end end @@ -193,24 +171,6 @@ def create_local_asset(barcode, updates) asset end - def is_digit_barcode?(barcode) - barcode.to_s.match(/^\d+$/) - end - - def find_asset_with_barcode(barcode) - asset = Asset.find_by_barcode(barcode) - asset = Asset.find_by_uuid(barcode) unless asset - updates = FactChanges.new - if asset.nil? && TokenUtil.is_valid_fluidx_barcode?(barcode) - asset = import_barcode(barcode) - asset = Asset.create_local_asset(barcode, updates) unless asset - end - if asset - asset.refresh(updates) - end - asset - end - def find_or_import_asset_with_barcode(barcode) barcode = TokenUtil.human_barcode(barcode) if TokenUtil.machine_barcode?(barcode) find_asset_with_barcode(barcode) || import_barcode(barcode) @@ -253,15 +213,6 @@ def annotate_container(asset, remote_asset, fact_changes) end end - def sample_id_to_study_name(sample_id) - sample_id.gsub(/\d*$/, '').gsub('-', '') - end - - def get_study_uuid(study_name) - @study_uuids ||= {} - @study_uuids[study_name] ||= SequencescapeClient::get_study_by_name(study_name)&.uuid - end - def annotate_study_name_from_aliquots(asset, remote_asset, fact_changes) fact_changes.tap do |updates| if remote_asset.try(:aliquots) @@ -342,7 +293,8 @@ def sequencescape_type_for_asset(remote_asset) def keep_sync_with_sequencescape?(remote_asset) class_name = sequencescape_type_for_asset(remote_asset) - (class_name != 'SampleTube') + class_name != 'SampleTube' + end end end end From ae57c328a2c124bedead768d92905d7bd5db904c Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 23 Mar 2022 14:30:22 +0000 Subject: [PATCH 129/303] Add simple Cov config --- .simplecov | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .simplecov diff --git a/.simplecov b/.simplecov new file mode 100644 index 00000000..2401368b --- /dev/null +++ b/.simplecov @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +SimpleCov.start 'rails' do + add_filter '/test/' + add_filter '/coverage/' + add_filter '/db/' + add_filter '/log/' + add_filter '/public/' + add_filter '/script/' + add_filter '/vendor/' + add_filter '/tmp/' + + enable_coverage :branch + + # You can add_filter here to add anything else you don't want to cover +end From 728d475342fa3d119242056f3c3fab860d400b27 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 23 Mar 2022 14:31:30 +0000 Subject: [PATCH 130/303] Fix asset url warnings The URL helper was trying to generate a patch to an image/js asset not the assets controller. It was pumping out warnings and empty urls. --- app/helpers/application_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e53026d0..ecfb94f6 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -95,10 +95,11 @@ def data_asset_display_for_plate(facts) else aliquotType = empty_well_aliquot_type end + memo[location] = { title: "#{asset.short_description}", cssClass: aliquotType, - url: asset_path(asset) + url: Rails.application.routes.url_helpers.asset_path(asset) } unless location.nil? end memo From 46d1a5ab4da03e649799ae67bd37677fef8fbbb1 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 23 Mar 2022 14:32:55 +0000 Subject: [PATCH 131/303] Remove warren initializer This now happens automatically --- config/initializers/warren.rb | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 config/initializers/warren.rb diff --git a/config/initializers/warren.rb b/config/initializers/warren.rb deleted file mode 100644 index 8746c2ef..00000000 --- a/config/initializers/warren.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -require 'warren' - -if Rails.application.config.warren.present? - Warren.setup(Rails.application.config.warren.deep_symbolize_keys.slice(:type, :config)) -else - Rails.logger.warn "Warren.yml not configured for #{ENV['RAILS_ENV']}" -end From a4c58fc5642469c45127cef98425015eec626e3b Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 23 Mar 2022 14:33:55 +0000 Subject: [PATCH 132/303] Remove unused code --- lib/actions/racking.rb | 56 +++--------------------------------------- 1 file changed, 3 insertions(+), 53 deletions(-) diff --git a/lib/actions/racking.rb b/lib/actions/racking.rb index 160fd8b1..1962256d 100644 --- a/lib/actions/racking.rb +++ b/lib/actions/racking.rb @@ -35,8 +35,7 @@ module Racking # Actions def rack_layout(options = {}) - content = selected_file.data - csv_parsing(Parsers::CsvLayout::CsvParser.new(content, options)) + csv_parsing(Parsers::CsvLayout::CsvParser.new(selected_file.data, options)) end def rack_layout_creating_tubes @@ -49,16 +48,14 @@ def rack_layout_any_barcode # Support methods and classes - def clean_rack(rack) - remove_facts(facts.with_predicate('contains')) - end - def reracking_tubes(rack, list_layout) fact_changes_unrack = fact_changes_for_unrack_tubes(list_layout, rack) fact_changes_rack = fact_changes_for_rack_tubes(list_layout, rack) fact_changes_unrack.merge(fact_changes_rack) end + private + def fact_changes_for_unrack_tubes(list_layout, destination_rack = nil) FactChanges.new.tap do |updates| rerackGroup = nil @@ -170,13 +167,6 @@ def put_tube_into_rack_position(tube, rack, location) end end - def remove_tube_from_rack(tube, rack) - FactChanges.new.tap do |updates| - updates.remove(tube.facts.with_predicate('location')) - updates.remove_where(rack, 'contains', tube) - end - end - def fact_changes_for_rack_tubes(list_layout, rack) FactChanges.new.tap do |updates| tubes = [] @@ -192,40 +182,6 @@ def fact_changes_for_rack_tubes(list_layout, rack) end end - def params_to_list_layout(params) - params.map do |location, barcode| - asset = Asset.find_or_import_asset_with_barcode(barcode) - { - :location => location, - :asset => asset, - :barcode => barcode - } - end - end - - def get_duplicates(list) - list.reduce({}) do |memo, element| - memo[element] = 0 unless memo[element] - memo[element] += 1 - memo - end.each_pair.select { |key, count| count > 1 } - end - - def check_duplicates(params, error_messages, error_locations) - duplicated_locations = get_duplicates(params.map { |location, barcode| location }) - duplicated_assets = get_duplicates(params.map { |location, barcode| barcode }) - - duplicated_locations.each do |location, count| - error_locations.push(location) - error_messages.push("Location #{location} is appearing #{count} times") - end - - duplicated_assets.each do |barcode, count| - # error_locations.push(barcode) - error_messages.push("Asset #{barcode} is appearing #{count} times") - end - end - def check_racking_barcodes(list_layout, error_messages, error_locations) list_layout.each do |obj| location = obj[:location] @@ -313,11 +269,5 @@ def csv_parsing(parser) raise InvalidDataParams, parser.error_list end end - - def samples_symphony(step_type, params) - rack = asset_group.assets.with_fact('a', 'TubeRack').first - msgs = Parsers::Symphony.parse(params[:file].read, rack) - raise InvalidDataParams, msgs if msgs.length > 0 - end end end From c99a7298d2631377f549f837e5ba5e5a8f6f2a82 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 23 Mar 2022 15:00:17 +0000 Subject: [PATCH 133/303] Remove unused code --- app/models/asset.rb | 80 --------------------------------------------- 1 file changed, 80 deletions(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index d086012f..fc19408d 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -151,36 +151,6 @@ def generate_barcode end end - def attrs_for_sequencescape(traversed_list = []) - hash = facts.map do |fact| - if fact.literal? - [fact.predicate, fact.object_value] - else - if traversed_list.include?(fact.object_value) - [fact.predicate, fact.object_value.uuid] - else - traversed_list.push(fact.object_value) - [fact.predicate, fact.object_value.attrs_for_sequencescape(traversed_list)] - end - end - end.reduce({}) do |memo, list| - predicate, object = list - if memo[predicate] || memo[predicate.pluralize] - # Updates name of list to pluralized name - unless memo[predicate].kind_of? Array - memo[predicate.pluralize] = [memo[predicate]] - memo = memo.except!(predicate) if predicate != predicate.pluralize - end - memo[predicate.pluralize].push(object) - else - memo[predicate] = object - end - memo - end - # return {:uuid => uuid, :barcode => { :prefix => 'SE', :number => 14 }} - hash - end - def study_and_barcode "#{study_name} #{barcode_sequencescaped}" end @@ -282,22 +252,6 @@ def aliquot return '' end - def position_name_for_symphony - str = first_value_for('location') - [str[0], str[1..-1]].join(':') - end - - def position_index_for_symphony - str = first_value_for('location') - (str[1..-1] * 12) + (str[0].ord - 'A'.ord) - end - - def asset_description - names = facts.with_predicate('a').map(&:object).join(' ') - types = facts.with_predicate('aliquotType').map(&:object).join(' ') - return names + ' ' + types - end - def self.class_type(facts) class_types = facts.select { |f| f[:predicate] == 'a' }.map(&:object) return 'TubeRack' if class_types.include?('TubeRack') @@ -321,36 +275,6 @@ def class_type Asset.class_type(facts) end - def contains_location?(location) - facts.with_predicate('contains').any? do |f| - f.object_asset.facts.with_predicate('location').map(&:object).include?(location) - end - end - - def assets_at_location(location) - facts.with_predicate('contains').map(&:object_asset).select do |a| - a.facts.with_predicate('location').map(&:object).include?(location) - end - end - - def remove_from_parent(parent) - facts.with_predicate('parent').select { |f| f.object_asset == parent }.each(&:destroy) - facts.with_predicate('location').each(&:destroy) - end - - def duplicated_tubes_validation - contained_assets = facts.with_predicate('contains').map(&:object_asset) - duplicated = contained_assets.select do |element| - element.facts.with_predicate('location').count > 1 - end.uniq - unless duplicated.empty? - return duplicated.map do |duplicate_tube| - "The tube #{duplicated_tube.barcode} is duplicated in the layout" - end - end - return [] - end - def more_than_one_aliquot_type_validation if facts.with_predicate('contains').map(&:object_asset).map do |well| well.facts.with_predicate('aliquotType').map(&:object) @@ -374,10 +298,6 @@ def validate_rack_content errors end - def is_sequencescape_plate? - has_literal?('barcodeType', 'SequencescapePlate') - end - def to_n3 render :n3 end From ad3d308e43bda50a9bf98b9b2b59aadc57cfe09a Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 25 Mar 2022 15:04:30 +0000 Subject: [PATCH 134/303] Rename class_name to purpose_name This method was misleadingly named. --- app/models/asset.rb | 22 ++++++++-------------- app/models/assets/export.rb | 4 ++-- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index fc19408d..ec43d0b9 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -231,25 +231,19 @@ def position_value end def info_line - "#{class_name} #{aliquot} #{position_value}".strip + "#{purpose_name} #{aliquot} #{position_value}".strip end - def class_name - purposes_facts = facts.with_predicate('purpose') - if purposes_facts.count > 0 - return purposes_facts.first.object - end - - return '' + def purpose_name + # @todo: Falling back to an empty string, rather than nil feels a bit risky, but this maintains earlier behaviour. + # (We don't have any cases of facts with predicate purpose and value NULL) + facts.with_predicate('purpose').first&.object || '' end def aliquot - purposes_facts = facts.with_predicate('aliquotType') - if purposes_facts.count > 0 - return purposes_facts.first.object - end - - return '' + # @todo: Falling back to an empty string, rather than nil feels a bit risky, but this maintains tearlier behaviour. + # (We don't have any cases of facts with predicate aliquotType and value NULL) + facts.with_predicate('aliquotType').first&.object || '' end def self.class_type(facts) diff --git a/app/models/assets/export.rb b/app/models/assets/export.rb index 21ee04e6..86b379a6 100644 --- a/app/models/assets/export.rb +++ b/app/models/assets/export.rb @@ -16,7 +16,7 @@ def update_sequencescape(_print_config, user, _step) update_wells(instance, updates) updates.add(self, 'beforeBarcode', old_barcode) if old_barcode - updates.add_remote(self, 'purpose', class_name) if class_name + updates.add_remote(self, 'purpose', purpose_name) if purpose_name updates.remove(facts.with_predicate('barcodeType')) updates.add(self, 'barcodeType', 'SequencescapePlate') @@ -35,7 +35,7 @@ def update_sequencescape(_print_config, user, _step) end def create_remote_asset - SequencescapeClient.create_plate(class_name, {}) if class_name + SequencescapeClient.create_plate(purpose_name) if purpose_name end def create_or_update_remote_contained_assets(instance, user) From 38b86503da46d0ea424bdb3e6ba5e8516f3259bf Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 25 Mar 2022 15:05:48 +0000 Subject: [PATCH 135/303] Minor Spec performance improvements These are unlikely to make significant improvements but should make the cops happy --- spec/controllers/steps_controller_spec.rb | 2 +- spec/models/step_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/controllers/steps_controller_spec.rb b/spec/controllers/steps_controller_spec.rb index 8645fbe2..f7f97fc0 100644 --- a/spec/controllers/steps_controller_spec.rb +++ b/spec/controllers/steps_controller_spec.rb @@ -90,7 +90,7 @@ allow_any_instance_of(Step).to receive(:process) do step.reload FactChanges.new.create_assets(["?p"]).apply(step) - expect(step.operations.length > 0).to eq(true) + expect(step.operations).to be_exist post :update, params: { id: step_id, step: { event_name: 'stop' } } end expect(step.operations.all? { |op| !op.cancelled? }).to eq(true) diff --git a/spec/models/step_spec.rb b/spec/models/step_spec.rb index 0632bdf2..6144f341 100644 --- a/spec/models/step_spec.rb +++ b/spec/models/step_spec.rb @@ -841,11 +841,11 @@ def create_assets(num, type) @racks.each(&:reload) @tubes.each do |tube| - assert_equal true, (tube.facts.select { |f| f.predicate == 'relatesTo' }.length > 0) + assert_equal true, tube.facts.any? { |f| f.predicate == 'relatesTo' } end @racks.each do |rack| - assert_equal true, (rack.facts.select { |f| f.predicate == 'relatesTo' }.length > 0) + assert_equal true, rack.facts.any? { |f| f.predicate == 'relatesTo' } end create_step From 5fa09aaa82ce32c575e168f9488b8282001d6362 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 25 Mar 2022 15:08:53 +0000 Subject: [PATCH 136/303] Initial improvement on applying layout These changes result in a 20 fold speed-up, taking the operation down to about 3s when query-logging is disabled. There is still scope for improvement, but I want to move on to the other bottlenecks for now. --- .rubocop.yml | 1 + .rubocop_todo.yml | 500 +++++++----------- app/helpers/activities_helper.rb | 45 +- app/models/activities/steps_management.rb | 8 +- app/models/assets/export.rb | 22 +- app/models/assets/import.rb | 63 ++- app/models/condition.rb | 17 +- app/models/fact.rb | 8 +- app/models/step_type.rb | 4 +- .../move_barcodes_from_tube_rack_to_plate.rb | 2 +- .../rack_layout_creating_tubes.rb | 2 +- lib/actions/racking.rb | 9 +- lib/changes_support/disjoint_list.rb | 4 +- lib/fact_changes.rb | 55 +- .../runner/step_execution.rb | 21 +- .../csv_layout/barcode_creatable_parser.rb | 2 +- lib/parsers/csv_layout/csv_parser.rb | 12 +- lib/sequencescape_client.rb | 19 +- script/runners/update_sequencescape.rb | 2 +- spec/models/assets/export_spec.rb | 2 +- spec/models/assets/import_spec.rb | 52 +- 21 files changed, 405 insertions(+), 445 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index b177bde0..dd149680 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -33,6 +33,7 @@ Metrics/BlockLength: - included - shared_context - shared_examples + - shared_examples_for - state_machine - configure - draw diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 154de920..149ae904 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,20 +1,21 @@ # This configuration was generated by # `rubocop --auto-gen-config --exclude-limit 1000` -# on 2020-10-21 10:05:59 UTC using RuboCop version 0.93.1. +# on 2022-03-23 14:20:20 UTC using RuboCop version 1.26.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 17 -# Cop supports --auto-correct. +# Offense count: 19 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. # Include: **/*.gemfile, **/Gemfile, **/gems.rb Bundler/OrderedGems: Exclude: - 'Gemfile' -# Offense count: 9 +# Offense count: 11 +# Configuration parameters: IgnoredMethods. Lint/AmbiguousBlockAssociation: Exclude: - 'spec/controllers/steps_controller_spec.rb' @@ -22,11 +23,12 @@ Lint/AmbiguousBlockAssociation: - 'spec/models/steps/job_spec.rb' - 'spec/models/steps/task_spec.rb' -# Offense count: 5 +# Offense count: 3 +# Configuration parameters: AllowedMethods. +# AllowedMethods: enums Lint/ConstantDefinitionInBlock: Exclude: - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' - 'spec/models/activities/background_tasks_spec.rb' # Offense count: 3 @@ -36,24 +38,23 @@ Lint/DuplicateMethods: - 'lib/support_n3.rb' # Offense count: 4 -# Cop supports --auto-correct. +# This cop supports unsafe auto-correction (--auto-correct-all). Lint/NonDeterministicRequireOrder: Exclude: - 'lib/tasks/setup_templates.rake' - 'spec/rails_helper.rb' -# Offense count: 9 -# Cop supports --auto-correct. +# Offense count: 7 +# This cop supports safe auto-correction (--auto-correct). Lint/ParenthesesAsGroupedExpression: Exclude: - 'script/runners/load_metadata.rb' - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - 'script/runners/rack_layout.rb' - 'script/runners/rack_layout_any_barcode.rb' - - 'script/runners/rack_layout_creating_tubes.rb' # Offense count: 10 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Lint/RedundantStringCoercion: Exclude: - 'app/helpers/activities_helper.rb' @@ -81,19 +82,19 @@ Lint/ShadowingOuterLocalVariable: - 'spec/lib/support_n3_spec.rb' # Offense count: 2 -# Configuration parameters: AllowComments. +# Configuration parameters: AllowComments, AllowNil. Lint/SuppressedException: Exclude: - 'spec/controllers/steps_controller_spec.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Lint/ToJSON: Exclude: - 'lib/fact_changes.rb' -# Offense count: 57 -# Cop supports --auto-correct. +# Offense count: 54 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. Lint/UnusedBlockArgument: Exclude: @@ -109,7 +110,6 @@ Lint/UnusedBlockArgument: - 'db/migrate/20170128170039_add_namespace_to_fact_predicate.rb' - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' - 'lib/actions/plate_transfer.rb' - - 'lib/actions/racking.rb' - 'lib/fact_changes.rb' - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/inference_engines/runner/step_execution.rb' @@ -122,8 +122,8 @@ Lint/UnusedBlockArgument: - 'spec/models/step_spec.rb' - 'spec/models/step_type_spec.rb' -# Offense count: 24 -# Cop supports --auto-correct. +# Offense count: 19 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. Lint/UnusedMethodArgument: Exclude: @@ -132,11 +132,9 @@ Lint/UnusedMethodArgument: - 'app/models/action.rb' - 'app/models/asset.rb' - 'app/models/assets/export.rb' - - 'app/models/assets/traction_fields.rb' - 'lib/actions/racking.rb' - 'lib/fact_changes.rb' - 'lib/inference_engines/cwm/step_execution.rb' - - 'lib/sequencescape_client.rb' - 'lib/support_n3.rb' - 'script/remove_duplicates.rb' - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' @@ -145,14 +143,13 @@ Lint/UnusedMethodArgument: - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' - 'spec/remote_assets_helper.rb' -# Offense count: 64 +# Offense count: 58 Lint/UselessAssignment: Exclude: - 'app/channels/activity_channel.rb' - 'app/controllers/activities_controller.rb' - 'app/helpers/application_helper.rb' - 'app/models/activities/json_attributes.rb' - - 'app/models/activities/tasks.rb' - 'app/models/assets/export.rb' - 'app/models/assets/facts_management.rb' - 'app/models/step_type.rb' @@ -160,7 +157,6 @@ Lint/UselessAssignment: - 'lib/actions/plate_transfer.rb' - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/inference_engines/runner/step_execution.rb' - - 'lib/parsers/csv_layout/barcode_parser.rb' - 'lib/parsers/csv_layout/location_parser.rb' - 'lib/sequencescape_client.rb' - 'lib/support_n3.rb' @@ -190,16 +186,16 @@ Lint/Void: - 'lib/inference_engines/default/step_execution.rb' - 'spec/models/assets/export_spec.rb' -# Offense count: 84 -# Configuration parameters: IgnoredMethods. +# Offense count: 85 +# Configuration parameters: IgnoredMethods, CountRepeatedAttributes. Metrics/AbcSize: Max: 79 -# Offense count: 12 -# Configuration parameters: CountComments, CountAsOne, ExcludedMethods. -# ExcludedMethods: refine +# Offense count: 11 +# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. +# IgnoredMethods: refine Metrics/BlockLength: - Max: 75 + Max: 71 # Offense count: 7 # Configuration parameters: CountBlocks. @@ -209,51 +205,45 @@ Metrics/BlockNesting: # Offense count: 11 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 474 + Max: 470 # Offense count: 37 # Configuration parameters: IgnoredMethods. Metrics/CyclomaticComplexity: Max: 26 -# Offense count: 106 -# Configuration parameters: CountComments, CountAsOne, ExcludedMethods. +# Offense count: 108 +# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. Metrics/MethodLength: Max: 334 -# Offense count: 7 +# Offense count: 6 # Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: - Max: 254 + Max: 202 # Offense count: 32 # Configuration parameters: IgnoredMethods. Metrics/PerceivedComplexity: Max: 26 -# Offense count: 7 +# Offense count: 6 Naming/AccessorMethodName: Exclude: - - 'app/models/assets/import.rb' - 'app/models/fact.rb' - 'app/models/step.rb' - 'lib/fact_changes.rb' - 'lib/sequencescape_client.rb' # Offense count: 1 -# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# CheckDefinitionPathHierarchyRoots: lib, spec, test, src # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS Naming/FileName: Exclude: - 'config/initializers/pmb_server-setup.rb' -# Offense count: 10 -# Configuration parameters: IgnoredPatterns. -# SupportedStyles: snake_case, camelCase -Naming/MethodName: - EnforcedStyle: snake_case - -# Offense count: 36 +# Offense count: 33 # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. # AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to Naming/MethodParameterName: @@ -269,7 +259,7 @@ Naming/MethodParameterName: - 'spec/models/step_type_spec.rb' - 'spec/models/steps/queueable_job_spec.rb' -# Offense count: 27 +# Offense count: 24 # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros. # NamePrefix: is_, has_, have_ # ForbiddenPrefixes: is_, has_, have_ @@ -277,7 +267,6 @@ Naming/MethodParameterName: # MethodDefinitionMacros: define_method, define_singleton_method Naming/PredicateName: Exclude: - - 'spec/**/*' - 'app/models/activities/websocket_events.rb' - 'app/models/asset.rb' - 'app/models/asset_group.rb' @@ -289,13 +278,11 @@ Naming/PredicateName: - 'app/models/steps/queueable_job.rb' - 'app/models/steps/state.rb' - 'lib/fact_changes.rb' - - 'lib/parsers/csv_layout/line_parser.rb' - - 'lib/parsers/csv_metadata/line_parser.rb' - 'lib/support_n3.rb' - 'lib/token_util.rb' # Offense count: 3 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: PreferredName. Naming/RescuedExceptionsVariableName: Exclude: @@ -303,7 +290,7 @@ Naming/RescuedExceptionsVariableName: - 'lib/sequencescape_client.rb' # Offense count: 40 -# Configuration parameters: EnforcedStyle. +# Configuration parameters: EnforcedStyle, AllowedIdentifiers. # SupportedStyles: snake_case, camelCase Naming/VariableName: Exclude: @@ -323,14 +310,14 @@ Performance/CollectionLiteralInLoop: - 'app/models/assets/export.rb' # Offense count: 2 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Performance/CompareWithBlock: Exclude: - 'app/controllers/samples_status_controller.rb' - 'app/models/activities/steps_management.rb' -# Offense count: 20 -# Cop supports --auto-correct. +# Offense count: 18 +# This cop supports safe auto-correction (--auto-correct). Performance/Count: Exclude: - 'app/models/step_type.rb' @@ -340,8 +327,8 @@ Performance/Count: - 'spec/models/steps/cancellable_spec.rb' - 'spec/models/steps/deprecatable_spec.rb' -# Offense count: 25 -# Cop supports --auto-correct. +# Offense count: 24 +# This cop supports safe auto-correction (--auto-correct). Performance/Detect: Exclude: - 'app/helpers/activities_helper.rb' @@ -350,7 +337,6 @@ Performance/Detect: - 'app/models/label_template.rb' - 'app/models/printer.rb' - 'lib/changes_support/disjoint_list.rb' - - 'lib/fact_changes.rb' - 'lib/parsers/csv_metadata/datum_parser.rb' - 'lib/sequencescape_client.rb' - 'lib/support_n3.rb' @@ -361,29 +347,27 @@ Performance/Detect: - 'spec/lib/support_n3_spec.rb' # Offense count: 3 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Performance/RedundantMatch: Exclude: - 'app/models/asset.rb' - 'lib/inference_engines/runner/step_execution.rb' # Offense count: 3 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Performance/RegexpMatch: Exclude: - 'app/models/asset.rb' - 'lib/inference_engines/runner/step_execution.rb' -# Offense count: 3 -# Cop supports --auto-correct. +# Offense count: 2 +# This cop supports safe auto-correction (--auto-correct). Performance/StringReplacement: Exclude: - - 'app/models/assets/import.rb' - 'lib/token_util.rb' # Offense count: 72 -# Cop supports --auto-correct. -# Configuration parameters: AutoCorrect. +# This cop supports safe auto-correction (--auto-correct). Performance/TimesMap: Exclude: - 'app/models/action.rb' @@ -413,8 +397,8 @@ Performance/TimesMap: - 'spec/script/runners/transfer_samples_spec.rb' - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' -# Offense count: 89 -# Cop supports --auto-correct. +# Offense count: 86 +# This cop supports safe auto-correction (--auto-correct). Rails/ActiveRecordAliases: Exclude: - 'app/controllers/asset_groups_controller.rb' @@ -449,42 +433,16 @@ Rails/ActiveRecordAliases: - 'spec/shared_examples/background_step.rb' - 'test/factories/assets.rb' -# Offense count: 2 -# Cop supports --auto-correct. +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: Include. # Include: app/models/**/*.rb Rails/ActiveRecordCallbacksOrder: Exclude: - - 'app/models/activity_type.rb' - - 'app/models/step_type.rb' - -# Offense count: 20 -# Cop supports --auto-correct. -Rails/ApplicationRecord: - Exclude: - - 'app/models/action.rb' - - 'app/models/activity.rb' - - 'app/models/activity_type.rb' - - 'app/models/activity_type_compatibility.rb' - - 'app/models/activity_type_step_type.rb' - - 'app/models/asset.rb' - - 'app/models/asset_group.rb' - - 'app/models/asset_groups_asset.rb' - - 'app/models/condition.rb' - - 'app/models/condition_group.rb' - - 'app/models/fact.rb' - - 'app/models/instrument.rb' - - 'app/models/kit.rb' - - 'app/models/kit_type.rb' - - 'app/models/label_template.rb' - - 'app/models/printer.rb' - - 'app/models/step.rb' - - 'app/models/step_message.rb' - 'app/models/step_type.rb' - - 'app/models/user.rb' # Offense count: 2 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: NilOrEmpty, NotPresent, UnlessPresent. Rails/Blank: Exclude: @@ -510,14 +468,14 @@ Rails/CreateTableWithTimestamps: - 'db/migrate/20160626224627_create_condition_groups.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforceForPrefixed. Rails/Delegate: Exclude: - 'lib/parsers/csv_metadata/csv_parser.rb' # Offense count: 28 -# Cop supports --auto-correct. +# This cop supports unsafe auto-correction (--auto-correct-all). # Configuration parameters: Whitelist, AllowedMethods, AllowedReceivers. # Whitelist: find_by_sql # AllowedMethods: find_by_sql @@ -536,18 +494,11 @@ Rails/FilePath: Exclude: - 'script/runners/transfer_plate_to_plate_and_update_sequencescape.rb' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: Include. -# Include: app/models/**/*.rb -Rails/FindBy: - Exclude: - - 'app/models/asset.rb' - # Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: Include. +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: Include, IgnoredMethods. # Include: app/models/**/*.rb +# IgnoredMethods: order, limit, select, lock Rails/FindEach: Exclude: - 'app/models/asset.rb' @@ -587,7 +538,7 @@ Rails/HelperInstanceVariable: - 'app/helpers/application_helper.rb' # Offense count: 9 -# Configuration parameters: Include. +# Configuration parameters: IgnoreScopes, Include. # Include: app/models/**/*.rb Rails/InverseOf: Exclude: @@ -604,14 +555,15 @@ Rails/LexicallyScopedActionFilter: Exclude: - 'app/controllers/reracking_controller.rb' -# Offense count: 2 -# Cop supports --auto-correct. +# Offense count: 1 +# This cop supports unsafe auto-correction (--auto-correct-all). Rails/NegateInclude: Exclude: - 'lib/changes_support/disjoint_list.rb' - 'lib/support_n3.rb' -# Offense count: 8 +# Offense count: 12 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: Include. # Include: app/**/*.rb, config/**/*.rb, db/**/*.rb, lib/**/*.rb Rails/Output: @@ -628,20 +580,20 @@ Rails/OutputSafety: - 'app/helpers/application_helper.rb' - 'app/helpers/steps_helper.rb' -# Offense count: 2 -# Cop supports --auto-correct. +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). Rails/Pluck: Exclude: - 'lib/actions/racking.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Rails/Presence: Exclude: - 'app/models/asset.rb' # Offense count: 6 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: NotNilAndNotEmpty, NotBlank, UnlessBlank. Rails/Present: Exclude: @@ -650,7 +602,7 @@ Rails/Present: - 'lib/support_n3.rb' # Offense count: 5 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Rails/RedundantForeignKey: Exclude: - 'app/models/concerns/deprecatable.rb' @@ -662,15 +614,14 @@ Rails/ReflectionClassName: Exclude: - 'app/models/concerns/deprecatable.rb' -# Offense count: 9 +# Offense count: 1 # Configuration parameters: Include. -# Include: db/migrate/*.rb +# Include: db/**/*.rb Rails/ReversibleMigration: Exclude: - - 'db/migrate/20170608101740_remove_unneeded_tables.rb' - 'db/migrate/20190516153622_remove_task_type.rb' -# Offense count: 24 +# Offense count: 23 # Configuration parameters: ForbiddenMethods, AllowedMethods. # ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all Rails/SkipsModelValidations: @@ -688,18 +639,17 @@ Rails/SkipsModelValidations: - 'db/migrate/20190528125756_fix_incorrect_fact_literals.rb' - 'db/migrate/20190717130805_change_sti_type.rb' - 'lib/fact_changes.rb' - - 'lib/inference_engines/runner/step_execution.rb' - 'spec/models/steps/job_spec.rb' - 'spec/shared_examples/background_step.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Rails/SquishedSQLHeredocs: Exclude: - 'db/migrate/20200709123033_create_heron_activities_view.rb' # Offense count: 3 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: strict, flexible Rails/TimeZone: @@ -708,7 +658,7 @@ Rails/TimeZone: - 'spec/remote_assets_helper.rb' # Offense count: 2 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: Include. # Include: app/models/**/*.rb Rails/Validation: @@ -716,53 +666,38 @@ Rails/Validation: - 'app/models/label_template.rb' # Offense count: 3 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Rails/WhereNot: Exclude: - 'app/models/activities/state.rb' - 'app/models/step_type.rb' - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' -# Offense count: 1 -# Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols. -# SupportedStyles: inline, group -Style/AccessModifierDeclarations: - Exclude: - - 'app/models/printables/group.rb' - -# Offense count: 16 -# Cop supports --auto-correct. +# Offense count: 14 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: separated, grouped Style/AccessorGrouping: Exclude: - 'lib/changes_support/disjoint_list.rb' - - 'lib/fact_changes.rb' - 'lib/inference_engines/default/step_execution.rb' - 'lib/support_n3.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: prefer_alias, prefer_alias_method Style/Alias: Exclude: - 'app/models/asset_group.rb' -# Offense count: 1 -# Configuration parameters: AllowedChars. -Style/AsciiComments: - Exclude: - - 'script/runners/transfer_plate_to_plate.rb' - -# Offense count: 83 -# Cop supports --auto-correct. +# Offense count: 82 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: percent_q, bare_percent Style/BarePercentLiterals: Exclude: - 'db/seeds.rb' - - 'db/views_schema.rb' - 'script/aliquot_type_inference.rb' - 'script/container_inferences.rb' - 'script/purpose_name_inference.rb' @@ -775,13 +710,13 @@ Style/BarePercentLiterals: - 'spec/models/steps/cancellable_spec.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/BlockComments: Exclude: - 'spec/spec_helper.rb' -# Offense count: 127 -# Cop supports --auto-correct. +# Offense count: 124 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, IgnoredMethods, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object @@ -805,8 +740,6 @@ Style/BlockDelimiters: - 'spec/lib/actions/racking_spec.rb' - 'spec/lib/changes_support/disjoint_list_spec.rb' - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' @@ -829,24 +762,23 @@ Style/BlockDelimiters: - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' # Offense count: 3 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowOnConstant. Style/CaseEquality: Exclude: - 'lib/sequencescape_client.rb' - 'lib/support_n3.rb' -# Offense count: 6 -# Cop supports --auto-correct. +# Offense count: 5 +# This cop supports unsafe auto-correction (--auto-correct-all). Style/CaseLikeIf: Exclude: - 'app/models/action.rb' - 'app/models/operation.rb' - 'app/models/step_type.rb' - - 'lib/actions/racking.rb' -# Offense count: 37 -# Cop supports --auto-correct. +# Offense count: 38 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: nested, compact Style/ClassAndModuleChildren: @@ -879,7 +811,7 @@ Style/ClassAndModuleChildren: - 'test/test_helper.rb' # Offense count: 39 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: is_a?, kind_of? Style/ClassCheck: @@ -901,15 +833,14 @@ Style/ClassCheck: - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' - 'spec/requests/api/v1/assets_spec.rb' -# Offense count: 4 -# Cop supports --auto-correct. +# Offense count: 3 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: IgnoredMethods. # IgnoredMethods: ==, equal?, eql? Style/ClassEqualityComparison: Exclude: - 'app/helpers/application_helper.rb' - 'lib/support_n3.rb' - - 'spec/remote_assets_helper.rb' # Offense count: 3 Style/ClassVars: @@ -917,11 +848,10 @@ Style/ClassVars: - 'app/models/action.rb' - 'lib/sequencescape_client.rb' -# Offense count: 26 -# Cop supports --auto-correct. +# Offense count: 24 +# This cop supports safe auto-correction (--auto-correct). Style/ColonMethodCall: Exclude: - - 'app/models/activity_type.rb' - 'app/models/assets/import.rb' - 'app/models/step_type.rb' - 'db/seeds.rb' @@ -933,7 +863,7 @@ Style/ColonMethodCall: - 'spec/models/assets/export_spec.rb' # Offense count: 8 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions. # SupportedStyles: assign_to_condition, assign_inside_condition Style/ConditionalAssignment: @@ -946,7 +876,8 @@ Style/ConditionalAssignment: - 'lib/inference_engines/runner/step_execution.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' -# Offense count: 213 +# Offense count: 192 +# Configuration parameters: AllowedConstants. Style/Documentation: Exclude: - 'spec/**/*' @@ -984,14 +915,10 @@ Style/Documentation: - 'app/models/activities/steps_management.rb' - 'app/models/activities/tasks.rb' - 'app/models/activities/websocket_events.rb' - - 'app/models/activity.rb' - 'app/models/activity_type.rb' - - 'app/models/activity_type_compatibility.rb' - - 'app/models/activity_type_step_type.rb' - 'app/models/application_record.rb' - 'app/models/asset.rb' - 'app/models/asset_group.rb' - - 'app/models/asset_groups_asset.rb' - 'app/models/assets/export.rb' - 'app/models/assets/facts_management.rb' - 'app/models/assets/import.rb' @@ -1000,17 +927,14 @@ Style/Documentation: - 'app/models/concerns/uuidable.rb' - 'app/models/condition.rb' - 'app/models/condition_group.rb' - - 'app/models/fact.rb' - 'app/models/instrument.rb' - 'app/models/kit.rb' - - 'app/models/kit_type.rb' - 'app/models/label_template.rb' - 'app/models/operation.rb' - 'app/models/printables/group.rb' - 'app/models/printables/instance.rb' - 'app/models/printer.rb' - 'app/models/step.rb' - - 'app/models/step_message.rb' - 'app/models/step_type.rb' - 'app/models/steps/background_tasks/inference.rb' - 'app/models/steps/background_tasks/runner.rb' @@ -1026,7 +950,6 @@ Style/Documentation: - 'app/models/steps/websocket_events.rb' - 'app/models/uploaded_file.rb' - 'app/models/user.rb' - - 'app/resources/api/v1/asset_resource.rb' - 'config/application.rb' - 'db/migrate/20160622135510_create_activity_types.rb' - 'db/migrate/20160622144557_create_kit_types.rb' @@ -1137,21 +1060,21 @@ Style/Documentation: - 'script/runners/print_barcodes.rb' - 'script/runners/rack_layout.rb' - 'script/runners/rack_layout_any_barcode.rb' - - 'script/runners/rack_layout_creating_tubes.rb' - 'script/runners/transfer_samples.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - 'script/study_name_inference.rb' - 'script/tasks/runners/aliquot_type_inference.rb' # Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: allowed_in_returns, forbidden Style/DoubleNegation: Exclude: - 'app/channels/activity_channel.rb' -# Offense count: 31 -# Cop supports --auto-correct. +# Offense count: 28 +# This cop supports safe auto-correction (--auto-correct). Style/EachWithObject: Exclude: - 'app/channels/activity_channel.rb' @@ -1166,9 +1089,7 @@ Style/EachWithObject: - 'app/models/step_type.rb' - 'app/models/steps/cancellable.rb' - 'lib/actions/plate_transfer.rb' - - 'lib/actions/racking.rb' - 'lib/fact_changes.rb' - - 'lib/parsers/csv_layout/line_parser.rb' - 'lib/parsers/csv_metadata/data_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - 'lib/support_n3.rb' @@ -1176,7 +1097,7 @@ Style/EachWithObject: - 'spec/lib/changes_support/disjoint_list_spec.rb' # Offense count: 28 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/EmptyLambdaParameter: Exclude: - 'app/models/activities/state.rb' @@ -1189,7 +1110,7 @@ Style/EmptyLambdaParameter: - 'app/models/steps/state.rb' # Offense count: 14 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: compact, expanded Style/EmptyMethod: @@ -1205,34 +1126,31 @@ Style/EmptyMethod: - 'app/controllers/users_controller.rb' # Offense count: 4 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/EvenOdd: Exclude: - 'spec/models/condition_spec.rb' - 'spec/models/step_execution_spec.rb' -# Offense count: 7 -# Cop supports --auto-correct. +# Offense count: 4 +# This cop supports safe auto-correction (--auto-correct). Style/ExpandPathArguments: Exclude: - 'Rakefile' - 'config.ru' - - 'config/application.rb' - - 'config/boot.rb' - - 'config/environment.rb' - 'spec/rails_helper.rb' - 'test/test_helper.rb' # Offense count: 2 -# Configuration parameters: EnforcedStyle. +# Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, IgnoredMethods. # SupportedStyles: annotated, template, unannotated Style/FormatStringToken: Exclude: - 'config/routes.rb' - 'lib/views_schema.rb' -# Offense count: 362 -# Cop supports --auto-correct. +# Offense count: 353 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: always, always_true, never Style/FrozenStringLiteralComment: @@ -1275,7 +1193,6 @@ Style/FrozenStringLiteralComment: - 'app/models/activities/steps_management.rb' - 'app/models/activities/tasks.rb' - 'app/models/activities/websocket_events.rb' - - 'app/models/activity.rb' - 'app/models/activity_type.rb' - 'app/models/activity_type_compatibility.rb' - 'app/models/activity_type_step_type.rb' @@ -1435,7 +1352,6 @@ Style/FrozenStringLiteralComment: - 'db/migrate/20191127154249_add_kit_type_abbreviation.rb' - 'db/migrate/20200709123033_create_heron_activities_view.rb' - 'db/seeds.rb' - - 'db/views_schema.rb' - 'lib/actions/plate_transfer.rb' - 'lib/actions/racking.rb' - 'lib/actions/tube_transfer.rb' @@ -1453,7 +1369,6 @@ Style/FrozenStringLiteralComment: - 'lib/label_types/plate.rb' - 'lib/label_types/tube.rb' - 'lib/parsers/csv_layout/barcode_creatable_parser.rb' - - 'lib/parsers/csv_layout/barcode_parser.rb' - 'lib/parsers/csv_layout/csv_parser.rb' - 'lib/parsers/csv_layout/line_parser.rb' - 'lib/parsers/csv_layout/line_reader.rb' @@ -1463,7 +1378,6 @@ Style/FrozenStringLiteralComment: - 'lib/parsers/csv_metadata/datum_parser.rb' - 'lib/parsers/csv_metadata/headers_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - - 'lib/sequencescape_client.rb' - 'lib/sequencescape_client_v2.rb' - 'lib/step_execution_process.rb' - 'lib/support_n3.rb' @@ -1490,7 +1404,6 @@ Style/FrozenStringLiteralComment: - 'script/runners/put_tubes_into_rack_by_column_order.rb' - 'script/runners/rack_layout.rb' - 'script/runners/rack_layout_any_barcode.rb' - - 'script/runners/rack_layout_creating_tubes.rb' - 'script/runners/transfer_plate_to_plate.rb' - 'script/runners/transfer_plate_to_plate_and_update_sequencescape.rb' - 'script/runners/transfer_samples.rb' @@ -1597,13 +1510,13 @@ Style/FrozenStringLiteralComment: - 'test/test_helper.rb' # Offense count: 2 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/GlobalStdStream: Exclude: - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/inference_engines/runner/step_execution.rb' -# Offense count: 32 +# Offense count: 28 # Configuration parameters: MinBodyLength. Style/GuardClause: Exclude: @@ -1612,7 +1525,6 @@ Style/GuardClause: - 'app/controllers/application_controller.rb' - 'app/controllers/asset_groups_controller.rb' - 'app/models/activities/websocket_events.rb' - - 'app/models/activity_type.rb' - 'app/models/asset.rb' - 'app/models/asset_group.rb' - 'app/models/condition.rb' @@ -1632,7 +1544,8 @@ Style/GuardClause: - 'lib/support_n3.rb' # Offense count: 7 -# Cop supports --auto-correct. +# This cop supports unsafe auto-correction (--auto-correct-all). +# Configuration parameters: AllowedReceivers. Style/HashEachMethods: Exclude: - 'lib/changes_support/disjoint_list.rb' @@ -1641,10 +1554,11 @@ Style/HashEachMethods: - 'script/runners/load_metadata.rb' - 'spec/requests/api/v1/assets_spec.rb' -# Offense count: 962 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. +# Offense count: 948 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys +# SupportedShorthandSyntax: always, never, either Style/HashSyntax: Exclude: - 'app/channels/activity_channel.rb' @@ -1702,7 +1616,6 @@ Style/HashSyntax: - 'db/migrate/20170710095951_change_extr_attr_to_long_text.rb' - 'db/migrate/20180428131814_create_uploaded_files.rb' - 'db/migrate/20190526185059_change_handler_to_long_text.rb' - - 'lib/actions/racking.rb' - 'lib/fact_changes.rb' - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/sequencescape_client.rb' @@ -1718,7 +1631,6 @@ Style/HashSyntax: - 'spec/inferences_helper.rb' - 'spec/integration/inference_spec.rb' - 'spec/integration/inferences_data.rb' - - 'spec/lib/fact_changes_spec.rb' - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - 'spec/lib/support_n3_spec.rb' @@ -1733,6 +1645,7 @@ Style/HashSyntax: - 'test/factories/users.rb' # Offense count: 6 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowIfModifier. Style/IfInsideElse: Exclude: @@ -1742,14 +1655,12 @@ Style/IfInsideElse: - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/support_n3.rb' -# Offense count: 72 -# Cop supports --auto-correct. +# Offense count: 64 +# This cop supports safe auto-correction (--auto-correct). Style/IfUnlessModifier: Exclude: - 'app/controllers/asset_groups_controller.rb' - 'app/controllers/changes_controller.rb' - - 'app/helpers/activities_helper.rb' - - 'app/models/activity_type.rb' - 'app/models/asset.rb' - 'app/models/asset_group.rb' - 'app/models/assets/export.rb' @@ -1773,7 +1684,6 @@ Style/IfUnlessModifier: - 'lib/inference_engines/runner/step_execution.rb' - 'lib/label_template_setup.rb' - 'lib/parsers/csv_layout/csv_parser.rb' - - 'lib/parsers/csv_layout/line_parser.rb' - 'lib/parsers/csv_metadata/csv_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - 'lib/support_n3.rb' @@ -1786,21 +1696,20 @@ Style/IfUnlessModifier: - 'test/factories/assets.rb' # Offense count: 2 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/IfUnlessModifierOfIfUnless: Exclude: - 'lib/actions/plate_transfer.rb' -# Offense count: 2 -# Cop supports --auto-correct. +# Offense count: 1 +# This cop supports unsafe auto-correction (--auto-correct-all). # Configuration parameters: InverseMethods, InverseBlocks. Style/InverseMethods: Exclude: - 'app/helpers/activities_helper.rb' - - 'lib/parsers/csv_layout/line_parser.rb' # Offense count: 11 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: line_count_dependent, lambda, literal Style/Lambda: @@ -1816,7 +1725,7 @@ Style/MixinUsage: - 'script/runners/put_tubes_into_rack_by_column_order.rb' - 'spec/inferences_helper.rb' -# Offense count: 16 +# Offense count: 15 Style/MultilineBlockChain: Exclude: - 'app/models/asset.rb' @@ -1829,7 +1738,7 @@ Style/MultilineBlockChain: - 'spec/script/runners/transfer_samples_spec.rb' # Offense count: 5 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/MultilineIfModifier: Exclude: - 'app/helpers/application_helper.rb' @@ -1837,28 +1746,28 @@ Style/MultilineIfModifier: - 'app/models/user.rb' # Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: AllowMethodComparison. Style/MultipleComparison: Exclude: - 'script/runners/load_metadata.rb' -# Offense count: 19 -# Cop supports --auto-correct. +# Offense count: 18 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: literals, strict Style/MutableConstant: Exclude: - - 'app/controllers/assets_controller.rb' - 'app/models/steps/state.rb' - 'config/initializers/version_string.rb' - 'lib/actions/racking.rb' - 'lib/changes_support/disjoint_list.rb' - - 'lib/parsers/csv_layout/barcode_parser.rb' - 'lib/parsers/csv_layout/csv_parser.rb' - 'lib/parsers/csv_layout/line_reader.rb' - 'lib/parsers/csv_metadata/csv_parser.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: both, prefix, postfix Style/NegatedIf: @@ -1866,13 +1775,13 @@ Style/NegatedIf: - 'app/models/printables/instance.rb' # Offense count: 2 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/NestedModifier: Exclude: - 'lib/actions/plate_transfer.rb' # Offense count: 11 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, MinBodyLength. # SupportedStyles: skip_modifier_ifs, always Style/Next: @@ -1888,13 +1797,13 @@ Style/Next: - 'spec/lib/support_n3_spec.rb' # Offense count: 13 -# Cop supports --auto-correct. -# Configuration parameters: Strict. +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: Strict, AllowedNumbers. Style/NumericLiterals: MinDigits: 14 -# Offense count: 73 -# Cop supports --auto-correct. +# Offense count: 70 +# This cop supports unsafe auto-correction (--auto-correct-all). # Configuration parameters: EnforcedStyle, IgnoredMethods. # SupportedStyles: predicate, comparison Style/NumericPredicate: @@ -1932,7 +1841,6 @@ Style/NumericPredicate: - 'script/runners/print_barcodes.rb' - 'script/runners/rack_layout.rb' - 'script/runners/rack_layout_any_barcode.rb' - - 'script/runners/rack_layout_creating_tubes.rb' - 'script/runners/transfer_plate_to_plate.rb' - 'script/runners/transfer_samples.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' @@ -1950,30 +1858,28 @@ Style/OptionalBooleanParameter: - 'lib/fact_changes.rb' - 'lib/support_n3.rb' -# Offense count: 7 -# Cop supports --auto-correct. +# Offense count: 5 +# This cop supports safe auto-correction (--auto-correct). Style/OrAssignment: Exclude: - 'app/controllers/asset_groups_controller.rb' - 'app/helpers/application_helper.rb' - 'app/models/assets/export.rb' - - 'app/models/assets/import.rb' - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/inference_engines/runner/step_execution.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/ParallelAssignment: Exclude: - 'spec/models/step_spec.rb' -# Offense count: 89 -# Cop supports --auto-correct. +# Offense count: 87 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowSafeAssignment, AllowInMultilineConditions. Style/ParenthesesAroundCondition: Exclude: - 'app/channels/activity_channel.rb' - - 'app/helpers/activities_helper.rb' - 'app/helpers/application_helper.rb' - 'app/models/action.rb' - 'app/models/activities/websocket_events.rb' @@ -2002,7 +1908,7 @@ Style/ParenthesesAroundCondition: - 'test/factories/assets.rb' # Offense count: 81 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: PreferredDelimiters. Style/PercentLiteralDelimiters: Exclude: @@ -2018,18 +1924,17 @@ Style/PercentLiteralDelimiters: - 'spec/models/assets/export_spec.rb' - 'spec/models/steps/cancellable_spec.rb' -# Offense count: 21 -# Cop supports --auto-correct. +# Offense count: 20 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: lower_case_q, upper_case_q Style/PercentQLiterals: Exclude: - - 'db/views_schema.rb' - 'spec/integration/inferences_data.rb' - 'spec/models/steps/cancellable_spec.rb' # Offense count: 8 -# Cop supports --auto-correct. +# This cop supports unsafe auto-correction (--auto-correct-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: short, verbose Style/PreferredHashMethods: @@ -2039,69 +1944,63 @@ Style/PreferredHashMethods: - 'spec/models/asset_spec.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/RedundantAssignment: Exclude: - 'app/models/asset.rb' -# Offense count: 9 -# Cop supports --auto-correct. +# Offense count: 8 +# This cop supports safe auto-correction (--auto-correct). Style/RedundantBegin: Exclude: - 'app/channels/activity_channel.rb' - 'app/models/assets/export.rb' - 'app/models/step_type.rb' - - 'lib/parsers/csv_layout/barcode_parser.rb' - 'lib/parsers/csv_layout/location_parser.rb' - 'lib/sequencescape_client.rb' - 'spec/controllers/steps_controller_spec.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/RedundantCondition: Exclude: - 'spec/integration/inference_spec.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/RedundantFreeze: Exclude: - 'lib/psd_formatter.rb' -# Offense count: 7 -# Cop supports --auto-correct. +# Offense count: 4 +# This cop supports safe auto-correction (--auto-correct). Style/RedundantInterpolation: Exclude: - 'app/helpers/application_helper.rb' - - 'app/models/asset.rb' -# Offense count: 32 -# Cop supports --auto-correct. +# Offense count: 28 +# This cop supports safe auto-correction (--auto-correct). Style/RedundantParentheses: Exclude: - - 'app/helpers/activities_helper.rb' - 'app/models/action.rb' - 'app/models/asset.rb' - 'app/models/assets/export.rb' - 'app/models/assets/import.rb' - 'app/models/condition_group.rb' - - 'app/models/step_type.rb' - 'lib/actions/plate_transfer.rb' - 'lib/actions/racking.rb' - 'lib/actions/tube_transfer.rb' - 'lib/changes_support/disjoint_list.rb' - 'lib/changes_support/transaction_scope.rb' - 'lib/fact_changes.rb' - - 'lib/parsers/csv_layout/csv_parser.rb' - 'lib/support_n3.rb' - 'script/runners/create_stamped_plate.rb' -# Offense count: 82 -# Cop supports --auto-correct. +# Offense count: 81 +# This cop supports safe auto-correction (--auto-correct). Style/RedundantPercentQ: Exclude: - 'db/seeds.rb' - - 'db/views_schema.rb' - 'script/aliquot_type_inference.rb' - 'script/container_inferences.rb' - 'script/purpose_name_inference.rb' @@ -2113,13 +2012,13 @@ Style/RedundantPercentQ: - 'spec/models/steps/cancellable_spec.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/RedundantRegexpEscape: Exclude: - 'lib/token_util.rb' # Offense count: 47 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowMultipleReturnValues. Style/RedundantReturn: Exclude: @@ -2151,7 +2050,7 @@ Style/RedundantReturn: - 'spec/requests/api/v1/assets_spec.rb' # Offense count: 22 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/RedundantSelf: Exclude: - 'app/channels/activity_channel.rb' @@ -2166,8 +2065,8 @@ Style/RedundantSelf: - 'app/models/steps/websocket_events.rb' - 'lib/sequencescape_client.rb' -# Offense count: 17 -# Cop supports --auto-correct. +# Offense count: 15 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods. # AllowedMethods: present?, blank?, presence, try, try! Style/SafeNavigation: @@ -2177,9 +2076,7 @@ Style/SafeNavigation: - 'app/helpers/activities_helper.rb' - 'app/models/activities/json_attributes.rb' - 'app/models/asset_group.rb' - - 'app/models/assets/import.rb' - 'app/models/condition.rb' - - 'app/models/step_type.rb' - 'app/models/steps/queueable_job.rb' - 'app/models/user.rb' - 'lib/changes_support/disjoint_list.rb' @@ -2187,26 +2084,24 @@ Style/SafeNavigation: - 'lib/support_n3.rb' - 'spec/models/steps/background_tasks/inference_spec.rb' -# Offense count: 7 -# Cop supports --auto-correct. +# Offense count: 5 +# This cop supports safe auto-correction (--auto-correct). Style/SelfAssignment: Exclude: - - 'app/models/assets/import.rb' - - 'lib/parsers/csv_layout/line_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - 'script/runners/create_file.rb' - 'script/runners/create_layout.rb' - 'spec/models/action_spec.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowAsExpressionSeparator. Style/Semicolon: Exclude: - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' # Offense count: 3 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: only_raise, only_fail, semantic Style/SignalException: @@ -2214,13 +2109,14 @@ Style/SignalException: - 'spec/inferences_helper.rb' # Offense count: 3 -# Cop supports --auto-correct. +# This cop supports unsafe auto-correction (--auto-correct-all). Style/SlicingWithRange: Exclude: - 'app/models/asset.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' -# Offense count: 14 +# Offense count: 13 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowModifier. Style/SoleNestedConditional: Exclude: @@ -2236,21 +2132,20 @@ Style/SoleNestedConditional: - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - 'spec/integration/inference_spec.rb' -# Offense count: 22 -# Cop supports --auto-correct. +# Offense count: 20 +# This cop supports unsafe auto-correction (--auto-correct-all). +# Configuration parameters: Mode. Style/StringConcatenation: Exclude: - 'app/controllers/assets_controller.rb' - 'app/helpers/activities_helper.rb' - 'app/models/asset.rb' - - 'app/models/assets/export.rb' - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/inference_engines/runner/step_execution.rb' - 'script/runners/load_metadata.rb' - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - 'script/runners/rack_layout.rb' - 'script/runners/rack_layout_any_barcode.rb' - - 'script/runners/rack_layout_creating_tubes.rb' - 'spec/inferences_helper.rb' - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' @@ -2259,8 +2154,8 @@ Style/StringConcatenation: - 'spec/script/runners/transfer_samples_spec.rb' - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' -# Offense count: 737 -# Cop supports --auto-correct. +# Offense count: 734 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes Style/StringLiterals: @@ -2273,7 +2168,6 @@ Style/StringLiterals: - 'app/helpers/steps_helper.rb' - 'app/models/asset.rb' - 'app/models/asset_group.rb' - - 'app/models/assets/import.rb' - 'app/models/fact.rb' - 'app/models/step_type.rb' - 'app/views/printers/show.json.jbuilder' @@ -2314,7 +2208,6 @@ Style/StringLiterals: - 'script/runners/put_tubes_into_rack_by_column_order.rb' - 'script/runners/rack_layout.rb' - 'script/runners/rack_layout_any_barcode.rb' - - 'script/runners/rack_layout_creating_tubes.rb' - 'script/runners/transfer_plate_to_plate.rb' - 'script/runners/transfer_plate_to_plate_and_update_sequencescape.rb' - 'script/runners/transfer_samples.rb' @@ -2370,22 +2263,16 @@ Style/StringLiterals: - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' - 'spec/shared_examples/background_step.rb' -# Offense count: 72 -# Cop supports --auto-correct. +# Offense count: 74 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: MinSize. # SupportedStyles: percent, brackets Style/SymbolArray: EnforcedStyle: brackets -# Offense count: 2 -# Cop supports --auto-correct. -Style/SymbolLiteral: - Exclude: - - 'spec/lib/fact_changes_spec.rb' - # Offense count: 16 -# Cop supports --auto-correct. -# Configuration parameters: IgnoredMethods. +# This cop supports unsafe auto-correction (--auto-correct-all). +# Configuration parameters: AllowMethodsWithArguments, IgnoredMethods. # IgnoredMethods: respond_to, define_method Style/SymbolProc: Exclude: @@ -2397,8 +2284,8 @@ Style/SymbolProc: - 'spec/controllers/steps_controller_spec.rb' - 'spec/models/steps/cancellable_spec.rb' -# Offense count: 8 -# Cop supports --auto-correct. +# Offense count: 7 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, AllowSafeAssignment. # SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex Style/TernaryParentheses: @@ -2408,10 +2295,9 @@ Style/TernaryParentheses: - 'lib/fact_changes.rb' - 'spec/models/condition_spec.rb' - 'spec/models/step_execution_spec.rb' - - 'spec/remote_assets_helper.rb' # Offense count: 2 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyleForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, no_comma Style/TrailingCommaInArguments: @@ -2419,7 +2305,7 @@ Style/TrailingCommaInArguments: - 'app/models/user.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyleForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, no_comma Style/TrailingCommaInArrayLiteral: @@ -2427,7 +2313,7 @@ Style/TrailingCommaInArrayLiteral: - 'spec/models/step_type_spec.rb' # Offense count: 5 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyleForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, no_comma Style/TrailingCommaInHashLiteral: @@ -2436,7 +2322,7 @@ Style/TrailingCommaInHashLiteral: - 'lib/support_n3.rb' # Offense count: 1 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, AllowedMethods. # AllowedMethods: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym Style/TrivialAccessors: @@ -2444,28 +2330,27 @@ Style/TrivialAccessors: - 'lib/support_n3.rb' # Offense count: 2 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/UnlessElse: Exclude: - 'lib/fact_changes.rb' - 'spec/inferences_helper.rb' # Offense count: 2 -# Cop supports --auto-correct. +# This cop supports safe auto-correction (--auto-correct). Style/WhileUntilDo: Exclude: - 'script/runners/create_file.rb' - 'script/runners/create_layout.rb' -# Offense count: 75 -# Cop supports --auto-correct. +# Offense count: 77 +# This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, MinSize, WordRegex. # SupportedStyles: percent, brackets Style/WordArray: Exclude: - 'app/channels/activity_channel.rb' - 'app/models/assets/export.rb' - - 'app/models/assets/import.rb' - 'app/models/label_template.rb' - 'app/models/printer.rb' - 'lib/actions/plate_transfer.rb' @@ -2487,8 +2372,8 @@ Style/WordArray: - 'spec/models/assets/import_spec.rb' - 'spec/script/runners/load_metadata_spec.rb' -# Offense count: 27 -# Cop supports --auto-correct. +# Offense count: 22 +# This cop supports unsafe auto-correction (--auto-correct-all). Style/ZeroLengthPredicate: Exclude: - 'app/models/action.rb' @@ -2496,21 +2381,18 @@ Style/ZeroLengthPredicate: - 'app/models/asset_group.rb' - 'app/models/assets/traction_fields.rb' - 'app/models/steps/task.rb' - - 'lib/actions/racking.rb' - 'lib/changes_support/transaction_scope.rb' - 'lib/fact_changes.rb' - - 'lib/inference_engines/runner/step_execution.rb' - 'lib/parsers/csv_layout/line_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - 'lib/token_util.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - - 'spec/controllers/steps_controller_spec.rb' - 'spec/lib/actions/plate_transfer_spec.rb' - 'spec/models/step_spec.rb' -# Offense count: 96 -# Cop supports --auto-correct. -# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. +# Offense count: 125 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Layout/LineLength: - Max: 2354 + Max: 259 diff --git a/app/helpers/activities_helper.rb b/app/helpers/activities_helper.rb index bd6fae9a..977c7d47 100644 --- a/app/helpers/activities_helper.rb +++ b/app/helpers/activities_helper.rb @@ -63,51 +63,36 @@ def steps_without_operations_data_for_steps(steps) end def operations_data(operations) - occured_predicates = [] - operations.reduce([]) do |memo, fact| - if occured_predicates.include?(fact.predicate) - obj = memo.select { |f| f["predicate"] == fact.predicate }.first - obj["repeats"] = obj["repeats"] ? obj["repeats"] + 1 : 0 - next memo - end + operations.map do |fact| elem = fact.object_asset - if elem - obj = { "object_asset" => { - uuid: elem.uuid, - barcode: elem.barcode, - id: elem.id, - info_line: elem.info_line - } }.merge(fact.attributes) - else - obj = fact.attributes - end + obj = if elem + { "object_asset" => { + uuid: elem.uuid, + barcode: elem.barcode, + id: elem.id, + info_line: elem.info_line + } }.merge(fact.attributes) + else + fact.attributes + end obj[:asset] = fact.asset.attributes - memo.push(obj) - memo + obj end end def facts_data(facts) - occured_predicates = [] - facts.reduce([]) do |memo, fact| - if occured_predicates.include?(fact.predicate) - obj = memo.select { |f| f["predicate"] == fact.predicate }.first - obj["repeats"] = obj["repeats"] ? obj["repeats"] + 1 : 0 - next memo - end + facts.map do |fact| elem = fact.object_asset if elem - obj = { "object_asset" => { + { "object_asset" => { uuid: elem.uuid, barcode: elem.barcode, id: elem.id, info_line: elem.info_line } }.merge(fact.attributes) else - obj = fact.attributes + fact.attributes end - memo.push(obj) - memo end end diff --git a/app/models/activities/steps_management.rb b/app/models/activities/steps_management.rb index 98f230ff..4e729256 100644 --- a/app/models/activities/steps_management.rb +++ b/app/models/activities/steps_management.rb @@ -18,11 +18,13 @@ def steps_for(assets) end def step_types_for(assets, required_assets = nil) - stypes = step_types.not_for_reasoning.includes(:condition_groups => :conditions).select do |step_type| + # @todo This could be moved to the relationship + compatible_step_types = step_types.not_for_reasoning.includes(condition_groups: :conditions).distinct.select do |step_type| step_type.compatible_with?(assets, required_assets) end.uniq - stype = stypes.detect { |stype| steps.in_progress.for_step_type(stype).count > 0 } - stype.nil? ? stypes : [stype] + in_progress_step_type_ids = steps.in_progress.group(:step_type_id).pluck(:step_type_id) + in_progress_step_type = compatible_step_types.detect { |stype| in_progress_step_type_ids.include?(stype.id) } + in_progress_step_type.nil? ? compatible_step_types : [in_progress_step_type] end def step_types_active diff --git a/app/models/assets/export.rb b/app/models/assets/export.rb index 86b379a6..aacd3030 100644 --- a/app/models/assets/export.rb +++ b/app/models/assets/export.rb @@ -1,12 +1,12 @@ module Assets::Export class DuplicateLocations < StandardError; end - def update_sequencescape(_print_config, user, _step) + def update_sequencescape(user) FactChanges.new.tap do |updates| begin # remote (Sequencescape) updates - instance = SequencescapeClient.version_1_find_by_uuid(uuid) - instance = create_remote_asset unless instance + instance = SequencescapeClient.version_1_find_by_uuid(uuid) || create_remote_asset + create_or_update_remote_contained_assets(instance, user) unless attributes_to_send.empty? # local (Samples Extraction) updates @@ -53,13 +53,13 @@ def code39_barcode(instance) SBCF::SangerBarcode.new(prefix: prefix, number: number).human_barcode end - def update_wells(instance, updates) - instance.wells.each do |well| - fact = fact_well_at(well.location) + def update_wells(remote_plate, updates) + remote_plate.wells.each do |remote_well| + fact = fact_well_at(remote_well.location) if fact - w = fact.object_asset - if w && w.uuid != well.uuid - w.update_attributes(uuid: well.uuid) + local_well = fact.object_asset + if local_well && local_well.uuid != remote_well.uuid + local_well.update_attributes(uuid: remote_well.uuid) fact.update_attributes(is_remote?: true) end end @@ -67,11 +67,11 @@ def update_wells(instance, updates) end def fact_well_at(location) - facts.with_predicate('contains').select do |f| + facts.with_predicate('contains').detect do |f| if f.object_asset TokenUtil.unpad_location(f.object_asset.facts.with_predicate('location').first.object) == TokenUtil.unpad_location(location) end - end.first + end end def mark_as_updated(updates) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 2e08c0d1..735c1bb5 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -89,16 +89,19 @@ def refresh(fact_changes = nil) remote_asset = SequencescapeClient::find_by_uuid(uuid) raise RefreshSourceNotFoundAnymore unless remote_asset - if changed_remote?(remote_asset) - unless is_refreshing_right_now? - @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Refresh'), state: 'running') - _process_refresh(remote_asset, fact_changes) - end - end + refresh_from_remote(fact_changes: fact_changes, remote_asset: remote_asset) end self end + def refresh_from_remote(remote_asset:, fact_changes: nil) + return unless changed_remote?(remote_asset) + return if is_refreshing_right_now? + + @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Refresh'), state: 'running') + _process_refresh(remote_asset, fact_changes) + end + def refresh!(fact_changes = nil) if is_remote_asset? @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Refresh!!'), state: 'running') @@ -143,21 +146,28 @@ def _process_refresh(remote_asset, fact_changes) module ClassMethods def import_barcode(barcode) - asset = nil - @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Import'), state: 'running') remote_asset = SequencescapeClient::get_remote_asset(barcode) - if remote_asset - asset = Asset.create(barcode: barcode, uuid: remote_asset.uuid) + import_remote_asset(remote_asset, barcode, @import_step) if remote_asset + end + + def import_remote_asset(remote_asset, barcode, import_step) + Asset.create!(barcode: barcode, uuid: remote_asset.uuid).tap do |asset| FactChanges.new.tap do |updates| updates.replace_remote(asset, 'a', sequencescape_type_for_asset(remote_asset)) updates.replace_remote(asset, 'remoteAsset', remote_asset.uuid) - end.apply(@import_step) - asset.refresh + end.apply(import_step) + asset.refresh_from_remote(remote_asset: remote_asset) asset.update_compatible_activity_type end - asset + end + + def import_barcodes(barcodes) + @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Import'), state: 'running') + SequencescapeClient.labware(barcode: barcodes).map do |remote_asset| + import_remote_asset(remote_asset, remote_asset.labware_barcode['human_barcode'], @import_step) + end end def create_local_asset(barcode, updates) @@ -295,6 +305,33 @@ def keep_sync_with_sequencescape?(remote_asset) class_name = sequencescape_type_for_asset(remote_asset) class_name != 'SampleTube' end + + # Finds Assets with the provided barcodes in the local Assets table, and + # looks up any missing barcodes in Sequencescape, importing the assets if + # required. If a barcode is missing both locally, and in Sequencescape, it + # will not be included in the response. It is up to the caller to determine + # how to handle this. @note The behaviour differs from the singular + # #find_or_import_asset_with_barcode in that it will not also attempt to + # lookup by uuid, and will not automatically register fluidx barcodes + def find_or_import_assets_with_barcodes(barcodes, includes: :facts) + local_assets = Asset.includes(includes).where(barcode: barcodes).to_a + remote_assets = import_barcodes(barcodes - local_assets.pluck(:barcode)) + local_assets + remote_assets + end + + private + + def find_asset_with_barcode(barcode) + asset = Asset.find_by_barcode(barcode) || Asset.find_by_uuid(barcode) + + updates = FactChanges.new + + if asset.nil? && TokenUtil.is_valid_fluidx_barcode?(barcode) + asset = import_barcode(barcode) || Asset.create_local_asset(barcode, updates) + end + + asset&.refresh(updates) + asset end end end diff --git a/app/models/condition.rb b/app/models/condition.rb index 0e440015..1bef7290 100644 --- a/app/models/condition.rb +++ b/app/models/condition.rb @@ -35,7 +35,7 @@ def store_wildcard_values(wildcard_values, cg, asset, actual_values) end def check_related_condition_group(cg, fact, related_assets = [], checked_condition_groups = [], wildcard_values = {}) - related_asset = Asset.find(fact.object_asset_id) + related_asset = fact.object_asset # This condition does not support evaluating relations like: # ?a :t ?b . ?b :t ?c . ?c :t ?a . @@ -43,12 +43,12 @@ def check_related_condition_group(cg, fact, related_assets = [], checked_conditi # we would need to pass as an argument the list of condition_groups valid up to # this point, in which the only thing we need to validate is the object in the relations. # For the moment these types of relations will remain unsupported - if checked_condition_groups.include?(cg) - compatible = (fact.predicate == predicate) - else - checked_condition_groups << cg - compatible = ((fact.predicate == predicate) && cg.compatible_with?(related_asset, related_assets, checked_condition_groups, wildcard_values)) - end + compatible = if checked_condition_groups.include?(cg) + fact.predicate == predicate + else + checked_condition_groups << cg + (fact.predicate == predicate) && cg.compatible_with?(related_asset, related_assets, checked_condition_groups, wildcard_values) + end related_assets.push(related_asset) if compatible compatible end @@ -87,8 +87,7 @@ def compatible_with?(asset, related_assets = [], checked_condition_groups = [], if (object_condition_group_id.nil? || (fact.respond_to?(:object_asset_id) && fact.object_asset_id.nil?)) ((fact.predicate == predicate) && (fact.object == object)) else - cg = ConditionGroup.find(object_condition_group_id) - check_related_condition_group(cg, fact, related_assets, + check_related_condition_group(object_condition_group, fact, related_assets, checked_condition_groups, wildcard_values) end end diff --git a/app/models/fact.rb b/app/models/fact.rb index 3b123d82..6ea53962 100644 --- a/app/models/fact.rb +++ b/app/models/fact.rb @@ -1,7 +1,7 @@ # A Fact stores information about an {Asset} class Fact < ApplicationRecord - belongs_to :asset, :counter_cache => true - belongs_to :object_asset, :class_name => 'Asset' + belongs_to :asset, counter_cache: true + belongs_to :object_asset, class_name: 'Asset' scope :not_to_remove, ->() { where(:to_remove_by => nil) } scope :with_predicate, ->(predicate) { where(:predicate => predicate) } @@ -24,11 +24,11 @@ def set_to_add_by(step) end def object_value - literal? ? object : Asset.find(object_asset_id) + literal? ? object : object_asset end def object_value_or_uuid - literal? ? object : Asset.find(object_asset_id).uuid + literal? ? object : object_asset.uuid end def object_label diff --git a/app/models/step_type.rb b/app/models/step_type.rb index 91ec6e53..a0bb94c9 100644 --- a/app/models/step_type.rb +++ b/app/models/step_type.rb @@ -26,9 +26,9 @@ def self.for_task_type(task_type) select { |stype| stype.task_type == task_type } end - scope :for_reasoning, ->() { not_deprecated.where(:for_reasoning => true).order(priority: :desc) } + scope :for_reasoning, ->() { not_deprecated.where(for_reasoning: true).order(priority: :desc) } - scope :not_for_reasoning, ->() { not_deprecated.where(:for_reasoning => false) } + scope :not_for_reasoning, ->() { not_deprecated.where(for_reasoning: false) } def touch_activities activities.each do |activity| diff --git a/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb b/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb index 6d2cf4b5..14bb50a5 100644 --- a/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb +++ b/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb @@ -85,7 +85,7 @@ def process end def updates - ActiveRecord::Base.transaction { process.to_h } + ActiveRecord::Base.transaction { process } rescue StandardError => e { set_errors: ["Unknown error while applying barcodes: #{e.message}, #{e.backtrace}"] } end diff --git a/app/step_planners/step_planner/rack_layout_creating_tubes.rb b/app/step_planners/step_planner/rack_layout_creating_tubes.rb index de232ba2..5c04330c 100644 --- a/app/step_planners/step_planner/rack_layout_creating_tubes.rb +++ b/app/step_planners/step_planner/rack_layout_creating_tubes.rb @@ -27,7 +27,7 @@ def process end def updates - ActiveRecord::Base.transaction { process.to_h } + ActiveRecord::Base.transaction { process } rescue InvalidDataParams => e { set_errors: e.errors } rescue StandardError => e diff --git a/lib/actions/racking.rb b/lib/actions/racking.rb index 1962256d..8cf3a2eb 100644 --- a/lib/actions/racking.rb +++ b/lib/actions/racking.rb @@ -65,8 +65,8 @@ def fact_changes_for_unrack_tubes(list_layout, destination_rack = nil) return updates if tubes.empty? tubes_ids = tubes.map(&:id) - tubes_list = Asset.where(id: tubes_ids).includes(:facts) - tubes_list.each_with_index do |tube, index| + # tubes_list = Asset.where(id: tubes_ids).includes(facts: { object_asset: { facts: :object_asset } }) + tubes.each_with_index do |tube, index| location_facts = tube.facts.with_predicate('location') unless location_facts.empty? location = location_facts.first.object @@ -76,7 +76,8 @@ def fact_changes_for_unrack_tubes(list_layout, destination_rack = nil) previous_rack = parent_fact.object_asset unless (previous_racks.include?(previous_rack)) previous_racks.push(previous_rack) - updates.remove(previous_rack.facts.with_predicate('contains').where(object_asset_id: tubes_ids)) + old_facts = previous_rack.facts.with_predicate('contains').select { |fact| tubes_ids.include?(fact.object_asset_id) } + updates.remove(old_facts) end if destination_rack @@ -243,7 +244,7 @@ def csv_parsing(parser) end raise InvalidDataParams, error_messages if error_messages.count > 0 - asset = asset_group.assets.with_fact('a', 'TubeRack').first + asset = tube_racks.first if parser.valid? rack = asset diff --git a/lib/changes_support/disjoint_list.rb b/lib/changes_support/disjoint_list.rb index bb035c2e..9d171322 100644 --- a/lib/changes_support/disjoint_list.rb +++ b/lib/changes_support/disjoint_list.rb @@ -216,9 +216,9 @@ def _unique_id_for_element(element, deep = 0) if element.kind_of?(String) sum_function_for(element) - elsif (element.respond_to?(:uuid) && (!element.uuid.nil?)) + elsif element.try(:uuid) sum_function_for(element.uuid) - elsif (element.respond_to?(:id) && !element.id.nil?) + elsif element.try(:id) sum_function_for("#{element.class.to_s}_#{element.id.to_s}") elsif element.kind_of?(Hash) if (element.has_key?(:uuid) && (!element[:uuid].nil?)) diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index 08a2fe1f..c21d7046 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -3,15 +3,18 @@ require 'changes_support/transaction_scope' class FactChanges + ACTIONS = [ + 'set_errors', 'create_assets', 'create_asset_groups', 'delete_asset_groups', + 'remove_facts', 'add_facts', 'delete_assets', 'add_assets', 'remove_assets' + ].freeze + include ChangesSupport::TransactionScope attr_accessor :facts_to_destroy, :facts_to_add, :assets_to_create, :assets_to_destroy, :assets_to_add, :assets_to_remove, :wildcards, :instances_from_uuid, :asset_groups_to_create, :asset_groups_to_destroy, :errors_added, :already_added_to_list, :instances_by_unique_id, - :facts_to_set_to_remote - - attr_accessor :operations + :facts_to_set_to_remote, :operations def initialize(json = nil) @assets_updated = [] @@ -19,12 +22,7 @@ def initialize(json = nil) parse_json(json) unless json.nil? end - def parsing_valid? - @parsing_valid - end - def reset - @parsing_valid = false @errors_added = [] @facts_to_set_to_remote = [] @@ -95,14 +93,11 @@ def to_json end def parse_json(json) - obj = json.is_a?(String) ? JSON.parse(json) : json.deep_stringify_keys - ['set_errors', 'create_assets', 'create_asset_groups', 'delete_asset_groups', - 'remove_facts', 'add_facts', 'delete_assets', 'add_assets', 'remove_assets'].each do |action_type| - if obj[action_type] - send(action_type, obj[action_type]) - end + actions_data = json.is_a?(String) ? JSON.parse(json) : json.deep_stringify_keys + actions_data.slice(*ACTIONS).each_pair do |action_type, action_value| + send(action_type, action_value) if action_value end - @parsing_valid = true + true end def values_for_predicate(asset, predicate) @@ -116,11 +111,11 @@ def values_for_predicate(asset, predicate) (actual_values + values_to_add - values_to_destroy) end - def _build_fact_attributes(s, p, o, options = {}) - t = [s, p, o, options] - params = { asset: t[0], predicate: t[1], literal: !(t[2].kind_of?(Asset)) } - params[:literal] ? params[:object] = t[2] : params[:object_asset] = t[2] - params = params.merge(t[3]) if t[3] + def _build_fact_attributes(asset, predicate, object, options = {}) + literal = !(object.kind_of?(Asset)) + params = { asset: asset, predicate: predicate, literal: literal } + literal ? params[:object] = object : params[:object_asset] = object + params = params.merge(options) if options params end @@ -134,13 +129,13 @@ def add(s, p, o, options = {}) # facts_to_add.push(track_object(params)) unless detected end - def add_facts(listOfLists) - listOfLists.each { |list| add(list[0], list[1], list[2]) } + def add_facts(list_of_lists) + list_of_lists.each { |list| add(list[0], list[1], list[2]) } self end - def remove_facts(listOfLists) - listOfLists.each { |list| remove_where(list[0], list[1], list[2]) } + def remove_facts(list_of_lists) + list_of_lists.each { |list| remove_where(list[0], list[1], list[2]) } self end @@ -148,14 +143,14 @@ def add_remote(s, p, o, options = {}) add(s, p, o, options.merge({ is_remote?: true })) if (s && p && o) end - def replace_remote(asset, p, o, options = {}) - if (asset && p && o) - asset.facts.with_predicate(p).each do |fact| + def replace_remote(asset, predicate, object, options = {}) + if (asset && predicate && object) + asset.facts.with_predicate(predicate).each do |fact| remove(fact) # In case they are not removed, at least they will be set as remote facts_to_set_to_remote << fact end - add_remote(asset, p, o, options) + add_remote(asset, predicate, object, options) end end @@ -165,7 +160,7 @@ def remove(f) if f.kind_of?(Enumerable) facts_to_destroy << f.map { |o| o.attributes.symbolize_keys } elsif f.kind_of?(Fact) - facts_to_destroy << f.attributes.symbolize_keys if f + facts_to_destroy << f.attributes.symbolize_keys end end @@ -274,7 +269,7 @@ def build_asset_groups(asset_groups) end def is_new_record?(uuid) - !!(instances_from_uuid[uuid] && instances_from_uuid[uuid].new_record?) + !!(instances_from_uuid[uuid]&.new_record?) end def find_instance_of_class_by_uuid(klass, instance_or_uuid_or_id, create = false) diff --git a/lib/inference_engines/runner/step_execution.rb b/lib/inference_engines/runner/step_execution.rb index 2b129841..1547df01 100644 --- a/lib/inference_engines/runner/step_execution.rb +++ b/lib/inference_engines/runner/step_execution.rb @@ -36,6 +36,17 @@ def debug_log(params) end end + def bm(step) + puts "=" * 80 + puts "#{step} STARTING" + t = Process.clock_gettime(Process::CLOCK_MONOTONIC) + r = yield + t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC) + puts "=" * 80 + puts "#{step} TOOK #{t2 - t}" + r + end + def step_action CONVERTED_CLASS_ACTIONS.fetch(@step.step_type.step_action, @step.step_type.step_action) end @@ -46,7 +57,7 @@ def handled_by_class? def generate_plan if handled_by_class? - generate_plan_from_class + bm(:generate_plan) { generate_plan_from_class } else generate_plan_from_external_process end @@ -56,9 +67,9 @@ def generate_plan_from_class klass = step_action.constantize step_planner = klass.new(@asset_group.id, @step.id) - @content = step_planner.updates - step.update_attributes(output: @content) - @updates = FactChanges.new(content) + @content = bm(:sp_updates) { step_planner.updates } + bm(:uat) { step.update_attributes(output: @content) } + @updates = bm(:FCN) { @content } end def generate_plan_from_external_process @@ -95,7 +106,7 @@ def plan def apply if asset_group.assets.with_fact('pushTo', 'Sequencescape').count > 0 asset_group.assets.with_fact('pushTo', 'Sequencescape').each do |asset| - @updates.merge(asset.update_sequencescape(step.printer_config, step.user, step)) + @updates.merge(asset.update_sequencescape(step.user)) end end @updates.apply(step) diff --git a/lib/parsers/csv_layout/barcode_creatable_parser.rb b/lib/parsers/csv_layout/barcode_creatable_parser.rb index 57f6eca9..886580b5 100644 --- a/lib/parsers/csv_layout/barcode_creatable_parser.rb +++ b/lib/parsers/csv_layout/barcode_creatable_parser.rb @@ -8,7 +8,7 @@ def updater end def asset - @instance ||= @parser.find_or_import_asset_with_barcode(barcode) + @instance ||= @parser.find_or_import_asset_with_barcode(barcode) # || Asset.create_local_asset(barcode, updater) return @instance if @instance diff --git a/lib/parsers/csv_layout/csv_parser.rb b/lib/parsers/csv_layout/csv_parser.rb index 7116b93f..37706b7e 100644 --- a/lib/parsers/csv_layout/csv_parser.rb +++ b/lib/parsers/csv_layout/csv_parser.rb @@ -58,11 +58,21 @@ def error_list end def find_or_import_asset_with_barcode(barcode) - Asset.find_or_import_asset_with_barcode(barcode) + asset_cache.fetch(barcode, nil) end protected + def asset_cache + @asset_cache ||= Asset.find_or_import_assets_with_barcodes( + @line_parser.barcodes, + # Include the facts, any associated objects (such as tube racks) + # and their associated facts + # It may make sense to tidy these up with explicit associations + includes: { facts: { object_asset: { facts: :object_asset } } } + ).index_by(&:barcode) + end + def validate_parsed_data parse unless @parsed unless @line_parser.valid? diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 67340623..9f4d25fd 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -1,12 +1,12 @@ -# This file is part of SEQUENCESCAPE is distributed under the terms of GNU General Public License version 1 or later; -# Please refer to the LICENSE and README files for information on licensing and authorship of this file. -# Copyright (C) 2007-2011 Genome Research Ltd. +# frozen_string_literal: true + require 'sequencescape-api' require 'sequencescape' require 'sequencescape_client_v2' class SequencescapeClient + SELECT_FOR_IMPORT = 'uuid,labware_barcode' @purposes = nil def self.api_connection_options @@ -38,10 +38,9 @@ def self.purpose_by_name(name) client.plate_purpose.all.select { |p| p.name === name }.first end - def self.create_plate(purpose_name, attrs) - attrs = {} + def self.create_plate(purpose_name) purpose = purpose_by_name(purpose_name) || purpose_by_name('Stock Plate') - purpose.plates.create!(attrs) + purpose.plates.create!({}) end def self.get_study_by_name(name) @@ -66,6 +65,14 @@ def self.find_by_uuid(uuid) find_by(uuid: uuid) end + def self.labware(conditions) + SequencescapeClientV2::Labware.select( + tubes: SELECT_FOR_IMPORT, + plates: SELECT_FOR_IMPORT, + tube_racks: SELECT_FOR_IMPORT + ).where(conditions) + end + # TODO: In most cases we should know what type of record we're looking up. def self.find_by(search_conditions) [ diff --git a/script/runners/update_sequencescape.rb b/script/runners/update_sequencescape.rb index 5fb345e5..84f25f65 100644 --- a/script/runners/update_sequencescape.rb +++ b/script/runners/update_sequencescape.rb @@ -25,7 +25,7 @@ def process if assets_compatible_with_step_type ActiveRecord::Base.transaction do asset_group.assets.with_fact('pushTo', 'Sequencescape').each do |asset| - updates.merge(asset.update_sequencescape(step.printer_config, step.user, step)) + updates.merge(asset.update_sequencescape(step.user)) end end end diff --git a/spec/models/assets/export_spec.rb b/spec/models/assets/export_spec.rb index b87270ce..8c7dcab8 100644 --- a/spec/models/assets/export_spec.rb +++ b/spec/models/assets/export_spec.rb @@ -116,7 +116,7 @@ allow(plate).to receive(:barcode).and_return(barcode) expect(asset.facts.where(predicate: 'contains').count).to eq(0) - asset.update_sequencescape(print_config, user, step).apply(step) + asset.update_sequencescape(user).apply(step) asset.refresh expect(asset.facts.where(predicate: 'contains').count).to eq(plate.wells.count) end diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index be8144f2..c08fd88a 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -138,13 +138,6 @@ end end - shared_examples 'an attempted import' do - it 'should try to obtain the asset through the Sequencescape API' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_asset.barcode) - expect(SequencescapeClient).to have_received(:find_by_uuid).with(@remote_asset.uuid) - end - end - shared_examples 'a plate or tube rack' do it 'should create the corresponding facts from the json' do @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) @@ -291,8 +284,6 @@ stub_client_with_asset(SequencescapeClient, @remote_asset) end - it_behaves_like 'an attempted import' - context 'when the supplier name has not been provided' do setup do sample_no_supplier_name = build_remote_sample( @@ -335,7 +326,6 @@ end it_behaves_like 'a plate or tube rack' - it_behaves_like 'an attempted import' context 'when the supplier sample name has not been provided to some samples' do setup do @@ -396,7 +386,6 @@ end it_behaves_like 'a plate or tube rack' - it_behaves_like 'an attempted import' context 'when the supplier sample name has not been provided to some samples' do setup do @@ -422,4 +411,45 @@ end end end + + describe '#find_or_import_assets_with_barcodes' do + let(:local_barcode) { generate(:barcode) } + let(:remote_barcode) { generate(:barcode) } + let(:non_existant_barcode) { 'NOT_FOUND' } + let(:remote_labware) do + SequencescapeClientV2::Labware.new(uuid: SecureRandom.uuid, labware_barcode: { 'human_barcode' => remote_barcode }, type: 'tubes') + end + let(:full_remote_labware) { build_remote_tube(barcode: generate(:barcode), uuid: remote_labware.uuid, labware_barcode: remote_labware.labware_barcode) } + let(:local_asset) { Asset.create!(barcode: local_barcode) } + + before do + local_asset + expect(SequencescapeClient).to receive(:labware).with(barcode: [remote_barcode, non_existant_barcode]).and_return([remote_labware]) + # We still need this as we're currently immediately refreshing the resource from SS + allow(SequencescapeClient).to receive(:find_by_uuid).with(remote_labware.uuid).and_return(full_remote_labware) + end + + subject(:find_or_import_assets_with_barcodes) do + Asset.find_or_import_assets_with_barcodes([local_barcode, remote_barcode, non_existant_barcode]) + end + + it 'imports only remote barcodes' do + expect { find_or_import_assets_with_barcodes }.to change(Asset, :count).by(1) + end + + it 'does not return an asset that does not exist' do + expect(find_or_import_assets_with_barcodes.pluck(:barcode)).not_to include(non_existant_barcode) + end + + it { is_expected.to(satisfy { |array| array.length == 2 }) } + it { is_expected.to all be_an Asset } + + it 'returns local assets' do + expect(find_or_import_assets_with_barcodes).to include(local_asset) + end + + it 'returns a newly registered remote labware' do + expect(find_or_import_assets_with_barcodes.pluck(:barcode)).to include(remote_barcode) + end + end end From b40bd9c018dc52381dd228e6faff7b767d8962d6 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 25 Mar 2022 16:20:47 +0000 Subject: [PATCH 137/303] Fix accidental external calls - Add webmock to block calls in future - Mock the SS calls, rather than higher level --- Gemfile | 4 ++++ Gemfile.lock | 8 ++++++++ spec/lib/actions/racking_spec.rb | 7 +++---- spec/lib/parsers/csv_layout/csv_parser_spec.rb | 6 +++--- spec/spec_helper.rb | 2 ++ 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Gemfile b/Gemfile index 58b16db5..e6069917 100644 --- a/Gemfile +++ b/Gemfile @@ -90,6 +90,10 @@ group :development do gem 'rubocop', require: false gem 'rubocop-performance' gem 'rubocop-rails' + # Lets mocking of HTTP requests, but importantly also prevents unintentional outbound connections + # I had tests connecting to my dev copy of SS and passing, and only noticed the failures on the CI. + # Suspect we'll also end up using it properly, especially for integration tests + gem 'webmock' end group :deployment do diff --git a/Gemfile.lock b/Gemfile.lock index 12d1efe9..599fc805 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -94,6 +94,8 @@ GEM coderay (1.1.3) concurrent-ruby (1.1.9) connection_pool (2.2.5) + crack (0.4.5) + rexml crass (1.0.6) daemons (1.3.1) database_cleaner (2.0.1) @@ -137,6 +139,7 @@ GEM gmetric (0.1.3) hamster (3.0.0) concurrent-ruby (~> 1.0) + hashdiff (1.0.1) http-cookie (1.0.3) domain_name (~> 0.5) i18n (1.10.0) @@ -397,6 +400,10 @@ GEM activemodel (>= 5.0) bindex (>= 0.4.0) railties (>= 5.0) + webmock (3.14.0) + addressable (>= 2.8.0) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) webpacker (5.4.3) activesupport (>= 5.2) rack-proxy (>= 0.6.1) @@ -471,6 +478,7 @@ DEPENDENCIES turbolinks tzinfo-data web-console + webmock webpacker webpacker-react will_paginate diff --git a/spec/lib/actions/racking_spec.rb b/spec/lib/actions/racking_spec.rb index 45b80fc6..4b8dac75 100644 --- a/spec/lib/actions/racking_spec.rb +++ b/spec/lib/actions/racking_spec.rb @@ -33,9 +33,7 @@ def initialize(asset_group) include Actions::Racking setup do - allow(Asset).to receive(:find_or_import_asset_with_barcode) do |barcode| - Asset.find_by(barcode: barcode) - end + allow(SequencescapeClient).to receive(:labware).and_return([]) end shared_examples_for 'rack_layout' do @@ -83,8 +81,9 @@ def initialize(asset_group) assets = asset.reload.facts.with_predicate('contains').map(&:object_asset) expect(assets.count).to eq(0) - assets = actual_parent.reload.facts.with_predicate('contains').map(&:object_asset) + assets = actual_parent.reload.facts.with_predicate('contains').includes(object_asset: :facts).map(&:object_asset) expect(assets.count).to eq(96) + assets.each do |a| expect(a.facts.with_predicate('location').count).to eq(1) expect(a.facts.with_predicate('parent').count).to eq(1) diff --git a/spec/lib/parsers/csv_layout/csv_parser_spec.rb b/spec/lib/parsers/csv_layout/csv_parser_spec.rb index bbaa4f23..e3678394 100644 --- a/spec/lib/parsers/csv_layout/csv_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/csv_parser_spec.rb @@ -19,9 +19,7 @@ } setup do - allow(Asset).to receive(:find_or_import_asset_with_barcode) do |barcode| - Asset.find_by(barcode: barcode) - end + allow(SequencescapeClient).to receive(:labware).and_return([]) @content = File.read('test/data/layout.csv') @assets = 96.times.map do |i| @@ -63,6 +61,7 @@ @csv = Parsers::CsvLayout::CsvParser.new("A01,FR11200002\rA02,FR11200003") expect(@csv).to be_valid end + it 'detects tube duplication' do asset1 = create :asset, barcode: 'FR000001' content = "A01,#{asset1.barcode}\nB01,#{asset1.barcode}" @@ -70,6 +69,7 @@ expect(csv).not_to be_valid expect(csv.error_list.length).to eq(1) end + it 'detects location duplication' do asset1 = create :asset, barcode: 'FR000001' asset2 = create :asset, barcode: 'FR000002' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ce600bce..0c15bb82 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -20,6 +20,8 @@ # # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration require 'aasm/rspec' +require 'webmock/rspec' + RSpec.configure do |config| # rspec-expectations config goes here. You can use an alternate # assertion/expectation library such as wrong or the stdlib/minitest From a9762d9019deccc089e4b6fcae5a97b7c9622e08 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 29 Mar 2022 16:15:44 +0100 Subject: [PATCH 138/303] Initial pass on asset_groups controller Still slow, and I need to evaluate the behaviour of tube racks as we're not including receptacles/racked tubes when loading in bulk --- app/channels/activity_channel.rb | 44 ++-- app/controllers/asset_groups_controller.rb | 1 - app/models/asset.rb | 2 +- app/models/assets/export.rb | 6 +- app/models/assets/import.rb | 198 ++++++++---------- lib/fact_changes.rb | 3 +- .../runner/step_execution.rb | 6 +- lib/sequencescape_client.rb | 24 ++- lib/sequencescape_client_v2.rb | 18 ++ .../asset_groups_controller_spec.rb | 5 +- spec/models/assets/export_spec.rb | 3 +- spec/models/assets/import_spec.rb | 12 +- spec/remote_assets_helper.rb | 31 ++- 13 files changed, 198 insertions(+), 155 deletions(-) diff --git a/app/channels/activity_channel.rb b/app/channels/activity_channel.rb index a892b215..0856f0d0 100644 --- a/app/channels/activity_channel.rb +++ b/app/channels/activity_channel.rb @@ -23,28 +23,38 @@ def self.subscribed_ids end def receive(data) - process_asset_group(strong_params_for_asset_group(data)) if (data["asset_group"]) - process_activity(strong_params_for_activity(data)) if (data["activity"]) + process_asset_group(strong_params_for_asset_group(data)) if data["asset_group"] + process_activity(strong_params_for_activity(data)) if data["activity"] end def process_asset_group(strong_params) asset_group = AssetGroup.find(strong_params[:id]) assets = strong_params[:assets] - if asset_group && assets - begin - received_list = assets.filter_map do |uuid_or_barcode| - Asset.find_or_import_asset_with_barcode(uuid_or_barcode) - end - - asset_group.update_with_assets(received_list) - - # asset_group.update_attributes(assets: received_list) - # asset_group.touch - rescue Errno::ECONNREFUSED => e - asset_group.activity.send_wss_event({ error: { type: 'danger', msg: 'Cannot connect with sequencescape' } }) - rescue StandardError => e - asset_group.activity.send_wss_event({ error: { type: 'danger', msg: e.message } }) - end + + # @todo This probably shouldn't a be a silent failure, and we should instead + # throw something akin to ActionController::ParameterMissing but I'm not + # currently sure what we expect here. So maintaining existing behaviour. + return unless assets + + # @note The array here can contain both asset barcodes, and uuids, or even a mixture of the + # two. + asset_uuids, asset_barcodes = assets.partition { |identifier| TokenUtil.is_uuid?(identifier) } + + begin + uuid_assets = Asset.where(uuid: asset_uuids).to_a + barcode_assets = Asset.find_or_import_assets_with_barcodes(asset_barcodes) + + # Maintaining existing behaviour: register previously unknown fluidx barcodes + fluidx_barcodes = asset_barcodes.select { |bc| TokenUtil.is_valid_fluidx_barcode?(bc) } + missing_barcodes = fluidx_barcodes - barcode_assets.map(&:barcode) + facts = FactChanges.new + generated_assets = missing_barcodes.map { |bc| Asset.create_local_asset(bc, facts) } + + asset_group.update_with_assets(uuid_assets + barcode_assets + generated_assets) + rescue Errno::ECONNREFUSED => e + asset_group.activity.send_wss_event({ error: { type: 'danger', msg: 'Cannot connect with sequencescape' } }) + rescue StandardError => e + asset_group.activity.send_wss_event({ error: { type: 'danger', msg: e.message } }) end end diff --git a/app/controllers/asset_groups_controller.rb b/app/controllers/asset_groups_controller.rb index e7cb7a68..76f2076e 100644 --- a/app/controllers/asset_groups_controller.rb +++ b/app/controllers/asset_groups_controller.rb @@ -21,7 +21,6 @@ def update @assets = @asset_group.assets head :ok - # render json: { asset_group: {assets: @asset_group.assets.map(&:uuid) }} end def upload diff --git a/app/models/asset.rb b/app/models/asset.rb index ec43d0b9..24fe30b6 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -241,7 +241,7 @@ def purpose_name end def aliquot - # @todo: Falling back to an empty string, rather than nil feels a bit risky, but this maintains tearlier behaviour. + # @todo: Falling back to an empty string, rather than nil feels a bit risky, but this maintains earlier behaviour. # (We don't have any cases of facts with predicate aliquotType and value NULL) facts.with_predicate('aliquotType').first&.object || '' end diff --git a/app/models/assets/export.rb b/app/models/assets/export.rb index aacd3030..b564c11e 100644 --- a/app/models/assets/export.rb +++ b/app/models/assets/export.rb @@ -1,11 +1,13 @@ module Assets::Export class DuplicateLocations < StandardError; end + # NOTE: This is a little concerning, as it will only work for plates, and yet + # pushTo is was also being set for wells (and tubeRacks, but that may be intentional) def update_sequencescape(user) FactChanges.new.tap do |updates| begin # remote (Sequencescape) updates - instance = SequencescapeClient.version_1_find_by_uuid(uuid) || create_remote_asset + instance = SequencescapeClient.version_1_find_by_uuid(uuid) || create_remote_plate create_or_update_remote_contained_assets(instance, user) unless attributes_to_send.empty? @@ -34,7 +36,7 @@ def update_sequencescape(user) end end - def create_remote_asset + def create_remote_plate SequencescapeClient.create_plate(purpose_name) if purpose_name end diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 735c1bb5..275b1e0f 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -18,14 +18,14 @@ def json_for_remote(remote_asset) # FOR A PLATE if remote_asset.respond_to?(:wells) && remote_asset.wells # wells.to_a because wells relation does not act as an array - listw = remote_asset.wells.to_a - if listw + wells = remote_asset.wells.to_a + if wells # aliquots.to_a, same reason - listal = listw.compact.map(&:aliquots).map(&:to_a) - if listal - listsa = listal.flatten.compact.map { |al| al.sample } - if listsa - distinct += listsa.compact.map(&:attributes).to_json + aliquots = wells.compact.map(&:aliquots).map(&:to_a) + if aliquots + samples = aliquots.flatten.compact.map { |al| al.sample } + if samples + distinct += samples.compact.map(&:attributes).to_json end end end @@ -34,11 +34,11 @@ def json_for_remote(remote_asset) # FOR A TUBE if remote_asset.respond_to?(:aliquots) && remote_asset.aliquots # aliquots.to_a, same reason - listal = remote_asset.aliquots.to_a - if listal - listsa = listal.flatten.compact.map { |al| al.sample } - if listsa - distinct += listsa.compact.map(&:attributes).to_json + aliquots = remote_asset.aliquots.to_a + if aliquots + samples = aliquots.flatten.compact.map { |al| al.sample } + if samples + distinct += samples.compact.map(&:attributes).to_json end end end @@ -52,11 +52,11 @@ def json_for_remote(remote_asset) if list_tubes # aliquots.to_a, same reason - listal = list_tubes.compact.map(&:aliquots).map(&:to_a) - if listal - listsa = listal.flatten.compact.map { |al| al.sample } - if listsa - distinct += listsa.compact.map(&:attributes).to_json + aliquots = list_tubes.compact.map(&:aliquots).map(&:to_a) + if aliquots + samples = aliquots.flatten.compact.map { |al| al.sample } + if samples + distinct += samples.compact.map(&:attributes).to_json end end end @@ -152,17 +152,6 @@ def import_barcode(barcode) import_remote_asset(remote_asset, barcode, @import_step) if remote_asset end - def import_remote_asset(remote_asset, barcode, import_step) - Asset.create!(barcode: barcode, uuid: remote_asset.uuid).tap do |asset| - FactChanges.new.tap do |updates| - updates.replace_remote(asset, 'a', sequencescape_type_for_asset(remote_asset)) - updates.replace_remote(asset, 'remoteAsset', remote_asset.uuid) - end.apply(import_step) - asset.refresh_from_remote(remote_asset: remote_asset) - asset.update_compatible_activity_type - end - end - def import_barcodes(barcodes) @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Import'), state: 'running') SequencescapeClient.labware(barcode: barcodes).map do |remote_asset| @@ -171,67 +160,62 @@ def import_barcodes(barcodes) end def create_local_asset(barcode, updates) - asset = nil ActiveRecord::Base.transaction do - asset = Asset.create!(:barcode => barcode) - updates.add(asset, 'a', 'Tube') - updates.add(asset, 'barcodeType', 'Code2D') - updates.add(asset, 'is', 'Empty') + Asset.create!(:barcode => barcode).tap do |asset| + updates.add(asset, 'a', 'Tube') + updates.add(asset, 'barcodeType', 'Code2D') + updates.add(asset, 'is', 'Empty') + end end - asset end + # Caution: This method had unexpected side effects. It will: + # 1) Also find assets by uuid + # 2) Automatically create an asset if the barcode passed to it is a fluidx format barcode def find_or_import_asset_with_barcode(barcode) barcode = TokenUtil.human_barcode(barcode) if TokenUtil.machine_barcode?(barcode) find_asset_with_barcode(barcode) || import_barcode(barcode) end + # One call def update_asset_from_remote_asset(asset, remote_asset, fact_changes) - fact_changes.tap do |updates| - class_name = sequencescape_type_for_asset(remote_asset) - updates.replace_remote(asset, 'a', class_name) - - if keep_sync_with_sequencescape?(remote_asset) - updates.replace_remote(asset, 'pushTo', 'Sequencescape') - if remote_asset.try(:purpose) - updates.replace_remote(asset, 'purpose', remote_asset.purpose.name) - end - end - updates.replace_remote(asset, 'is', 'NotStarted') + fact_changes.replace_remote(asset, 'a', sequencescape_type_for_asset(remote_asset)) - annotate_container(asset, remote_asset, updates) - annotate_wells(asset, remote_asset, updates) - annotate_tubes(asset, remote_asset, updates) - annotate_study_name(asset, remote_asset, updates) - - asset.update_digest_with_remote(remote_asset) + if remote_asset.sync? + fact_changes.replace_remote(asset, 'pushTo', 'Sequencescape') + fact_changes.replace_remote(asset, 'purpose', remote_asset.purpose.name) if remote_asset.try(:purpose) end + + fact_changes.replace_remote(asset, 'is', 'NotStarted') + + annotate_container(asset, remote_asset, fact_changes) + annotate_wells(asset, remote_asset, fact_changes) + annotate_tubes(asset, remote_asset, fact_changes) + annotate_study_name(asset, remote_asset, fact_changes) + + asset.update_digest_with_remote(remote_asset) end def annotate_container(asset, remote_asset, fact_changes) - fact_changes.tap do |updates| - if remote_asset.try(:aliquots) - remote_asset.aliquots.each do |aliquot| - updates.replace_remote(asset, 'sample_tube', asset) - updates.replace_remote(asset, 'sanger_sample_id', TokenUtil.quote_if_uuid(aliquot&.sample&.sanger_sample_id)) - updates.replace_remote(asset, 'sample_uuid', TokenUtil.quote(aliquot&.sample&.uuid), literal: true) - updates.replace_remote(asset, 'sanger_sample_name', TokenUtil.quote_if_uuid(aliquot&.sample&.name)) - updates.replace_remote(asset, 'supplier_sample_name', TokenUtil.quote_if_uuid(aliquot&.sample&.sample_metadata&.supplier_name)) - updates.replace_remote(asset, 'sample_common_name', TokenUtil.quote_if_uuid(aliquot&.sample&.sample_metadata&.sample_common_name)) - end - end + return unless remote_asset.try(:aliquots) + + remote_asset.aliquots.each do |aliquot| + fact_changes.replace_remote(asset, 'sample_tube', asset) + fact_changes.replace_remote(asset, 'sanger_sample_id', TokenUtil.quote_if_uuid(aliquot&.sample&.sanger_sample_id)) + fact_changes.replace_remote(asset, 'sample_uuid', TokenUtil.quote(aliquot&.sample&.uuid), literal: true) + fact_changes.replace_remote(asset, 'sanger_sample_name', TokenUtil.quote_if_uuid(aliquot&.sample&.name)) + fact_changes.replace_remote(asset, 'supplier_sample_name', TokenUtil.quote_if_uuid(aliquot&.sample&.sample_metadata&.supplier_name)) + fact_changes.replace_remote(asset, 'sample_common_name', TokenUtil.quote_if_uuid(aliquot&.sample&.sample_metadata&.sample_common_name)) end end def annotate_study_name_from_aliquots(asset, remote_asset, fact_changes) - fact_changes.tap do |updates| - if remote_asset.try(:aliquots) - if ((remote_asset.aliquots.count == 1) && (remote_asset.aliquots.first.sample)) - updates.replace_remote(asset, 'study_name', remote_asset.aliquots.first.study.name) - updates.replace_remote(asset, 'study_uuid', TokenUtil.quote(remote_asset.aliquots.first.study.uuid), literal: true) - end - end - end + return unless remote_asset.try(:aliquots) + + return unless ((remote_asset.aliquots.count == 1) && (remote_asset.aliquots.first.sample)) + + fact_changes.replace_remote(asset, 'study_name', remote_asset.aliquots.first.study.name) + fact_changes.replace_remote(asset, 'study_uuid', TokenUtil.quote(remote_asset.aliquots.first.study.uuid), literal: true) end def annotate_study_name(asset, remote_asset, fact_changes) @@ -249,45 +233,41 @@ def annotate_study_name(asset, remote_asset, fact_changes) end def annotate_wells(asset, remote_asset, fact_changes) - fact_changes.tap do |updates| - if remote_asset.try(:wells) - remote_asset.wells.each do |well| - local_well = Asset.find_or_create_by!(:uuid => well.uuid) + return unless remote_asset.try(:wells) - updates.replace_remote(asset, 'contains', local_well) + remote_asset.wells.each do |well| + local_well = Asset.find_or_create_by!(uuid: well.uuid) - # Updated wells will also mean that the plate is out of date, so we'll set it in the asset - updates.replace_remote(local_well, 'a', 'Well') - updates.replace_remote(local_well, 'location', well.position['name']) - updates.replace_remote(local_well, 'parent', asset) + fact_changes.replace_remote(asset, 'contains', local_well) - if (well.try(:aliquots)&.first&.sample&.sample_metadata&.supplier_name) - annotate_container(local_well, well, fact_changes) - end - end + # Updated wells will also mean that the plate is out of date, so we'll set it in the asset + fact_changes.replace_remote(local_well, 'a', 'Well') + fact_changes.replace_remote(local_well, 'location', well.position['name']) + fact_changes.replace_remote(local_well, 'parent', asset) + + if (well.try(:aliquots)&.first&.sample&.sample_metadata&.supplier_name) + annotate_container(local_well, well, fact_changes) end end end def annotate_tubes(asset, remote_asset, fact_changes) - fact_changes.tap do |updates| - if remote_asset.try(:racked_tubes) - remote_asset.racked_tubes.each do |racked_tube| - remote_tube = racked_tube.tube - local_tube = Asset.find_or_create_by!(:uuid => remote_tube.uuid) - local_tube.update!(barcode: remote_tube.labware_barcode['human_barcode']) - - updates.replace_remote(asset, 'contains', local_tube) - - # Updated tubes will also mean that the plate is out of date, so we'll set it in the asset - updates.replace_remote(local_tube, 'a', 'SampleTube') - updates.replace_remote(local_tube, 'location', racked_tube.coordinate) - updates.replace_remote(local_tube, 'parent', asset) - - if (remote_tube.try(:aliquots)&.first&.sample&.sample_metadata&.supplier_name) - annotate_container(local_tube, remote_tube, fact_changes) - end - end + return unless remote_asset.try(:racked_tubes) + + remote_asset.racked_tubes.each do |racked_tube| + remote_tube = racked_tube.tube + local_tube = Asset.find_or_create_by!(uuid: remote_tube.uuid) + local_tube.update!(barcode: remote_tube.labware_barcode['human_barcode']) + + fact_changes.replace_remote(asset, 'contains', local_tube) + + # Updated tubes will also mean that the plate is out of date, so we'll set it in the asset + fact_changes.replace_remote(local_tube, 'a', 'SampleTube') + fact_changes.replace_remote(local_tube, 'location', racked_tube.coordinate) + fact_changes.replace_remote(local_tube, 'parent', asset) + + if (remote_tube.try(:aliquots)&.first&.sample&.sample_metadata&.supplier_name) + annotate_container(local_tube, remote_tube, fact_changes) end end end @@ -301,11 +281,6 @@ def sequencescape_type_for_asset(remote_asset) return type end - def keep_sync_with_sequencescape?(remote_asset) - class_name = sequencescape_type_for_asset(remote_asset) - class_name != 'SampleTube' - end - # Finds Assets with the provided barcodes in the local Assets table, and # looks up any missing barcodes in Sequencescape, importing the assets if # required. If a barcode is missing both locally, and in Sequencescape, it @@ -321,6 +296,17 @@ def find_or_import_assets_with_barcodes(barcodes, includes: :facts) private + def import_remote_asset(remote_asset, barcode, import_step) + Asset.create!(barcode: barcode, uuid: remote_asset.uuid).tap do |asset| + FactChanges.new.tap do |updates| + updates.replace_remote(asset, 'a', sequencescape_type_for_asset(remote_asset)) + updates.replace_remote(asset, 'remoteAsset', remote_asset.uuid) + end.apply(import_step) + asset.refresh_from_remote(remote_asset: remote_asset) + asset.update_compatible_activity_type + end + end + def find_asset_with_barcode(barcode) asset = Asset.find_by_barcode(barcode) || Asset.find_by_uuid(barcode) diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index c21d7046..5a9fae04 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -126,7 +126,6 @@ def add(s, p, o, options = {}) fact = _build_fact_attributes(s, p, o, options) facts_to_add << fact if fact - # facts_to_add.push(track_object(params)) unless detected end def add_facts(list_of_lists) @@ -288,7 +287,7 @@ def find_instance_of_class_by_uuid(klass, instance_or_uuid_or_id, create = false else found = instance_or_uuid_or_id end - _produce_error(["Element identified by #{instance_or_uuid_or_id} should be declared before using it"]) unless found + _produce_error(["#{klass} identified by '#{instance_or_uuid_or_id}' should be declared before using it"]) unless found found end diff --git a/lib/inference_engines/runner/step_execution.rb b/lib/inference_engines/runner/step_execution.rb index 1547df01..9ad211d8 100644 --- a/lib/inference_engines/runner/step_execution.rb +++ b/lib/inference_engines/runner/step_execution.rb @@ -104,10 +104,8 @@ def plan end def apply - if asset_group.assets.with_fact('pushTo', 'Sequencescape').count > 0 - asset_group.assets.with_fact('pushTo', 'Sequencescape').each do |asset| - @updates.merge(asset.update_sequencescape(step.user)) - end + asset_group.assets.with_fact('pushTo', 'Sequencescape').each do |asset| + @updates.merge(asset.update_sequencescape(step.user)) end @updates.apply(step) end diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 9f4d25fd..475811b4 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -6,7 +6,7 @@ require 'sequencescape_client_v2' class SequencescapeClient - SELECT_FOR_IMPORT = 'uuid,labware_barcode' + SELECT_FOR_IMPORT = 'uuid,labware_barcode,receptacles' @purposes = nil def self.api_connection_options @@ -66,20 +66,24 @@ def self.find_by_uuid(uuid) end def self.labware(conditions) - SequencescapeClientV2::Labware.select( - tubes: SELECT_FOR_IMPORT, - plates: SELECT_FOR_IMPORT, - tube_racks: SELECT_FOR_IMPORT - ).where(conditions) + SequencescapeClientV2::Labware + .includes('receptacles.aliquots.sample.sample_metadata') + .select( + tubes: SELECT_FOR_IMPORT, + plates: SELECT_FOR_IMPORT, + tube_racks: 'uuid,labware_barcode', + samples: 'sanger_sample_id,uuid,name', + sample_metadata: 'supplier_name,sample_common_name' + ).where(conditions) end # TODO: In most cases we should know what type of record we're looking up. def self.find_by(search_conditions) [ - SequencescapeClientV2::Plate.includes('wells.aliquots.sample'), - SequencescapeClientV2::Tube.includes('aliquots.sample'), - SequencescapeClientV2::Well.includes('aliquots.sample'), - SequencescapeClientV2::TubeRack.includes('racked_tubes.tube.aliquots.sample') + SequencescapeClientV2::Plate.includes('wells.aliquots.sample.sample_metadata'), + SequencescapeClientV2::Tube.includes('aliquots.sample.sample_metadata'), + SequencescapeClientV2::Well.includes('aliquots.sample.sample_metadata'), + SequencescapeClientV2::TubeRack.includes('racked_tubes.tube.aliquots.sample.sample_metadata') ].each do |klass| begin search = klass.where(search_conditions).first diff --git a/lib/sequencescape_client_v2.rb b/lib/sequencescape_client_v2.rb index 090d6d53..a8313533 100644 --- a/lib/sequencescape_client_v2.rb +++ b/lib/sequencescape_client_v2.rb @@ -2,8 +2,11 @@ module SequencescapeClientV2 class SequencescapeClientV2::Model < JsonApiClient::Resource + # Indicates if the asset should be synced back with the remove + class_attribute :sync # set the api base url in an abstract base class self.site = "#{Rails.configuration.ss_api_v2_uri}/api/v2/" + self.sync = false end class SequencescapeClientV2::Asset < SequencescapeClientV2::Model @@ -14,6 +17,16 @@ class SequencescapeClientV2::Labware < SequencescapeClientV2::Model def self.table_name 'labware' end + + has_many :receptacles + + def sync? + %w[plates tube_racks].include? type + end + + def wells + type == 'plates' ? receptacles : [] + end end class SequencescapeClientV2::Plate < SequencescapeClientV2::Model @@ -21,6 +34,8 @@ class SequencescapeClientV2::Plate < SequencescapeClientV2::Model has_many :studies, through: :well has_many :samples, through: :well has_one :purpose + + self.sync = true end class SequencescapeClientV2::TubeRack < SequencescapeClientV2::Model @@ -31,6 +46,9 @@ class SequencescapeClientV2::TubeRack < SequencescapeClientV2::Model class SequencescapeClientV2::Purpose < SequencescapeClientV2::Model end + class SequencescapeClientV2::Receptacle < SequencescapeClientV2::Model + end + class SequencescapeClientV2::Well < SequencescapeClientV2::Model has_many :aliquots has_many :studies, through: :aliquot diff --git a/spec/controllers/asset_groups_controller_spec.rb b/spec/controllers/asset_groups_controller_spec.rb index 469c739d..7dcf93de 100644 --- a/spec/controllers/asset_groups_controller_spec.rb +++ b/spec/controllers/asset_groups_controller_spec.rb @@ -54,7 +54,6 @@ context "when the asset is not in the database" do let(:barcode) { generate :barcode } let(:uuid) { SecureRandom.uuid } - let(:SequencescapeClient) { double('sequencescape_client') } let(:remote_asset) { build_remote_tube(barcode: barcode, uuid: uuid) } before do @@ -63,7 +62,9 @@ context "when it is in Sequencescape" do context 'finding by uuid' do - it "retrieves the asset from Sequencescape" do + # NOTE: We previously had an innaccurate mock making this test pass. + # We're just pulling assets from SS based on barcode. + xit "retrieves the asset from Sequencescape" do expect { post :update, params: { :asset_group => { :assets => [uuid] }, :id => asset_group.id, :activity_id => activity.id } diff --git a/spec/models/assets/export_spec.rb b/spec/models/assets/export_spec.rb index 8c7dcab8..145bb530 100644 --- a/spec/models/assets/export_spec.rb +++ b/spec/models/assets/export_spec.rb @@ -102,13 +102,14 @@ let(:user) { create :user, username: 'test' } let(:print_config) { { "Plate" => 'Pum', "Tube" => 'Pim' } } let(:plate) { build_remote_plate } + let(:plate_v2) { build_remote_v2_plate(uuid: plate.uuid) } let(:asset) { create :asset } it 'updates a plate in sequencescape' do allow(SequencescapeClient).to receive(:version_1_find_by_uuid).with(asset.uuid).and_return(nil) allow(SequencescapeClient).to receive(:version_1_find_by_uuid).with(plate.uuid).and_return(plate) allow(SequencescapeClient).to receive(:find_by_uuid).with(asset.uuid).and_return(nil) - allow(SequencescapeClient).to receive(:find_by_uuid).with(plate.uuid).and_return(plate) + allow(SequencescapeClient).to receive(:find_by_uuid).with(plate.uuid).and_return(plate_v2) allow(SequencescapeClient).to receive(:create_plate).and_return(plate) barcode = double('barcode') allow(barcode).to receive(:prefix).and_return('DN') diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index c08fd88a..72dc2edd 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -6,7 +6,7 @@ context '#refresh!' do let(:asset) { create :asset } - let(:plate) { build_remote_plate } + let(:plate) { build_remote_v2_plate } before do allow(asset).to receive(:_process_refresh) @@ -55,7 +55,7 @@ context '#refresh' do let(:asset) { create :asset } - let(:plate) { build_remote_plate } + let(:plate) { build_remote_v2_plate } before do allow(SequencescapeClient).to receive(:find_by_uuid).and_return(true) @@ -320,7 +320,7 @@ context 'when the asset is a plate' do setup do - @remote_asset = build_remote_plate(barcode: generate(:barcode)) + @remote_asset = build_remote_v2_plate(barcode: generate(:barcode)) @barcode_asset = @remote_asset.barcode stub_client_with_asset(SequencescapeClient, @remote_asset) end @@ -342,7 +342,7 @@ build_remote_sample(sample_metadata: double('sample_metadata', sample_common_name: 'species', supplier_name: 'a supplier name')))]) ] - @remote_asset_without_supplier = build_remote_plate(barcode: generate(:barcode), wells: wells) + @remote_asset_without_supplier = build_remote_v2_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_asset_without_supplier) end @@ -352,7 +352,7 @@ context 'when the plate does not have aliquots in its wells' do setup do wells = ['A1', 'B1'].map { |l| build_remote_well(l, aliquots: []) } - @remote_asset_without_aliquots = build_remote_plate(barcode: generate(:barcode), wells: wells) + @remote_asset_without_aliquots = build_remote_v2_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_asset_without_aliquots) end @@ -366,7 +366,7 @@ context 'when the plate does not have samples in its wells' do setup do wells = ['A1', 'B1'].map { |l| build_remote_well(l, aliquots: [build_remote_aliquot(sample: nil)]) } - @remote_asset_without_samples = build_remote_plate(barcode: generate(:barcode), wells: wells) + @remote_asset_without_samples = build_remote_v2_plate(barcode: generate(:barcode), wells: wells) stub_client_with_asset(SequencescapeClient, @remote_asset_without_samples) end diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index 1e90142e..4fbaf8db 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -15,8 +15,31 @@ def build_remote_plate(opts = {}) my_double end + def build_remote_v2_plate(opts = {}) + purpose = double('purpose', name: 'A purpose') + obj = { + uuid: SecureRandom.uuid, + wells: [build_remote_well('A1'), build_remote_well('A4')], + purpose: purpose, + type: 'plates', + sync?: true + }.merge(opts) + + my_double = double('remote_asset', obj) + allow(my_double).to receive(:attributes).and_return(obj) + allow(my_double).to receive(:class).and_return(SequencescapeClientV2::Plate) + + my_double + end + def build_remote_well(location, opts = {}) - double('well', { aliquots: [build_remote_aliquot], location: location, position: { "name" => location }, uuid: SecureRandom.uuid }.merge(opts)) + double('well', { + aliquots: [build_remote_aliquot], + location: location, + position: { "name" => location }, + uuid: SecureRandom.uuid, + sync?: false + }.merge(opts)) end def build_remote_tube_rack(opts = {}) @@ -25,7 +48,8 @@ def build_remote_tube_rack(opts = {}) uuid: SecureRandom.uuid, racked_tubes: [build_remote_racked_tube('A1'), build_remote_racked_tube('A4')], purpose: purpose, - type: 'tube_racks' + type: 'tube_racks', + sync?: true }.merge(opts) my_double = double('remote_asset', obj) @@ -50,7 +74,8 @@ def build_remote_tube(opts = {}) type: 'tubes', plate_purpose: purpose, aliquots: [build_remote_aliquot], - labware_barcode: { 'human_barcode' => 'test' } + labware_barcode: { 'human_barcode' => 'test' }, + sync?: false }.merge(opts) my_double = double('remote_asset', obj) From b7890a18f03b8700bacdbd68d67ac8151ef0f7ad Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 30 Mar 2022 09:04:17 +0100 Subject: [PATCH 139/303] Initial improvement on applying layout These changes result in a 20 fold speed-up, taking the operation down to about 3s when query-logging is disabled. There is still scope for improvement, but I want to move on to the other bottlenecks for now. --- app/models/asset.rb | 24 ++++++------ .../move_barcodes_from_tube_rack_to_plate.rb | 38 ++++++++++--------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index 24fe30b6..2b8fd96a 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -25,6 +25,14 @@ def with_predicate(predicate) super end end + + def predicate_matching?(predicate, value) + if loaded? + with_predicate(predicate).any? { |fact| fact.object == value } + else + exists?(predicate: 'a', object: 'Plate') + end + end end has_many :asset_groups_assets, dependent: :destroy @@ -53,17 +61,9 @@ def update_compatible_activity_type joins(:activities).where(:activities => { :activity_type_id => activity_type.id }) } - scope :not_started, ->() { - with_fact('is', 'NotStarted') - } - - scope :started, ->() { - with_fact('is', 'Started') - } - - scope :for_printing, ->() { - where.not(barcode: nil) - } + scope :not_started, ->() { with_fact('is', 'NotStarted') } + scope :started, ->() { with_fact('is', 'Started') } + scope :for_printing, ->() { where.not(barcode: nil) } scope :assets_for_queries, ->(queries) { queries.each_with_index.reduce(Asset) do |memo, list| @@ -88,6 +88,8 @@ def update_compatible_activity_type end } + delegate :predicate_matching?, to: :facts + def short_description "#{aliquot_type} #{class_type} #{barcode.blank? ? '#' : barcode}".chomp end diff --git a/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb b/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb index 14bb50a5..b01fdbc8 100644 --- a/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb +++ b/app/step_planners/step_planner/move_barcodes_from_tube_rack_to_plate.rb @@ -23,43 +23,44 @@ module StepPlanner class MoveBarcodesFromTubeRackToPlate attr_reader :asset_group + delegate :assets, to: :asset_group + def initialize(asset_group_id, _step_id) - @asset_group = AssetGroup.find(asset_group_id) + @asset_group = AssetGroup.includes(assets: { facts: { object_asset: :facts } }).find(asset_group_id) end def assets_compatible_with_step_type - [plate, tube_rack].flatten.any? + # @note I'm not sure why any? is accepted here, I'd have thought we'd want both + # plus failing silently in the event we have nothing to do seem undesireable + [plate, tube_rack].any? end def plate - # TODO: Scope for improvement here, just adapted it sufficiently to make rubocop happy as I want to keep this - # commit focussed on the move to using the same process - asset_group.assets.detect { |a| a.facts.exists?(predicate: 'a', object: 'Plate') } + @plate ||= assets.detect { |a| a.predicate_matching?('a', 'Plate') } end def tube_rack - # TODO: Scope for improvement here, just adapted it sufficiently to make rubocop happy as I want to keep this - # commit focussed on the move to using the same process - asset_group.assets.detect { |a| a.facts.exists?(predicate: 'a', object: 'TubeRack') } + @tube_rack ||= assets.detect { |a| a.predicate_matching?('a', 'TubeRack') } end def wells_for(asset) - asset.facts.where(predicate: 'contains').map(&:object_asset) + asset.facts.with_predicate('contains').map(&:object_asset) end - def well_at_location(asset, location) - wells_for(asset).detect do |w| - location_facts = w.facts.where(predicate: 'location') - if location_facts.count == 1 - location_fact = location_facts.first - (TokenUtil.pad_location(location_fact.object) == TokenUtil.pad_location(location)) - end + def index_wells_in(asset) + wells_for(asset).index_by do |w| + location_facts = w.facts.with_predicate('location').map(&:object).uniq + # We don't seem to have any case of this occurring in the production database, although there are some historic + # records with multiple location facts with the same location. + raise StandardError, "Could not identify location for Asset #{asset.id}. Possible locations: #{location_facts}" unless location_facts.one? + + TokenUtil.pad_location(location_facts.first) end end def traverse_wells(asset) wells_for(asset).each do |w| - location = w.facts.where(predicate: 'location').first.object + location = w.facts.with_predicate('location').first.object yield w, TokenUtil.pad_location(location) end end @@ -67,8 +68,9 @@ def traverse_wells(asset) def process FactChanges.new.tap do |updates| if assets_compatible_with_step_type + plate_wells = index_wells_in(plate) traverse_wells(tube_rack) do |well_from_tube_rack, location| - well_from_plate = well_at_location(plate, location) + well_from_plate = plate_wells.fetch(TokenUtil.pad_location(location)) barcode = well_from_tube_rack.barcode updates.remove_where(well_from_tube_rack, 'barcode', barcode) updates.add(well_from_tube_rack, 'previousBarcode', barcode) From f2d8d3ebc9658bbcb64128402014dd5db7b08193 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 30 Mar 2022 13:30:49 +0100 Subject: [PATCH 140/303] Rubocop performance fixes I had had hoped that I might just be able to use the auto-correct, but there were a few places where this was still resulting in sub-optimal behaviour. --- .rubocop_todo.yml | 94 ------------------ app/controllers/samples_status_controller.rb | 2 +- app/models/action.rb | 4 +- app/models/activities/steps_management.rb | 2 +- app/models/activity_type.rb | 2 + app/models/asset.rb | 13 ++- app/models/assets/export.rb | 13 +-- app/models/label_template.rb | 17 ++-- app/models/printer.rb | 16 ++-- app/models/step_type.rb | 11 +-- lib/changes_support/disjoint_list.rb | 30 +----- .../runner/step_execution.rb | 2 +- lib/parsers/csv_metadata/datum_parser.rb | 4 +- lib/sequencescape_client.rb | 16 +--- lib/support_n3.rb | 4 +- lib/token_util.rb | 31 ++---- script/runners/create_12_tubes.rb | 6 +- script/runners/create_file.rb | 4 +- script/runners/create_layout.rb | 4 +- script/runners/full_rack_generator.rb | 4 +- .../move_barcodes_from_tube_rack_to_plate.rb | 95 ------------------- spec/concerns/deprecatable_spec.rb | 2 +- spec/lib/actions/plate_transfer_spec.rb | 10 +- spec/lib/actions/racking_spec.rb | 16 ++-- spec/lib/actions/tube_transfer_spec.rb | 4 +- .../lib/changes_support/disjoint_list_spec.rb | 6 +- spec/lib/fact_changes_spec.rb | 4 +- .../lib/parsers/csv_layout/csv_parser_spec.rb | 2 +- .../parsers/csv_metadata/csv_parser_spec.rb | 2 +- spec/lib/support_n3_spec.rb | 8 +- .../activities/background_tasks_spec.rb | 4 +- spec/models/asset_group_spec.rb | 4 +- spec/models/condition_spec.rb | 4 +- spec/models/step_execution_spec.rb | 4 +- spec/models/step_spec.rb | 32 +++---- spec/models/step_type_spec.rb | 28 +++--- .../steps/background_tasks/inference_spec.rb | 2 +- spec/models/steps/cancellable_spec.rb | 6 +- spec/models/steps/deprecatable_spec.rb | 12 +-- spec/models/steps/queueable_job_spec.rb | 4 +- spec/models/steps/stoppable_spec.rb | 16 +--- spec/script/runners/load_metadata_spec.rb | 2 +- spec/script/runners/transfer_samples_spec.rb | 8 +- ...fer_tubes_to_tube_rack_by_position_spec.rb | 6 +- 44 files changed, 154 insertions(+), 406 deletions(-) delete mode 100644 script/runners/move_barcodes_from_tube_rack_to_plate.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 149ae904..0bc18e10 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -303,100 +303,6 @@ Naming/VariableName: - 'spec/script/runners/transfer_samples_spec.rb' - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' -# Offense count: 2 -# Configuration parameters: MinSize. -Performance/CollectionLiteralInLoop: - Exclude: - - 'app/models/assets/export.rb' - -# Offense count: 2 -# This cop supports safe auto-correction (--auto-correct). -Performance/CompareWithBlock: - Exclude: - - 'app/controllers/samples_status_controller.rb' - - 'app/models/activities/steps_management.rb' - -# Offense count: 18 -# This cop supports safe auto-correction (--auto-correct). -Performance/Count: - Exclude: - - 'app/models/step_type.rb' - - 'lib/support_n3.rb' - - 'spec/lib/actions/plate_transfer_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/steps/cancellable_spec.rb' - - 'spec/models/steps/deprecatable_spec.rb' - -# Offense count: 24 -# This cop supports safe auto-correction (--auto-correct). -Performance/Detect: - Exclude: - - 'app/helpers/activities_helper.rb' - - 'app/models/asset.rb' - - 'app/models/assets/export.rb' - - 'app/models/label_template.rb' - - 'app/models/printer.rb' - - 'lib/changes_support/disjoint_list.rb' - - 'lib/parsers/csv_metadata/datum_parser.rb' - - 'lib/sequencescape_client.rb' - - 'lib/support_n3.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - - 'spec/lib/actions/plate_transfer_spec.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/lib/actions/tube_transfer_spec.rb' - - 'spec/lib/support_n3_spec.rb' - -# Offense count: 3 -# This cop supports safe auto-correction (--auto-correct). -Performance/RedundantMatch: - Exclude: - - 'app/models/asset.rb' - - 'lib/inference_engines/runner/step_execution.rb' - -# Offense count: 3 -# This cop supports safe auto-correction (--auto-correct). -Performance/RegexpMatch: - Exclude: - - 'app/models/asset.rb' - - 'lib/inference_engines/runner/step_execution.rb' - -# Offense count: 2 -# This cop supports safe auto-correction (--auto-correct). -Performance/StringReplacement: - Exclude: - - 'lib/token_util.rb' - -# Offense count: 72 -# This cop supports safe auto-correction (--auto-correct). -Performance/TimesMap: - Exclude: - - 'app/models/action.rb' - - 'lib/token_util.rb' - - 'script/runners/create_12_tubes.rb' - - 'script/runners/create_file.rb' - - 'script/runners/create_layout.rb' - - 'script/runners/full_rack_generator.rb' - - 'spec/concerns/deprecatable_spec.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/lib/changes_support/disjoint_list_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - - 'spec/models/activities/background_tasks_spec.rb' - - 'spec/models/asset_group_spec.rb' - - 'spec/models/condition_spec.rb' - - 'spec/models/step_execution_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/models/steps/background_tasks/inference_spec.rb' - - 'spec/models/steps/cancellable_spec.rb' - - 'spec/models/steps/deprecatable_spec.rb' - - 'spec/models/steps/queueable_job_spec.rb' - - 'spec/models/steps/stoppable_spec.rb' - - 'spec/script/runners/load_metadata_spec.rb' - - 'spec/script/runners/transfer_samples_spec.rb' - - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' - # Offense count: 86 # This cop supports safe auto-correction (--auto-correct). Rails/ActiveRecordAliases: diff --git a/app/controllers/samples_status_controller.rb b/app/controllers/samples_status_controller.rb index 96faaca4..79ea531b 100644 --- a/app/controllers/samples_status_controller.rb +++ b/app/controllers/samples_status_controller.rb @@ -27,7 +27,7 @@ def set_activity_type_selected end def set_activity_types - @activity_types = ActivityType.all.visible.sort { |a, b| a.name <=> b.name }.uniq + @activity_types = ActivityType.visible.alphabetical end def set_assets_for_activity_types diff --git a/app/models/action.rb b/app/models/action.rb index e882601a..6b53860a 100644 --- a/app/models/action.rb +++ b/app/models/action.rb @@ -60,7 +60,7 @@ def sources(asset_group) def destinations(asset_group) if object_condition_group.nil? - sources(asset_group).length.times.map { object } + Array.new(sources(asset_group).length) { object } else asset_group.classified_by_condition_group(object_condition_group) end @@ -72,7 +72,7 @@ def run(asset_group, wildcard_values = {}) if (asset_group.classified_by_condition_group(subject_condition_group).length > 0) assets = asset_group.classified_by_condition_group(subject_condition_group) else - assets = num_assets_to_create(asset_group).times.map { Asset.new } + assets = Array.new(num_assets_to_create(asset_group)) { Asset.new } updates.create_assets(assets) updates.add_assets([[asset_group, assets]]) # asset_group.assets << assets diff --git a/app/models/activities/steps_management.rb b/app/models/activities/steps_management.rb index 4e729256..8604cf9b 100644 --- a/app/models/activities/steps_management.rb +++ b/app/models/activities/steps_management.rb @@ -6,7 +6,7 @@ def active_step end def previous_steps - asset_group.assets.includes(:steps).map(&:steps).concat(steps).flatten.sort { |a, b| a.id <=> b.id }.uniq + asset_group.assets.includes(:steps).map(&:steps).concat(steps).flatten.sort_by(&:id).uniq end def assets diff --git a/app/models/activity_type.rb b/app/models/activity_type.rb index 11347158..32f2e64c 100644 --- a/app/models/activity_type.rb +++ b/app/models/activity_type.rb @@ -14,6 +14,8 @@ class ActivityType < ApplicationRecord has_many :activity_type_compatibilities has_many :assets, -> { distinct }, :through => :activity_type_compatibilities + scope :alphabetical, -> { order(name: :asc) } + include Deprecatable def touch_activities diff --git a/app/models/asset.rb b/app/models/asset.rb index 2b8fd96a..a0e22963 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -158,11 +158,8 @@ def study_and_barcode end def barcode_sequencescaped - unless barcode.match(/^\d+$/) - return barcode.match(/\d+/)[0] if barcode.match(/\d+/) + return barcode.match(/\d+/).to_s unless /^\d+$/.match?(barcode) - return "" - end ean13 = barcode.rjust(13, '0') ean13.slice!(0, 3) ean13.slice!(ean13.length - 3, 3) @@ -249,14 +246,16 @@ def aliquot end def self.class_type(facts) - class_types = facts.select { |f| f[:predicate] == 'a' }.map(&:object) + # @note This appears to exist to 'prioritise' which class_type takes affect. + # We do seem to have some assets which are both 'Tube' and 'Well'. This + # may be due to the representation of some tube racks in SS as plates. + class_types = facts.with_predicate('a').map(&:object) return 'TubeRack' if class_types.include?('TubeRack') return 'Plate' if class_types.include?('Plate') return 'Tube' if class_types.include?('Tube') return 'SampleTube' if class_types.include?('SampleTube') - return facts.select { |f| f[:predicate] == 'a' }.first.object if facts.select { |f| f[:predicate] == 'a' }.first - return "" + facts.first&.object || '' end def kind_of_plate? diff --git a/app/models/assets/export.rb b/app/models/assets/export.rb index b564c11e..4c3a3b35 100644 --- a/app/models/assets/export.rb +++ b/app/models/assets/export.rb @@ -119,18 +119,15 @@ def attributes_to_send_for_well(well) return nil unless well.has_sample? # extract the 'facts' that we want to send to Sequencescape for creation of wells - well.facts.reduce({}) do |memo, fact| - if (['sample_tube'].include?(fact.predicate)) + well.facts.each_with_object({}) do |fact, memo| + case fact.predicate + when 'sample_tube' memo["#{fact.predicate}_uuid".to_sym] = fact.object_asset.uuid - end - if (fact.predicate == 'location') + when 'location' memo[fact.predicate.to_sym] = TokenUtil.unpad_location(fact.object) - end - if (['aliquotType', 'sanger_sample_id', - 'sanger_sample_name', 'sample_uuid'].include?(fact.predicate)) + when 'aliquotType', 'sanger_sample_id', 'sanger_sample_name', 'sample_uuid' memo[fact.predicate.to_sym] = TokenUtil.unquote(fact.object) end - memo end end end diff --git a/app/models/label_template.rb b/app/models/label_template.rb index c2e4d55b..c5bc6e81 100644 --- a/app/models/label_template.rb +++ b/app/models/label_template.rb @@ -1,18 +1,19 @@ class LabelTemplate < ApplicationRecord + CLASS_TYPE_TEMPLATE_ALIASES = { + 'TubeRack' => 'Plate', + 'Tube' => 'SampleTube' + }.freeze + validates_presence_of :name, :external_id validates_uniqueness_of :name, :external_id - def self.for_type(type, barcodetype = 'ean13') - type = { - 'Plate' => ['TubeRack', 'Plate'], - 'Tube' => ['Tube', 'SampleTube'] - }.select { |k, v| v.include?(type) }.first[0] + def self.for_type(class_type, barcodetype = 'ean13') + type = CLASS_TYPE_TEMPLATE_ALIASES.fetch(class_type, class_type) - templates = where(:template_type => type) + templates = where(template_type: type) templates_by_barcodetype = templates.select { |t| t.name.include?(barcodetype) } - return templates if templates_by_barcodetype.empty? - return templates_by_barcodetype + templates_by_barcodetype.presence || templates end end diff --git a/app/models/printer.rb b/app/models/printer.rb index 033e9af8..cf81a570 100644 --- a/app/models/printer.rb +++ b/app/models/printer.rb @@ -1,18 +1,18 @@ class Printer < ApplicationRecord + CLASS_TYPE_PRINTER_ALIASES = { + 'TubeRack' => 'Plate', + 'Tube' => 'SampleTube' + }.freeze + scope :for_tube, ->() { where(:printer_type => 'Tube') } scope :for_plate, ->() { where(:printer_type => 'Plate') } scope :for_default, ->() { where(:default_printer => true) } def self.for_type(type) - type = printer_type_for(type) - - where(:printer_type => type) + where(printer_type: printer_type_for(type)) end - def self.printer_type_for(type) - { - 'Plate' => ['TubeRack', 'Plate'], - 'Tube' => ['Tube', 'SampleTube'] - }.select { |k, v| v.include?(type) }.first[0] + def self.printer_type_for(class_type) + CLASS_TYPE_PRINTER_ALIASES.fetch(class_type, class_type) end end diff --git a/app/models/step_type.rb b/app/models/step_type.rb index a0bb94c9..0c619f74 100644 --- a/app/models/step_type.rb +++ b/app/models/step_type.rb @@ -195,7 +195,7 @@ def classification_for(assets, cgroups) def check_dependency_compatibility_for(asset, condition_group, assets) check_cgs = condition_groups.select do |cg| - cg.conditions.select { |c| c.object_condition_group == condition_group }.count > 0 + cg.conditions.any? { |c| c.object_condition_group == condition_group } end return true if check_cgs.empty? @@ -204,12 +204,9 @@ def check_dependency_compatibility_for(asset, condition_group, assets) classification = classification_for(ancestors, check_cgs) - compatible = every_condition_group_satisfies_cardinality(classification) && - every_condition_group_has_at_least_one_asset?(classification, check_cgs) && - every_asset_has_at_least_one_condition_group?(classification) - return true if compatible - - return false + every_condition_group_satisfies_cardinality(classification) && + every_condition_group_has_at_least_one_asset?(classification, check_cgs) && + every_asset_has_at_least_one_condition_group?(classification) end def to_n3 diff --git a/lib/changes_support/disjoint_list.rb b/lib/changes_support/disjoint_list.rb index 9d171322..70ab61fb 100644 --- a/lib/changes_support/disjoint_list.rb +++ b/lib/changes_support/disjoint_list.rb @@ -14,6 +14,8 @@ class ChangesSupport::DisjointList DISABLED_NAME = "DISABLED" + delegate :each, :length, :[], :flatten, :uniq!, to: :list + def initialize(list) @name = "object_id_#{object_id}" @@ -44,7 +46,7 @@ def _store_for(unique_id) store_name = location_for_unique_id[unique_id] return nil if store_name.nil? || store_name == DISABLED_NAME - @disjoint_lists.select { |l| l.name == store_name }.first + @disjoint_lists.find { |l| l.name == store_name } end def enabled?(element) @@ -83,26 +85,6 @@ def remove_from_raw_list_by_id(unique_id) end end - def length - @list.length - end - - def each(&block) - @list.each(&block) - end - - def [](index) - @list[index] - end - - def flatten - @list.flatten - end - - def uniq! - @list.uniq! - end - def <<(element) if element.kind_of?(Array) element.each { |e| add(e) } @@ -138,13 +120,11 @@ def add(element) end def sum_function_for(value) - return value.hash - # Value to create checksum and seed - # XXhash.xxh32(value, SEED_FOR_UNIQUE_IDS) + value.hash end def unique_id_for_element(element) - return _unique_id_for_element(element, 0) + _unique_id_for_element(element, 0) end def concat_disjoint_list(disjoint_list) diff --git a/lib/inference_engines/runner/step_execution.rb b/lib/inference_engines/runner/step_execution.rb index 9ad211d8..e8b820e3 100644 --- a/lib/inference_engines/runner/step_execution.rb +++ b/lib/inference_engines/runner/step_execution.rb @@ -73,7 +73,7 @@ def generate_plan_from_class end def generate_plan_from_external_process - if step_action.match(/\.rb$/) + if step_action.end_with?('.rb') cmd = ["bin/rails", "runner", "#{Rails.root}/script/runners/#{step_action}"] else cmd = "#{Rails.root}/script/runners/#{step_action}" diff --git a/lib/parsers/csv_metadata/datum_parser.rb b/lib/parsers/csv_metadata/datum_parser.rb index 2e6fd69b..2b841edc 100644 --- a/lib/parsers/csv_metadata/datum_parser.rb +++ b/lib/parsers/csv_metadata/datum_parser.rb @@ -12,9 +12,9 @@ def validations end def validator - @parser.components[:fields].select do |entry| + @parser.components[:fields].find do |entry| entry[:header] == @header - end.first[:validator] + end[:validator] end def initialize(datum, header, parser) diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 475811b4..955e9e18 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -35,7 +35,7 @@ def self.update_extraction_attributes(instance, attrs, username = 'test') end def self.purpose_by_name(name) - client.plate_purpose.all.select { |p| p.name === name }.first + client.plate_purpose.all.find { |p| p.name === name } end def self.create_plate(purpose_name) @@ -43,20 +43,6 @@ def self.create_plate(purpose_name) purpose.plates.create!({}) end - def self.get_study_by_name(name) - get_study_searcher_by_name.first(name: name) - rescue Sequencescape::Api::ResourceNotFound => exception - return nil - end - - def self.get_study_searcher_by_name - @@study_searcher ||= client.search.all.select { |s| s.name == Rails.configuration.searcher_study_by_name }.first - end - - def self.get_searcher_by_barcode - @@searcher ||= client.search.all.select { |s| s.name == Rails.configuration.searcher_name_by_barcode }.first - end - def self.get_remote_asset(barcode) find_by(barcode: barcode) end diff --git a/lib/support_n3.rb b/lib/support_n3.rb index fe5deab7..63379103 100644 --- a/lib/support_n3.rb +++ b/lib/support_n3.rb @@ -81,7 +81,7 @@ def self.build_asset(name, create_assets = true, created_assets = []) if create_assets asset = Asset.find_or_create_by(:name => name) else - asset = created_assets.select { |a| a.name == name }.first + asset = created_assets.find { |a| a.name == name } unless asset asset = Asset.create(:name => name) created_assets.push(asset) @@ -91,7 +91,7 @@ def self.build_asset(name, create_assets = true, created_assets = []) end def self.is_literal?(element, quads) - element.literal? || quads.select { |q| q[0] == element }.count == 0 + element.literal? || quads.none? { |q| q[0] == element } end def self.load_step_actions(content, options = {}) diff --git a/lib/token_util.rb b/lib/token_util.rb index e66e6dbf..a3e59d20 100644 --- a/lib/token_util.rb +++ b/lib/token_util.rb @@ -65,50 +65,37 @@ def self.kind_of_asset_id?(str) end def self.to_asset_group_name(wildcard) - return wildcard if wildcard.nil? - - wildcard.gsub('?', '') + wildcard&.delete('?') end - def self.generate_positions(letters, columns) - size = letters.size * columns.size - location_for_position = size.times.map do |i| - "#{letters[(i % letters.length).floor]}#{pad((columns[(i / letters.length).floor]).to_s, '0', 2)}" - end + def self.generate_positions(rows, columns) + columns.flat_map { |col| rows.map { |row| "#{row}#{pad(col, '0', 2)}" } } end def self.pad(str, chr, size) - "#{(size - str.size).times.map { chr }.join}#{str}" + str.rjust(size, chr) end def self.unpad_location(location) return location unless location - loc = location.match(/(\w)(0*)(\d*)/) - loc[1] + loc[3] + location.match(/(\w)0*(\d*)/).captures.join end def self.pad_location(location) return location unless location - parts = location.match(LOCATION_REGEXP) - return nil if parts.length == 0 - - letter = parts[1] - number = parts[2] - number = TokenUtil.pad(number, "0", 2) unless number.length == 2 - "#{letter}#{number}" + letter, number = location.match(LOCATION_REGEXP)&.captures || raise("Invalid location: #{location}") + "#{letter}#{pad(number, '0', 2)}" end def self.quote(str) return str unless str - "\"#{str}\"" + %("#{str}") end def self.unquote(str) - return str unless str - - str.gsub(/\"/, "") + str&.delete('"') end end diff --git a/script/runners/create_12_tubes.rb b/script/runners/create_12_tubes.rb index bb23fc27..4dd0285f 100755 --- a/script/runners/create_12_tubes.rb +++ b/script/runners/create_12_tubes.rb @@ -2,9 +2,9 @@ TOTAL_NUMBER = 12 -tubes = TOTAL_NUMBER.times.map { |i| "?p#{i}" } -samples = TOTAL_NUMBER.times.map { |i| "?q#{i}" } -sanger_sample_id = TOTAL_NUMBER.times.map { |i| "SAMPLE#{i}" } +tubes = Array.new(TOTAL_NUMBER) { |i| "?p#{i}" } +samples = Array.new(TOTAL_NUMBER) { |i| "?q#{i}" } +sanger_sample_id = Array.new(TOTAL_NUMBER) { |i| "SAMPLE#{i}" } study_name = "STDY1" f1 = tubes.each_with_index.map { |t, i| [t, 'a', 'SampleTube'] } diff --git a/script/runners/create_file.rb b/script/runners/create_file.rb index 0dd33a41..51900ef8 100755 --- a/script/runners/create_file.rb +++ b/script/runners/create_file.rb @@ -7,7 +7,7 @@ barcodes = [] while (num < NUM_BARCODES) do number = (rand * 999999).floor.to_s - barcode = ["FR"].concat((6 - number.length).times.map { "0" }).concat([number]).join + barcode = ["FR"].concat(Array.new((6 - number.length)) { "0" }).concat([number]).join found = Asset.find_by(barcode: barcode) unless found barcodes.push(barcode) @@ -18,7 +18,7 @@ letters = ("A".."H").to_a columns = (1..12).to_a -location_for_position = NUM_BARCODES.times.map do |i| +location_for_position = Array.new(NUM_BARCODES) do |i| "#{letters[(i / columns.length).floor]}#{(columns[i % columns.length]).to_s}" end diff --git a/script/runners/create_layout.rb b/script/runners/create_layout.rb index 9a9ab6c1..9b862999 100755 --- a/script/runners/create_layout.rb +++ b/script/runners/create_layout.rb @@ -7,7 +7,7 @@ barcodes = [] while (num < NUM_BARCODES) do number = (rand * 999999).floor.to_s - barcode = ["FR"].concat((6 - number.length).times.map { "0" }).concat([number]).join + barcode = ["FR"].concat(Array.new((6 - number.length)) { "0" }).concat([number]).join found = Asset.find_by(barcode: barcode) unless found barcodes.push(barcode) @@ -18,7 +18,7 @@ letters = ("A".."H").to_a columns = (1..12).to_a -location_for_position = NUM_BARCODES.times.map do |i| +location_for_position = Array.new(NUM_BARCODES) do |i| "#{letters[(i / columns.length).floor]}#{(columns[i % columns.length]).to_s}" end diff --git a/script/runners/full_rack_generator.rb b/script/runners/full_rack_generator.rb index 3d17fd6e..c012ca9a 100644 --- a/script/runners/full_rack_generator.rb +++ b/script/runners/full_rack_generator.rb @@ -12,10 +12,10 @@ facts_from_tubes = current_tubes.pluck(:facts) locations_with_tube = facts_from_tubes.empty? ? [] : facts_from_tubes.where(predicate: 'location').pluck(:object) -tubes = 96.times.map { |i| "?tube#{i}" } +tubes = Array.new(96) { |i| "?tube#{i}" } letters = ("A".."H").to_a columns = (1..12).to_a -location_for_position = 96.times.map do |i| +location_for_position = Array.new(96) do |i| "#{letters[(i / columns.length).floor]}#{(columns[i % columns.length]).to_s}" end diff --git a/script/runners/move_barcodes_from_tube_rack_to_plate.rb b/script/runners/move_barcodes_from_tube_rack_to_plate.rb deleted file mode 100644 index 58656081..00000000 --- a/script/runners/move_barcodes_from_tube_rack_to_plate.rb +++ /dev/null @@ -1,95 +0,0 @@ -# # This rule applies the barcodes from a rack into a plate -# { -# ?plate se:a Plate . -# ?rack se:a TubeRack . -# ?rack se:mergeInto ?plate . -# ?rack se:contains ?tube . -# ?plate se:contains ?well . -# ?tube se:location ?location . -# ?tube se:barcode ?barcode . -# ?well se:location ?location . -# } => { -# :step :addFacts { ?well se:barcode ?barcode . } . -# :step :removeFacts { ?tube se:barcode ?barcode . } . -# :step :addFacts { ?tube se:barcode . } . -# :step :addFacts { ?tube se:previousBarcode ?barcode . } . -# :step :addFacts { ?tube se:appliedBarcodeTo ?well . } . -# :step :addFacts { ?rack se:mergedInto ?plate .}. -# :step :addFacts { ?plate se:mergedFrom ?rack .}. -# }. - -class MoveBarcodesFromTubeRackToPlate - attr_reader :asset_group - - def initialize(params) - @asset_group = params[:asset_group] - end - - def assets_compatible_with_step_type - [plate, tube_rack].flatten.compact.count > 0 - end - - def plate - asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'Plate').count > 0 }.first - end - - def tube_rack - asset_group.assets.select { |a| a.facts.where(predicate: 'a', object: 'TubeRack').count > 0 }.first - end - - def wells_for(asset) - asset.facts.where(predicate: 'contains').map(&:object_asset) - end - - def well_at_location(asset, location) - wells_for(asset).select do |w| - location_facts = w.facts.where(predicate: 'location') - if (location_facts.count == 1) - location_fact = location_facts.first - (TokenUtil.pad_location(location_fact.object) == TokenUtil.pad_location(location)) - end - end.first - end - - def traverse_wells(asset, &block) - wells_for(asset).each do |w| - location = w.facts.where(predicate: 'location').first.object - yield w, TokenUtil.pad_location(location) - end - end - - def process - FactChanges.new.tap do |updates| - if assets_compatible_with_step_type - traverse_wells(tube_rack) do |well_from_tube_rack, location| - well_from_plate = well_at_location(plate, location) - barcode = well_from_tube_rack.barcode - updates.remove_where(well_from_tube_rack, 'barcode', barcode) - updates.add(well_from_tube_rack, 'previousBarcode', barcode) - updates.add(well_from_tube_rack, 'appliedBarcodeTo', well_from_plate) - well_from_tube_rack.update_attributes(barcode: nil) - well_from_plate.update_attributes(barcode: barcode) - updates.add(well_from_plate, 'barcode', barcode) - end - - updates.add(tube_rack, 'mergedInto', plate) - updates.add(plate, 'mergedFrom', tube_rack) - end - end - end -end - -args = ARGV[0] -asset_group_id = args.match(/(\d*)\.json/)[1] -asset_group = AssetGroup.find(asset_group_id) -begin - updates = nil - ActiveRecord::Base.transaction do - updates = MoveBarcodesFromTubeRackToPlate.new(asset_group: asset_group).process - end - json = updates.to_json - JSON.parse(json) - puts json -rescue StandardError => e - puts ({ set_errors: ['Unknown error while applying barcodes' + e.backtrace.to_s] }.to_json) -end diff --git a/spec/concerns/deprecatable_spec.rb b/spec/concerns/deprecatable_spec.rb index 2f8a1ad3..f72b6024 100644 --- a/spec/concerns/deprecatable_spec.rb +++ b/spec/concerns/deprecatable_spec.rb @@ -8,7 +8,7 @@ def build_instance let(:model) { described_class } it "deprecates all the instances of the class with the same name" do - deprecatable_list = 10.times.map { build_instance } + deprecatable_list = Array.new(10) { build_instance } expect(model.all.count).to eq(deprecatable_list.count) expect(model.visible.count).to eq(deprecatable_list.count) diff --git a/spec/lib/actions/plate_transfer_spec.rb b/spec/lib/actions/plate_transfer_spec.rb index f1ea741c..d509b739 100644 --- a/spec/lib/actions/plate_transfer_spec.rb +++ b/spec/lib/actions/plate_transfer_spec.rb @@ -10,7 +10,7 @@ source.facts << create(:fact, predicate: 'contains', object_asset: tube) destination = create :asset updates = Actions::PlateTransfer.transfer_plates(source, destination) - expect(updates.to_h[:add_facts].select { |t| t[1] == 'barcode' }.length).to eq(0) + expect(updates.to_h[:add_facts].none? { |t| t[1] == 'barcode' }).to be(true) end it 'copies facts from source wells to destination wells' do source = create :asset @@ -58,8 +58,8 @@ updates.add(destination, 'aliquotType', 'DNA') updates = Actions::PlateTransfer.transfer_plates(source, destination, updates) - created_well = updates.to_h[:add_facts].select { |t| (t[1] == 'location') }.first[0] - expect(updates.to_h[:add_facts].select { |t| (t[0] == created_well) && (t[1] == 'aliquotType') }.first[2]).to eq('DNA') + created_well = updates.to_h[:add_facts].find { |t| (t[1] == 'location') }[0] + expect(updates.to_h[:add_facts].find { |t| (t[0] == created_well) && (t[1] == 'aliquotType') }[2]).to eq('DNA') end it 'does not copy ignored predicates' do source = create :asset @@ -75,8 +75,8 @@ updates = Actions::PlateTransfer.transfer_plates(source, destination, FactChanges.new) - expect(updates.to_h[:add_facts].select { |t| (t[1] == 'pushedTo') }.length).to eq(0) - expect(updates.to_h[:add_facts].select { |t| (t[1] == 'location') }.length > 0).to eq(true) + expect(updates.to_h[:add_facts].none? { |t| (t[1] == 'pushedTo') }).to be true + expect(updates.to_h[:add_facts].any? { |t| (t[1] == 'location') }).to be true end end end diff --git a/spec/lib/actions/racking_spec.rb b/spec/lib/actions/racking_spec.rb index 4b8dac75..9e5615ef 100644 --- a/spec/lib/actions/racking_spec.rb +++ b/spec/lib/actions/racking_spec.rb @@ -129,9 +129,7 @@ def add_empty_slots(content, num_empty, start_pos = 0) describe '#fact_changes_for_rack_when_unracking_tubes' do before do - @tubes = 15.times.map do |line| - create(:asset) - end + @tubes = create_list :asset, 15 @tubes.each do |tube| asset.facts << create(:fact, predicate: 'contains', object_asset: tube) end @@ -174,9 +172,7 @@ def add_empty_slots(content, num_empty, start_pos = 0) describe '#fact_changes_for_rack_when_racking_tubes' do before do - @tubes = 15.times.map do |line| - create(:asset) - end + @tubes = create_list :asset, 15 end it 'returns all the different studies for this rack' do @tubes.first.facts << create(:fact, predicate: 'study_name', object: 'STDY2') @@ -194,18 +190,18 @@ def add_empty_slots(content, num_empty, start_pos = 0) tube.facts << create(:fact, predicate: 'aliquotType', object: 'DNA') unless idx == 0 end updates = fact_changes_for_rack_when_racking_tubes(asset, @tubes) - expect(updates.to_h[:add_facts].select do |triple| + expect(updates.to_h[:add_facts].find do |triple| triple[1] == 'purpose' - end.first[2]).to eq('DNA Stock Plate') + end[2]).to eq('DNA Stock Plate') end it 'generates the RNA stock plate purpose' do @tubes.each_with_index do |tube, idx| tube.facts << create(:fact, predicate: 'aliquotType', object: 'RNA') unless idx == 0 end updates = fact_changes_for_rack_when_racking_tubes(asset, @tubes) - expect(updates.to_h[:add_facts].select do |triple| + expect(updates.to_h[:add_facts].find do |triple| triple[1] == 'purpose' - end.first[2]).to eq('RNA Stock Plate') + end[2]).to eq('RNA Stock Plate') end end diff --git a/spec/lib/actions/tube_transfer_spec.rb b/spec/lib/actions/tube_transfer_spec.rb index 43fe5ba5..28794fe6 100644 --- a/spec/lib/actions/tube_transfer_spec.rb +++ b/spec/lib/actions/tube_transfer_spec.rb @@ -15,11 +15,11 @@ end it 'transfers study_uuid' do updates = transfer_tubes(source, destination) - expect(updates.to_h[:add_facts].select { |t| t[1] == 'study_uuid' }.first[2]).to eq(quoted_study_uuid) + expect(updates.to_h[:add_facts].find { |t| t[1] == 'study_uuid' }[2]).to eq(quoted_study_uuid) end it 'transfers common name' do updates = transfer_tubes(source, destination) - expect(updates.to_h[:add_facts].select { |t| t[1] == 'sample_common_name' }.first[2]).to eq(common_name) + expect(updates.to_h[:add_facts].find { |t| t[1] == 'sample_common_name' }[2]).to eq(common_name) end end end diff --git a/spec/lib/changes_support/disjoint_list_spec.rb b/spec/lib/changes_support/disjoint_list_spec.rb index 8d399f3b..5cb0b975 100644 --- a/spec/lib/changes_support/disjoint_list_spec.rb +++ b/spec/lib/changes_support/disjoint_list_spec.rb @@ -152,7 +152,7 @@ context 'with a group of disjoint lists' do let(:lists) { - l = 5.times.map { ChangesSupport::DisjointList.new([]) } + l = Array.new(5) { ChangesSupport::DisjointList.new([]) } l[0].add_disjoint_list(l[1]) l[0].add_disjoint_list(l[2]) l[0].add_disjoint_list(l[3]) @@ -388,8 +388,8 @@ end context 'when merging a chain of objects' do - let(:winners) { 6.times.map { ChangesSupport::DisjointList.new([]) } } - let(:losers) { 6.times.map { ChangesSupport::DisjointList.new([]) } } + let(:winners) { Array.new(6) { ChangesSupport::DisjointList.new([]) } } + let(:losers) { Array.new(6) { ChangesSupport::DisjointList.new([]) } } let(:list) { winners.zip(losers).map { |l| l[0].add_disjoint_list(l[1]) diff --git a/spec/lib/fact_changes_spec.rb b/spec/lib/fact_changes_spec.rb index bc57ff50..9c19ce2b 100644 --- a/spec/lib/fact_changes_spec.rb +++ b/spec/lib/fact_changes_spec.rb @@ -913,7 +913,7 @@ context 'with add_assets' do let(:asset_group) { create :asset_group } - let(:assets) { 2.times.map { create :asset } } + let(:assets) { create_list :asset, 2 } let(:updates) { FactChanges.new } before do step.update_attributes(asset_group: create(:asset_group)) @@ -945,7 +945,7 @@ context 'with remove_assets' do let(:asset_group) { create :asset_group } - let(:assets) { 2.times.map { create :asset } } + let(:assets) { Array.new(2) { create :asset } } let(:updates) { FactChanges.new } before do step.update_attributes(asset_group: create(:asset_group)) diff --git a/spec/lib/parsers/csv_layout/csv_parser_spec.rb b/spec/lib/parsers/csv_layout/csv_parser_spec.rb index e3678394..312c1125 100644 --- a/spec/lib/parsers/csv_layout/csv_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/csv_parser_spec.rb @@ -22,7 +22,7 @@ allow(SequencescapeClient).to receive(:labware).and_return([]) @content = File.read('test/data/layout.csv') - @assets = 96.times.map do |i| + @assets = Array.new(96) do |i| FactoryBot.create(:asset, { :barcode => 'FR' + (11200002 + i).to_s }) diff --git a/spec/lib/parsers/csv_metadata/csv_parser_spec.rb b/spec/lib/parsers/csv_metadata/csv_parser_spec.rb index 8208ac63..496f8f5b 100644 --- a/spec/lib/parsers/csv_metadata/csv_parser_spec.rb +++ b/spec/lib/parsers/csv_metadata/csv_parser_spec.rb @@ -24,7 +24,7 @@ end @content = File.read('test/data/metadata.csv') - @assets = 96.times.map do |i| + @assets = Array.new(96) do |i| FactoryBot.create(:asset, { :barcode => 'FR' + (11200002 + i).to_s }) diff --git a/spec/lib/support_n3_spec.rb b/spec/lib/support_n3_spec.rb index 8ade1863..674908a7 100644 --- a/spec/lib/support_n3_spec.rb +++ b/spec/lib/support_n3_spec.rb @@ -266,9 +266,9 @@ def validates_rule_with(parsed_obj) }) p = ConditionGroup.find_by_name('p') q = ConditionGroup.find_by_name('q') - expect(p.conditions.select do |c| + expect(p.conditions.find do |c| c.predicate == 'contains' - end.first.object_condition_group_id).to eq(q.id) + end.object_condition_group_id).to eq(q.id) end it '{ ' \ @@ -321,9 +321,9 @@ def validates_rule_with(parsed_obj) d = ConditionGroup.find_by_name('d') [a, b, c, d].zip([b, c, d, a]).each do |p, q| - expect(p.conditions.select do |c| + expect(p.conditions.find do |c| c.predicate == 'transfer' - end.first.object_condition_group_id).to eq(q.id) + end.object_condition_group_id).to eq(q.id) end end end diff --git a/spec/models/activities/background_tasks_spec.rb b/spec/models/activities/background_tasks_spec.rb index 525273a1..3b20d609 100644 --- a/spec/models/activities/background_tasks_spec.rb +++ b/spec/models/activities/background_tasks_spec.rb @@ -17,7 +17,7 @@ def self.update_attributes!(params) let(:step) { create :step, step_type: step_type } context '#create_background_steps' do - let(:list_of_tasks) { 5.times.map { DummyBackgroundStep } } + let(:list_of_tasks) { Array.new(5) { DummyBackgroundStep } } it 'creates the list of steps' do activity.create_background_steps(list_of_tasks, {}) expect(Step.all.count).to eq(5) @@ -34,7 +34,7 @@ def self.update_attributes!(params) end context '#create_connected_tasks' do - let(:list_of_tasks) { 5.times.map { DummyBackgroundStep } } + let(:list_of_tasks) { Array.new(5) { DummyBackgroundStep } } let(:other_step) { create :step, step_type: step_type } context 'when it does not have any background task defined' do diff --git a/spec/models/asset_group_spec.rb b/spec/models/asset_group_spec.rb index 075e9de1..33c483fa 100644 --- a/spec/models/asset_group_spec.rb +++ b/spec/models/asset_group_spec.rb @@ -1,8 +1,8 @@ require 'rails_helper' RSpec.describe AssetGroup, type: :model do context '#update_with_assets' do - let(:existing_assets) { 3.times.map { create :asset } } - let(:new_assets) { 2.times.map { create :asset } } + let(:existing_assets) { create_list :asset, 3 } + let(:new_assets) { create_list :asset, 2 } let(:group) { create(:asset_group, assets: existing_assets) } before do allow(group).to receive(:refresh!).and_return(true) diff --git a/spec/models/condition_spec.rb b/spec/models/condition_spec.rb index 16e767af..3ccab0ce 100644 --- a/spec/models/condition_spec.rb +++ b/spec/models/condition_spec.rb @@ -22,7 +22,7 @@ describe 'wildcard creation on compatible_with()' do # assets, required_assets=nil, checked_condition_groups=[], wildcard_values={}) setup do - @assets = 5.times.map do |i| + @assets = Array.new(5) do |i| facts = [ FactoryBot.create(:fact, { :predicate => 'a', :object => 'Tube' }) ] @@ -31,7 +31,7 @@ FactoryBot.create(:asset, :facts => facts) end - @wells = 5.times.map do |i| + @wells = Array.new(5) do |i| facts = [ FactoryBot.create(:fact, { :predicate => 'a', :object => 'Well' }) ] diff --git a/spec/models/step_execution_spec.rb b/spec/models/step_execution_spec.rb index 74ad0e87..313fea14 100644 --- a/spec/models/step_execution_spec.rb +++ b/spec/models/step_execution_spec.rb @@ -5,7 +5,7 @@ describe 'wildcard creation on compatible_with()' do # assets, required_assets=nil, checked_condition_groups=[], wildcard_values={}) setup do - @assets = 5.times.map do |i| + @assets = Array.new(5) do |i| facts = [ FactoryBot.create(:fact, { :predicate => 'a', :object => 'Tube' }) ] @@ -14,7 +14,7 @@ FactoryBot.create(:asset, :facts => facts) end - @wells = 5.times.map do |i| + @wells = Array.new(5) do |i| facts = [ FactoryBot.create(:fact, { :predicate => 'a', :object => 'Well' }) ] diff --git a/spec/models/step_spec.rb b/spec/models/step_spec.rb index 6144f341..b329fd7a 100644 --- a/spec/models/step_spec.rb +++ b/spec/models/step_spec.rb @@ -67,7 +67,7 @@ def create_condition_group_to_select_asset_type(asset_type, name = nil) end def create_assets(num, type) - num.times.map { create_asset(type) } + Array.new(num) { create_asset(type) } end describe '#create' do @@ -95,13 +95,13 @@ def create_assets(num, type) }) @step_type.condition_groups << @cg1 @step_type.condition_groups << @cg2 - @tubes = 7.times.map { |i| + @tubes = Array.new(7) { |i| FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') ] }) } - @racks = 5.times.map { |i| + @racks = Array.new(5) { |i| FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') @@ -293,7 +293,7 @@ def create_assets(num, type) expect(Operation.all.count).to eq(assets_created.count * 3) else expect(assets_created.length).to eq(previous_num) - expect(Operation.all.select { |o| o.action_type == 'createAssets' }.count).to eq(assets_created.count) + expect(Operation.all.count { |o| o.action_type == 'createAssets' }).to eq(assets_created.count) end expect(assets_created.length + previous_num).to eq(@asset_group.assets.count) end @@ -310,7 +310,7 @@ def create_assets(num, type) expect(assets_created.length).to eq(6) expect(assets_created.length + previous_num).to eq(@asset_group.assets.count) - expect(Operation.all.select { |o| o.action_type == 'createAssets' }.count).to eq(assets_created.count) + expect(Operation.all.count { |o| o.action_type == 'createAssets' }).to eq(assets_created.count) end it 'cardinality does not restrict the number of assets created when it is over the number of inputs' do @@ -325,7 +325,7 @@ def create_assets(num, type) expect(assets_created.length).to eq(cardinality) # expect(assets_created.length+previous_num).to eq(@asset_group.assets.count) - expect(Operation.all.select { |o| o.action_type == 'createAssets' }.count).to eq(assets_created.count) + expect(Operation.all.count { |o| o.action_type == 'createAssets' }).to eq(assets_created.count) end end @@ -358,12 +358,12 @@ def create_assets(num, type) @step_type.actions << action @step = create_step expect(@asset_group.assets.count).to eq(previous_num * 2) - expect(Operation.all.select { |o| o.action_type == 'addFacts' }.count).to eq(2 * previous_num) + expect(Operation.all.count { |o| o.action_type == 'addFacts' }).to eq(2 * previous_num) end describe 'with overlapping assets' do setup do - @tubes_and_racks = 7.times.map do + @tubes_and_racks = Array.new(7) do FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') @@ -420,7 +420,7 @@ def create_assets(num, type) describe 'with overlapping assets' do setup do - @tubes_and_racks = 7.times.map do + @tubes_and_racks = Array.new(7) do FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') @@ -652,7 +652,7 @@ def create_assets(num, type) describe 'with overlapping assets' do setup do - @tubes_and_racks = 7.times.map do + @tubes_and_racks = Array.new(7) do FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube') @@ -780,14 +780,14 @@ def create_assets(num, type) :literal => false }) - assert_equal 1, @tubes.first.facts.select { |f| f.predicate == 'relatesTo' }.length + assert_equal 1, @tubes.first.facts.count { |f| f.predicate == 'relatesTo' } @asset_group.update_attributes(:assets => [@tubes.first, @racks.first].flatten) create_step @tubes.each(&:reload) @racks.each(&:reload) - assert_equal 0, @tubes.first.facts.select { |f| f.predicate == 'relatesTo' }.length + assert_equal 0, @tubes.first.facts.count { |f| f.predicate == 'relatesTo' } expect(Operation.all.count).to eq(1) end describe 'relating several assets' do @@ -806,7 +806,7 @@ def create_assets(num, type) @racks.each(&:reload) @tubes.each do |tube| - assert_equal true, (tube.facts.select { |f| f.predicate == 'relatesTo' }.length > 0) + assert_equal true, (tube.facts.count { |f| f.predicate == 'relatesTo' } > 0) end create_step @@ -815,7 +815,7 @@ def create_assets(num, type) @racks.each(&:reload) @tubes.each do |tube| - assert_equal 0, tube.facts.select { |f| f.predicate == 'relatesTo' }.length + assert_equal 0, tube.facts.count { |f| f.predicate == 'relatesTo' } end expect(Operation.all.count).to eq(@racks.length * @tubes.length) end @@ -854,11 +854,11 @@ def create_assets(num, type) @racks.each(&:reload) @tubes.each do |tube| - assert_equal 0, tube.facts.select { |f| f.predicate == 'relatesTo' }.length + assert_equal 0, tube.facts.count { |f| f.predicate == 'relatesTo' } end @racks.each do |rack| - assert_equal 1, rack.facts.select { |f| f.predicate == 'relatesTo' }.length + assert_equal 1, rack.facts.count { |f| f.predicate == 'relatesTo' } end expect(Operation.all.count).to eq(@tubes.length) diff --git a/spec/models/step_type_spec.rb b/spec/models/step_type_spec.rb index f0a24f28..ce7f921b 100644 --- a/spec/models/step_type_spec.rb +++ b/spec/models/step_type_spec.rb @@ -28,9 +28,9 @@ def assert_equal(a, b) describe '#for_task_type' do it 'returns the step types for that task_type' do - runners = 2.times.map { create(:step_type, step_action: 'myscript.rb') } - inferences = 2.times.map { create(:step_type, step_action: 'other.n3') } - others = 2.times.map { create(:step_type) } + runners = create_list(:step_type, 2, step_action: 'myscript.rb') + inferences = create_list(:step_type, 2, step_action: 'other.n3') + others = create_list(:step_type, 2) expect(StepType.for_task_type('runner')).to eq(runners) expect(StepType.for_task_type('cwm')).to eq(inferences) expect(StepType.all).to eq(runners.concat(inferences).concat(others)) @@ -116,7 +116,7 @@ def assert_equal(a, b) describe "with special configuration" do describe "related with cardinality" do setup do - @assets = 5.times.map { |i| + @assets = Array.new(5) { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') @@ -150,7 +150,7 @@ def assert_equal(a, b) describe 'matching more than one asset' do describe 'for the same condition group' do setup do - @assets = 5.times.map { |i| + @assets = Array.new(5) { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') @@ -190,14 +190,14 @@ def assert_equal(a, b) @step_type.condition_groups << @cg2 - @assets = 5.times.map { |i| + @assets = Array.new(5) { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') ] } } - @racks = 5.times.map { |i| + @racks = Array.new(5) { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), ] } @@ -237,7 +237,7 @@ def assert_equal(a, b) describe 'with assets that overlap between condition groups' do it 'is compatible with overlapped assets' do - @tubes_and_racks = 7.times.map do + @tubes_and_racks = Array.new(7) do FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), @@ -264,19 +264,19 @@ def assert_equal(a, b) :object_condition_group_id => @cg2.id }) - @racks = 5.times.map { |i| + @racks = Array.new(5) { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack') ] } } - @bad_racks = 5.times.map { |i| + @bad_racks = Array.new(5) { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack') ] } } - @assets = 5.times.map { |i| + @assets = Array.new(5) { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), @@ -288,13 +288,13 @@ def assert_equal(a, b) assert_equal true, @step_type.compatible_with?([@assets, @racks].flatten) end it 'is not compatible when the relation is not matching the conditions required' do - @bad_racks = 5.times.map { |i| + @bad_racks = Array.new(5) { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'BadRack') ] } } - @assets = 5.times.map { |i| + @assets = Array.new(5) { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), @@ -316,7 +316,7 @@ def assert_equal(a, b) }) end it 'is compatible with any literal when met the other conditions' do - @assets = 5.times.map { |i| + @assets = Array.new(5) { |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), diff --git a/spec/models/steps/background_tasks/inference_spec.rb b/spec/models/steps/background_tasks/inference_spec.rb index 00ceee9a..a7740889 100644 --- a/spec/models/steps/background_tasks/inference_spec.rb +++ b/spec/models/steps/background_tasks/inference_spec.rb @@ -35,7 +35,7 @@ end it 'executes the rest of next steps' do - inferences = 5.times.map { create :inference, activity: activity } + inferences = create_list :inference, 5, activity: activity inferences.reverse.reduce(nil) do |memo, step| id = (memo && memo.id) || nil step.update_attributes(next_step_id: id) diff --git a/spec/models/steps/cancellable_spec.rb b/spec/models/steps/cancellable_spec.rb index 0e12d8a8..41ba4a1f 100644 --- a/spec/models/steps/cancellable_spec.rb +++ b/spec/models/steps/cancellable_spec.rb @@ -11,7 +11,7 @@ @asset_group.assets << @asset @activity_type = FactoryBot.create :activity_type @activity = FactoryBot.create :activity, activity_type: @activity_type, asset_group: @asset_group - @steps = 10.times.map do + @steps = Array.new(10) do step = build_step(%Q{{?p :a :Rack.} => {:step :addFacts {?p :a :TubeRack .}.} .}, %Q{}, activity: @activity, asset_group: @asset_group) step.run! step @@ -49,7 +49,7 @@ expect(@steps.any? { |s| s.cancelled? }).to eq(false) @steps[5].cancel @steps.each(&:reload) - expect(@steps.select { |s| s.cancelled? }.count).to eq(5) + expect(@steps.count { |s| s.cancelled? }).to eq(5) expected_ids = [@steps[5].id, @steps[5].steps_newer_than_me.map(&:id)].flatten.sort expect(@steps.select { |s| s.cancelled? }.map(&:id).sort).to eq(expected_ids) end @@ -58,7 +58,7 @@ expect(@steps.any? { |s| s.cancelled? }).to eq(false) @steps[5].cancel @steps.each(&:reload) - expect(@steps.select { |s| s.cancelled? }.count).to eq(5) + expect(@steps.count { |s| s.cancelled? }).to eq(5) expected_ids = [@steps[5].id, @steps[5].steps_newer_than_me.map(&:id)].flatten.sort expect(@steps.select { |s| s.cancelled? }.map(&:id).sort).to eq(expected_ids) diff --git a/spec/models/steps/deprecatable_spec.rb b/spec/models/steps/deprecatable_spec.rb index 9c5b52ee..5e629e00 100644 --- a/spec/models/steps/deprecatable_spec.rb +++ b/spec/models/steps/deprecatable_spec.rb @@ -7,7 +7,7 @@ context '#execute_actions' do let(:state) { Step::STATE_CANCELLED } it 'deprecates all cancelled steps created before me on step execution' do - steps = 10.times.map { create(:step, state: state, activity: activity) } + steps = create_list(:step, 10, state: state, activity: activity) step = create(:step, activity: activity, asset_group: asset_group, step_type: step_type) expect(steps.all?(&:cancelled?)).to eq(true) @@ -19,7 +19,7 @@ end it 'deprecates all stopped steps created before me on step execution' do - steps = 10.times.map { create(:step, state: Step::STATE_STOPPED, activity: activity) } + steps = create_list(:step, 10, state: Step::STATE_STOPPED, activity: activity) step = create(:step, activity: activity, asset_group: asset_group, step_type: step_type) expect(activity.steps.count).to eq(11) @@ -30,7 +30,7 @@ end it 'does not deprecate anything if is completed' do - steps = 10.times.map { create(:step, state: Step::STATE_COMPLETE, activity: activity) } + steps = create_list(:step, 10, state: Step::STATE_COMPLETE, activity: activity) step = create(:step, activity: activity, state: Step::STATE_PENDING, asset_group: asset_group, step_type: step_type) expect(activity.steps.count).to eq(11) @@ -42,7 +42,7 @@ it 'does not deprecate anything created after me' do step = create(:step, activity: activity, asset_group: asset_group, step_type: step_type) - steps = 10.times.map { create(:step, state: 'cancelled', activity: activity) } + steps = create_list(:step, 10, state: 'cancelled', activity: activity) expect(activity.steps.count).to eq(11) step.run! @@ -52,13 +52,13 @@ end it 'does not deprecate any steps created before me that are in my chain for next_step' do - steps = 10.times.map { create(:step, state: Step::STATE_STOPPED, activity: activity, asset_group: asset_group, step_type: step_type) } + steps = create_list(:step, 10, state: Step::STATE_STOPPED, activity: activity, asset_group: asset_group, step_type: step_type) step = create(:step, activity: activity, asset_group: asset_group, step_type: step_type, next_step: steps.last) expect(activity.steps.count).to eq(11) step.run! steps.each(&:reload) - expect(steps.select(&:ignored?).count).to eq(9) + expect(steps.count(&:ignored?)).to eq(9) expect(activity.steps.count).to eq(2) end end diff --git a/spec/models/steps/queueable_job_spec.rb b/spec/models/steps/queueable_job_spec.rb index a17e91b9..7169f333 100644 --- a/spec/models/steps/queueable_job_spec.rb +++ b/spec/models/steps/queueable_job_spec.rb @@ -35,7 +35,7 @@ def build_instance_with_activity end context 'when it has several steps configured' do - let(:my_steps) { 5.times.map { build_instance_with_activity } } + let(:my_steps) { Array.new(5) { build_instance_with_activity } } it 'does not execute any of the steps' do my_steps.reverse.reduce(nil) do |next_step, step| step.update_attributes(next_step: next_step) @@ -112,7 +112,7 @@ def build_instance_with_activity end end context 'when it has several steps configured' do - let(:my_steps) { 5.times.map { build_instance_with_activity } } + let(:my_steps) { Array.new(5) { build_instance_with_activity } } context 'when all the steps are correct' do it 'executes all steps until the last one' do diff --git a/spec/models/steps/stoppable_spec.rb b/spec/models/steps/stoppable_spec.rb index 59c90893..5660c471 100644 --- a/spec/models/steps/stoppable_spec.rb +++ b/spec/models/steps/stoppable_spec.rb @@ -5,14 +5,10 @@ let(:step_type) { create(:step_type) } let(:previous_steps) { - 2.times.map { - create(:step, state: Step::STATE_RUNNING, activity: activity, asset_group: asset_group, step_type: step_type) - } + create_list(:step, 2, state: Step::STATE_RUNNING, activity: activity, asset_group: asset_group, step_type: step_type) } let(:next_steps) { - 2.times.map { - create(:step, state: Step::STATE_RUNNING, activity: activity, asset_group: asset_group, step_type: step_type) - } + create_list(:step, 2, state: Step::STATE_RUNNING, activity: activity, asset_group: asset_group, step_type: step_type) } let(:step) { create(:step, state: previous_state, activity: activity, asset_group: asset_group, step_type: step_type) } @@ -69,14 +65,10 @@ } let(:next_steps_stopped) { - 2.times.map { - create(:step, state: Step::STATE_STOPPED, activity: activity, asset_group: asset_group, step_type: step_type) - } + create_list(:step, 2, state: Step::STATE_STOPPED, activity: activity, asset_group: asset_group, step_type: step_type) } let(:next_steps_not_stopped) { - 2.times.map { - create(:step, state: Step::STATE_FAILED, activity: activity, asset_group: asset_group, step_type: step_type) - } + create_list(:step, 2, state: Step::STATE_FAILED, activity: activity, asset_group: asset_group, step_type: step_type) } let(:next_steps) { [next_steps_stopped, next_steps_not_stopped].flatten } diff --git a/spec/script/runners/load_metadata_spec.rb b/spec/script/runners/load_metadata_spec.rb index 8a661ec5..674fa4ae 100644 --- a/spec/script/runners/load_metadata_spec.rb +++ b/spec/script/runners/load_metadata_spec.rb @@ -10,7 +10,7 @@ let(:positions) { TokenUtil.generate_positions(('A'..'H').to_a, ('1'..'12').to_a) } let(:wells) { - 96.times.map do |i| + Array.new(96) do |i| asset = FactoryBot.create(:asset) asset.facts << create(:fact, predicate: 'location', object: positions[i]) asset.facts << create(:fact, predicate: 'a', object: 'Well') diff --git a/spec/script/runners/transfer_samples_spec.rb b/spec/script/runners/transfer_samples_spec.rb index 014a8925..dc99172f 100644 --- a/spec/script/runners/transfer_samples_spec.rb +++ b/spec/script/runners/transfer_samples_spec.rb @@ -4,7 +4,7 @@ RSpec.describe 'TransferSamples' do let(:sample) { create(:asset, facts: [create(:fact, predicate: 'sample_name', object: 'sample1')]) } let(:sources) { - 5.times.map { + Array.new(5) { create(:asset, facts: [ create(:fact, predicate: 'a', object: 'Tube'), create(:fact, predicate: 'study_name', object: 'Study 1'), @@ -13,7 +13,7 @@ } } let(:destinations) { - 5.times.map { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } + Array.new(5) { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } } let(:instance) { TransferSamples.new(asset_group: group) @@ -25,11 +25,11 @@ study_names_transferred = added_facts.select do |triple| triple[1] == 'study_name' end.map { |triple| [triple[0], triple[2]] } - expect(study_names_transferred).to eq(destinations.map(&:uuid).zip(destinations.length.times.map { 'Study 1' })) + expect(study_names_transferred).to eq(destinations.map(&:uuid).zip(Array.new(destinations.length) { 'Study 1' })) sample_tubes_transferred = added_facts.select do |triple| triple[1] == 'sample_tube' end.map { |triple| [triple[0], triple[2]] } - expect(sample_tubes_transferred).to eq(destinations.map(&:uuid).zip(destinations.length.times.map { sample.uuid })) + expect(sample_tubes_transferred).to eq(destinations.map(&:uuid).zip(Array.new(destinations.length) { sample.uuid })) end context 'when there is no inverse relation transferredFrom' do it 'creates the inverse relation transferredFrom' do diff --git a/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb b/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb index e91e2ad4..626b454e 100644 --- a/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb +++ b/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb @@ -18,7 +18,7 @@ ].flatten) } let(:tubes) { - 5.times.map { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } + Array.new(5) { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } } let(:instance) { TransferTubesToTubeRackByPosition.new(asset_group: group) @@ -38,7 +38,7 @@ end context 'when only some of the tubes are related with the rack' do let(:unrelated_tubes) { - 5.times.map { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } + Array.new(5) { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } } before do group.assets << unrelated_tubes @@ -171,7 +171,7 @@ end context 'when there are no more space left in the rack' do let(:tubes) { - 7.times.map { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } + Array.new(7) { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } } it 'produces an error' do set_errors = instance.process.to_h[:set_errors] From 42da0d2913b7ed6314b6e9d81e036d085172121a Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 30 Mar 2022 13:37:10 +0100 Subject: [PATCH 141/303] Remove benchmarking --- .../runner/step_execution.rb | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/lib/inference_engines/runner/step_execution.rb b/lib/inference_engines/runner/step_execution.rb index e8b820e3..8b84ab6d 100644 --- a/lib/inference_engines/runner/step_execution.rb +++ b/lib/inference_engines/runner/step_execution.rb @@ -36,17 +36,6 @@ def debug_log(params) end end - def bm(step) - puts "=" * 80 - puts "#{step} STARTING" - t = Process.clock_gettime(Process::CLOCK_MONOTONIC) - r = yield - t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC) - puts "=" * 80 - puts "#{step} TOOK #{t2 - t}" - r - end - def step_action CONVERTED_CLASS_ACTIONS.fetch(@step.step_type.step_action, @step.step_type.step_action) end @@ -57,7 +46,7 @@ def handled_by_class? def generate_plan if handled_by_class? - bm(:generate_plan) { generate_plan_from_class } + generate_plan_from_class else generate_plan_from_external_process end @@ -67,9 +56,9 @@ def generate_plan_from_class klass = step_action.constantize step_planner = klass.new(@asset_group.id, @step.id) - @content = bm(:sp_updates) { step_planner.updates } - bm(:uat) { step.update_attributes(output: @content) } - @updates = bm(:FCN) { @content } + @content = step_planner.updates + step.update_attributes(output: @content) + @updates = @content end def generate_plan_from_external_process From 7225210aa5c95416f0e7715eeb64f5e75d486497 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 30 Mar 2022 13:57:42 +0100 Subject: [PATCH 142/303] Remove temporary shim for new step actions --- .rubocop_todo.yml | 8 ----- ...3815_move_script_based_actions_to_class.rb | 32 +++++++++++++++++++ db/schema.rb | 2 +- db/seeds.rb | 2 +- db/workflows/qiacube.n3 | 4 +-- db/workflows/reracking.n3 | 4 +-- .../runner/step_execution.rb | 8 +---- script/recreate_steptypes.rb | 2 +- 8 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 db/migrate/20220330123815_move_script_based_actions_to_class.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 0bc18e10..835ec117 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -49,7 +49,6 @@ Lint/NonDeterministicRequireOrder: Lint/ParenthesesAsGroupedExpression: Exclude: - 'script/runners/load_metadata.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - 'script/runners/rack_layout.rb' - 'script/runners/rack_layout_any_barcode.rb' @@ -137,7 +136,6 @@ Lint/UnusedMethodArgument: - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/support_n3.rb' - 'script/remove_duplicates.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - 'script/runners/transfer_samples.rb' - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' @@ -327,7 +325,6 @@ Rails/ActiveRecordAliases: - 'lib/inference_engines/runner/step_execution.rb' - 'lib/support_n3.rb' - 'script/plate_to_code39.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - 'spec/helpers/application_helper_spec.rb' - 'spec/lib/fact_changes_spec.rb' - 'spec/models/activities/background_tasks_spec.rb' @@ -962,7 +959,6 @@ Style/Documentation: - 'script/purpose_name_inference.rb' - 'script/runners/create_stamped_plate.rb' - 'script/runners/load_metadata.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - 'script/runners/print_barcodes.rb' - 'script/runners/rack_layout.rb' - 'script/runners/rack_layout_any_barcode.rb' @@ -1305,7 +1301,6 @@ Style/FrozenStringLiteralComment: - 'script/runners/create_stamped_plate.rb' - 'script/runners/full_rack_generator.rb' - 'script/runners/load_metadata.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - 'script/runners/print_barcodes.rb' - 'script/runners/put_tubes_into_rack_by_column_order.rb' - 'script/runners/rack_layout.rb' @@ -1743,7 +1738,6 @@ Style/NumericPredicate: - 'script/container_inferences.rb' - 'script/purpose_name_inference.rb' - 'script/runners/load_metadata.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - 'script/runners/print_barcodes.rb' - 'script/runners/rack_layout.rb' - 'script/runners/rack_layout_any_barcode.rb' @@ -1807,7 +1801,6 @@ Style/ParenthesesAroundCondition: - 'lib/support_n3.rb' - 'script/runners/create_file.rb' - 'script/runners/create_layout.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - 'spec/models/activities/background_tasks_spec.rb' - 'spec/models/step_spec.rb' @@ -2049,7 +2042,6 @@ Style/StringConcatenation: - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/inference_engines/runner/step_execution.rb' - 'script/runners/load_metadata.rb' - - 'script/runners/move_barcodes_from_tube_rack_to_plate.rb' - 'script/runners/rack_layout.rb' - 'script/runners/rack_layout_any_barcode.rb' - 'spec/inferences_helper.rb' diff --git a/db/migrate/20220330123815_move_script_based_actions_to_class.rb b/db/migrate/20220330123815_move_script_based_actions_to_class.rb new file mode 100644 index 00000000..30a8143b --- /dev/null +++ b/db/migrate/20220330123815_move_script_based_actions_to_class.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +# We've replaces some scripts with simple classes for performance reasons. Not only +# does this avoid us needing to spin up a new process per job, but also avoids the need to +# go through a round trip of serialization and deserialization, which inccurs a further +# penalty when it results in additional trips to the database +class MoveScriptBasedActionsToClass < ActiveRecord::Migration[5.2] + CONVERTED_CLASS_ACTIONS = { + 'move_barcodes_from_tube_rack_to_plate.rb' => 'StepPlanner::MoveBarcodesFromTubeRackToPlate', + 'rack_layout_creating_tubes.rb' => 'StepPlanner::RackLayoutCreatingTubes' + }.freeze + + def up + CONVERTED_CLASS_ACTIONS.each do |from, to| + convert(from, to) + end + end + + def down + CONVERTED_CLASS_ACTIONS.each do |from, to| + convert(to, from) + end + end + + private + + def convert(from, to) + say "Converting #{from} to #{to}" + # We update in bulk to improve performance, and avoid coupling to future validation changes + StepType.where(step_action: from).update_all(step_action: to) # rubocop:disable Rails/SkipsModelValidations + end +end diff --git a/db/schema.rb b/db/schema.rb index 6ae54d84..7f4bc40f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20200709123033) do +ActiveRecord::Schema.define(version: 2022_03_30_123815) do create_table "actions", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "action_type", null: false diff --git a/db/seeds.rb b/db/seeds.rb index eaf41de8..ba03ab5c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -54,7 +54,7 @@ ?q :a :File . }=>{}. }], - ['Rack Layout creating tubes', 'rack_layout_creating_tubes.rb', %Q{ + ['Rack Layout creating tubes', 'StepPlanner::RackLayoutCreatingTubes', %Q{ { ?p :contains ?q . ?p :a :TubeRack . diff --git a/db/workflows/qiacube.n3 b/db/workflows/qiacube.n3 index 32e7bc17..225630ea 100644 --- a/db/workflows/qiacube.n3 +++ b/db/workflows/qiacube.n3 @@ -401,7 +401,7 @@ ?file :maxCardinality """1""". } => { :step :stepTypeName """Apply layout of fluidx tubes in Empty TubeRack""" . - :step :stepAction """rack_layout_creating_tubes.rb""" . + :step :stepAction """StepPlanner::RackLayoutCreatingTubes""" . :step :addFacts { ?tube_rack :layout :Complete . } . } . @@ -425,5 +425,3 @@ :step :addFacts { ?tube_rack :pushTo :Sequencescape. }. :step :stepAction """update_sequencescape.rb""" . } . - - diff --git a/db/workflows/reracking.n3 b/db/workflows/reracking.n3 index 5a761163..a75fc758 100644 --- a/db/workflows/reracking.n3 +++ b/db/workflows/reracking.n3 @@ -37,7 +37,7 @@ ?f :fileType :CSV . } => { :step :stepTypeName """Apply layout from file into the rack""". - :step :stepAction """rack_layout_creating_tubes.rb""" . + :step :stepAction """StepPlanner::RackLayoutCreatingTubes""" . }. { @@ -48,5 +48,3 @@ :step :stepAction """update_sequencescape.rb""" . :step :addFacts { ?p :pushTo :Sequencescape . } . }. - - diff --git a/lib/inference_engines/runner/step_execution.rb b/lib/inference_engines/runner/step_execution.rb index 8b84ab6d..98fb624d 100644 --- a/lib/inference_engines/runner/step_execution.rb +++ b/lib/inference_engines/runner/step_execution.rb @@ -4,12 +4,6 @@ module InferenceEngines module Runner class StepExecution - # Temporary constant to assist refactor - # @todo Remove this and migrate actions instead - CONVERTED_CLASS_ACTIONS = { - 'move_barcodes_from_tube_rack_to_plate.rb' => 'StepPlanner::MoveBarcodesFromTubeRackToPlate', - 'rack_layout_creating_tubes.rb' => 'StepPlanner::RackLayoutCreatingTubes' - }.freeze include StepExecutionProcess attr_accessor :step, :asset_group, :original_assets, @@ -37,7 +31,7 @@ def debug_log(params) end def step_action - CONVERTED_CLASS_ACTIONS.fetch(@step.step_type.step_action, @step.step_type.step_action) + @step.step_type.step_action end def handled_by_class? diff --git a/script/recreate_steptypes.rb b/script/recreate_steptypes.rb index 04e6f4e6..46a1fe8a 100755 --- a/script/recreate_steptypes.rb +++ b/script/recreate_steptypes.rb @@ -19,7 +19,7 @@ ?q :a :File . }=>{}. }], - ['Rack Layout creating tubes', 'rack_layout_creating_tubes.rb', %Q{ + ['Rack Layout creating tubes', 'StepPlanner::RackLayoutCreatingTubes', %Q{ { ?p :contains ?q . ?p :a :TubeRack . From 5d535cc0a6fdafc6b307d6c23ee03185182018c1 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 30 Mar 2022 15:36:51 +0100 Subject: [PATCH 143/303] Remove unused code --- app/models/condition_group.rb | 14 ---------- lib/parsers/csv_metadata/datum_parser.rb | 33 ------------------------ 2 files changed, 47 deletions(-) delete mode 100644 lib/parsers/csv_metadata/datum_parser.rb diff --git a/app/models/condition_group.rb b/app/models/condition_group.rb index 65918d08..e58ddb6b 100644 --- a/app/models/condition_group.rb +++ b/app/models/condition_group.rb @@ -29,20 +29,6 @@ def compatible_with?(assets, related_assets = [], checked_condition_groups = [], end end - def has_runtime_conditions? - runtime_conditions.count > 0 - end - - def runtime_conditions - conditions.select { |c| c.is_runtime_evaluable_condition? } - end - - def runtime_conditions_compatible_with?(asset, related_asset) - runtime_conditions.all? do |c| - c.runtime_compatible_with?(asset, related_asset) - end - end - def conditions_compatible_with?(assets, related_assets = []) [assets].flatten.all? do |asset| conditions.all? do |condition| diff --git a/lib/parsers/csv_metadata/datum_parser.rb b/lib/parsers/csv_metadata/datum_parser.rb deleted file mode 100644 index 2b841edc..00000000 --- a/lib/parsers/csv_metadata/datum_parser.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Parsers - module CsvMetadata - class DatumParser - attr_reader :datum - - include ActiveModel::Validations - - validate :validations - - def validations - validates_with validator - end - - def validator - @parser.components[:fields].find do |entry| - entry[:header] == @header - end[:validator] - end - - def initialize(datum, header, parser) - @parser = parser - @header = header - _parse(datum) - - valid? - end - - def _parse(datum) - @datum = datum - end - end - end -end From 1dc6a399ca131db161df757abe5310dadfa2b4a9 Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 30 Mar 2022 15:37:31 +0100 Subject: [PATCH 144/303] Rename get_remote_asset --- app/models/assets/import.rb | 2 +- lib/sequencescape_client.rb | 2 +- spec/models/assets/import_spec.rb | 2 +- spec/remote_assets_helper.rb | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 275b1e0f..115a2ec8 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -147,7 +147,7 @@ def _process_refresh(remote_asset, fact_changes) module ClassMethods def import_barcode(barcode) @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Import'), state: 'running') - remote_asset = SequencescapeClient::get_remote_asset(barcode) + remote_asset = SequencescapeClient::find_by_barcode(barcode) import_remote_asset(remote_asset, barcode, @import_step) if remote_asset end diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 955e9e18..4b711acf 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -43,7 +43,7 @@ def self.create_plate(purpose_name) purpose.plates.create!({}) end - def self.get_remote_asset(barcode) + def self.find_by_barcode(barcode) find_by(barcode: barcode) end diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 72dc2edd..8054f96e 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -249,7 +249,7 @@ describe '#find_or_import_asset_with_barcode' do context 'when importing an asset that does not exist' do setup do - allow(SequencescapeClient).to receive(:get_remote_asset).and_return(nil) + allow(SequencescapeClient).to receive(:find_by_barcode).and_return(nil) end it 'should return nil' do diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index 4fbaf8db..5664addf 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -111,8 +111,8 @@ def build_remote_sample(opts = {}) def stub_client_with_asset(double, asset) allow(double).to receive(:find_by_uuid).with(asset.uuid).and_return(asset) - allow(double).to receive(:get_remote_asset) { nil } - allow(double).to receive(:get_remote_asset).with(asset.barcode).and_return(asset) - allow(double).to receive(:get_remote_asset).with(asset.uuid).and_return(asset) + allow(double).to receive(:find_by_barcode) { nil } + allow(double).to receive(:find_by_barcode).with(asset.barcode).and_return(asset) + allow(double).to receive(:find_by_barcode).with(asset.uuid).and_return(asset) end end From 462d20a59aa0cf2bac4a18199b07096476c591a3 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 31 Mar 2022 13:34:18 +0100 Subject: [PATCH 145/303] Refactor RSpec tests for improved reuse I want to extend some of the tests to cover the newer mass import functionality that I'd previously only covered with integration tests. This should help me nail the tube rack import issues. --- spec/models/assets/import_spec.rb | 224 +++++++++++++----------------- spec/spec_helper.rb | 10 +- 2 files changed, 101 insertions(+), 133 deletions(-) diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 8054f96e..7908e320 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -140,74 +140,54 @@ shared_examples 'a plate or tube rack' do it 'should create the corresponding facts from the json' do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) - @asset.facts.reload - + facts = the_method.facts.reload predicates = ["a", "pushTo", "purpose", "is", "contains", "contains", "study_name", "study_uuid"] - - expect(predicates.all? do |predicate| - @asset.facts.where(predicate: predicate).count > 0 - end).to eq(true) + predicate_facts = predicates.map { |predicate| facts.with_predicate(predicate) } + expect(predicate_facts).to all be_present end it 'should store the study uuid in a safe format' do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) - expected_study_uuid = if @remote_asset.respond_to?(:wells) - @remote_asset.wells.first.aliquots.first.study.uuid - else - @remote_asset.racked_tubes.first.tube.aliquots.first.study.uuid - end - @asset.facts.reload - - asset_study_uuid = @asset.facts.where(predicate: 'study_uuid').first.object + asset_study_uuid = the_method.facts.reload.with_predicate('study_uuid').first.object expect(asset_study_uuid).to eq(TokenUtil.quote(expected_study_uuid)) end context 'for the first time' do it 'should create the local asset' do - expect(Asset.count).to eq(0) - Asset.find_or_import_asset_with_barcode(@barcode_asset) - - expect(Asset.count > 0).to eq(true) + expect { the_method }.to change(Asset, :count).by(created_assets) end end context 'when is already imported' do + let!(:original_import) { Asset.find_or_import_asset_with_barcode(barcode) } + context 'when the remote source is not present anymore' do setup do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) allow(SequencescapeClient).to receive(:find_by_uuid).and_return(nil) end it 'should raise an exception' do - expect { Asset.find_or_import_asset_with_barcode(@barcode_asset) }.to raise_exception Assets::Import::RefreshSourceNotFoundAnymore + expect { the_method }.to raise_exception Assets::Import::RefreshSourceNotFoundAnymore end end context 'when the remote source is present' do - setup do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) - end - it 'should not create a new local asset' do - count = Asset.count - Asset.find_or_import_asset_with_barcode(@barcode_asset) - expect(Asset.count).to eq(count) + expect { the_method }.not_to change(Asset, :count) end context 'when the local copy is up to date' do it 'should not destroy any remote facts' do - remote_facts = @asset.facts.from_remote_asset + remote_facts = the_method.facts.from_remote_asset remote_facts.each(&:reload) - Asset.find_or_import_asset_with_barcode(@barcode_asset) + the_method expect { remote_facts.each(&:reload) }.not_to raise_error end end context 'when the local copy is out of date' do before do - @asset.update_attributes(remote_digest: 'RANDOM') - @fact_changed = @asset.facts.from_remote_asset.where(predicate: 'contains').first + original_import.update_attributes(remote_digest: 'RANDOM') + @fact_changed = original_import.facts.from_remote_asset.where(predicate: 'contains').first @well_changed = create :asset @dependant_fact = create :fact, predicate: 'some', object: 'Moredata', is_remote?: true @@ -216,19 +196,17 @@ end it 'should destroy any remote facts that has changed' do - Asset.find_or_import_asset_with_barcode(@barcode_asset) + the_method expect { @fact_changed.reload }.to raise_exception ActiveRecord::RecordNotFound end it 'should destroy any contains dependant remote facts' do - Asset.find_or_import_asset_with_barcode(@barcode_asset) + the_method expect { @dependant_fact.reload }.to raise_exception ActiveRecord::RecordNotFound end it 'should re-create new remote facts' do - @asset = Asset.find_or_import_asset_with_barcode(@barcode_asset) - @asset.facts.reload - expect(@asset.facts.from_remote_asset.all? { |f| f.object_asset != @well_changed }) + expect(the_method.facts.from_remote_asset.all? { |f| f.object_asset != @well_changed }) end end end @@ -237,9 +215,8 @@ shared_examples 'a partial import of samples' do it 'imports the information of the tubes that have a supplier name' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_supplier.barcode) - tubes = @asset.facts.with_predicate('contains').map(&:object_asset) - tubes_with_info = tubes.select { |t| t.facts.where(predicate: 'supplier_sample_name').count > 0 } + tubes = subject.facts.with_predicate('contains').map(&:object_asset) + tubes_with_info = tubes.select { |t| t.facts.with_predicate('supplier_sample_name').present? } locations_with_info = tubes_with_info.map { |t| t.facts.with_predicate('location').first.object } expect(locations_with_info).to eq(['C1', 'D1']) @@ -247,148 +224,140 @@ end describe '#find_or_import_asset_with_barcode' do + subject(:the_method) { Asset.find_or_import_asset_with_barcode(barcode) } + context 'when importing an asset that does not exist' do + let(:barcode) { 'NOT FOUND' } + setup do allow(SequencescapeClient).to receive(:find_by_barcode).and_return(nil) end - it 'should return nil' do - expect(Asset.find_or_import_asset_with_barcode('NOT_FOUND')).to eq(nil) - end + it { is_expected.to be_nil } it 'should not create a new asset' do - expect { Asset.find_or_import_asset_with_barcode('NOT_FOUND') }.not_to change(Asset, :count) + expect { the_method }.not_to change(Asset, :count) end end - context 'when importing a local asset' do - setup do - @barcode_asset = generate(:barcode) - @asset = Asset.create!(barcode: @barcode_asset) - end + context 'when importing a local asset via its barcode' do + let(:barcode) { generate(:barcode) } + let!(:local_asset) { Asset.create!(barcode: barcode) } - it 'should return the local asset when looking by its barcode' do - expect(Asset.find_or_import_asset_with_barcode(@barcode_asset)).to eq(@asset) - end + it { is_expected.to eq local_asset } + end - it 'should return the local asset when looking by its uuid' do - expect(Asset.find_or_import_asset_with_barcode(@asset.uuid)).to eq(@asset) - end + context 'when importing a local asset via its uuid' do + # @todo This behaviour is a bit unexpected for a method called #find_or_import_asset_with_barcode. + # We should either explicitly look up by UUID where required, or have a separate method to + # handle the ambiguity + let(:barcode) { local_asset.uuid } + let!(:local_asset) { Asset.create!(barcode: generate(:barcode)) } + + it { is_expected.to eq local_asset } end context 'when importing a remote asset' do - context 'when the asset is a tube' do - setup do - @remote_asset = build_remote_tube(barcode: generate(:barcode)) - @asset_barcode = @remote_asset.barcode - stub_client_with_asset(SequencescapeClient, @remote_asset) - end + let(:barcode) { remote_asset.barcode } + setup do + stub_client_with_asset(SequencescapeClient, remote_asset) + end + + context 'when the asset is a tube' do context 'when the supplier name has not been provided' do - setup do + let(:remote_asset) do sample_no_supplier_name = build_remote_sample( sample_metadata: double('sample_metadata', supplier_name: nil, sample_common_name: 'species') ) - @remote_tube_asset_without_supplier = build_remote_tube( + build_remote_tube( barcode: generate(:barcode), aliquots: [build_remote_aliquot(sample: sample_no_supplier_name)] ) - stub_client_with_asset(SequencescapeClient, @remote_tube_asset_without_supplier) end it 'imports the information of the tube but does not set any supplier name' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_tube_asset_without_supplier.barcode) - @asset.facts.reload - expect(@asset.facts.with_predicate('supplier_sample_name').count).to eq(0) + expect(the_method.facts.reload.with_predicate('supplier_sample_name')).to be_empty end end context 'when the supplier name has been provided' do + let(:remote_asset) { build_remote_tube(barcode: generate(:barcode)) } + it 'imports the supplier name' do - @asset = Asset.find_or_import_asset_with_barcode(@asset_barcode) - expect(@asset.facts.with_predicate('supplier_sample_name').count).to eq(1) + expect(the_method.facts.reload.with_predicate('supplier_sample_name')).to be_one end it 'imports the common name' do - @asset = Asset.find_or_import_asset_with_barcode(@asset_barcode) - expect(@asset.facts.with_predicate('sample_common_name').count).to eq(1) + expect(the_method.facts.reload.with_predicate('sample_common_name')).to be_one end end end - context 'when the asset is a plate' do - setup do - @remote_asset = build_remote_v2_plate(barcode: generate(:barcode)) - @barcode_asset = @remote_asset.barcode - stub_client_with_asset(SequencescapeClient, @remote_asset) - end + context 'when the asset is a plate with complete information' do + let(:remote_asset) { build_remote_v2_plate(barcode: generate(:barcode)) } + let(:expected_study_uuid) { remote_asset.wells.first.aliquots.first.study.uuid } + let(:created_assets) { 3 } it_behaves_like 'a plate or tube rack' + end - context 'when the supplier sample name has not been provided to some samples' do - setup do - wells = [ - build_remote_well('A1', aliquots: [build_remote_aliquot(sample: - build_remote_sample(sample_metadata: nil))]), - build_remote_well('B1', aliquots: [build_remote_aliquot(sample: - build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: nil)))]), - build_remote_well('C1', aliquots: [build_remote_aliquot(sample: - build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: 'a supplier name')))]), - build_remote_well('D1', aliquots: [build_remote_aliquot(sample: - build_remote_sample(sample_metadata: double('sample_metadata', - sample_common_name: 'species', supplier_name: 'a supplier name')))]) - ] - @remote_asset_without_supplier = build_remote_v2_plate(barcode: generate(:barcode), wells: wells) - stub_client_with_asset(SequencescapeClient, @remote_asset_without_supplier) - end - - it_behaves_like 'a partial import of samples' + context 'when the supplier sample name has not been provided to some samples' do + let(:remote_asset) do + wells = [ + build_remote_well('A1', aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: nil))]), + build_remote_well('B1', aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: double('sample_metadata', + sample_common_name: 'species', supplier_name: nil)))]), + build_remote_well('C1', aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: double('sample_metadata', + sample_common_name: 'species', supplier_name: 'a supplier name')))]), + build_remote_well('D1', aliquots: [build_remote_aliquot(sample: + build_remote_sample(sample_metadata: double('sample_metadata', + sample_common_name: 'species', supplier_name: 'a supplier name')))]) + ] + build_remote_v2_plate(barcode: generate(:barcode), wells: wells) end - context 'when the plate does not have aliquots in its wells' do - setup do - wells = ['A1', 'B1'].map { |l| build_remote_well(l, aliquots: []) } - @remote_asset_without_aliquots = build_remote_v2_plate(barcode: generate(:barcode), wells: wells) - stub_client_with_asset(SequencescapeClient, @remote_asset_without_aliquots) - end + it_behaves_like 'a partial import of samples' + end - it 'creates the wells with the same uuid as in the remote asset' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_aliquots.barcode) - wells = @asset.facts.with_predicate('contains').map(&:object_asset) - expect(wells.zip(@remote_asset_without_aliquots.wells).all? { |w, w2| w.uuid == w2.uuid }).to eq(true) - end + context 'when the plate does not have aliquots in its wells' do + let(:remote_asset) do + wells = ['A1', 'B1'].map { |l| build_remote_well(l, aliquots: []) } + build_remote_v2_plate(barcode: generate(:barcode), wells: wells) end - context 'when the plate does not have samples in its wells' do - setup do - wells = ['A1', 'B1'].map { |l| build_remote_well(l, aliquots: [build_remote_aliquot(sample: nil)]) } - @remote_asset_without_samples = build_remote_v2_plate(barcode: generate(:barcode), wells: wells) - stub_client_with_asset(SequencescapeClient, @remote_asset_without_samples) - end + it 'creates the wells with the same uuid as in the remote asset' do + wells = the_method.facts.with_predicate('contains').map(&:object_asset) + expect(wells.zip(remote_asset.wells).all? { |w, w2| w.uuid == w2.uuid }).to eq(true) + end + end - it 'creates the wells with the same uuid as in the remote asset' do - @asset = Asset.find_or_import_asset_with_barcode(@remote_asset_without_samples.barcode) - wells = @asset.facts.with_predicate('contains').map(&:object_asset) - expect(wells.zip(@remote_asset_without_samples.wells).all? { |w, w2| w.uuid == w2.uuid }).to eq(true) - end + context 'when the plate does not have samples in its wells' do + let(:remote_asset) do + wells = ['A1', 'B1'].map { |l| build_remote_well(l, aliquots: [build_remote_aliquot(sample: nil)]) } + build_remote_v2_plate(barcode: generate(:barcode), wells: wells) + end + + it 'creates the wells with the same uuid as in the remote asset' do + wells = the_method.facts.with_predicate('contains').map(&:object_asset) + expect(wells.zip(remote_asset.wells).all? { |w, w2| w.uuid == w2.uuid }).to eq(true) end end context 'when the asset is a tube rack' do - setup do - @remote_asset = build_remote_tube_rack(barcode: generate(:barcode)) - @barcode_asset = @remote_asset.barcode - stub_client_with_asset(SequencescapeClient, @remote_asset) - end + let(:remote_asset) { build_remote_tube_rack(barcode: generate(:barcode)) } + let(:expected_study_uuid) { remote_asset.racked_tubes.first.tube.aliquots.first.study.uuid } + let(:created_assets) { 3 } it_behaves_like 'a plate or tube rack' context 'when the supplier sample name has not been provided to some samples' do - setup do + let(:remote_asset) do racked_tubes = [ build_remote_racked_tube('A1', build_remote_tube(aliquots: [build_remote_aliquot(sample: build_remote_sample(sample_metadata: nil))])), @@ -402,8 +371,7 @@ build_remote_sample(sample_metadata: double('sample_metadata', sample_common_name: 'species', supplier_name: 'a supplier name')))])) ] - @remote_asset_without_supplier = build_remote_tube_rack(barcode: generate(:barcode), racked_tubes: racked_tubes) - stub_client_with_asset(SequencescapeClient, @remote_asset_without_supplier) + build_remote_tube_rack(barcode: generate(:barcode), racked_tubes: racked_tubes) end it_behaves_like 'a partial import of samples' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0c15bb82..c7099a8d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -64,6 +64,11 @@ # particularly slow. config.profile_examples = 10 + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = 'tmp/spec_failures.txt' + # The settings below are suggested to provide a good initial experience # with RSpec, but feel free to customize to your heart's content. =begin @@ -74,11 +79,6 @@ # metadata: `fit`, `fdescribe` and `fcontext`, respectively. config.filter_run_when_matching :focus - # Allows RSpec to persist some state between runs in order to support - # the `--only-failures` and `--next-failure` CLI options. We recommend - # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = "spec/examples.txt" - # Limits the available syntax to the non-monkey patched syntax that is # recommended. For more details, see: # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ From 5d4bbc40f1e10b5235b35aafae0430e3d6c3aaa8 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 31 Mar 2022 13:50:10 +0100 Subject: [PATCH 146/303] Clean up rubocop_todo.yml --- .rubocop_todo.yml | 148 ++++++++++++++-------------------------------- 1 file changed, 46 insertions(+), 102 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 835ec117..d6932791 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --exclude-limit 1000` -# on 2022-03-23 14:20:20 UTC using RuboCop version 1.26.0. +# on 2022-03-31 12:36:56 UTC using RuboCop version 1.26.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -14,7 +14,7 @@ Bundler/OrderedGems: Exclude: - 'Gemfile' -# Offense count: 11 +# Offense count: 16 # Configuration parameters: IgnoredMethods. Lint/AmbiguousBlockAssociation: Exclude: @@ -44,7 +44,7 @@ Lint/NonDeterministicRequireOrder: - 'lib/tasks/setup_templates.rake' - 'spec/rails_helper.rb' -# Offense count: 7 +# Offense count: 6 # This cop supports safe auto-correction (--auto-correct). Lint/ParenthesesAsGroupedExpression: Exclude: @@ -65,16 +65,9 @@ Lint/RedundantStringCoercion: - 'script/runners/full_rack_generator.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' -# Offense count: 1 -# Configuration parameters: IgnoreImplicitReferences. -Lint/ShadowedArgument: - Exclude: - - 'lib/sequencescape_client.rb' - -# Offense count: 10 +# Offense count: 9 Lint/ShadowingOuterLocalVariable: Exclude: - - 'app/models/activities/steps_management.rb' - 'app/models/printables/group.rb' - 'lib/actions/plate_transfer.rb' - 'lib/support_n3.rb' @@ -92,16 +85,13 @@ Lint/ToJSON: Exclude: - 'lib/fact_changes.rb' -# Offense count: 54 +# Offense count: 49 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. Lint/UnusedBlockArgument: Exclude: - 'app/models/action.rb' - - 'app/models/asset.rb' - - 'app/models/label_template.rb' - 'app/models/printables/print_asset.rb' - - 'app/models/printer.rb' - 'db/migrate/20161028122148_add_action_type_to_operations.rb' - 'db/migrate/20161028134840_add_connect_by_to_step_type.rb' - 'db/migrate/20170122001651_add_active_step_to_activity.rb' @@ -116,12 +106,11 @@ Lint/UnusedBlockArgument: - 'script/fix_duplicated_tubes.rb' - 'script/runners/create_12_tubes.rb' - 'script/runners/load_metadata.rb' - - 'spec/lib/actions/racking_spec.rb' - 'spec/models/activities/background_tasks_spec.rb' - 'spec/models/step_spec.rb' - 'spec/models/step_type_spec.rb' -# Offense count: 19 +# Offense count: 18 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. Lint/UnusedMethodArgument: @@ -141,7 +130,7 @@ Lint/UnusedMethodArgument: - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' - 'spec/remote_assets_helper.rb' -# Offense count: 58 +# Offense count: 56 Lint/UselessAssignment: Exclude: - 'app/channels/activity_channel.rb' @@ -158,7 +147,6 @@ Lint/UselessAssignment: - 'lib/parsers/csv_layout/location_parser.rb' - 'lib/sequencescape_client.rb' - 'lib/support_n3.rb' - - 'lib/token_util.rb' - 'script/fix_duplicated_tubes.rb' - 'script/recreate_steptypes.rb' - 'script/remove_duplicates.rb' @@ -184,7 +172,7 @@ Lint/Void: - 'lib/inference_engines/default/step_execution.rb' - 'spec/models/assets/export_spec.rb' -# Offense count: 85 +# Offense count: 80 # Configuration parameters: IgnoredMethods, CountRepeatedAttributes. Metrics/AbcSize: Max: 79 @@ -205,12 +193,12 @@ Metrics/BlockNesting: Metrics/ClassLength: Max: 470 -# Offense count: 37 +# Offense count: 36 # Configuration parameters: IgnoredMethods. Metrics/CyclomaticComplexity: Max: 26 -# Offense count: 108 +# Offense count: 106 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. Metrics/MethodLength: Max: 334 @@ -220,18 +208,17 @@ Metrics/MethodLength: Metrics/ModuleLength: Max: 202 -# Offense count: 32 +# Offense count: 30 # Configuration parameters: IgnoredMethods. Metrics/PerceivedComplexity: Max: 26 -# Offense count: 6 +# Offense count: 4 Naming/AccessorMethodName: Exclude: - 'app/models/fact.rb' - 'app/models/step.rb' - 'lib/fact_changes.rb' - - 'lib/sequencescape_client.rb' # Offense count: 1 # Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms. @@ -241,7 +228,7 @@ Naming/FileName: Exclude: - 'config/initializers/pmb_server-setup.rb' -# Offense count: 33 +# Offense count: 29 # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. # AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to Naming/MethodParameterName: @@ -257,7 +244,7 @@ Naming/MethodParameterName: - 'spec/models/step_type_spec.rb' - 'spec/models/steps/queueable_job_spec.rb' -# Offense count: 24 +# Offense count: 22 # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros. # NamePrefix: is_, has_, have_ # ForbiddenPrefixes: is_, has_, have_ @@ -279,7 +266,7 @@ Naming/PredicateName: - 'lib/support_n3.rb' - 'lib/token_util.rb' -# Offense count: 3 +# Offense count: 2 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: PreferredName. Naming/RescuedExceptionsVariableName: @@ -287,7 +274,7 @@ Naming/RescuedExceptionsVariableName: - 'app/models/assets/export.rb' - 'lib/sequencescape_client.rb' -# Offense count: 40 +# Offense count: 36 # Configuration parameters: EnforcedStyle, AllowedIdentifiers. # SupportedStyles: snake_case, camelCase Naming/VariableName: @@ -297,11 +284,10 @@ Naming/VariableName: - 'lib/actions/plate_transfer.rb' - 'lib/actions/racking.rb' - 'lib/actions/tube_transfer.rb' - - 'lib/fact_changes.rb' - 'spec/script/runners/transfer_samples_spec.rb' - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' -# Offense count: 86 +# Offense count: 84 # This cop supports safe auto-correction (--auto-correct). Rails/ActiveRecordAliases: Exclude: @@ -377,7 +363,7 @@ Rails/Delegate: Exclude: - 'lib/parsers/csv_metadata/csv_parser.rb' -# Offense count: 28 +# Offense count: 29 # This cop supports unsafe auto-correction (--auto-correct-all). # Configuration parameters: Whitelist, AllowedMethods, AllowedReceivers. # Whitelist: find_by_sql @@ -465,7 +451,7 @@ Rails/NegateInclude: - 'lib/changes_support/disjoint_list.rb' - 'lib/support_n3.rb' -# Offense count: 12 +# Offense count: 8 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: Include. # Include: app/**/*.rb, config/**/*.rb, db/**/*.rb, lib/**/*.rb @@ -618,7 +604,7 @@ Style/BlockComments: Exclude: - 'spec/spec_helper.rb' -# Offense count: 124 +# Offense count: 120 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, IgnoredMethods, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces @@ -680,7 +666,7 @@ Style/CaseLikeIf: - 'app/models/operation.rb' - 'app/models/step_type.rb' -# Offense count: 38 +# Offense count: 39 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: nested, compact @@ -713,13 +699,12 @@ Style/ClassAndModuleChildren: - 'lib/sequencescape_client_v2.rb' - 'test/test_helper.rb' -# Offense count: 39 +# Offense count: 38 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: is_a?, kind_of? Style/ClassCheck: Exclude: - - 'app/models/asset.rb' - 'app/models/assets/facts_management.rb' - 'app/models/assets/traction_fields.rb' - 'app/models/condition.rb' @@ -745,11 +730,10 @@ Style/ClassEqualityComparison: - 'app/helpers/application_helper.rb' - 'lib/support_n3.rb' -# Offense count: 3 +# Offense count: 1 Style/ClassVars: Exclude: - 'app/models/action.rb' - - 'lib/sequencescape_client.rb' # Offense count: 24 # This cop supports safe auto-correction (--auto-correct). @@ -765,13 +749,12 @@ Style/ColonMethodCall: - 'spec/integration/inference_spec.rb' - 'spec/models/assets/export_spec.rb' -# Offense count: 8 +# Offense count: 6 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions. # SupportedStyles: assign_to_condition, assign_inside_condition Style/ConditionalAssignment: Exclude: - - 'app/helpers/activities_helper.rb' - 'app/helpers/application_helper.rb' - 'app/models/asset_group.rb' - 'app/models/condition.rb' @@ -779,12 +762,11 @@ Style/ConditionalAssignment: - 'lib/inference_engines/runner/step_execution.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' -# Offense count: 192 +# Offense count: 191 # Configuration parameters: AllowedConstants. Style/Documentation: Exclude: - 'spec/**/*' - - 'test/**/*' - 'app/channels/activity_channel.rb' - 'app/channels/application_cable/connection.rb' - 'app/controllers/activities_controller.rb' @@ -944,7 +926,6 @@ Style/Documentation: - 'lib/parsers/csv_layout/location_parser.rb' - 'lib/parsers/csv_metadata/csv_parser.rb' - 'lib/parsers/csv_metadata/data_parser.rb' - - 'lib/parsers/csv_metadata/datum_parser.rb' - 'lib/parsers/csv_metadata/headers_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - 'lib/psd_formatter.rb' @@ -975,7 +956,7 @@ Style/DoubleNegation: Exclude: - 'app/channels/activity_channel.rb' -# Offense count: 28 +# Offense count: 25 # This cop supports safe auto-correction (--auto-correct). Style/EachWithObject: Exclude: @@ -985,7 +966,6 @@ Style/EachWithObject: - 'app/helpers/step_types_helper.rb' - 'app/models/activities/background_tasks.rb' - 'app/models/activities/websocket_events.rb' - - 'app/models/assets/export.rb' - 'app/models/assets/traction_fields.rb' - 'app/models/printables/group.rb' - 'app/models/step_type.rb' @@ -1051,7 +1031,7 @@ Style/FormatStringToken: - 'config/routes.rb' - 'lib/views_schema.rb' -# Offense count: 353 +# Offense count: 351 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: always, always_true, never @@ -1277,7 +1257,6 @@ Style/FrozenStringLiteralComment: - 'lib/parsers/csv_layout/location_parser.rb' - 'lib/parsers/csv_metadata/csv_parser.rb' - 'lib/parsers/csv_metadata/data_parser.rb' - - 'lib/parsers/csv_metadata/datum_parser.rb' - 'lib/parsers/csv_metadata/headers_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - 'lib/sequencescape_client_v2.rb' @@ -1417,11 +1396,10 @@ Style/GlobalStdStream: - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/inference_engines/runner/step_execution.rb' -# Offense count: 28 +# Offense count: 27 # Configuration parameters: MinBodyLength. Style/GuardClause: Exclude: - - 'app/channels/activity_channel.rb' - 'app/controllers/activities_controller.rb' - 'app/controllers/application_controller.rb' - 'app/controllers/asset_groups_controller.rb' @@ -1455,7 +1433,7 @@ Style/HashEachMethods: - 'script/runners/load_metadata.rb' - 'spec/requests/api/v1/assets_spec.rb' -# Offense count: 948 +# Offense count: 939 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys @@ -1481,7 +1459,6 @@ Style/HashSyntax: - 'app/models/action.rb' - 'app/models/activities/background_tasks.rb' - 'app/models/activities/state.rb' - - 'app/models/activities/steps_management.rb' - 'app/models/activity.rb' - 'app/models/activity_type.rb' - 'app/models/asset.rb' @@ -1494,7 +1471,6 @@ Style/HashSyntax: - 'app/models/condition_group.rb' - 'app/models/fact.rb' - 'app/models/kit.rb' - - 'app/models/label_template.rb' - 'app/models/printer.rb' - 'app/models/step.rb' - 'app/models/step_type.rb' @@ -1545,7 +1521,7 @@ Style/HashSyntax: - 'test/factories/steps.rb' - 'test/factories/users.rb' -# Offense count: 6 +# Offense count: 5 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowIfModifier. Style/IfInsideElse: @@ -1556,7 +1532,7 @@ Style/IfInsideElse: - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/support_n3.rb' -# Offense count: 64 +# Offense count: 59 # This cop supports safe auto-correction (--auto-correct). Style/IfUnlessModifier: Exclude: @@ -1609,7 +1585,7 @@ Style/InverseMethods: Exclude: - 'app/helpers/activities_helper.rb' -# Offense count: 11 +# Offense count: 8 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. # SupportedStyles: line_count_dependent, lambda, literal @@ -1626,10 +1602,9 @@ Style/MixinUsage: - 'script/runners/put_tubes_into_rack_by_column_order.rb' - 'spec/inferences_helper.rb' -# Offense count: 15 +# Offense count: 14 Style/MultilineBlockChain: Exclude: - - 'app/models/asset.rb' - 'app/models/asset_group.rb' - 'lib/actions/racking.rb' - 'lib/fact_changes.rb' @@ -1703,7 +1678,7 @@ Style/Next: Style/NumericLiterals: MinDigits: 14 -# Offense count: 70 +# Offense count: 59 # This cop supports unsafe auto-correction (--auto-correct-all). # Configuration parameters: EnforcedStyle, IgnoredMethods. # SupportedStyles: predicate, comparison @@ -1713,7 +1688,6 @@ Style/NumericPredicate: - 'app/helpers/application_helper.rb' - 'app/models/action.rb' - 'app/models/activities/state.rb' - - 'app/models/activities/steps_management.rb' - 'app/models/activities/websocket_events.rb' - 'app/models/asset.rb' - 'app/models/asset_group.rb' @@ -1733,7 +1707,6 @@ Style/NumericPredicate: - 'lib/parsers/csv_layout/line_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - 'lib/support_n3.rb' - - 'lib/token_util.rb' - 'script/aliquot_type_inference.rb' - 'script/container_inferences.rb' - 'script/purpose_name_inference.rb' @@ -1758,13 +1731,12 @@ Style/OptionalBooleanParameter: - 'lib/fact_changes.rb' - 'lib/support_n3.rb' -# Offense count: 5 +# Offense count: 4 # This cop supports safe auto-correction (--auto-correct). Style/OrAssignment: Exclude: - 'app/controllers/asset_groups_controller.rb' - 'app/helpers/application_helper.rb' - - 'app/models/assets/export.rb' - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/inference_engines/runner/step_execution.rb' @@ -1774,18 +1746,16 @@ Style/ParallelAssignment: Exclude: - 'spec/models/step_spec.rb' -# Offense count: 87 +# Offense count: 79 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowSafeAssignment, AllowInMultilineConditions. Style/ParenthesesAroundCondition: Exclude: - - 'app/channels/activity_channel.rb' - 'app/helpers/application_helper.rb' - 'app/models/action.rb' - 'app/models/activities/websocket_events.rb' - 'app/models/asset.rb' - 'app/models/asset_group.rb' - - 'app/models/assets/export.rb' - 'app/models/assets/import.rb' - 'app/models/condition.rb' - 'app/models/condition_group.rb' @@ -1842,12 +1812,6 @@ Style/PreferredHashMethods: - 'lib/changes_support/transaction_scope.rb' - 'spec/models/asset_spec.rb' -# Offense count: 1 -# This cop supports safe auto-correction (--auto-correct). -Style/RedundantAssignment: - Exclude: - - 'app/models/asset.rb' - # Offense count: 8 # This cop supports safe auto-correction (--auto-correct). Style/RedundantBegin: @@ -1877,13 +1841,12 @@ Style/RedundantInterpolation: Exclude: - 'app/helpers/application_helper.rb' -# Offense count: 28 +# Offense count: 25 # This cop supports safe auto-correction (--auto-correct). Style/RedundantParentheses: Exclude: - 'app/models/action.rb' - 'app/models/asset.rb' - - 'app/models/assets/export.rb' - 'app/models/assets/import.rb' - 'app/models/condition_group.rb' - 'lib/actions/plate_transfer.rb' @@ -1910,13 +1873,7 @@ Style/RedundantPercentQ: - 'spec/models/assets/export_spec.rb' - 'spec/models/steps/cancellable_spec.rb' -# Offense count: 1 -# This cop supports safe auto-correction (--auto-correct). -Style/RedundantRegexpEscape: - Exclude: - - 'lib/token_util.rb' - -# Offense count: 47 +# Offense count: 37 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowMultipleReturnValues. Style/RedundantReturn: @@ -1928,12 +1885,10 @@ Style/RedundantReturn: - 'app/models/asset_group.rb' - 'app/models/assets/import.rb' - 'app/models/condition.rb' - - 'app/models/label_template.rb' - 'app/models/step_type.rb' - 'app/models/steps/compatible.rb' - 'app/models/uploaded_file.rb' - 'lib/actions/racking.rb' - - 'lib/changes_support/disjoint_list.rb' - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/label_template_setup.rb' - 'lib/sequencescape_client.rb' @@ -2007,21 +1962,19 @@ Style/SignalException: Exclude: - 'spec/inferences_helper.rb' -# Offense count: 3 +# Offense count: 1 # This cop supports unsafe auto-correction (--auto-correct-all). Style/SlicingWithRange: Exclude: - - 'app/models/asset.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' -# Offense count: 13 +# Offense count: 12 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowModifier. Style/SoleNestedConditional: Exclude: - 'app/models/action.rb' - 'app/models/asset.rb' - - 'app/models/assets/import.rb' - 'app/models/condition_group.rb' - 'lib/actions/plate_transfer.rb' - 'lib/actions/racking.rb' @@ -2031,14 +1984,13 @@ Style/SoleNestedConditional: - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - 'spec/integration/inference_spec.rb' -# Offense count: 20 +# Offense count: 18 # This cop supports unsafe auto-correction (--auto-correct-all). # Configuration parameters: Mode. Style/StringConcatenation: Exclude: - 'app/controllers/assets_controller.rb' - 'app/helpers/activities_helper.rb' - - 'app/models/asset.rb' - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/inference_engines/runner/step_execution.rb' - 'script/runners/load_metadata.rb' @@ -2052,7 +2004,7 @@ Style/StringConcatenation: - 'spec/script/runners/transfer_samples_spec.rb' - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' -# Offense count: 734 +# Offense count: 720 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes @@ -2090,7 +2042,6 @@ Style/StringLiterals: - 'lib/sequencescape_client_v2.rb' - 'lib/support_n3.rb' - 'lib/tasks/setup_templates.rake' - - 'lib/token_util.rb' - 'script/aliquot_type_inference.rb' - 'script/claim_uuids.rb' - 'script/container_inferences.rb' @@ -2168,14 +2119,13 @@ Style/StringLiterals: Style/SymbolArray: EnforcedStyle: brackets -# Offense count: 16 +# Offense count: 15 # This cop supports unsafe auto-correction (--auto-correct-all). # Configuration parameters: AllowMethodsWithArguments, IgnoredMethods. # IgnoredMethods: respond_to, define_method Style/SymbolProc: Exclude: - 'app/models/assets/import.rb' - - 'app/models/condition_group.rb' - 'lib/label_template_setup.rb' - 'lib/parsers/csv_metadata/headers_parser.rb' - 'lib/support_n3.rb' @@ -2241,16 +2191,13 @@ Style/WhileUntilDo: - 'script/runners/create_file.rb' - 'script/runners/create_layout.rb' -# Offense count: 77 +# Offense count: 72 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, MinSize, WordRegex. # SupportedStyles: percent, brackets Style/WordArray: Exclude: - 'app/channels/activity_channel.rb' - - 'app/models/assets/export.rb' - - 'app/models/label_template.rb' - - 'app/models/printer.rb' - 'lib/actions/plate_transfer.rb' - 'lib/actions/tube_transfer.rb' - 'lib/fact_changes.rb' @@ -2270,7 +2217,7 @@ Style/WordArray: - 'spec/models/assets/import_spec.rb' - 'spec/script/runners/load_metadata_spec.rb' -# Offense count: 22 +# Offense count: 19 # This cop supports unsafe auto-correction (--auto-correct-all). Style/ZeroLengthPredicate: Exclude: @@ -2283,12 +2230,9 @@ Style/ZeroLengthPredicate: - 'lib/fact_changes.rb' - 'lib/parsers/csv_layout/line_parser.rb' - 'lib/parsers/csv_metadata/line_parser.rb' - - 'lib/token_util.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - - 'spec/lib/actions/plate_transfer_spec.rb' - - 'spec/models/step_spec.rb' -# Offense count: 125 +# Offense count: 130 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https From 2ba51ae3e3eee2e377368e97f0231a757491243f Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 1 Apr 2022 13:25:39 +0100 Subject: [PATCH 147/303] Fix tube rack import and asset syncing - Extend the import tests to cover more functionality - Ensure tube racks can load their tubes - Ensure existing assests will 'refresh' --- app/models/asset.rb | 2 + app/models/assets/import.rb | 85 +++++++----- config/environments/test.rb | 2 + lib/fact_changes.rb | 22 ++-- lib/sequencescape_client.rb | 20 +-- lib/sequencescape_client_v2.rb | 4 + spec/models/assets/export_spec.rb | 2 +- spec/models/assets/import_spec.rb | 121 ++++++++++++------ .../sequencescape/v2/empty_response.txt | 18 +++ .../v2/labware_plate_response.txt | 18 +++ .../v2/labware_tube_rack_response.txt | 18 +++ .../sequencescape/v2/plate_response.txt | 18 +++ .../sequencescape/v2/tube_rack_response.txt | 18 +++ 13 files changed, 253 insertions(+), 95 deletions(-) create mode 100644 spec/support/responses/sequencescape/v2/empty_response.txt create mode 100644 spec/support/responses/sequencescape/v2/labware_plate_response.txt create mode 100644 spec/support/responses/sequencescape/v2/labware_tube_rack_response.txt create mode 100644 spec/support/responses/sequencescape/v2/plate_response.txt create mode 100644 spec/support/responses/sequencescape/v2/tube_rack_response.txt diff --git a/app/models/asset.rb b/app/models/asset.rb index a0e22963..d822bf06 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -88,6 +88,8 @@ def update_compatible_activity_type end } + scope :for_refreshing, -> { includes(facts: { object_asset: :facts }) } + delegate :predicate_matching?, to: :facts def short_description diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 115a2ec8..0cb9025d 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -75,9 +75,7 @@ def changed_remote?(remote_asset) def assets_to_refresh # We need to destroy also the remote facts of the contained wells on refresh - [self, facts.with_predicate('contains').map(&:object_asset).select do |asset| - asset.facts.from_remote_asset.count > 0 - end].flatten + [self, *facts.with_predicate('contains').map(&:object_asset).select(&:remote_asset?)] end def is_refreshing_right_now? @@ -85,12 +83,12 @@ def is_refreshing_right_now? end def refresh(fact_changes = nil) - if is_remote_asset? - remote_asset = SequencescapeClient::find_by_uuid(uuid) - raise RefreshSourceNotFoundAnymore unless remote_asset + return self unless remote_asset? - refresh_from_remote(fact_changes: fact_changes, remote_asset: remote_asset) - end + remote_asset = SequencescapeClient::find_by_uuid(uuid) + raise RefreshSourceNotFoundAnymore unless remote_asset + + refresh_from_remote(fact_changes: fact_changes, remote_asset: remote_asset) self end @@ -103,18 +101,22 @@ def refresh_from_remote(remote_asset:, fact_changes: nil) end def refresh!(fact_changes = nil) - if is_remote_asset? - @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Refresh!!'), state: 'running') - remote_asset = SequencescapeClient::find_by_uuid(uuid) - raise RefreshSourceNotFoundAnymore unless remote_asset + return self unless remote_asset? - _process_refresh(remote_asset, fact_changes) - end + @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Refresh!!'), state: 'running') + remote_asset = SequencescapeClient::find_by_uuid(uuid) + raise RefreshSourceNotFoundAnymore unless remote_asset + + _process_refresh(remote_asset, fact_changes) self end - def is_remote_asset? - facts.from_remote_asset.count > 0 + def remote_asset? + if facts.loaded? + facts.any?(&:is_remote?) + else + facts.from_remote_asset.exists? + end end private @@ -200,26 +202,28 @@ def annotate_container(asset, remote_asset, fact_changes) return unless remote_asset.try(:aliquots) remote_asset.aliquots.each do |aliquot| + sample = aliquot.sample fact_changes.replace_remote(asset, 'sample_tube', asset) - fact_changes.replace_remote(asset, 'sanger_sample_id', TokenUtil.quote_if_uuid(aliquot&.sample&.sanger_sample_id)) - fact_changes.replace_remote(asset, 'sample_uuid', TokenUtil.quote(aliquot&.sample&.uuid), literal: true) - fact_changes.replace_remote(asset, 'sanger_sample_name', TokenUtil.quote_if_uuid(aliquot&.sample&.name)) - fact_changes.replace_remote(asset, 'supplier_sample_name', TokenUtil.quote_if_uuid(aliquot&.sample&.sample_metadata&.supplier_name)) - fact_changes.replace_remote(asset, 'sample_common_name', TokenUtil.quote_if_uuid(aliquot&.sample&.sample_metadata&.sample_common_name)) + fact_changes.replace_remote(asset, 'sanger_sample_id', TokenUtil.quote_if_uuid(sample&.sanger_sample_id)) + fact_changes.replace_remote(asset, 'sample_uuid', TokenUtil.quote(sample&.uuid), literal: true) + fact_changes.replace_remote(asset, 'sanger_sample_name', TokenUtil.quote_if_uuid(sample&.name)) + fact_changes.replace_remote(asset, 'supplier_sample_name', TokenUtil.quote_if_uuid(sample&.sample_metadata&.supplier_name)) + fact_changes.replace_remote(asset, 'sample_common_name', TokenUtil.quote_if_uuid(sample&.sample_metadata&.sample_common_name)) end end def annotate_study_name_from_aliquots(asset, remote_asset, fact_changes) - return unless remote_asset.try(:aliquots) + return if remote_asset.try(:aliquots).blank? - return unless ((remote_asset.aliquots.count == 1) && (remote_asset.aliquots.first.sample)) + study = remote_asset.aliquots.lazy.map(&:study).detect(&:present?) + return unless study - fact_changes.replace_remote(asset, 'study_name', remote_asset.aliquots.first.study.name) - fact_changes.replace_remote(asset, 'study_uuid', TokenUtil.quote(remote_asset.aliquots.first.study.uuid), literal: true) + fact_changes.replace_remote(asset, 'study_name', study.name) + fact_changes.replace_remote(asset, 'study_uuid', TokenUtil.quote(study.uuid), literal: true) end def annotate_study_name(asset, remote_asset, fact_changes) - if remote_asset.try(:wells) + if remote_asset.try(:wells).present? remote_asset.wells.detect do |w| annotate_study_name_from_aliquots(asset, w, fact_changes) end @@ -233,10 +237,13 @@ def annotate_study_name(asset, remote_asset, fact_changes) end def annotate_wells(asset, remote_asset, fact_changes) - return unless remote_asset.try(:wells) + return if remote_asset.try(:wells).blank? + + well_uuids = remote_asset.wells.map(&:uuid) + existing_wells = Asset.includes(:facts).where(uuid: well_uuids).index_by(&:uuid) remote_asset.wells.each do |well| - local_well = Asset.find_or_create_by!(uuid: well.uuid) + local_well = existing_wells.fetch(well.uuid) { Asset.new(uuid: well.uuid) } fact_changes.replace_remote(asset, 'contains', local_well) @@ -252,12 +259,15 @@ def annotate_wells(asset, remote_asset, fact_changes) end def annotate_tubes(asset, remote_asset, fact_changes) - return unless remote_asset.try(:racked_tubes) + return if remote_asset.try(:racked_tubes).blank? + + tube_uuids = remote_asset.racked_tubes.map { |rt| rt.tube.uuid } + existing_tubes = Asset.includes(:facts).where(uuid: tube_uuids).index_by(&:uuid) remote_asset.racked_tubes.each do |racked_tube| remote_tube = racked_tube.tube - local_tube = Asset.find_or_create_by!(uuid: remote_tube.uuid) - local_tube.update!(barcode: remote_tube.labware_barcode['human_barcode']) + local_tube = existing_tubes.fetch(remote_tube.uuid) { Asset.new(uuid: remote_tube.uuid) } + local_tube.barcode = remote_tube.labware_barcode['human_barcode'] fact_changes.replace_remote(asset, 'contains', local_tube) @@ -265,7 +275,6 @@ def annotate_tubes(asset, remote_asset, fact_changes) fact_changes.replace_remote(local_tube, 'a', 'SampleTube') fact_changes.replace_remote(local_tube, 'location', racked_tube.coordinate) fact_changes.replace_remote(local_tube, 'parent', asset) - if (remote_tube.try(:aliquots)&.first&.sample&.sample_metadata&.supplier_name) annotate_container(local_tube, remote_tube, fact_changes) end @@ -288,20 +297,26 @@ def sequencescape_type_for_asset(remote_asset) # how to handle this. @note The behaviour differs from the singular # #find_or_import_asset_with_barcode in that it will not also attempt to # lookup by uuid, and will not automatically register fluidx barcodes - def find_or_import_assets_with_barcodes(barcodes, includes: :facts) - local_assets = Asset.includes(includes).where(barcode: barcodes).to_a + def find_or_import_assets_with_barcodes(barcodes, includes: {}) + local_assets = Asset.for_refreshing.includes(includes).where(barcode: barcodes).to_a remote_assets = import_barcodes(barcodes - local_assets.pluck(:barcode)) + # This synchronises the local assets with the version in Sequencescape + local_assets.each(&:refresh) local_assets + remote_assets end private def import_remote_asset(remote_asset, barcode, import_step) - Asset.create!(barcode: barcode, uuid: remote_asset.uuid).tap do |asset| + Asset.create!(barcode: barcode, uuid: remote_asset.uuid, facts: []).tap do |asset| FactChanges.new.tap do |updates| updates.replace_remote(asset, 'a', sequencescape_type_for_asset(remote_asset)) updates.replace_remote(asset, 'remoteAsset', remote_asset.uuid) end.apply(import_step) + # We initialize the asset with an empty facts array, but then modify it indirectly + # Ideally this wouldn't be the case, and we'd keep the instance in sync. However + # for now we unload the association to ensure we don't end up working with stale data + asset.facts.reset asset.refresh_from_remote(remote_asset: remote_asset) asset.update_compatible_activity_type end diff --git a/config/environments/test.rb b/config/environments/test.rb index 1b9922e9..e2ffd0bd 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -58,4 +58,6 @@ config.cwm_path = ENV.fetch('CWM_PATH', '') config.enable_reasoning = true + + config.active_record.verbose_query_logs = true end diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index 5a9fae04..8090859a 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -529,30 +529,24 @@ def _fact_operations(action_type, step, facts) operations end - def all_values_are_new_records(hash) - hash.values.all? do |value| - (value.respond_to?(:new_record?) && value.new_record?) - end + def any_values_are_new_records(hash) + hash.values.any? { |value| value.try(:new_record?) } end def _instance_builder_for_import(klass, params_list, &block) instances = params_list.filter_map do |params_for_instance| - unless (params_for_instance.kind_of?(klass)) - if (all_values_are_new_records(params_for_instance) || - (!klass.exists?(params_for_instance))) - klass.new(params_for_instance) - end - else - if params_for_instance.new_record? - params_for_instance - end + if params_for_instance.kind_of?(klass) + params_for_instance if params_for_instance.new_record? + elsif any_values_are_new_records(params_for_instance) || !klass.exists?(params_for_instance) + klass.new(params_for_instance) end end.uniq instances.each do |instance| + # Runs the callbacks (See https://github.com/zdennis/activerecord-import#callbacks) instance.run_callbacks(:save) { false } instance.run_callbacks(:create) { false } end - if instances && !instances.empty? + if instances.present? klass.import(instances) # import does not return the ids for the instances, so we need to reload # again. Uuid is the only identificable attribute set diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 4b711acf..7768686e 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -6,7 +6,7 @@ require 'sequencescape_client_v2' class SequencescapeClient - SELECT_FOR_IMPORT = 'uuid,labware_barcode,receptacles' + SELECT_FOR_IMPORT = 'uuid,labware_barcode,receptacles,purpose' @purposes = nil def self.api_connection_options @@ -53,23 +53,25 @@ def self.find_by_uuid(uuid) def self.labware(conditions) SequencescapeClientV2::Labware - .includes('receptacles.aliquots.sample.sample_metadata') + .includes('receptacles.aliquots.sample.sample_metadata,receptacles.aliquots.study,purpose') .select( tubes: SELECT_FOR_IMPORT, plates: SELECT_FOR_IMPORT, - tube_racks: 'uuid,labware_barcode', + tube_racks: 'uuid,labware_barcode,purpose', samples: 'sanger_sample_id,uuid,name', - sample_metadata: 'supplier_name,sample_common_name' - ).where(conditions) + sample_metadata: 'supplier_name,sample_common_name', + study: 'name,uuid', + purpose: 'name' + ).where(**conditions) end # TODO: In most cases we should know what type of record we're looking up. def self.find_by(search_conditions) [ - SequencescapeClientV2::Plate.includes('wells.aliquots.sample.sample_metadata'), - SequencescapeClientV2::Tube.includes('aliquots.sample.sample_metadata'), - SequencescapeClientV2::Well.includes('aliquots.sample.sample_metadata'), - SequencescapeClientV2::TubeRack.includes('racked_tubes.tube.aliquots.sample.sample_metadata') + SequencescapeClientV2::Plate.includes('wells.aliquots.sample.sample_metadata,wells.aliquots.study,purpose'), + SequencescapeClientV2::Tube.includes('aliquots.sample.sample_metadata,aliquots.study'), + SequencescapeClientV2::Well.includes('aliquots.sample.sample_metadata,aliquots.study'), + SequencescapeClientV2::TubeRack.includes('racked_tubes.tube.aliquots.sample.sample_metadata,racked_tubes.tube.aliquots.study,purpose') ].each do |klass| begin search = klass.where(search_conditions).first diff --git a/lib/sequencescape_client_v2.rb b/lib/sequencescape_client_v2.rb index a8313533..65d0d097 100644 --- a/lib/sequencescape_client_v2.rb +++ b/lib/sequencescape_client_v2.rb @@ -27,6 +27,10 @@ def sync? def wells type == 'plates' ? receptacles : [] end + + def racked_tubes + type == 'tube_racks' ? SequencescapeClientV2::TubeRack.includes('racked_tubes.tube.aliquots.sample.sample_metadata,racked_tubes.tube.aliquots.study').find(id).first.racked_tubes : [] + end end class SequencescapeClientV2::Plate < SequencescapeClientV2::Model diff --git a/spec/models/assets/export_spec.rb b/spec/models/assets/export_spec.rb index 145bb530..ee9b16f9 100644 --- a/spec/models/assets/export_spec.rb +++ b/spec/models/assets/export_spec.rb @@ -58,7 +58,7 @@ } @assets = SupportN3::parse_facts(facts) - @rack1 = Asset.find_by(uuid: 'rack1') + @rack1 = Asset.includes(:facts).find_by(uuid: 'rack1') expect(@rack1.attributes_to_send).to eq([ { sample_tube_uuid: "s1", location: "A1" }, { sample_tube_uuid: "s2", location: "B1" }, diff --git a/spec/models/assets/import_spec.rb b/spec/models/assets/import_spec.rb index 7908e320..1a5faa4d 100644 --- a/spec/models/assets/import_spec.rb +++ b/spec/models/assets/import_spec.rb @@ -15,7 +15,7 @@ context 'when it is not a remote asset' do before do - allow(asset).to receive(:is_remote_asset?).and_return(false) + allow(asset).to receive(:remote_asset?).and_return(false) end it 'does not refresh' do @@ -26,7 +26,7 @@ context 'when it is a remote asset' do before do - allow(asset).to receive(:is_remote_asset?).and_return(true) + allow(asset).to receive(:remote_asset?).and_return(true) end context 'when the asset has changed' do @@ -139,21 +139,22 @@ end shared_examples 'a plate or tube rack' do - it 'should create the corresponding facts from the json' do - facts = the_method.facts.reload + it 'should create the corresponding facts from the json', :aggregate_failures do + facts = subject.facts.reload predicates = ["a", "pushTo", "purpose", "is", "contains", "contains", "study_name", "study_uuid"] - predicate_facts = predicates.map { |predicate| facts.with_predicate(predicate) } - expect(predicate_facts).to all be_present + predicates.each do |predicate| + expect(facts.with_predicate(predicate)).to be_present, "No fact with predicate: #{predicate}" + end end it 'should store the study uuid in a safe format' do - asset_study_uuid = the_method.facts.reload.with_predicate('study_uuid').first.object + asset_study_uuid = subject.facts.reload.with_predicate('study_uuid').first&.object expect(asset_study_uuid).to eq(TokenUtil.quote(expected_study_uuid)) end context 'for the first time' do it 'should create the local asset' do - expect { the_method }.to change(Asset, :count).by(created_assets) + expect { subject }.to change(Asset, :count).by(created_assets) end end @@ -166,20 +167,28 @@ end it 'should raise an exception' do - expect { the_method }.to raise_exception Assets::Import::RefreshSourceNotFoundAnymore + expect { subject }.to raise_exception Assets::Import::RefreshSourceNotFoundAnymore end end context 'when the remote source is present' do + setup do + # We could do this via webmock, but it all gets a bit complicated, and our return value + # is nice and simple here. So instead we just dummy out an empty response for the second + # query. + allow(SequencescapeClient).to receive(:labware).and_call_original + allow(SequencescapeClient).to receive(:labware).with(barcode: ['NOT_FOUND']).and_return([]) + end + it 'should not create a new local asset' do - expect { the_method }.not_to change(Asset, :count) + expect { subject }.not_to change(Asset, :count) end context 'when the local copy is up to date' do it 'should not destroy any remote facts' do - remote_facts = the_method.facts.from_remote_asset + remote_facts = original_import.facts.from_remote_asset remote_facts.each(&:reload) - the_method + subject expect { remote_facts.each(&:reload) }.not_to raise_error end end @@ -196,17 +205,17 @@ end it 'should destroy any remote facts that has changed' do - the_method + subject expect { @fact_changed.reload }.to raise_exception ActiveRecord::RecordNotFound end it 'should destroy any contains dependant remote facts' do - the_method + subject expect { @dependant_fact.reload }.to raise_exception ActiveRecord::RecordNotFound end it 'should re-create new remote facts' do - expect(the_method.facts.from_remote_asset.all? { |f| f.object_asset != @well_changed }) + expect(subject.facts.from_remote_asset.where(object_asset: @well_changed)).to be_empty end end end @@ -215,7 +224,8 @@ shared_examples 'a partial import of samples' do it 'imports the information of the tubes that have a supplier name' do - tubes = subject.facts.with_predicate('contains').map(&:object_asset) + facts = subject.facts + tubes = facts.with_predicate('contains').map(&:object_asset) tubes_with_info = tubes.select { |t| t.facts.with_predicate('supplier_sample_name').present? } locations_with_info = tubes_with_info.map { |t| t.facts.with_predicate('location').first.object } @@ -390,34 +400,73 @@ let(:full_remote_labware) { build_remote_tube(barcode: generate(:barcode), uuid: remote_labware.uuid, labware_barcode: remote_labware.labware_barcode) } let(:local_asset) { Asset.create!(barcode: local_barcode) } - before do - local_asset - expect(SequencescapeClient).to receive(:labware).with(barcode: [remote_barcode, non_existant_barcode]).and_return([remote_labware]) - # We still need this as we're currently immediately refreshing the resource from SS - allow(SequencescapeClient).to receive(:find_by_uuid).with(remote_labware.uuid).and_return(full_remote_labware) - end + context 'a tube and an unknown barcode' do + before do + local_asset + expect(SequencescapeClient).to receive(:labware).with(barcode: [remote_barcode, non_existant_barcode]).and_return([remote_labware]) + # We still need this as we're currently immediately refreshing the resource from SS + allow(SequencescapeClient).to receive(:find_by_uuid).with(remote_labware.uuid).and_return(full_remote_labware) + end - subject(:find_or_import_assets_with_barcodes) do - Asset.find_or_import_assets_with_barcodes([local_barcode, remote_barcode, non_existant_barcode]) - end + subject(:find_or_import_assets_with_barcodes) do + Asset.find_or_import_assets_with_barcodes([local_barcode, remote_barcode, non_existant_barcode]) + end - it 'imports only remote barcodes' do - expect { find_or_import_assets_with_barcodes }.to change(Asset, :count).by(1) - end + it 'imports only remote barcodes' do + expect { find_or_import_assets_with_barcodes }.to change(Asset, :count).by(1) + end + + it 'does not return an asset that does not exist' do + expect(find_or_import_assets_with_barcodes.pluck(:barcode)).not_to include(non_existant_barcode) + end + + it { is_expected.to(satisfy { |array| array.length == 2 }) } + it { is_expected.to all be_an Asset } - it 'does not return an asset that does not exist' do - expect(find_or_import_assets_with_barcodes.pluck(:barcode)).not_to include(non_existant_barcode) + it 'returns local assets' do + expect(find_or_import_assets_with_barcodes).to include(local_asset) + end + + it 'returns a newly registered remote labware' do + expect(find_or_import_assets_with_barcodes.pluck(:barcode)).to include(remote_barcode) + end end - it { is_expected.to(satisfy { |array| array.length == 2 }) } - it { is_expected.to all be_an Asset } + context 'with a plate' do + let(:expected_study_uuid) { '6d4617ea-9a21-11ec-9a02-acde48001122' } + let(:created_assets) { 97 } + let(:barcode) { 'DN9000001W' } + + subject(:find_or_import_assets_with_barcodes) do + Asset.find_or_import_assets_with_barcodes([barcode, non_existant_barcode]).first + end + + setup do + # We're using find_or_import_asset_with_barcode to set-up our state + stub_request(:get, %r{api/v2/plates}).to_return(File.new('./spec/support/responses/sequencescape/v2/plate_response.txt')) + stub_request(:get, %r{api/v2/labware}).to_return(File.new('./spec/support/responses/sequencescape/v2/labware_plate_response.txt')) + end - it 'returns local assets' do - expect(find_or_import_assets_with_barcodes).to include(local_asset) + it_behaves_like 'a plate or tube rack' end - it 'returns a newly registered remote labware' do - expect(find_or_import_assets_with_barcodes.pluck(:barcode)).to include(remote_barcode) + context 'with a tube rack' do + let(:expected_study_uuid) { '6d4617ea-9a21-11ec-9a02-acde48001122' } + let(:created_assets) { 97 } + let(:barcode) { 'AB42785517' } + + subject(:find_or_import_assets_with_barcodes) do + Asset.find_or_import_assets_with_barcodes([barcode, non_existant_barcode]).first + end + + setup do + # We're using find_or_import_asset_with_barcode to set-up our state + stub_request(:get, %r{api/v2/(plates|tubes|wells)}).to_return(File.new('./spec/support/responses/sequencescape/v2/empty_response.txt')) + stub_request(:get, %r{api/v2/tube_racks}).to_return(File.new('./spec/support/responses/sequencescape/v2/tube_rack_response.txt')) + stub_request(:get, %r{api/v2/labware}).to_return(File.new('./spec/support/responses/sequencescape/v2/labware_tube_rack_response.txt')) + end + + it_behaves_like 'a plate or tube rack' end end end diff --git a/spec/support/responses/sequencescape/v2/empty_response.txt b/spec/support/responses/sequencescape/v2/empty_response.txt new file mode 100644 index 00000000..4ffafe60 --- /dev/null +++ b/spec/support/responses/sequencescape/v2/empty_response.txt @@ -0,0 +1,18 @@ +HTTP/1.1 200 OK +X-Frame-Options: SAMEORIGIN +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +X-Download-Options: noopen +X-Permitted-Cross-Domain-Policies: none +Referrer-Policy: strict-origin-when-cross-origin +Content-Type: application/vnd.api+json +Cache-Control: no-store, must-revalidate, private, max-age=0 +X-Request-Id: 897500d8-ae1e-43e1-b258-580962b39b34 +X-Runtime: 0.033948 +Vary: Origin +X-MiniProfiler-Original-Cache-Control: max-age=0, private, must-revalidate +X-MiniProfiler-Ids: r0266h9nt6vv4c6yshsf,lybddp5q6m1b0wja5zl7,h8dyv9vj5146riqk702a,6maz376ry77dilgxstce,ro1x2x8m9yhaa6h1kl64,mmipw1q7smx83bo9fpxk,yi14cm97b0meme37a7fd,lvuylwm990jpzb5044dk,nnfyr6zzn1fv5hv4nq8l,crmk9clc654pm1orvbf2 +Set-Cookie: __profilin=p%3Dt; path=/; HttpOnly; SameSite=Lax +Transfer-Encoding: chunked + +{"data":[],"links":{"first":"http://localhost:3000/api/v2/tube_racks?filter%5Bbarcode%5D=nothing&include=racked_tubes.tube.aliquots.sample.sample_metadata&page%5Bnumber%5D=1&page%5Bsize%5D=100","last":"http://localhost:3000/api/v2/tube_racks?filter%5Bbarcode%5D=nothing&include=racked_tubes.tube.aliquots.sample.sample_metadata&page%5Bnumber%5D=1&page%5Bsize%5D=100"}} \ No newline at end of file diff --git a/spec/support/responses/sequencescape/v2/labware_plate_response.txt b/spec/support/responses/sequencescape/v2/labware_plate_response.txt new file mode 100644 index 00000000..82cbb094 --- /dev/null +++ b/spec/support/responses/sequencescape/v2/labware_plate_response.txt @@ -0,0 +1,18 @@ +HTTP/1.1 200 OK +X-Frame-Options: SAMEORIGIN +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +X-Download-Options: noopen +X-Permitted-Cross-Domain-Policies: none +Referrer-Policy: strict-origin-when-cross-origin +Content-Type: application/vnd.api+json +Cache-Control: no-store, must-revalidate, private, max-age=0 +X-Request-Id: f62a6576-4f43-4b5d-973d-9b1d103dbe11 +X-Runtime: 0.773061 +Vary: Origin +X-MiniProfiler-Original-Cache-Control: max-age=0, private, must-revalidate +X-MiniProfiler-Ids: 67pmtv59y0qgswh86phf,tei9eifhqr5ai5wsr37h,u51wi3xrsy4nno21z5y1,k7zjigrzrl5xqtzptj79,v3g61r5x6i8vcoiz41n2,hixdm5dp9js34vvd5n1j,h5nry8521lil2x65eyi7,do19v972tj6g4j0fb0ab,tgbpp7q89bzob2eol0b9,wiq23okz07dl48t7xj3d,hhjcy0xhsxo88qstns8w,en9xjfcoe8m7c4spdmta,khokuqgbpk813qg0cm39,xt1w47sa31bq51t6w0zv,hbl5nvzt63kldp07w5up,cfcbxfyqtnrs00z7q2yr,hfb2tbpi95jmao5dwpdl,v3ajhlkw9fzj6wd6sbxm,jbisvmgaoaxtyniy584t,34vv0rflxbjhjo5f5075 +Set-Cookie: __profilin=p%3Dt; path=/; HttpOnly; SameSite=Lax +Transfer-Encoding: chunked + +{"data":[{"id":"1","type":"plates","links":{"self":"http://localhost:3000/api/v2/plates/1"},"attributes":{"uuid":"769d93b8-9a21-11ec-9a02-acde48001122","labware_barcode":{"ean13_barcode":"1229000001872","machine_barcode":"DN9000001W","human_barcode":"DN9000001W"}},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/purpose","related":"http://localhost:3000/api/v2/plates/1/purpose"},"data":{"type":"purposes","id":"77"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/receptacles","related":"http://localhost:3000/api/v2/plates/1/receptacles"},"data":[{"type":"wells","id":"1"},{"type":"wells","id":"2"},{"type":"wells","id":"3"},{"type":"wells","id":"4"},{"type":"wells","id":"5"},{"type":"wells","id":"6"},{"type":"wells","id":"7"},{"type":"wells","id":"8"},{"type":"wells","id":"9"},{"type":"wells","id":"10"},{"type":"wells","id":"11"},{"type":"wells","id":"12"},{"type":"wells","id":"13"},{"type":"wells","id":"14"},{"type":"wells","id":"15"},{"type":"wells","id":"16"},{"type":"wells","id":"17"},{"type":"wells","id":"18"},{"type":"wells","id":"19"},{"type":"wells","id":"20"},{"type":"wells","id":"21"},{"type":"wells","id":"22"},{"type":"wells","id":"23"},{"type":"wells","id":"24"},{"type":"wells","id":"25"},{"type":"wells","id":"26"},{"type":"wells","id":"27"},{"type":"wells","id":"28"},{"type":"wells","id":"29"},{"type":"wells","id":"30"},{"type":"wells","id":"31"},{"type":"wells","id":"32"},{"type":"wells","id":"33"},{"type":"wells","id":"34"},{"type":"wells","id":"35"},{"type":"wells","id":"36"},{"type":"wells","id":"37"},{"type":"wells","id":"38"},{"type":"wells","id":"39"},{"type":"wells","id":"40"},{"type":"wells","id":"41"},{"type":"wells","id":"42"},{"type":"wells","id":"43"},{"type":"wells","id":"44"},{"type":"wells","id":"45"},{"type":"wells","id":"46"},{"type":"wells","id":"47"},{"type":"wells","id":"48"},{"type":"wells","id":"49"},{"type":"wells","id":"50"},{"type":"wells","id":"51"},{"type":"wells","id":"52"},{"type":"wells","id":"53"},{"type":"wells","id":"54"},{"type":"wells","id":"55"},{"type":"wells","id":"56"},{"type":"wells","id":"57"},{"type":"wells","id":"58"},{"type":"wells","id":"59"},{"type":"wells","id":"60"},{"type":"wells","id":"61"},{"type":"wells","id":"62"},{"type":"wells","id":"63"},{"type":"wells","id":"64"},{"type":"wells","id":"65"},{"type":"wells","id":"66"},{"type":"wells","id":"67"},{"type":"wells","id":"68"},{"type":"wells","id":"69"},{"type":"wells","id":"70"},{"type":"wells","id":"71"},{"type":"wells","id":"72"},{"type":"wells","id":"73"},{"type":"wells","id":"74"},{"type":"wells","id":"75"},{"type":"wells","id":"76"},{"type":"wells","id":"77"},{"type":"wells","id":"78"},{"type":"wells","id":"79"},{"type":"wells","id":"80"},{"type":"wells","id":"81"},{"type":"wells","id":"82"},{"type":"wells","id":"83"},{"type":"wells","id":"84"},{"type":"wells","id":"85"},{"type":"wells","id":"86"},{"type":"wells","id":"87"},{"type":"wells","id":"88"},{"type":"wells","id":"89"},{"type":"wells","id":"90"},{"type":"wells","id":"91"},{"type":"wells","id":"92"},{"type":"wells","id":"93"},{"type":"wells","id":"94"},{"type":"wells","id":"95"},{"type":"wells","id":"96"}]}}}],"included":[{"id":"77","type":"purposes","links":{"self":"http://localhost:3000/api/v2/purposes/77"},"attributes":{"uuid":"6f34b728-9a21-11ec-9a02-acde48001122","name":"Stock Plate","size":96}},{"id":"1","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/1"},"attributes":{"uuid":"76c222fa-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/samples","related":"http://localhost:3000/api/v2/wells/1/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/studies","related":"http://localhost:3000/api/v2/wells/1/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/projects","related":"http://localhost:3000/api/v2/wells/1/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/1/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/1/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/1/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/1/aliquots"},"data":[{"type":"aliquots","id":"1"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/1/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/1/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/1/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/1/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/1/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/1/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/1/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/1/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/1/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/1/transfer_requests_as_target"}}}},{"id":"2","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/2"},"attributes":{"uuid":"76c224d0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/samples","related":"http://localhost:3000/api/v2/wells/2/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/studies","related":"http://localhost:3000/api/v2/wells/2/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/projects","related":"http://localhost:3000/api/v2/wells/2/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/2/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/2/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/2/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/2/aliquots"},"data":[{"type":"aliquots","id":"2"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/2/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/2/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/2/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/2/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/2/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/2/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/2/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/2/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/2/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/2/transfer_requests_as_target"}}}},{"id":"3","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/3"},"attributes":{"uuid":"76c2278c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/samples","related":"http://localhost:3000/api/v2/wells/3/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/studies","related":"http://localhost:3000/api/v2/wells/3/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/projects","related":"http://localhost:3000/api/v2/wells/3/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/3/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/3/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/3/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/3/aliquots"},"data":[{"type":"aliquots","id":"3"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/3/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/3/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/3/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/3/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/3/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/3/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/3/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/3/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/3/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/3/transfer_requests_as_target"}}}},{"id":"4","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/4"},"attributes":{"uuid":"76c22a98-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/samples","related":"http://localhost:3000/api/v2/wells/4/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/studies","related":"http://localhost:3000/api/v2/wells/4/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/projects","related":"http://localhost:3000/api/v2/wells/4/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/4/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/4/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/4/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/4/aliquots"},"data":[{"type":"aliquots","id":"4"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/4/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/4/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/4/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/4/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/4/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/4/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/4/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/4/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/4/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/4/transfer_requests_as_target"}}}},{"id":"5","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/5"},"attributes":{"uuid":"76c22b1a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/samples","related":"http://localhost:3000/api/v2/wells/5/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/studies","related":"http://localhost:3000/api/v2/wells/5/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/projects","related":"http://localhost:3000/api/v2/wells/5/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/5/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/5/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/5/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/5/aliquots"},"data":[{"type":"aliquots","id":"5"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/5/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/5/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/5/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/5/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/5/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/5/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/5/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/5/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/5/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/5/transfer_requests_as_target"}}}},{"id":"6","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/6"},"attributes":{"uuid":"76c22c50-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/samples","related":"http://localhost:3000/api/v2/wells/6/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/studies","related":"http://localhost:3000/api/v2/wells/6/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/projects","related":"http://localhost:3000/api/v2/wells/6/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/6/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/6/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/6/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/6/aliquots"},"data":[{"type":"aliquots","id":"6"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/6/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/6/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/6/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/6/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/6/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/6/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/6/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/6/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/6/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/6/transfer_requests_as_target"}}}},{"id":"7","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/7"},"attributes":{"uuid":"76c22cc8-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/samples","related":"http://localhost:3000/api/v2/wells/7/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/studies","related":"http://localhost:3000/api/v2/wells/7/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/projects","related":"http://localhost:3000/api/v2/wells/7/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/7/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/7/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/7/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/7/aliquots"},"data":[{"type":"aliquots","id":"7"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/7/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/7/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/7/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/7/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/7/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/7/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/7/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/7/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/7/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/7/transfer_requests_as_target"}}}},{"id":"8","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/8"},"attributes":{"uuid":"76c22ebc-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/samples","related":"http://localhost:3000/api/v2/wells/8/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/studies","related":"http://localhost:3000/api/v2/wells/8/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/projects","related":"http://localhost:3000/api/v2/wells/8/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/8/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/8/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/8/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/8/aliquots"},"data":[{"type":"aliquots","id":"8"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/8/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/8/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/8/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/8/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/8/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/8/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/8/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/8/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/8/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/8/transfer_requests_as_target"}}}},{"id":"9","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/9"},"attributes":{"uuid":"76c22fde-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/samples","related":"http://localhost:3000/api/v2/wells/9/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/studies","related":"http://localhost:3000/api/v2/wells/9/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/projects","related":"http://localhost:3000/api/v2/wells/9/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/9/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/9/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/9/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/9/aliquots"},"data":[{"type":"aliquots","id":"9"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/9/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/9/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/9/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/9/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/9/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/9/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/9/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/9/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/9/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/9/transfer_requests_as_target"}}}},{"id":"10","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/10"},"attributes":{"uuid":"76c23592-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/samples","related":"http://localhost:3000/api/v2/wells/10/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/studies","related":"http://localhost:3000/api/v2/wells/10/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/projects","related":"http://localhost:3000/api/v2/wells/10/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/10/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/10/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/10/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/10/aliquots"},"data":[{"type":"aliquots","id":"10"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/10/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/10/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/10/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/10/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/10/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/10/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/10/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/10/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/10/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/10/transfer_requests_as_target"}}}},{"id":"11","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/11"},"attributes":{"uuid":"76c23808-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/samples","related":"http://localhost:3000/api/v2/wells/11/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/studies","related":"http://localhost:3000/api/v2/wells/11/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/projects","related":"http://localhost:3000/api/v2/wells/11/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/11/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/11/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/11/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/11/aliquots"},"data":[{"type":"aliquots","id":"11"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/11/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/11/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/11/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/11/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/11/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/11/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/11/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/11/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/11/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/11/transfer_requests_as_target"}}}},{"id":"12","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/12"},"attributes":{"uuid":"76c23ba0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/samples","related":"http://localhost:3000/api/v2/wells/12/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/studies","related":"http://localhost:3000/api/v2/wells/12/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/projects","related":"http://localhost:3000/api/v2/wells/12/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/12/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/12/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/12/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/12/aliquots"},"data":[{"type":"aliquots","id":"12"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/12/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/12/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/12/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/12/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/12/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/12/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/12/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/12/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/12/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/12/transfer_requests_as_target"}}}},{"id":"13","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/13"},"attributes":{"uuid":"76c23ccc-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/samples","related":"http://localhost:3000/api/v2/wells/13/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/studies","related":"http://localhost:3000/api/v2/wells/13/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/projects","related":"http://localhost:3000/api/v2/wells/13/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/13/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/13/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/13/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/13/aliquots"},"data":[{"type":"aliquots","id":"13"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/13/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/13/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/13/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/13/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/13/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/13/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/13/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/13/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/13/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/13/transfer_requests_as_target"}}}},{"id":"14","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/14"},"attributes":{"uuid":"76c23d4e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/samples","related":"http://localhost:3000/api/v2/wells/14/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/studies","related":"http://localhost:3000/api/v2/wells/14/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/projects","related":"http://localhost:3000/api/v2/wells/14/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/14/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/14/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/14/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/14/aliquots"},"data":[{"type":"aliquots","id":"14"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/14/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/14/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/14/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/14/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/14/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/14/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/14/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/14/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/14/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/14/transfer_requests_as_target"}}}},{"id":"15","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/15"},"attributes":{"uuid":"76c23dc6-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/samples","related":"http://localhost:3000/api/v2/wells/15/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/studies","related":"http://localhost:3000/api/v2/wells/15/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/projects","related":"http://localhost:3000/api/v2/wells/15/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/15/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/15/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/15/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/15/aliquots"},"data":[{"type":"aliquots","id":"15"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/15/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/15/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/15/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/15/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/15/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/15/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/15/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/15/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/15/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/15/transfer_requests_as_target"}}}},{"id":"16","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/16"},"attributes":{"uuid":"76c23f56-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/samples","related":"http://localhost:3000/api/v2/wells/16/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/studies","related":"http://localhost:3000/api/v2/wells/16/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/projects","related":"http://localhost:3000/api/v2/wells/16/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/16/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/16/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/16/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/16/aliquots"},"data":[{"type":"aliquots","id":"16"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/16/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/16/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/16/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/16/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/16/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/16/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/16/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/16/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/16/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/16/transfer_requests_as_target"}}}},{"id":"17","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/17"},"attributes":{"uuid":"76c23fce-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/samples","related":"http://localhost:3000/api/v2/wells/17/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/studies","related":"http://localhost:3000/api/v2/wells/17/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/projects","related":"http://localhost:3000/api/v2/wells/17/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/17/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/17/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/17/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/17/aliquots"},"data":[{"type":"aliquots","id":"17"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/17/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/17/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/17/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/17/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/17/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/17/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/17/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/17/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/17/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/17/transfer_requests_as_target"}}}},{"id":"18","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/18"},"attributes":{"uuid":"76c2403c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/samples","related":"http://localhost:3000/api/v2/wells/18/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/studies","related":"http://localhost:3000/api/v2/wells/18/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/projects","related":"http://localhost:3000/api/v2/wells/18/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/18/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/18/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/18/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/18/aliquots"},"data":[{"type":"aliquots","id":"18"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/18/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/18/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/18/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/18/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/18/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/18/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/18/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/18/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/18/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/18/transfer_requests_as_target"}}}},{"id":"19","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/19"},"attributes":{"uuid":"76c240aa-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/samples","related":"http://localhost:3000/api/v2/wells/19/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/studies","related":"http://localhost:3000/api/v2/wells/19/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/projects","related":"http://localhost:3000/api/v2/wells/19/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/19/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/19/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/19/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/19/aliquots"},"data":[{"type":"aliquots","id":"19"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/19/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/19/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/19/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/19/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/19/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/19/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/19/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/19/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/19/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/19/transfer_requests_as_target"}}}},{"id":"20","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/20"},"attributes":{"uuid":"76c241c2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/samples","related":"http://localhost:3000/api/v2/wells/20/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/studies","related":"http://localhost:3000/api/v2/wells/20/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/projects","related":"http://localhost:3000/api/v2/wells/20/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/20/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/20/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/20/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/20/aliquots"},"data":[{"type":"aliquots","id":"20"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/20/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/20/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/20/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/20/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/20/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/20/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/20/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/20/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/20/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/20/transfer_requests_as_target"}}}},{"id":"21","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/21"},"attributes":{"uuid":"76c24230-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/samples","related":"http://localhost:3000/api/v2/wells/21/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/studies","related":"http://localhost:3000/api/v2/wells/21/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/projects","related":"http://localhost:3000/api/v2/wells/21/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/21/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/21/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/21/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/21/aliquots"},"data":[{"type":"aliquots","id":"21"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/21/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/21/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/21/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/21/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/21/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/21/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/21/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/21/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/21/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/21/transfer_requests_as_target"}}}},{"id":"22","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/22"},"attributes":{"uuid":"76c2429e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/samples","related":"http://localhost:3000/api/v2/wells/22/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/studies","related":"http://localhost:3000/api/v2/wells/22/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/projects","related":"http://localhost:3000/api/v2/wells/22/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/22/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/22/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/22/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/22/aliquots"},"data":[{"type":"aliquots","id":"22"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/22/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/22/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/22/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/22/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/22/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/22/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/22/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/22/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/22/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/22/transfer_requests_as_target"}}}},{"id":"23","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/23"},"attributes":{"uuid":"76c2430c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/samples","related":"http://localhost:3000/api/v2/wells/23/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/studies","related":"http://localhost:3000/api/v2/wells/23/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/projects","related":"http://localhost:3000/api/v2/wells/23/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/23/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/23/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/23/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/23/aliquots"},"data":[{"type":"aliquots","id":"23"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/23/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/23/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/23/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/23/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/23/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/23/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/23/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/23/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/23/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/23/transfer_requests_as_target"}}}},{"id":"24","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/24"},"attributes":{"uuid":"76c244e2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/samples","related":"http://localhost:3000/api/v2/wells/24/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/studies","related":"http://localhost:3000/api/v2/wells/24/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/projects","related":"http://localhost:3000/api/v2/wells/24/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/24/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/24/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/24/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/24/aliquots"},"data":[{"type":"aliquots","id":"24"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/24/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/24/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/24/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/24/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/24/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/24/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/24/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/24/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/24/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/24/transfer_requests_as_target"}}}},{"id":"25","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/25"},"attributes":{"uuid":"76c2455a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/samples","related":"http://localhost:3000/api/v2/wells/25/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/studies","related":"http://localhost:3000/api/v2/wells/25/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/projects","related":"http://localhost:3000/api/v2/wells/25/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/25/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/25/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/25/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/25/aliquots"},"data":[{"type":"aliquots","id":"25"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/25/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/25/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/25/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/25/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/25/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/25/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/25/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/25/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/25/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/25/transfer_requests_as_target"}}}},{"id":"26","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/26"},"attributes":{"uuid":"76c245d2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/samples","related":"http://localhost:3000/api/v2/wells/26/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/studies","related":"http://localhost:3000/api/v2/wells/26/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/projects","related":"http://localhost:3000/api/v2/wells/26/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/26/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/26/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/26/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/26/aliquots"},"data":[{"type":"aliquots","id":"26"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/26/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/26/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/26/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/26/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/26/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/26/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/26/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/26/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/26/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/26/transfer_requests_as_target"}}}},{"id":"27","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/27"},"attributes":{"uuid":"76c24988-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/samples","related":"http://localhost:3000/api/v2/wells/27/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/studies","related":"http://localhost:3000/api/v2/wells/27/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/projects","related":"http://localhost:3000/api/v2/wells/27/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/27/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/27/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/27/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/27/aliquots"},"data":[{"type":"aliquots","id":"27"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/27/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/27/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/27/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/27/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/27/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/27/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/27/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/27/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/27/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/27/transfer_requests_as_target"}}}},{"id":"28","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/28"},"attributes":{"uuid":"76c24aa0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/samples","related":"http://localhost:3000/api/v2/wells/28/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/studies","related":"http://localhost:3000/api/v2/wells/28/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/projects","related":"http://localhost:3000/api/v2/wells/28/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/28/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/28/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/28/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/28/aliquots"},"data":[{"type":"aliquots","id":"28"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/28/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/28/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/28/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/28/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/28/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/28/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/28/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/28/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/28/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/28/transfer_requests_as_target"}}}},{"id":"29","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/29"},"attributes":{"uuid":"76c24b18-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/samples","related":"http://localhost:3000/api/v2/wells/29/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/studies","related":"http://localhost:3000/api/v2/wells/29/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/projects","related":"http://localhost:3000/api/v2/wells/29/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/29/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/29/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/29/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/29/aliquots"},"data":[{"type":"aliquots","id":"29"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/29/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/29/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/29/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/29/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/29/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/29/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/29/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/29/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/29/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/29/transfer_requests_as_target"}}}},{"id":"30","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/30"},"attributes":{"uuid":"76c24c44-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/samples","related":"http://localhost:3000/api/v2/wells/30/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/studies","related":"http://localhost:3000/api/v2/wells/30/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/projects","related":"http://localhost:3000/api/v2/wells/30/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/30/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/30/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/30/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/30/aliquots"},"data":[{"type":"aliquots","id":"30"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/30/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/30/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/30/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/30/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/30/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/30/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/30/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/30/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/30/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/30/transfer_requests_as_target"}}}},{"id":"31","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/31"},"attributes":{"uuid":"76c24e38-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/samples","related":"http://localhost:3000/api/v2/wells/31/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/studies","related":"http://localhost:3000/api/v2/wells/31/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/projects","related":"http://localhost:3000/api/v2/wells/31/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/31/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/31/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/31/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/31/aliquots"},"data":[{"type":"aliquots","id":"31"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/31/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/31/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/31/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/31/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/31/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/31/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/31/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/31/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/31/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/31/transfer_requests_as_target"}}}},{"id":"32","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/32"},"attributes":{"uuid":"76c24f78-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/samples","related":"http://localhost:3000/api/v2/wells/32/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/studies","related":"http://localhost:3000/api/v2/wells/32/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/projects","related":"http://localhost:3000/api/v2/wells/32/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/32/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/32/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/32/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/32/aliquots"},"data":[{"type":"aliquots","id":"32"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/32/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/32/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/32/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/32/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/32/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/32/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/32/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/32/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/32/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/32/transfer_requests_as_target"}}}},{"id":"33","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/33"},"attributes":{"uuid":"76c24fe6-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/samples","related":"http://localhost:3000/api/v2/wells/33/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/studies","related":"http://localhost:3000/api/v2/wells/33/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/projects","related":"http://localhost:3000/api/v2/wells/33/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/33/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/33/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/33/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/33/aliquots"},"data":[{"type":"aliquots","id":"33"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/33/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/33/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/33/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/33/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/33/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/33/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/33/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/33/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/33/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/33/transfer_requests_as_target"}}}},{"id":"34","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/34"},"attributes":{"uuid":"76c2537e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/samples","related":"http://localhost:3000/api/v2/wells/34/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/studies","related":"http://localhost:3000/api/v2/wells/34/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/projects","related":"http://localhost:3000/api/v2/wells/34/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/34/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/34/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/34/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/34/aliquots"},"data":[{"type":"aliquots","id":"34"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/34/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/34/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/34/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/34/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/34/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/34/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/34/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/34/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/34/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/34/transfer_requests_as_target"}}}},{"id":"35","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/35"},"attributes":{"uuid":"76c255a4-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/samples","related":"http://localhost:3000/api/v2/wells/35/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/studies","related":"http://localhost:3000/api/v2/wells/35/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/projects","related":"http://localhost:3000/api/v2/wells/35/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/35/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/35/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/35/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/35/aliquots"},"data":[{"type":"aliquots","id":"35"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/35/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/35/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/35/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/35/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/35/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/35/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/35/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/35/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/35/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/35/transfer_requests_as_target"}}}},{"id":"36","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/36"},"attributes":{"uuid":"76c2590a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/samples","related":"http://localhost:3000/api/v2/wells/36/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/studies","related":"http://localhost:3000/api/v2/wells/36/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/projects","related":"http://localhost:3000/api/v2/wells/36/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/36/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/36/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/36/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/36/aliquots"},"data":[{"type":"aliquots","id":"36"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/36/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/36/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/36/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/36/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/36/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/36/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/36/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/36/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/36/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/36/transfer_requests_as_target"}}}},{"id":"37","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/37"},"attributes":{"uuid":"76c25a86-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/samples","related":"http://localhost:3000/api/v2/wells/37/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/studies","related":"http://localhost:3000/api/v2/wells/37/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/projects","related":"http://localhost:3000/api/v2/wells/37/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/37/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/37/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/37/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/37/aliquots"},"data":[{"type":"aliquots","id":"37"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/37/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/37/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/37/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/37/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/37/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/37/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/37/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/37/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/37/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/37/transfer_requests_as_target"}}}},{"id":"38","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/38"},"attributes":{"uuid":"76c25cc0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/samples","related":"http://localhost:3000/api/v2/wells/38/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/studies","related":"http://localhost:3000/api/v2/wells/38/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/projects","related":"http://localhost:3000/api/v2/wells/38/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/38/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/38/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/38/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/38/aliquots"},"data":[{"type":"aliquots","id":"38"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/38/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/38/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/38/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/38/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/38/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/38/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/38/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/38/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/38/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/38/transfer_requests_as_target"}}}},{"id":"39","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/39"},"attributes":{"uuid":"76c25d4c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/samples","related":"http://localhost:3000/api/v2/wells/39/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/studies","related":"http://localhost:3000/api/v2/wells/39/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/projects","related":"http://localhost:3000/api/v2/wells/39/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/39/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/39/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/39/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/39/aliquots"},"data":[{"type":"aliquots","id":"39"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/39/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/39/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/39/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/39/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/39/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/39/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/39/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/39/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/39/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/39/transfer_requests_as_target"}}}},{"id":"40","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/40"},"attributes":{"uuid":"76c25dc4-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/samples","related":"http://localhost:3000/api/v2/wells/40/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/studies","related":"http://localhost:3000/api/v2/wells/40/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/projects","related":"http://localhost:3000/api/v2/wells/40/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/40/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/40/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/40/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/40/aliquots"},"data":[{"type":"aliquots","id":"40"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/40/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/40/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/40/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/40/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/40/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/40/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/40/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/40/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/40/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/40/transfer_requests_as_target"}}}},{"id":"41","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/41"},"attributes":{"uuid":"76c25e3c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/samples","related":"http://localhost:3000/api/v2/wells/41/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/studies","related":"http://localhost:3000/api/v2/wells/41/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/projects","related":"http://localhost:3000/api/v2/wells/41/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/41/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/41/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/41/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/41/aliquots"},"data":[{"type":"aliquots","id":"41"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/41/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/41/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/41/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/41/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/41/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/41/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/41/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/41/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/41/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/41/transfer_requests_as_target"}}}},{"id":"42","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/42"},"attributes":{"uuid":"76c25eb4-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/samples","related":"http://localhost:3000/api/v2/wells/42/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/studies","related":"http://localhost:3000/api/v2/wells/42/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/projects","related":"http://localhost:3000/api/v2/wells/42/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/42/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/42/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/42/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/42/aliquots"},"data":[{"type":"aliquots","id":"42"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/42/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/42/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/42/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/42/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/42/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/42/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/42/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/42/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/42/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/42/transfer_requests_as_target"}}}},{"id":"43","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/43"},"attributes":{"uuid":"76c2603a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/samples","related":"http://localhost:3000/api/v2/wells/43/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/studies","related":"http://localhost:3000/api/v2/wells/43/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/projects","related":"http://localhost:3000/api/v2/wells/43/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/43/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/43/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/43/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/43/aliquots"},"data":[{"type":"aliquots","id":"43"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/43/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/43/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/43/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/43/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/43/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/43/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/43/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/43/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/43/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/43/transfer_requests_as_target"}}}},{"id":"44","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/44"},"attributes":{"uuid":"76c260b2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/samples","related":"http://localhost:3000/api/v2/wells/44/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/studies","related":"http://localhost:3000/api/v2/wells/44/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/projects","related":"http://localhost:3000/api/v2/wells/44/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/44/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/44/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/44/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/44/aliquots"},"data":[{"type":"aliquots","id":"44"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/44/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/44/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/44/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/44/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/44/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/44/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/44/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/44/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/44/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/44/transfer_requests_as_target"}}}},{"id":"45","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/45"},"attributes":{"uuid":"76c2612a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/samples","related":"http://localhost:3000/api/v2/wells/45/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/studies","related":"http://localhost:3000/api/v2/wells/45/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/projects","related":"http://localhost:3000/api/v2/wells/45/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/45/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/45/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/45/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/45/aliquots"},"data":[{"type":"aliquots","id":"45"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/45/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/45/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/45/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/45/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/45/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/45/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/45/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/45/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/45/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/45/transfer_requests_as_target"}}}},{"id":"46","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/46"},"attributes":{"uuid":"76c26198-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/samples","related":"http://localhost:3000/api/v2/wells/46/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/studies","related":"http://localhost:3000/api/v2/wells/46/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/projects","related":"http://localhost:3000/api/v2/wells/46/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/46/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/46/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/46/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/46/aliquots"},"data":[{"type":"aliquots","id":"46"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/46/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/46/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/46/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/46/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/46/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/46/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/46/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/46/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/46/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/46/transfer_requests_as_target"}}}},{"id":"47","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/47"},"attributes":{"uuid":"76c262ec-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/samples","related":"http://localhost:3000/api/v2/wells/47/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/studies","related":"http://localhost:3000/api/v2/wells/47/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/projects","related":"http://localhost:3000/api/v2/wells/47/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/47/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/47/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/47/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/47/aliquots"},"data":[{"type":"aliquots","id":"47"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/47/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/47/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/47/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/47/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/47/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/47/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/47/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/47/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/47/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/47/transfer_requests_as_target"}}}},{"id":"48","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/48"},"attributes":{"uuid":"76c2635a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/samples","related":"http://localhost:3000/api/v2/wells/48/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/studies","related":"http://localhost:3000/api/v2/wells/48/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/projects","related":"http://localhost:3000/api/v2/wells/48/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/48/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/48/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/48/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/48/aliquots"},"data":[{"type":"aliquots","id":"48"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/48/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/48/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/48/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/48/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/48/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/48/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/48/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/48/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/48/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/48/transfer_requests_as_target"}}}},{"id":"49","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/49"},"attributes":{"uuid":"76c263d2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/samples","related":"http://localhost:3000/api/v2/wells/49/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/studies","related":"http://localhost:3000/api/v2/wells/49/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/projects","related":"http://localhost:3000/api/v2/wells/49/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/49/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/49/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/49/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/49/aliquots"},"data":[{"type":"aliquots","id":"49"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/49/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/49/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/49/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/49/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/49/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/49/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/49/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/49/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/49/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/49/transfer_requests_as_target"}}}},{"id":"50","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/50"},"attributes":{"uuid":"76c264ea-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/samples","related":"http://localhost:3000/api/v2/wells/50/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/studies","related":"http://localhost:3000/api/v2/wells/50/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/projects","related":"http://localhost:3000/api/v2/wells/50/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/50/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/50/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/50/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/50/aliquots"},"data":[{"type":"aliquots","id":"50"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/50/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/50/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/50/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/50/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/50/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/50/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/50/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/50/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/50/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/50/transfer_requests_as_target"}}}},{"id":"51","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/51"},"attributes":{"uuid":"76c26562-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/samples","related":"http://localhost:3000/api/v2/wells/51/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/studies","related":"http://localhost:3000/api/v2/wells/51/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/projects","related":"http://localhost:3000/api/v2/wells/51/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/51/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/51/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/51/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/51/aliquots"},"data":[{"type":"aliquots","id":"51"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/51/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/51/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/51/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/51/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/51/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/51/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/51/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/51/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/51/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/51/transfer_requests_as_target"}}}},{"id":"52","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/52"},"attributes":{"uuid":"76c265d0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/samples","related":"http://localhost:3000/api/v2/wells/52/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/studies","related":"http://localhost:3000/api/v2/wells/52/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/projects","related":"http://localhost:3000/api/v2/wells/52/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/52/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/52/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/52/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/52/aliquots"},"data":[{"type":"aliquots","id":"52"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/52/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/52/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/52/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/52/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/52/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/52/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/52/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/52/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/52/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/52/transfer_requests_as_target"}}}},{"id":"53","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/53"},"attributes":{"uuid":"76c26878-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/samples","related":"http://localhost:3000/api/v2/wells/53/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/studies","related":"http://localhost:3000/api/v2/wells/53/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/projects","related":"http://localhost:3000/api/v2/wells/53/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/53/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/53/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/53/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/53/aliquots"},"data":[{"type":"aliquots","id":"53"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/53/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/53/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/53/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/53/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/53/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/53/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/53/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/53/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/53/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/53/transfer_requests_as_target"}}}},{"id":"54","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/54"},"attributes":{"uuid":"76c26904-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/samples","related":"http://localhost:3000/api/v2/wells/54/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/studies","related":"http://localhost:3000/api/v2/wells/54/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/projects","related":"http://localhost:3000/api/v2/wells/54/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/54/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/54/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/54/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/54/aliquots"},"data":[{"type":"aliquots","id":"54"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/54/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/54/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/54/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/54/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/54/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/54/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/54/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/54/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/54/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/54/transfer_requests_as_target"}}}},{"id":"55","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/55"},"attributes":{"uuid":"76c26a3a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/samples","related":"http://localhost:3000/api/v2/wells/55/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/studies","related":"http://localhost:3000/api/v2/wells/55/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/projects","related":"http://localhost:3000/api/v2/wells/55/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/55/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/55/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/55/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/55/aliquots"},"data":[{"type":"aliquots","id":"55"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/55/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/55/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/55/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/55/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/55/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/55/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/55/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/55/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/55/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/55/transfer_requests_as_target"}}}},{"id":"56","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/56"},"attributes":{"uuid":"76c26bac-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/samples","related":"http://localhost:3000/api/v2/wells/56/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/studies","related":"http://localhost:3000/api/v2/wells/56/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/projects","related":"http://localhost:3000/api/v2/wells/56/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/56/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/56/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/56/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/56/aliquots"},"data":[{"type":"aliquots","id":"56"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/56/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/56/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/56/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/56/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/56/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/56/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/56/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/56/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/56/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/56/transfer_requests_as_target"}}}},{"id":"57","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/57"},"attributes":{"uuid":"76c26c2e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/samples","related":"http://localhost:3000/api/v2/wells/57/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/studies","related":"http://localhost:3000/api/v2/wells/57/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/projects","related":"http://localhost:3000/api/v2/wells/57/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/57/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/57/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/57/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/57/aliquots"},"data":[{"type":"aliquots","id":"57"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/57/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/57/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/57/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/57/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/57/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/57/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/57/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/57/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/57/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/57/transfer_requests_as_target"}}}},{"id":"58","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/58"},"attributes":{"uuid":"76c26c9c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/samples","related":"http://localhost:3000/api/v2/wells/58/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/studies","related":"http://localhost:3000/api/v2/wells/58/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/projects","related":"http://localhost:3000/api/v2/wells/58/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/58/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/58/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/58/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/58/aliquots"},"data":[{"type":"aliquots","id":"58"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/58/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/58/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/58/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/58/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/58/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/58/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/58/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/58/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/58/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/58/transfer_requests_as_target"}}}},{"id":"59","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/59"},"attributes":{"uuid":"76c26d0a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/samples","related":"http://localhost:3000/api/v2/wells/59/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/studies","related":"http://localhost:3000/api/v2/wells/59/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/projects","related":"http://localhost:3000/api/v2/wells/59/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/59/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/59/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/59/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/59/aliquots"},"data":[{"type":"aliquots","id":"59"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/59/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/59/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/59/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/59/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/59/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/59/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/59/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/59/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/59/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/59/transfer_requests_as_target"}}}},{"id":"60","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/60"},"attributes":{"uuid":"76c26e72-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/samples","related":"http://localhost:3000/api/v2/wells/60/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/studies","related":"http://localhost:3000/api/v2/wells/60/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/projects","related":"http://localhost:3000/api/v2/wells/60/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/60/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/60/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/60/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/60/aliquots"},"data":[{"type":"aliquots","id":"60"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/60/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/60/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/60/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/60/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/60/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/60/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/60/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/60/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/60/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/60/transfer_requests_as_target"}}}},{"id":"61","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/61"},"attributes":{"uuid":"76c26eea-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/samples","related":"http://localhost:3000/api/v2/wells/61/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/studies","related":"http://localhost:3000/api/v2/wells/61/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/projects","related":"http://localhost:3000/api/v2/wells/61/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/61/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/61/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/61/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/61/aliquots"},"data":[{"type":"aliquots","id":"61"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/61/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/61/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/61/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/61/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/61/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/61/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/61/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/61/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/61/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/61/transfer_requests_as_target"}}}},{"id":"62","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/62"},"attributes":{"uuid":"76c26f62-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/samples","related":"http://localhost:3000/api/v2/wells/62/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/studies","related":"http://localhost:3000/api/v2/wells/62/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/projects","related":"http://localhost:3000/api/v2/wells/62/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/62/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/62/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/62/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/62/aliquots"},"data":[{"type":"aliquots","id":"62"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/62/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/62/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/62/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/62/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/62/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/62/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/62/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/62/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/62/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/62/transfer_requests_as_target"}}}},{"id":"63","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/63"},"attributes":{"uuid":"76c27200-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/samples","related":"http://localhost:3000/api/v2/wells/63/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/studies","related":"http://localhost:3000/api/v2/wells/63/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/projects","related":"http://localhost:3000/api/v2/wells/63/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/63/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/63/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/63/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/63/aliquots"},"data":[{"type":"aliquots","id":"63"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/63/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/63/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/63/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/63/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/63/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/63/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/63/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/63/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/63/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/63/transfer_requests_as_target"}}}},{"id":"64","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/64"},"attributes":{"uuid":"76c273cc-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/samples","related":"http://localhost:3000/api/v2/wells/64/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/studies","related":"http://localhost:3000/api/v2/wells/64/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/projects","related":"http://localhost:3000/api/v2/wells/64/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/64/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/64/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/64/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/64/aliquots"},"data":[{"type":"aliquots","id":"64"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/64/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/64/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/64/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/64/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/64/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/64/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/64/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/64/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/64/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/64/transfer_requests_as_target"}}}},{"id":"65","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/65"},"attributes":{"uuid":"76c27494-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/samples","related":"http://localhost:3000/api/v2/wells/65/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/studies","related":"http://localhost:3000/api/v2/wells/65/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/projects","related":"http://localhost:3000/api/v2/wells/65/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/65/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/65/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/65/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/65/aliquots"},"data":[{"type":"aliquots","id":"65"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/65/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/65/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/65/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/65/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/65/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/65/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/65/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/65/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/65/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/65/transfer_requests_as_target"}}}},{"id":"66","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/66"},"attributes":{"uuid":"76c2750c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/samples","related":"http://localhost:3000/api/v2/wells/66/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/studies","related":"http://localhost:3000/api/v2/wells/66/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/projects","related":"http://localhost:3000/api/v2/wells/66/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/66/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/66/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/66/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/66/aliquots"},"data":[{"type":"aliquots","id":"66"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/66/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/66/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/66/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/66/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/66/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/66/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/66/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/66/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/66/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/66/transfer_requests_as_target"}}}},{"id":"67","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/67"},"attributes":{"uuid":"76c276a6-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/samples","related":"http://localhost:3000/api/v2/wells/67/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/studies","related":"http://localhost:3000/api/v2/wells/67/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/projects","related":"http://localhost:3000/api/v2/wells/67/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/67/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/67/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/67/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/67/aliquots"},"data":[{"type":"aliquots","id":"67"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/67/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/67/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/67/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/67/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/67/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/67/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/67/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/67/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/67/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/67/transfer_requests_as_target"}}}},{"id":"68","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/68"},"attributes":{"uuid":"76c278ea-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/samples","related":"http://localhost:3000/api/v2/wells/68/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/studies","related":"http://localhost:3000/api/v2/wells/68/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/projects","related":"http://localhost:3000/api/v2/wells/68/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/68/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/68/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/68/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/68/aliquots"},"data":[{"type":"aliquots","id":"68"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/68/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/68/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/68/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/68/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/68/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/68/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/68/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/68/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/68/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/68/transfer_requests_as_target"}}}},{"id":"69","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/69"},"attributes":{"uuid":"76c27980-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/samples","related":"http://localhost:3000/api/v2/wells/69/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/studies","related":"http://localhost:3000/api/v2/wells/69/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/projects","related":"http://localhost:3000/api/v2/wells/69/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/69/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/69/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/69/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/69/aliquots"},"data":[{"type":"aliquots","id":"69"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/69/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/69/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/69/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/69/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/69/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/69/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/69/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/69/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/69/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/69/transfer_requests_as_target"}}}},{"id":"70","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/70"},"attributes":{"uuid":"76c27a02-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/samples","related":"http://localhost:3000/api/v2/wells/70/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/studies","related":"http://localhost:3000/api/v2/wells/70/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/projects","related":"http://localhost:3000/api/v2/wells/70/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/70/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/70/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/70/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/70/aliquots"},"data":[{"type":"aliquots","id":"70"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/70/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/70/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/70/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/70/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/70/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/70/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/70/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/70/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/70/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/70/transfer_requests_as_target"}}}},{"id":"71","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/71"},"attributes":{"uuid":"76c27c6e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/samples","related":"http://localhost:3000/api/v2/wells/71/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/studies","related":"http://localhost:3000/api/v2/wells/71/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/projects","related":"http://localhost:3000/api/v2/wells/71/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/71/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/71/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/71/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/71/aliquots"},"data":[{"type":"aliquots","id":"71"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/71/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/71/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/71/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/71/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/71/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/71/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/71/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/71/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/71/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/71/transfer_requests_as_target"}}}},{"id":"72","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/72"},"attributes":{"uuid":"76c27d72-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/samples","related":"http://localhost:3000/api/v2/wells/72/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/studies","related":"http://localhost:3000/api/v2/wells/72/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/projects","related":"http://localhost:3000/api/v2/wells/72/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/72/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/72/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/72/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/72/aliquots"},"data":[{"type":"aliquots","id":"72"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/72/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/72/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/72/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/72/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/72/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/72/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/72/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/72/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/72/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/72/transfer_requests_as_target"}}}},{"id":"73","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/73"},"attributes":{"uuid":"76c27fde-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/samples","related":"http://localhost:3000/api/v2/wells/73/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/studies","related":"http://localhost:3000/api/v2/wells/73/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/projects","related":"http://localhost:3000/api/v2/wells/73/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/73/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/73/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/73/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/73/aliquots"},"data":[{"type":"aliquots","id":"73"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/73/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/73/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/73/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/73/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/73/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/73/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/73/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/73/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/73/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/73/transfer_requests_as_target"}}}},{"id":"74","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/74"},"attributes":{"uuid":"76c2810a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/samples","related":"http://localhost:3000/api/v2/wells/74/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/studies","related":"http://localhost:3000/api/v2/wells/74/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/projects","related":"http://localhost:3000/api/v2/wells/74/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/74/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/74/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/74/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/74/aliquots"},"data":[{"type":"aliquots","id":"74"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/74/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/74/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/74/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/74/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/74/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/74/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/74/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/74/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/74/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/74/transfer_requests_as_target"}}}},{"id":"75","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/75"},"attributes":{"uuid":"76c282e0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/samples","related":"http://localhost:3000/api/v2/wells/75/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/studies","related":"http://localhost:3000/api/v2/wells/75/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/projects","related":"http://localhost:3000/api/v2/wells/75/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/75/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/75/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/75/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/75/aliquots"},"data":[{"type":"aliquots","id":"75"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/75/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/75/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/75/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/75/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/75/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/75/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/75/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/75/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/75/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/75/transfer_requests_as_target"}}}},{"id":"76","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/76"},"attributes":{"uuid":"76c28358-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/samples","related":"http://localhost:3000/api/v2/wells/76/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/studies","related":"http://localhost:3000/api/v2/wells/76/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/projects","related":"http://localhost:3000/api/v2/wells/76/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/76/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/76/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/76/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/76/aliquots"},"data":[{"type":"aliquots","id":"76"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/76/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/76/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/76/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/76/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/76/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/76/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/76/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/76/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/76/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/76/transfer_requests_as_target"}}}},{"id":"77","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/77"},"attributes":{"uuid":"76c283d0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/samples","related":"http://localhost:3000/api/v2/wells/77/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/studies","related":"http://localhost:3000/api/v2/wells/77/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/projects","related":"http://localhost:3000/api/v2/wells/77/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/77/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/77/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/77/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/77/aliquots"},"data":[{"type":"aliquots","id":"77"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/77/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/77/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/77/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/77/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/77/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/77/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/77/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/77/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/77/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/77/transfer_requests_as_target"}}}},{"id":"78","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/78"},"attributes":{"uuid":"76c284ac-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/samples","related":"http://localhost:3000/api/v2/wells/78/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/studies","related":"http://localhost:3000/api/v2/wells/78/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/projects","related":"http://localhost:3000/api/v2/wells/78/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/78/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/78/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/78/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/78/aliquots"},"data":[{"type":"aliquots","id":"78"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/78/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/78/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/78/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/78/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/78/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/78/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/78/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/78/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/78/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/78/transfer_requests_as_target"}}}},{"id":"79","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/79"},"attributes":{"uuid":"76c28524-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/samples","related":"http://localhost:3000/api/v2/wells/79/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/studies","related":"http://localhost:3000/api/v2/wells/79/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/projects","related":"http://localhost:3000/api/v2/wells/79/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/79/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/79/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/79/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/79/aliquots"},"data":[{"type":"aliquots","id":"79"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/79/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/79/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/79/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/79/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/79/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/79/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/79/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/79/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/79/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/79/transfer_requests_as_target"}}}},{"id":"80","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/80"},"attributes":{"uuid":"76c28592-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/samples","related":"http://localhost:3000/api/v2/wells/80/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/studies","related":"http://localhost:3000/api/v2/wells/80/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/projects","related":"http://localhost:3000/api/v2/wells/80/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/80/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/80/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/80/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/80/aliquots"},"data":[{"type":"aliquots","id":"80"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/80/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/80/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/80/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/80/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/80/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/80/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/80/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/80/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/80/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/80/transfer_requests_as_target"}}}},{"id":"81","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/81"},"attributes":{"uuid":"76c28632-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/samples","related":"http://localhost:3000/api/v2/wells/81/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/studies","related":"http://localhost:3000/api/v2/wells/81/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/projects","related":"http://localhost:3000/api/v2/wells/81/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/81/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/81/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/81/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/81/aliquots"},"data":[{"type":"aliquots","id":"81"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/81/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/81/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/81/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/81/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/81/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/81/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/81/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/81/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/81/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/81/transfer_requests_as_target"}}}},{"id":"82","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/82"},"attributes":{"uuid":"76c28736-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/samples","related":"http://localhost:3000/api/v2/wells/82/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/studies","related":"http://localhost:3000/api/v2/wells/82/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/projects","related":"http://localhost:3000/api/v2/wells/82/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/82/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/82/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/82/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/82/aliquots"},"data":[{"type":"aliquots","id":"82"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/82/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/82/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/82/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/82/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/82/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/82/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/82/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/82/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/82/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/82/transfer_requests_as_target"}}}},{"id":"83","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/83"},"attributes":{"uuid":"76c287ae-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/samples","related":"http://localhost:3000/api/v2/wells/83/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/studies","related":"http://localhost:3000/api/v2/wells/83/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/projects","related":"http://localhost:3000/api/v2/wells/83/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/83/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/83/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/83/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/83/aliquots"},"data":[{"type":"aliquots","id":"83"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/83/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/83/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/83/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/83/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/83/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/83/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/83/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/83/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/83/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/83/transfer_requests_as_target"}}}},{"id":"84","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/84"},"attributes":{"uuid":"76c2881c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/samples","related":"http://localhost:3000/api/v2/wells/84/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/studies","related":"http://localhost:3000/api/v2/wells/84/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/projects","related":"http://localhost:3000/api/v2/wells/84/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/84/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/84/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/84/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/84/aliquots"},"data":[{"type":"aliquots","id":"84"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/84/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/84/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/84/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/84/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/84/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/84/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/84/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/84/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/84/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/84/transfer_requests_as_target"}}}},{"id":"85","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/85"},"attributes":{"uuid":"76c28998-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/samples","related":"http://localhost:3000/api/v2/wells/85/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/studies","related":"http://localhost:3000/api/v2/wells/85/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/projects","related":"http://localhost:3000/api/v2/wells/85/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/85/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/85/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/85/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/85/aliquots"},"data":[{"type":"aliquots","id":"85"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/85/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/85/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/85/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/85/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/85/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/85/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/85/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/85/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/85/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/85/transfer_requests_as_target"}}}},{"id":"86","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/86"},"attributes":{"uuid":"76c28a06-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/samples","related":"http://localhost:3000/api/v2/wells/86/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/studies","related":"http://localhost:3000/api/v2/wells/86/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/projects","related":"http://localhost:3000/api/v2/wells/86/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/86/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/86/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/86/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/86/aliquots"},"data":[{"type":"aliquots","id":"86"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/86/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/86/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/86/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/86/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/86/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/86/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/86/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/86/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/86/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/86/transfer_requests_as_target"}}}},{"id":"87","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/87"},"attributes":{"uuid":"76c28ba0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/samples","related":"http://localhost:3000/api/v2/wells/87/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/studies","related":"http://localhost:3000/api/v2/wells/87/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/projects","related":"http://localhost:3000/api/v2/wells/87/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/87/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/87/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/87/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/87/aliquots"},"data":[{"type":"aliquots","id":"87"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/87/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/87/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/87/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/87/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/87/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/87/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/87/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/87/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/87/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/87/transfer_requests_as_target"}}}},{"id":"88","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/88"},"attributes":{"uuid":"76c28c0e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/samples","related":"http://localhost:3000/api/v2/wells/88/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/studies","related":"http://localhost:3000/api/v2/wells/88/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/projects","related":"http://localhost:3000/api/v2/wells/88/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/88/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/88/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/88/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/88/aliquots"},"data":[{"type":"aliquots","id":"88"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/88/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/88/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/88/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/88/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/88/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/88/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/88/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/88/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/88/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/88/transfer_requests_as_target"}}}},{"id":"89","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/89"},"attributes":{"uuid":"76c28c7c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/samples","related":"http://localhost:3000/api/v2/wells/89/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/studies","related":"http://localhost:3000/api/v2/wells/89/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/projects","related":"http://localhost:3000/api/v2/wells/89/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/89/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/89/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/89/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/89/aliquots"},"data":[{"type":"aliquots","id":"89"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/89/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/89/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/89/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/89/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/89/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/89/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/89/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/89/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/89/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/89/transfer_requests_as_target"}}}},{"id":"90","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/90"},"attributes":{"uuid":"76c28cf4-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/samples","related":"http://localhost:3000/api/v2/wells/90/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/studies","related":"http://localhost:3000/api/v2/wells/90/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/projects","related":"http://localhost:3000/api/v2/wells/90/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/90/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/90/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/90/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/90/aliquots"},"data":[{"type":"aliquots","id":"90"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/90/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/90/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/90/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/90/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/90/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/90/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/90/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/90/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/90/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/90/transfer_requests_as_target"}}}},{"id":"91","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/91"},"attributes":{"uuid":"76c28e16-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/samples","related":"http://localhost:3000/api/v2/wells/91/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/studies","related":"http://localhost:3000/api/v2/wells/91/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/projects","related":"http://localhost:3000/api/v2/wells/91/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/91/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/91/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/91/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/91/aliquots"},"data":[{"type":"aliquots","id":"91"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/91/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/91/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/91/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/91/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/91/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/91/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/91/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/91/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/91/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/91/transfer_requests_as_target"}}}},{"id":"92","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/92"},"attributes":{"uuid":"76c28e84-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/samples","related":"http://localhost:3000/api/v2/wells/92/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/studies","related":"http://localhost:3000/api/v2/wells/92/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/projects","related":"http://localhost:3000/api/v2/wells/92/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/92/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/92/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/92/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/92/aliquots"},"data":[{"type":"aliquots","id":"92"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/92/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/92/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/92/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/92/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/92/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/92/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/92/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/92/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/92/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/92/transfer_requests_as_target"}}}},{"id":"93","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/93"},"attributes":{"uuid":"76c28ef2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/samples","related":"http://localhost:3000/api/v2/wells/93/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/studies","related":"http://localhost:3000/api/v2/wells/93/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/projects","related":"http://localhost:3000/api/v2/wells/93/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/93/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/93/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/93/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/93/aliquots"},"data":[{"type":"aliquots","id":"93"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/93/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/93/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/93/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/93/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/93/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/93/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/93/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/93/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/93/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/93/transfer_requests_as_target"}}}},{"id":"94","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/94"},"attributes":{"uuid":"76c29028-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/samples","related":"http://localhost:3000/api/v2/wells/94/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/studies","related":"http://localhost:3000/api/v2/wells/94/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/projects","related":"http://localhost:3000/api/v2/wells/94/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/94/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/94/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/94/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/94/aliquots"},"data":[{"type":"aliquots","id":"94"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/94/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/94/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/94/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/94/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/94/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/94/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/94/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/94/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/94/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/94/transfer_requests_as_target"}}}},{"id":"95","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/95"},"attributes":{"uuid":"76c29096-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/samples","related":"http://localhost:3000/api/v2/wells/95/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/studies","related":"http://localhost:3000/api/v2/wells/95/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/projects","related":"http://localhost:3000/api/v2/wells/95/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/95/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/95/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/95/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/95/aliquots"},"data":[{"type":"aliquots","id":"95"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/95/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/95/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/95/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/95/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/95/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/95/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/95/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/95/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/95/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/95/transfer_requests_as_target"}}}},{"id":"96","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/96"},"attributes":{"uuid":"76c29104-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/samples","related":"http://localhost:3000/api/v2/wells/96/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/studies","related":"http://localhost:3000/api/v2/wells/96/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/projects","related":"http://localhost:3000/api/v2/wells/96/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/96/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/96/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/96/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/96/aliquots"},"data":[{"type":"aliquots","id":"96"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/96/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/96/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/96/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/96/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/96/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/96/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/96/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/96/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/96/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/96/transfer_requests_as_target"}}}},{"id":"1","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/1"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/1/relationships/study","related":"http://localhost:3000/api/v2/aliquots/1/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/1/relationships/project","related":"http://localhost:3000/api/v2/aliquots/1/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/1/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/1/sample"},"data":{"type":"samples","id":"2"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/1/relationships/request","related":"http://localhost:3000/api/v2/aliquots/1/request"}}}},{"id":"2","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/2"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/2/relationships/study","related":"http://localhost:3000/api/v2/aliquots/2/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/2/relationships/project","related":"http://localhost:3000/api/v2/aliquots/2/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/2/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/2/sample"},"data":{"type":"samples","id":"3"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/2/relationships/request","related":"http://localhost:3000/api/v2/aliquots/2/request"}}}},{"id":"3","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/3"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/3/relationships/study","related":"http://localhost:3000/api/v2/aliquots/3/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/3/relationships/project","related":"http://localhost:3000/api/v2/aliquots/3/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/3/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/3/sample"},"data":{"type":"samples","id":"4"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/3/relationships/request","related":"http://localhost:3000/api/v2/aliquots/3/request"}}}},{"id":"4","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/4"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/4/relationships/study","related":"http://localhost:3000/api/v2/aliquots/4/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/4/relationships/project","related":"http://localhost:3000/api/v2/aliquots/4/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/4/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/4/sample"},"data":{"type":"samples","id":"5"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/4/relationships/request","related":"http://localhost:3000/api/v2/aliquots/4/request"}}}},{"id":"5","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/5"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/5/relationships/study","related":"http://localhost:3000/api/v2/aliquots/5/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/5/relationships/project","related":"http://localhost:3000/api/v2/aliquots/5/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/5/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/5/sample"},"data":{"type":"samples","id":"6"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/5/relationships/request","related":"http://localhost:3000/api/v2/aliquots/5/request"}}}},{"id":"6","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/6"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/6/relationships/study","related":"http://localhost:3000/api/v2/aliquots/6/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/6/relationships/project","related":"http://localhost:3000/api/v2/aliquots/6/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/6/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/6/sample"},"data":{"type":"samples","id":"7"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/6/relationships/request","related":"http://localhost:3000/api/v2/aliquots/6/request"}}}},{"id":"7","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/7"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/7/relationships/study","related":"http://localhost:3000/api/v2/aliquots/7/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/7/relationships/project","related":"http://localhost:3000/api/v2/aliquots/7/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/7/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/7/sample"},"data":{"type":"samples","id":"8"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/7/relationships/request","related":"http://localhost:3000/api/v2/aliquots/7/request"}}}},{"id":"8","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/8"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/8/relationships/study","related":"http://localhost:3000/api/v2/aliquots/8/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/8/relationships/project","related":"http://localhost:3000/api/v2/aliquots/8/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/8/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/8/sample"},"data":{"type":"samples","id":"9"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/8/relationships/request","related":"http://localhost:3000/api/v2/aliquots/8/request"}}}},{"id":"9","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/9"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/9/relationships/study","related":"http://localhost:3000/api/v2/aliquots/9/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/9/relationships/project","related":"http://localhost:3000/api/v2/aliquots/9/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/9/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/9/sample"},"data":{"type":"samples","id":"10"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/9/relationships/request","related":"http://localhost:3000/api/v2/aliquots/9/request"}}}},{"id":"10","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/10"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/10/relationships/study","related":"http://localhost:3000/api/v2/aliquots/10/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/10/relationships/project","related":"http://localhost:3000/api/v2/aliquots/10/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/10/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/10/sample"},"data":{"type":"samples","id":"11"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/10/relationships/request","related":"http://localhost:3000/api/v2/aliquots/10/request"}}}},{"id":"11","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/11"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/11/relationships/study","related":"http://localhost:3000/api/v2/aliquots/11/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/11/relationships/project","related":"http://localhost:3000/api/v2/aliquots/11/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/11/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/11/sample"},"data":{"type":"samples","id":"12"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/11/relationships/request","related":"http://localhost:3000/api/v2/aliquots/11/request"}}}},{"id":"12","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/12"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/12/relationships/study","related":"http://localhost:3000/api/v2/aliquots/12/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/12/relationships/project","related":"http://localhost:3000/api/v2/aliquots/12/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/12/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/12/sample"},"data":{"type":"samples","id":"13"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/12/relationships/request","related":"http://localhost:3000/api/v2/aliquots/12/request"}}}},{"id":"13","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/13"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/13/relationships/study","related":"http://localhost:3000/api/v2/aliquots/13/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/13/relationships/project","related":"http://localhost:3000/api/v2/aliquots/13/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/13/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/13/sample"},"data":{"type":"samples","id":"14"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/13/relationships/request","related":"http://localhost:3000/api/v2/aliquots/13/request"}}}},{"id":"14","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/14"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/14/relationships/study","related":"http://localhost:3000/api/v2/aliquots/14/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/14/relationships/project","related":"http://localhost:3000/api/v2/aliquots/14/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/14/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/14/sample"},"data":{"type":"samples","id":"15"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/14/relationships/request","related":"http://localhost:3000/api/v2/aliquots/14/request"}}}},{"id":"15","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/15"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/15/relationships/study","related":"http://localhost:3000/api/v2/aliquots/15/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/15/relationships/project","related":"http://localhost:3000/api/v2/aliquots/15/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/15/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/15/sample"},"data":{"type":"samples","id":"16"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/15/relationships/request","related":"http://localhost:3000/api/v2/aliquots/15/request"}}}},{"id":"16","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/16"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/16/relationships/study","related":"http://localhost:3000/api/v2/aliquots/16/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/16/relationships/project","related":"http://localhost:3000/api/v2/aliquots/16/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/16/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/16/sample"},"data":{"type":"samples","id":"17"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/16/relationships/request","related":"http://localhost:3000/api/v2/aliquots/16/request"}}}},{"id":"17","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/17"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/17/relationships/study","related":"http://localhost:3000/api/v2/aliquots/17/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/17/relationships/project","related":"http://localhost:3000/api/v2/aliquots/17/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/17/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/17/sample"},"data":{"type":"samples","id":"18"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/17/relationships/request","related":"http://localhost:3000/api/v2/aliquots/17/request"}}}},{"id":"18","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/18"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/18/relationships/study","related":"http://localhost:3000/api/v2/aliquots/18/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/18/relationships/project","related":"http://localhost:3000/api/v2/aliquots/18/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/18/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/18/sample"},"data":{"type":"samples","id":"19"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/18/relationships/request","related":"http://localhost:3000/api/v2/aliquots/18/request"}}}},{"id":"19","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/19"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/19/relationships/study","related":"http://localhost:3000/api/v2/aliquots/19/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/19/relationships/project","related":"http://localhost:3000/api/v2/aliquots/19/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/19/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/19/sample"},"data":{"type":"samples","id":"20"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/19/relationships/request","related":"http://localhost:3000/api/v2/aliquots/19/request"}}}},{"id":"20","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/20"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/20/relationships/study","related":"http://localhost:3000/api/v2/aliquots/20/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/20/relationships/project","related":"http://localhost:3000/api/v2/aliquots/20/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/20/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/20/sample"},"data":{"type":"samples","id":"21"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/20/relationships/request","related":"http://localhost:3000/api/v2/aliquots/20/request"}}}},{"id":"21","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/21"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/21/relationships/study","related":"http://localhost:3000/api/v2/aliquots/21/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/21/relationships/project","related":"http://localhost:3000/api/v2/aliquots/21/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/21/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/21/sample"},"data":{"type":"samples","id":"22"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/21/relationships/request","related":"http://localhost:3000/api/v2/aliquots/21/request"}}}},{"id":"22","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/22"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/22/relationships/study","related":"http://localhost:3000/api/v2/aliquots/22/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/22/relationships/project","related":"http://localhost:3000/api/v2/aliquots/22/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/22/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/22/sample"},"data":{"type":"samples","id":"23"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/22/relationships/request","related":"http://localhost:3000/api/v2/aliquots/22/request"}}}},{"id":"23","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/23"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/23/relationships/study","related":"http://localhost:3000/api/v2/aliquots/23/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/23/relationships/project","related":"http://localhost:3000/api/v2/aliquots/23/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/23/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/23/sample"},"data":{"type":"samples","id":"24"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/23/relationships/request","related":"http://localhost:3000/api/v2/aliquots/23/request"}}}},{"id":"24","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/24"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/24/relationships/study","related":"http://localhost:3000/api/v2/aliquots/24/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/24/relationships/project","related":"http://localhost:3000/api/v2/aliquots/24/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/24/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/24/sample"},"data":{"type":"samples","id":"25"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/24/relationships/request","related":"http://localhost:3000/api/v2/aliquots/24/request"}}}},{"id":"25","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/25"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/25/relationships/study","related":"http://localhost:3000/api/v2/aliquots/25/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/25/relationships/project","related":"http://localhost:3000/api/v2/aliquots/25/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/25/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/25/sample"},"data":{"type":"samples","id":"26"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/25/relationships/request","related":"http://localhost:3000/api/v2/aliquots/25/request"}}}},{"id":"26","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/26"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/26/relationships/study","related":"http://localhost:3000/api/v2/aliquots/26/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/26/relationships/project","related":"http://localhost:3000/api/v2/aliquots/26/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/26/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/26/sample"},"data":{"type":"samples","id":"27"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/26/relationships/request","related":"http://localhost:3000/api/v2/aliquots/26/request"}}}},{"id":"27","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/27"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/27/relationships/study","related":"http://localhost:3000/api/v2/aliquots/27/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/27/relationships/project","related":"http://localhost:3000/api/v2/aliquots/27/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/27/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/27/sample"},"data":{"type":"samples","id":"28"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/27/relationships/request","related":"http://localhost:3000/api/v2/aliquots/27/request"}}}},{"id":"28","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/28"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/28/relationships/study","related":"http://localhost:3000/api/v2/aliquots/28/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/28/relationships/project","related":"http://localhost:3000/api/v2/aliquots/28/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/28/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/28/sample"},"data":{"type":"samples","id":"29"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/28/relationships/request","related":"http://localhost:3000/api/v2/aliquots/28/request"}}}},{"id":"29","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/29"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/29/relationships/study","related":"http://localhost:3000/api/v2/aliquots/29/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/29/relationships/project","related":"http://localhost:3000/api/v2/aliquots/29/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/29/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/29/sample"},"data":{"type":"samples","id":"30"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/29/relationships/request","related":"http://localhost:3000/api/v2/aliquots/29/request"}}}},{"id":"30","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/30"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/30/relationships/study","related":"http://localhost:3000/api/v2/aliquots/30/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/30/relationships/project","related":"http://localhost:3000/api/v2/aliquots/30/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/30/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/30/sample"},"data":{"type":"samples","id":"31"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/30/relationships/request","related":"http://localhost:3000/api/v2/aliquots/30/request"}}}},{"id":"31","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/31"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/31/relationships/study","related":"http://localhost:3000/api/v2/aliquots/31/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/31/relationships/project","related":"http://localhost:3000/api/v2/aliquots/31/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/31/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/31/sample"},"data":{"type":"samples","id":"32"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/31/relationships/request","related":"http://localhost:3000/api/v2/aliquots/31/request"}}}},{"id":"32","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/32"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/32/relationships/study","related":"http://localhost:3000/api/v2/aliquots/32/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/32/relationships/project","related":"http://localhost:3000/api/v2/aliquots/32/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/32/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/32/sample"},"data":{"type":"samples","id":"33"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/32/relationships/request","related":"http://localhost:3000/api/v2/aliquots/32/request"}}}},{"id":"33","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/33"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/33/relationships/study","related":"http://localhost:3000/api/v2/aliquots/33/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/33/relationships/project","related":"http://localhost:3000/api/v2/aliquots/33/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/33/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/33/sample"},"data":{"type":"samples","id":"34"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/33/relationships/request","related":"http://localhost:3000/api/v2/aliquots/33/request"}}}},{"id":"34","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/34"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/34/relationships/study","related":"http://localhost:3000/api/v2/aliquots/34/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/34/relationships/project","related":"http://localhost:3000/api/v2/aliquots/34/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/34/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/34/sample"},"data":{"type":"samples","id":"35"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/34/relationships/request","related":"http://localhost:3000/api/v2/aliquots/34/request"}}}},{"id":"35","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/35"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/35/relationships/study","related":"http://localhost:3000/api/v2/aliquots/35/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/35/relationships/project","related":"http://localhost:3000/api/v2/aliquots/35/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/35/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/35/sample"},"data":{"type":"samples","id":"36"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/35/relationships/request","related":"http://localhost:3000/api/v2/aliquots/35/request"}}}},{"id":"36","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/36"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/36/relationships/study","related":"http://localhost:3000/api/v2/aliquots/36/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/36/relationships/project","related":"http://localhost:3000/api/v2/aliquots/36/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/36/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/36/sample"},"data":{"type":"samples","id":"37"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/36/relationships/request","related":"http://localhost:3000/api/v2/aliquots/36/request"}}}},{"id":"37","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/37"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/37/relationships/study","related":"http://localhost:3000/api/v2/aliquots/37/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/37/relationships/project","related":"http://localhost:3000/api/v2/aliquots/37/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/37/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/37/sample"},"data":{"type":"samples","id":"38"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/37/relationships/request","related":"http://localhost:3000/api/v2/aliquots/37/request"}}}},{"id":"38","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/38"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/38/relationships/study","related":"http://localhost:3000/api/v2/aliquots/38/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/38/relationships/project","related":"http://localhost:3000/api/v2/aliquots/38/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/38/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/38/sample"},"data":{"type":"samples","id":"39"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/38/relationships/request","related":"http://localhost:3000/api/v2/aliquots/38/request"}}}},{"id":"39","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/39"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/39/relationships/study","related":"http://localhost:3000/api/v2/aliquots/39/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/39/relationships/project","related":"http://localhost:3000/api/v2/aliquots/39/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/39/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/39/sample"},"data":{"type":"samples","id":"40"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/39/relationships/request","related":"http://localhost:3000/api/v2/aliquots/39/request"}}}},{"id":"40","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/40"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/40/relationships/study","related":"http://localhost:3000/api/v2/aliquots/40/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/40/relationships/project","related":"http://localhost:3000/api/v2/aliquots/40/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/40/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/40/sample"},"data":{"type":"samples","id":"41"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/40/relationships/request","related":"http://localhost:3000/api/v2/aliquots/40/request"}}}},{"id":"41","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/41"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/41/relationships/study","related":"http://localhost:3000/api/v2/aliquots/41/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/41/relationships/project","related":"http://localhost:3000/api/v2/aliquots/41/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/41/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/41/sample"},"data":{"type":"samples","id":"42"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/41/relationships/request","related":"http://localhost:3000/api/v2/aliquots/41/request"}}}},{"id":"42","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/42"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/42/relationships/study","related":"http://localhost:3000/api/v2/aliquots/42/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/42/relationships/project","related":"http://localhost:3000/api/v2/aliquots/42/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/42/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/42/sample"},"data":{"type":"samples","id":"43"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/42/relationships/request","related":"http://localhost:3000/api/v2/aliquots/42/request"}}}},{"id":"43","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/43"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/43/relationships/study","related":"http://localhost:3000/api/v2/aliquots/43/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/43/relationships/project","related":"http://localhost:3000/api/v2/aliquots/43/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/43/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/43/sample"},"data":{"type":"samples","id":"44"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/43/relationships/request","related":"http://localhost:3000/api/v2/aliquots/43/request"}}}},{"id":"44","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/44"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/44/relationships/study","related":"http://localhost:3000/api/v2/aliquots/44/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/44/relationships/project","related":"http://localhost:3000/api/v2/aliquots/44/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/44/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/44/sample"},"data":{"type":"samples","id":"45"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/44/relationships/request","related":"http://localhost:3000/api/v2/aliquots/44/request"}}}},{"id":"45","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/45"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/45/relationships/study","related":"http://localhost:3000/api/v2/aliquots/45/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/45/relationships/project","related":"http://localhost:3000/api/v2/aliquots/45/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/45/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/45/sample"},"data":{"type":"samples","id":"46"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/45/relationships/request","related":"http://localhost:3000/api/v2/aliquots/45/request"}}}},{"id":"46","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/46"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/46/relationships/study","related":"http://localhost:3000/api/v2/aliquots/46/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/46/relationships/project","related":"http://localhost:3000/api/v2/aliquots/46/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/46/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/46/sample"},"data":{"type":"samples","id":"47"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/46/relationships/request","related":"http://localhost:3000/api/v2/aliquots/46/request"}}}},{"id":"47","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/47"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/47/relationships/study","related":"http://localhost:3000/api/v2/aliquots/47/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/47/relationships/project","related":"http://localhost:3000/api/v2/aliquots/47/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/47/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/47/sample"},"data":{"type":"samples","id":"48"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/47/relationships/request","related":"http://localhost:3000/api/v2/aliquots/47/request"}}}},{"id":"48","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/48"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/48/relationships/study","related":"http://localhost:3000/api/v2/aliquots/48/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/48/relationships/project","related":"http://localhost:3000/api/v2/aliquots/48/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/48/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/48/sample"},"data":{"type":"samples","id":"49"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/48/relationships/request","related":"http://localhost:3000/api/v2/aliquots/48/request"}}}},{"id":"49","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/49"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/49/relationships/study","related":"http://localhost:3000/api/v2/aliquots/49/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/49/relationships/project","related":"http://localhost:3000/api/v2/aliquots/49/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/49/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/49/sample"},"data":{"type":"samples","id":"50"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/49/relationships/request","related":"http://localhost:3000/api/v2/aliquots/49/request"}}}},{"id":"50","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/50"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/50/relationships/study","related":"http://localhost:3000/api/v2/aliquots/50/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/50/relationships/project","related":"http://localhost:3000/api/v2/aliquots/50/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/50/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/50/sample"},"data":{"type":"samples","id":"51"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/50/relationships/request","related":"http://localhost:3000/api/v2/aliquots/50/request"}}}},{"id":"51","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/51"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/51/relationships/study","related":"http://localhost:3000/api/v2/aliquots/51/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/51/relationships/project","related":"http://localhost:3000/api/v2/aliquots/51/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/51/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/51/sample"},"data":{"type":"samples","id":"52"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/51/relationships/request","related":"http://localhost:3000/api/v2/aliquots/51/request"}}}},{"id":"52","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/52"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/52/relationships/study","related":"http://localhost:3000/api/v2/aliquots/52/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/52/relationships/project","related":"http://localhost:3000/api/v2/aliquots/52/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/52/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/52/sample"},"data":{"type":"samples","id":"53"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/52/relationships/request","related":"http://localhost:3000/api/v2/aliquots/52/request"}}}},{"id":"53","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/53"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/53/relationships/study","related":"http://localhost:3000/api/v2/aliquots/53/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/53/relationships/project","related":"http://localhost:3000/api/v2/aliquots/53/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/53/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/53/sample"},"data":{"type":"samples","id":"54"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/53/relationships/request","related":"http://localhost:3000/api/v2/aliquots/53/request"}}}},{"id":"54","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/54"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/54/relationships/study","related":"http://localhost:3000/api/v2/aliquots/54/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/54/relationships/project","related":"http://localhost:3000/api/v2/aliquots/54/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/54/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/54/sample"},"data":{"type":"samples","id":"55"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/54/relationships/request","related":"http://localhost:3000/api/v2/aliquots/54/request"}}}},{"id":"55","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/55"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/55/relationships/study","related":"http://localhost:3000/api/v2/aliquots/55/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/55/relationships/project","related":"http://localhost:3000/api/v2/aliquots/55/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/55/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/55/sample"},"data":{"type":"samples","id":"56"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/55/relationships/request","related":"http://localhost:3000/api/v2/aliquots/55/request"}}}},{"id":"56","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/56"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/56/relationships/study","related":"http://localhost:3000/api/v2/aliquots/56/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/56/relationships/project","related":"http://localhost:3000/api/v2/aliquots/56/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/56/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/56/sample"},"data":{"type":"samples","id":"57"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/56/relationships/request","related":"http://localhost:3000/api/v2/aliquots/56/request"}}}},{"id":"57","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/57"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/57/relationships/study","related":"http://localhost:3000/api/v2/aliquots/57/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/57/relationships/project","related":"http://localhost:3000/api/v2/aliquots/57/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/57/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/57/sample"},"data":{"type":"samples","id":"58"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/57/relationships/request","related":"http://localhost:3000/api/v2/aliquots/57/request"}}}},{"id":"58","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/58"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/58/relationships/study","related":"http://localhost:3000/api/v2/aliquots/58/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/58/relationships/project","related":"http://localhost:3000/api/v2/aliquots/58/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/58/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/58/sample"},"data":{"type":"samples","id":"59"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/58/relationships/request","related":"http://localhost:3000/api/v2/aliquots/58/request"}}}},{"id":"59","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/59"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/59/relationships/study","related":"http://localhost:3000/api/v2/aliquots/59/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/59/relationships/project","related":"http://localhost:3000/api/v2/aliquots/59/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/59/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/59/sample"},"data":{"type":"samples","id":"60"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/59/relationships/request","related":"http://localhost:3000/api/v2/aliquots/59/request"}}}},{"id":"60","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/60"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/60/relationships/study","related":"http://localhost:3000/api/v2/aliquots/60/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/60/relationships/project","related":"http://localhost:3000/api/v2/aliquots/60/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/60/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/60/sample"},"data":{"type":"samples","id":"61"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/60/relationships/request","related":"http://localhost:3000/api/v2/aliquots/60/request"}}}},{"id":"61","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/61"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/61/relationships/study","related":"http://localhost:3000/api/v2/aliquots/61/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/61/relationships/project","related":"http://localhost:3000/api/v2/aliquots/61/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/61/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/61/sample"},"data":{"type":"samples","id":"62"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/61/relationships/request","related":"http://localhost:3000/api/v2/aliquots/61/request"}}}},{"id":"62","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/62"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/62/relationships/study","related":"http://localhost:3000/api/v2/aliquots/62/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/62/relationships/project","related":"http://localhost:3000/api/v2/aliquots/62/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/62/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/62/sample"},"data":{"type":"samples","id":"63"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/62/relationships/request","related":"http://localhost:3000/api/v2/aliquots/62/request"}}}},{"id":"63","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/63"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/63/relationships/study","related":"http://localhost:3000/api/v2/aliquots/63/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/63/relationships/project","related":"http://localhost:3000/api/v2/aliquots/63/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/63/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/63/sample"},"data":{"type":"samples","id":"64"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/63/relationships/request","related":"http://localhost:3000/api/v2/aliquots/63/request"}}}},{"id":"64","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/64"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/64/relationships/study","related":"http://localhost:3000/api/v2/aliquots/64/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/64/relationships/project","related":"http://localhost:3000/api/v2/aliquots/64/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/64/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/64/sample"},"data":{"type":"samples","id":"65"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/64/relationships/request","related":"http://localhost:3000/api/v2/aliquots/64/request"}}}},{"id":"65","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/65"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/65/relationships/study","related":"http://localhost:3000/api/v2/aliquots/65/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/65/relationships/project","related":"http://localhost:3000/api/v2/aliquots/65/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/65/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/65/sample"},"data":{"type":"samples","id":"66"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/65/relationships/request","related":"http://localhost:3000/api/v2/aliquots/65/request"}}}},{"id":"66","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/66"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/66/relationships/study","related":"http://localhost:3000/api/v2/aliquots/66/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/66/relationships/project","related":"http://localhost:3000/api/v2/aliquots/66/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/66/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/66/sample"},"data":{"type":"samples","id":"67"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/66/relationships/request","related":"http://localhost:3000/api/v2/aliquots/66/request"}}}},{"id":"67","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/67"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/67/relationships/study","related":"http://localhost:3000/api/v2/aliquots/67/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/67/relationships/project","related":"http://localhost:3000/api/v2/aliquots/67/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/67/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/67/sample"},"data":{"type":"samples","id":"68"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/67/relationships/request","related":"http://localhost:3000/api/v2/aliquots/67/request"}}}},{"id":"68","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/68"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/68/relationships/study","related":"http://localhost:3000/api/v2/aliquots/68/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/68/relationships/project","related":"http://localhost:3000/api/v2/aliquots/68/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/68/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/68/sample"},"data":{"type":"samples","id":"69"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/68/relationships/request","related":"http://localhost:3000/api/v2/aliquots/68/request"}}}},{"id":"69","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/69"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/69/relationships/study","related":"http://localhost:3000/api/v2/aliquots/69/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/69/relationships/project","related":"http://localhost:3000/api/v2/aliquots/69/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/69/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/69/sample"},"data":{"type":"samples","id":"70"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/69/relationships/request","related":"http://localhost:3000/api/v2/aliquots/69/request"}}}},{"id":"70","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/70"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/70/relationships/study","related":"http://localhost:3000/api/v2/aliquots/70/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/70/relationships/project","related":"http://localhost:3000/api/v2/aliquots/70/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/70/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/70/sample"},"data":{"type":"samples","id":"71"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/70/relationships/request","related":"http://localhost:3000/api/v2/aliquots/70/request"}}}},{"id":"71","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/71"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/71/relationships/study","related":"http://localhost:3000/api/v2/aliquots/71/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/71/relationships/project","related":"http://localhost:3000/api/v2/aliquots/71/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/71/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/71/sample"},"data":{"type":"samples","id":"72"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/71/relationships/request","related":"http://localhost:3000/api/v2/aliquots/71/request"}}}},{"id":"72","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/72"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/72/relationships/study","related":"http://localhost:3000/api/v2/aliquots/72/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/72/relationships/project","related":"http://localhost:3000/api/v2/aliquots/72/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/72/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/72/sample"},"data":{"type":"samples","id":"73"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/72/relationships/request","related":"http://localhost:3000/api/v2/aliquots/72/request"}}}},{"id":"73","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/73"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/73/relationships/study","related":"http://localhost:3000/api/v2/aliquots/73/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/73/relationships/project","related":"http://localhost:3000/api/v2/aliquots/73/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/73/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/73/sample"},"data":{"type":"samples","id":"74"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/73/relationships/request","related":"http://localhost:3000/api/v2/aliquots/73/request"}}}},{"id":"74","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/74"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/74/relationships/study","related":"http://localhost:3000/api/v2/aliquots/74/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/74/relationships/project","related":"http://localhost:3000/api/v2/aliquots/74/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/74/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/74/sample"},"data":{"type":"samples","id":"75"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/74/relationships/request","related":"http://localhost:3000/api/v2/aliquots/74/request"}}}},{"id":"75","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/75"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/75/relationships/study","related":"http://localhost:3000/api/v2/aliquots/75/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/75/relationships/project","related":"http://localhost:3000/api/v2/aliquots/75/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/75/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/75/sample"},"data":{"type":"samples","id":"76"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/75/relationships/request","related":"http://localhost:3000/api/v2/aliquots/75/request"}}}},{"id":"76","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/76"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/76/relationships/study","related":"http://localhost:3000/api/v2/aliquots/76/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/76/relationships/project","related":"http://localhost:3000/api/v2/aliquots/76/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/76/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/76/sample"},"data":{"type":"samples","id":"77"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/76/relationships/request","related":"http://localhost:3000/api/v2/aliquots/76/request"}}}},{"id":"77","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/77"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/77/relationships/study","related":"http://localhost:3000/api/v2/aliquots/77/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/77/relationships/project","related":"http://localhost:3000/api/v2/aliquots/77/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/77/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/77/sample"},"data":{"type":"samples","id":"78"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/77/relationships/request","related":"http://localhost:3000/api/v2/aliquots/77/request"}}}},{"id":"78","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/78"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/78/relationships/study","related":"http://localhost:3000/api/v2/aliquots/78/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/78/relationships/project","related":"http://localhost:3000/api/v2/aliquots/78/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/78/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/78/sample"},"data":{"type":"samples","id":"79"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/78/relationships/request","related":"http://localhost:3000/api/v2/aliquots/78/request"}}}},{"id":"79","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/79"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/79/relationships/study","related":"http://localhost:3000/api/v2/aliquots/79/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/79/relationships/project","related":"http://localhost:3000/api/v2/aliquots/79/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/79/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/79/sample"},"data":{"type":"samples","id":"80"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/79/relationships/request","related":"http://localhost:3000/api/v2/aliquots/79/request"}}}},{"id":"80","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/80"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/80/relationships/study","related":"http://localhost:3000/api/v2/aliquots/80/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/80/relationships/project","related":"http://localhost:3000/api/v2/aliquots/80/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/80/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/80/sample"},"data":{"type":"samples","id":"81"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/80/relationships/request","related":"http://localhost:3000/api/v2/aliquots/80/request"}}}},{"id":"81","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/81"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/81/relationships/study","related":"http://localhost:3000/api/v2/aliquots/81/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/81/relationships/project","related":"http://localhost:3000/api/v2/aliquots/81/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/81/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/81/sample"},"data":{"type":"samples","id":"82"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/81/relationships/request","related":"http://localhost:3000/api/v2/aliquots/81/request"}}}},{"id":"82","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/82"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/82/relationships/study","related":"http://localhost:3000/api/v2/aliquots/82/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/82/relationships/project","related":"http://localhost:3000/api/v2/aliquots/82/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/82/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/82/sample"},"data":{"type":"samples","id":"83"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/82/relationships/request","related":"http://localhost:3000/api/v2/aliquots/82/request"}}}},{"id":"83","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/83"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/83/relationships/study","related":"http://localhost:3000/api/v2/aliquots/83/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/83/relationships/project","related":"http://localhost:3000/api/v2/aliquots/83/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/83/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/83/sample"},"data":{"type":"samples","id":"84"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/83/relationships/request","related":"http://localhost:3000/api/v2/aliquots/83/request"}}}},{"id":"84","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/84"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/84/relationships/study","related":"http://localhost:3000/api/v2/aliquots/84/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/84/relationships/project","related":"http://localhost:3000/api/v2/aliquots/84/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/84/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/84/sample"},"data":{"type":"samples","id":"85"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/84/relationships/request","related":"http://localhost:3000/api/v2/aliquots/84/request"}}}},{"id":"85","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/85"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/85/relationships/study","related":"http://localhost:3000/api/v2/aliquots/85/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/85/relationships/project","related":"http://localhost:3000/api/v2/aliquots/85/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/85/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/85/sample"},"data":{"type":"samples","id":"86"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/85/relationships/request","related":"http://localhost:3000/api/v2/aliquots/85/request"}}}},{"id":"86","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/86"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/86/relationships/study","related":"http://localhost:3000/api/v2/aliquots/86/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/86/relationships/project","related":"http://localhost:3000/api/v2/aliquots/86/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/86/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/86/sample"},"data":{"type":"samples","id":"87"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/86/relationships/request","related":"http://localhost:3000/api/v2/aliquots/86/request"}}}},{"id":"87","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/87"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/87/relationships/study","related":"http://localhost:3000/api/v2/aliquots/87/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/87/relationships/project","related":"http://localhost:3000/api/v2/aliquots/87/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/87/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/87/sample"},"data":{"type":"samples","id":"88"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/87/relationships/request","related":"http://localhost:3000/api/v2/aliquots/87/request"}}}},{"id":"88","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/88"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/88/relationships/study","related":"http://localhost:3000/api/v2/aliquots/88/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/88/relationships/project","related":"http://localhost:3000/api/v2/aliquots/88/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/88/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/88/sample"},"data":{"type":"samples","id":"89"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/88/relationships/request","related":"http://localhost:3000/api/v2/aliquots/88/request"}}}},{"id":"89","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/89"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/89/relationships/study","related":"http://localhost:3000/api/v2/aliquots/89/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/89/relationships/project","related":"http://localhost:3000/api/v2/aliquots/89/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/89/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/89/sample"},"data":{"type":"samples","id":"90"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/89/relationships/request","related":"http://localhost:3000/api/v2/aliquots/89/request"}}}},{"id":"90","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/90"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/90/relationships/study","related":"http://localhost:3000/api/v2/aliquots/90/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/90/relationships/project","related":"http://localhost:3000/api/v2/aliquots/90/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/90/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/90/sample"},"data":{"type":"samples","id":"91"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/90/relationships/request","related":"http://localhost:3000/api/v2/aliquots/90/request"}}}},{"id":"91","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/91"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/91/relationships/study","related":"http://localhost:3000/api/v2/aliquots/91/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/91/relationships/project","related":"http://localhost:3000/api/v2/aliquots/91/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/91/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/91/sample"},"data":{"type":"samples","id":"92"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/91/relationships/request","related":"http://localhost:3000/api/v2/aliquots/91/request"}}}},{"id":"92","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/92"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/92/relationships/study","related":"http://localhost:3000/api/v2/aliquots/92/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/92/relationships/project","related":"http://localhost:3000/api/v2/aliquots/92/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/92/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/92/sample"},"data":{"type":"samples","id":"93"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/92/relationships/request","related":"http://localhost:3000/api/v2/aliquots/92/request"}}}},{"id":"93","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/93"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/93/relationships/study","related":"http://localhost:3000/api/v2/aliquots/93/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/93/relationships/project","related":"http://localhost:3000/api/v2/aliquots/93/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/93/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/93/sample"},"data":{"type":"samples","id":"94"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/93/relationships/request","related":"http://localhost:3000/api/v2/aliquots/93/request"}}}},{"id":"94","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/94"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/94/relationships/study","related":"http://localhost:3000/api/v2/aliquots/94/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/94/relationships/project","related":"http://localhost:3000/api/v2/aliquots/94/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/94/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/94/sample"},"data":{"type":"samples","id":"95"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/94/relationships/request","related":"http://localhost:3000/api/v2/aliquots/94/request"}}}},{"id":"95","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/95"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/95/relationships/study","related":"http://localhost:3000/api/v2/aliquots/95/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/95/relationships/project","related":"http://localhost:3000/api/v2/aliquots/95/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/95/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/95/sample"},"data":{"type":"samples","id":"96"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/95/relationships/request","related":"http://localhost:3000/api/v2/aliquots/95/request"}}}},{"id":"96","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/96"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/96/relationships/study","related":"http://localhost:3000/api/v2/aliquots/96/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/96/relationships/project","related":"http://localhost:3000/api/v2/aliquots/96/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/96/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/96/sample"},"data":{"type":"samples","id":"97"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/96/relationships/request","related":"http://localhost:3000/api/v2/aliquots/96/request"}}}},{"id":"1","type":"studies","links":{"self":"http://localhost:3000/api/v2/studies/1"},"attributes":{"name":"UAT Study","uuid":"6d4617ea-9a21-11ec-9a02-acde48001122"}},{"id":"2","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/2"},"attributes":{"sanger_sample_id":null,"uuid":"76c97050-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A1"}},{"id":"3","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/3"},"attributes":{"sanger_sample_id":null,"uuid":"76d347a6-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A2"}},{"id":"4","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/4"},"attributes":{"sanger_sample_id":null,"uuid":"76e0c2aa-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A3"}},{"id":"5","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/5"},"attributes":{"sanger_sample_id":null,"uuid":"76ead326-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A4"}},{"id":"6","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/6"},"attributes":{"sanger_sample_id":null,"uuid":"76f29340-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A5"}},{"id":"7","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/7"},"attributes":{"sanger_sample_id":null,"uuid":"76fa2ed4-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A6"}},{"id":"8","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/8"},"attributes":{"sanger_sample_id":null,"uuid":"77017158-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A7"}},{"id":"9","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/9"},"attributes":{"sanger_sample_id":null,"uuid":"7708b58a-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A8"}},{"id":"10","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/10"},"attributes":{"sanger_sample_id":null,"uuid":"771063fc-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A9"}},{"id":"11","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/11"},"attributes":{"sanger_sample_id":null,"uuid":"7717deb6-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A10"}},{"id":"12","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/12"},"attributes":{"sanger_sample_id":null,"uuid":"771f368e-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A11"}},{"id":"13","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/13"},"attributes":{"sanger_sample_id":null,"uuid":"7726dd76-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_A12"}},{"id":"14","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/14"},"attributes":{"sanger_sample_id":null,"uuid":"772e9e12-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B1"}},{"id":"15","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/15"},"attributes":{"sanger_sample_id":null,"uuid":"77351fee-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B2"}},{"id":"16","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/16"},"attributes":{"sanger_sample_id":null,"uuid":"773b2d9e-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B3"}},{"id":"17","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/17"},"attributes":{"sanger_sample_id":null,"uuid":"774d0bfe-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B4"}},{"id":"18","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/18"},"attributes":{"sanger_sample_id":null,"uuid":"7758a09a-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B5"}},{"id":"19","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/19"},"attributes":{"sanger_sample_id":null,"uuid":"7767bddc-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B6"}},{"id":"20","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/20"},"attributes":{"sanger_sample_id":null,"uuid":"777214e4-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B7"}},{"id":"21","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/21"},"attributes":{"sanger_sample_id":null,"uuid":"77841720-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B8"}},{"id":"22","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/22"},"attributes":{"sanger_sample_id":null,"uuid":"778c55ac-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B9"}},{"id":"23","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/23"},"attributes":{"sanger_sample_id":null,"uuid":"779931b4-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B10"}},{"id":"24","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/24"},"attributes":{"sanger_sample_id":null,"uuid":"77a0e4ea-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B11"}},{"id":"25","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/25"},"attributes":{"sanger_sample_id":null,"uuid":"77aa1646-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_B12"}},{"id":"26","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/26"},"attributes":{"sanger_sample_id":null,"uuid":"77b240fa-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C1"}},{"id":"27","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/27"},"attributes":{"sanger_sample_id":null,"uuid":"77ba2068-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C2"}},{"id":"28","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/28"},"attributes":{"sanger_sample_id":null,"uuid":"77c1d29a-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C3"}},{"id":"29","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/29"},"attributes":{"sanger_sample_id":null,"uuid":"77c98166-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C4"}},{"id":"30","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/30"},"attributes":{"sanger_sample_id":null,"uuid":"77d122cc-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C5"}},{"id":"31","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/31"},"attributes":{"sanger_sample_id":null,"uuid":"77d85e3e-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C6"}},{"id":"32","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/32"},"attributes":{"sanger_sample_id":null,"uuid":"77df9a00-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C7"}},{"id":"33","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/33"},"attributes":{"sanger_sample_id":null,"uuid":"77e6fed0-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C8"}},{"id":"34","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/34"},"attributes":{"sanger_sample_id":null,"uuid":"77ee42a8-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C9"}},{"id":"35","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/35"},"attributes":{"sanger_sample_id":null,"uuid":"77f56eca-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C10"}},{"id":"36","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/36"},"attributes":{"sanger_sample_id":null,"uuid":"77fd6d6e-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C11"}},{"id":"37","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/37"},"attributes":{"sanger_sample_id":null,"uuid":"780ac018-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_C12"}},{"id":"38","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/38"},"attributes":{"sanger_sample_id":null,"uuid":"7811ced0-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D1"}},{"id":"39","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/39"},"attributes":{"sanger_sample_id":null,"uuid":"78192216-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D2"}},{"id":"40","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/40"},"attributes":{"sanger_sample_id":null,"uuid":"7822e08a-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D3"}},{"id":"41","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/41"},"attributes":{"sanger_sample_id":null,"uuid":"782a1a26-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D4"}},{"id":"42","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/42"},"attributes":{"sanger_sample_id":null,"uuid":"783160ba-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D5"}},{"id":"43","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/43"},"attributes":{"sanger_sample_id":null,"uuid":"78411b36-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D6"}},{"id":"44","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/44"},"attributes":{"sanger_sample_id":null,"uuid":"78531a7a-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D7"}},{"id":"45","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/45"},"attributes":{"sanger_sample_id":null,"uuid":"785ca31a-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D8"}},{"id":"46","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/46"},"attributes":{"sanger_sample_id":null,"uuid":"78643e22-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D9"}},{"id":"47","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/47"},"attributes":{"sanger_sample_id":null,"uuid":"786bd72c-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D10"}},{"id":"48","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/48"},"attributes":{"sanger_sample_id":null,"uuid":"7873aeb6-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D11"}},{"id":"49","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/49"},"attributes":{"sanger_sample_id":null,"uuid":"787d84a4-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_D12"}},{"id":"50","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/50"},"attributes":{"sanger_sample_id":null,"uuid":"78849e10-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E1"}},{"id":"51","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/51"},"attributes":{"sanger_sample_id":null,"uuid":"788b88f6-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E2"}},{"id":"52","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/52"},"attributes":{"sanger_sample_id":null,"uuid":"7892a03c-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E3"}},{"id":"53","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/53"},"attributes":{"sanger_sample_id":null,"uuid":"789f9184-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E4"}},{"id":"54","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/54"},"attributes":{"sanger_sample_id":null,"uuid":"78b92bda-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E5"}},{"id":"55","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/55"},"attributes":{"sanger_sample_id":null,"uuid":"78c23ec8-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E6"}},{"id":"56","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/56"},"attributes":{"sanger_sample_id":null,"uuid":"78d934d4-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E7"}},{"id":"57","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/57"},"attributes":{"sanger_sample_id":null,"uuid":"78e25dfc-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E8"}},{"id":"58","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/58"},"attributes":{"sanger_sample_id":null,"uuid":"78ed8740-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E9"}},{"id":"59","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/59"},"attributes":{"sanger_sample_id":null,"uuid":"78f6ce9a-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E10"}},{"id":"60","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/60"},"attributes":{"sanger_sample_id":null,"uuid":"78fef296-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E11"}},{"id":"61","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/61"},"attributes":{"sanger_sample_id":null,"uuid":"7906692c-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_E12"}},{"id":"62","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/62"},"attributes":{"sanger_sample_id":null,"uuid":"790db880-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F1"}},{"id":"63","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/63"},"attributes":{"sanger_sample_id":null,"uuid":"7914f69a-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F2"}},{"id":"64","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/64"},"attributes":{"sanger_sample_id":null,"uuid":"791c50c0-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F3"}},{"id":"65","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/65"},"attributes":{"sanger_sample_id":null,"uuid":"7923e628-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F4"}},{"id":"66","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/66"},"attributes":{"sanger_sample_id":null,"uuid":"7932f816-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F5"}},{"id":"67","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/67"},"attributes":{"sanger_sample_id":null,"uuid":"793c21de-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F6"}},{"id":"68","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/68"},"attributes":{"sanger_sample_id":null,"uuid":"79449cec-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F7"}},{"id":"69","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/69"},"attributes":{"sanger_sample_id":null,"uuid":"794cb7b0-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F8"}},{"id":"70","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/70"},"attributes":{"sanger_sample_id":null,"uuid":"7956ea00-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F9"}},{"id":"71","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/71"},"attributes":{"sanger_sample_id":null,"uuid":"796952bc-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F10"}},{"id":"72","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/72"},"attributes":{"sanger_sample_id":null,"uuid":"7972d026-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F11"}},{"id":"73","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/73"},"attributes":{"sanger_sample_id":null,"uuid":"797a4d4c-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_F12"}},{"id":"74","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/74"},"attributes":{"sanger_sample_id":null,"uuid":"7981542a-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G1"}},{"id":"75","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/75"},"attributes":{"sanger_sample_id":null,"uuid":"798950e4-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G2"}},{"id":"76","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/76"},"attributes":{"sanger_sample_id":null,"uuid":"79916f18-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G3"}},{"id":"77","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/77"},"attributes":{"sanger_sample_id":null,"uuid":"79993ef0-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G4"}},{"id":"78","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/78"},"attributes":{"sanger_sample_id":null,"uuid":"79a144f6-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G5"}},{"id":"79","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/79"},"attributes":{"sanger_sample_id":null,"uuid":"79a86a60-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G6"}},{"id":"80","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/80"},"attributes":{"sanger_sample_id":null,"uuid":"79afc850-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G7"}},{"id":"81","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/81"},"attributes":{"sanger_sample_id":null,"uuid":"79b73b08-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G8"}},{"id":"82","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/82"},"attributes":{"sanger_sample_id":null,"uuid":"79c71032-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G9"}},{"id":"83","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/83"},"attributes":{"sanger_sample_id":null,"uuid":"79ce40a0-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G10"}},{"id":"84","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/84"},"attributes":{"sanger_sample_id":null,"uuid":"79d553f4-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G11"}},{"id":"85","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/85"},"attributes":{"sanger_sample_id":null,"uuid":"79dcc076-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_G12"}},{"id":"86","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/86"},"attributes":{"sanger_sample_id":null,"uuid":"79e41ab0-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H1"}},{"id":"87","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/87"},"attributes":{"sanger_sample_id":null,"uuid":"79f1f536-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H2"}},{"id":"88","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/88"},"attributes":{"sanger_sample_id":null,"uuid":"79fa86ba-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H3"}},{"id":"89","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/89"},"attributes":{"sanger_sample_id":null,"uuid":"7a0abe68-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H4"}},{"id":"90","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/90"},"attributes":{"sanger_sample_id":null,"uuid":"7a129eb2-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H5"}},{"id":"91","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/91"},"attributes":{"sanger_sample_id":null,"uuid":"7a1ac51a-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H6"}},{"id":"92","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/92"},"attributes":{"sanger_sample_id":null,"uuid":"7a22a0b4-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H7"}},{"id":"93","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/93"},"attributes":{"sanger_sample_id":null,"uuid":"7a2b6eb0-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H8"}},{"id":"94","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/94"},"attributes":{"sanger_sample_id":null,"uuid":"7a3578d8-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H9"}},{"id":"95","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/95"},"attributes":{"sanger_sample_id":null,"uuid":"7a3c7264-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H10"}},{"id":"96","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/96"},"attributes":{"sanger_sample_id":null,"uuid":"7a445a56-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H11"}},{"id":"97","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/97"},"attributes":{"sanger_sample_id":null,"uuid":"7a4de788-9a21-11ec-9a02-acde48001122","name":"sample_DN9000001W_H12"}},{"id":"2","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/2"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"3","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/3"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"4","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/4"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"5","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/5"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"6","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/6"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"7","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/7"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"8","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/8"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"9","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/9"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"10","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/10"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"11","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/11"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"12","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/12"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"13","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/13"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"14","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/14"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"15","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/15"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"16","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/16"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"17","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/17"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"18","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/18"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"19","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/19"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"20","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/20"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"21","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/21"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"22","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/22"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"23","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/23"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"24","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/24"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"25","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/25"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"26","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/26"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"27","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/27"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"28","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/28"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"29","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/29"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"30","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/30"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"31","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/31"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"32","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/32"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"33","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/33"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"34","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/34"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"35","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/35"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"36","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/36"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"37","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/37"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"38","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/38"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"39","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/39"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"40","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/40"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"41","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/41"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"42","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/42"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"43","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/43"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"44","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/44"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"45","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/45"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"46","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/46"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"47","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/47"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"48","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/48"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"49","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/49"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"50","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/50"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"51","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/51"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"52","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/52"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"53","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/53"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"54","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/54"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"55","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/55"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"56","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/56"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"57","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/57"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"58","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/58"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"59","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/59"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"60","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/60"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"61","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/61"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"62","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/62"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"63","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/63"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"64","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/64"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"65","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/65"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"66","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/66"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"67","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/67"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"68","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/68"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"69","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/69"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"70","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/70"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"71","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/71"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"72","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/72"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"73","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/73"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"74","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/74"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"75","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/75"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"76","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/76"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"77","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/77"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"78","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/78"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"79","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/79"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"80","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/80"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"81","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/81"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"82","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/82"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"83","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/83"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"84","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/84"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"85","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/85"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"86","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/86"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"87","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/87"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"88","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/88"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"89","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/89"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"90","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/90"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"91","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/91"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"92","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/92"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"93","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/93"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"94","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/94"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"95","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/95"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"96","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/96"},"attributes":{"supplier_name":null,"sample_common_name":null}},{"id":"97","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/97"},"attributes":{"supplier_name":null,"sample_common_name":null}}],"links":{"first":"http://localhost:3000/api/v2/labware?fields%5Bplates%5D=uuid%2Clabware_barcode%2Creceptacles%2Cpurpose&fields%5Bpurpose%5D=name&fields%5Bsample_metadata%5D=supplier_name%2Csample_common_name&fields%5Bsamples%5D=sanger_sample_id%2Cuuid%2Cname&fields%5Bstudy%5D=name%2Cuuid&fields%5Btube_racks%5D=uuid%2Clabware_barcode&fields%5Btubes%5D=uuid%2Clabware_barcode%2Creceptacles%2Cpurpose&filter%5Bbarcode%5D=DN9000001W%2CNOT_FOUND&include=receptacles.aliquots.sample.sample_metadata%2Creceptacles.aliquots.study%2Cpurpose&page%5Bnumber%5D=1&page%5Bsize%5D=100","last":"http://localhost:3000/api/v2/labware?fields%5Bplates%5D=uuid%2Clabware_barcode%2Creceptacles%2Cpurpose&fields%5Bpurpose%5D=name&fields%5Bsample_metadata%5D=supplier_name%2Csample_common_name&fields%5Bsamples%5D=sanger_sample_id%2Cuuid%2Cname&fields%5Bstudy%5D=name%2Cuuid&fields%5Btube_racks%5D=uuid%2Clabware_barcode&fields%5Btubes%5D=uuid%2Clabware_barcode%2Creceptacles%2Cpurpose&filter%5Bbarcode%5D=DN9000001W%2CNOT_FOUND&include=receptacles.aliquots.sample.sample_metadata%2Creceptacles.aliquots.study%2Cpurpose&page%5Bnumber%5D=1&page%5Bsize%5D=100"}} \ No newline at end of file diff --git a/spec/support/responses/sequencescape/v2/labware_tube_rack_response.txt b/spec/support/responses/sequencescape/v2/labware_tube_rack_response.txt new file mode 100644 index 00000000..05805581 --- /dev/null +++ b/spec/support/responses/sequencescape/v2/labware_tube_rack_response.txt @@ -0,0 +1,18 @@ +HTTP/1.1 200 OK +X-Frame-Options: SAMEORIGIN +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +X-Download-Options: noopen +X-Permitted-Cross-Domain-Policies: none +Referrer-Policy: strict-origin-when-cross-origin +Content-Type: application/vnd.api+json +Cache-Control: no-store, must-revalidate, private, max-age=0 +X-Request-Id: 4c11e98f-e564-4214-8658-fe963747b5a0 +X-Runtime: 0.034263 +Vary: Origin +X-MiniProfiler-Original-Cache-Control: max-age=0, private, must-revalidate +X-MiniProfiler-Ids: dbebqz2k1y074mg30fb6,dw048ingt3p8h0e2t2ci,91wr17h4h7nwlyq3bopp,p2lk18v81us8d2lqo8od,yk3ewri34ey1gwth6llw,srx9veqj73onmo4b90oq,67pmtv59y0qgswh86phf,tei9eifhqr5ai5wsr37h,u51wi3xrsy4nno21z5y1,k7zjigrzrl5xqtzptj79,v3g61r5x6i8vcoiz41n2,hixdm5dp9js34vvd5n1j,h5nry8521lil2x65eyi7,do19v972tj6g4j0fb0ab,tgbpp7q89bzob2eol0b9,wiq23okz07dl48t7xj3d,hhjcy0xhsxo88qstns8w,en9xjfcoe8m7c4spdmta,khokuqgbpk813qg0cm39,xt1w47sa31bq51t6w0zv +Set-Cookie: __profilin=p%3Dt; path=/; HttpOnly; SameSite=Lax +Transfer-Encoding: chunked + +{"data":[{"id":"4","type":"tube_racks","links":{"self":"http://localhost:3000/api/v2/tube_racks/4"},"attributes":{"uuid":"f3834d5e-9fb3-11ec-a4f7-acde48001122","labware_barcode":{"ean13_barcode":null,"machine_barcode":"AB42785517","human_barcode":"AB42785517"}},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tube_racks/4/relationships/purpose","related":"http://localhost:3000/api/v2/tube_racks/4/purpose"},"data":{"type":"purposes","id":"74"}}}}],"included":[{"id":"74","type":"purposes","links":{"self":"http://localhost:3000/api/v2/purposes/74"},"attributes":{"uuid":"6eda06d4-9a21-11ec-9a02-acde48001122","name":"TR Stock 96","size":96}}],"links":{"first":"http://localhost:3000/api/v2/labware?fields%5Bplates%5D=uuid%2Clabware_barcode%2Creceptacles%2Cpurpose&fields%5Bpurpose%5D=name&fields%5Bsample_metadata%5D=supplier_name%2Csample_common_name&fields%5Bsamples%5D=sanger_sample_id%2Cuuid%2Cname&fields%5Bstudy%5D=name%2Cuuid&fields%5Btube_racks%5D=uuid%2Clabware_barcode%2Cpurpose&fields%5Btubes%5D=uuid%2Clabware_barcode%2Creceptacles%2Cpurpose&filter%5Bbarcode%5D=AB42785517%2CNOT_FOUND&include=receptacles.aliquots.sample.sample_metadata%2Creceptacles.aliquots.study%2Cpurpose&page%5Bnumber%5D=1&page%5Bsize%5D=100","last":"http://localhost:3000/api/v2/labware?fields%5Bplates%5D=uuid%2Clabware_barcode%2Creceptacles%2Cpurpose&fields%5Bpurpose%5D=name&fields%5Bsample_metadata%5D=supplier_name%2Csample_common_name&fields%5Bsamples%5D=sanger_sample_id%2Cuuid%2Cname&fields%5Bstudy%5D=name%2Cuuid&fields%5Btube_racks%5D=uuid%2Clabware_barcode%2Cpurpose&fields%5Btubes%5D=uuid%2Clabware_barcode%2Creceptacles%2Cpurpose&filter%5Bbarcode%5D=AB42785517%2CNOT_FOUND&include=receptacles.aliquots.sample.sample_metadata%2Creceptacles.aliquots.study%2Cpurpose&page%5Bnumber%5D=1&page%5Bsize%5D=100"}} \ No newline at end of file diff --git a/spec/support/responses/sequencescape/v2/plate_response.txt b/spec/support/responses/sequencescape/v2/plate_response.txt new file mode 100644 index 00000000..4421bfae --- /dev/null +++ b/spec/support/responses/sequencescape/v2/plate_response.txt @@ -0,0 +1,18 @@ +HTTP/1.1 200 OK +X-Frame-Options: SAMEORIGIN +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +X-Download-Options: noopen +X-Permitted-Cross-Domain-Policies: none +Referrer-Policy: strict-origin-when-cross-origin +Content-Type: application/vnd.api+json +Cache-Control: no-store, must-revalidate, private, max-age=0 +X-Request-Id: c77d5c6f-e932-4d60-ada1-41aea6fda503 +X-Runtime: 0.161034 +Vary: Origin +X-MiniProfiler-Original-Cache-Control: max-age=0, private, must-revalidate +X-MiniProfiler-Ids: z37vj9bnjbs5axnpibhz,zefd3e9hcd9u3w0c0y3g,m6epucidfi055lx60z1z,kd9eqlh6f36or8r6gfav,vjl0yz1jnm9ki7arr1ej,wszgceac9sgn0jl5rx71,uo03fw227ne416z4s47p,g1waecks8hogp977ck3y,psonsyz3b2zjyfuh9z3r,uvj2z64xujm35luv0cv6 +Set-Cookie: __profilin=p%3Dt; path=/; HttpOnly; SameSite=Lax +Transfer-Encoding: chunked + +{"data":[{"id":"1","type":"plates","links":{"self":"http://localhost:3000/api/v2/plates/1"},"attributes":{"uuid":"769d93b8-9a21-11ec-9a02-acde48001122","name":"Plate DN9000001W","labware_barcode":{"ean13_barcode":"1229000001872","machine_barcode":"DN9000001W","human_barcode":"DN9000001W"},"state":"pending","created_at":"2022-03-02T12:08:25+00:00","updated_at":"2022-03-02T12:08:25+00:00","number_of_rows":8,"number_of_columns":12,"size":96},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/purpose","related":"http://localhost:3000/api/v2/plates/1/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/plates/1/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/samples","related":"http://localhost:3000/api/v2/plates/1/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/studies","related":"http://localhost:3000/api/v2/plates/1/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/projects","related":"http://localhost:3000/api/v2/plates/1/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/comments","related":"http://localhost:3000/api/v2/plates/1/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/receptacles","related":"http://localhost:3000/api/v2/plates/1/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/ancestors","related":"http://localhost:3000/api/v2/plates/1/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/descendants","related":"http://localhost:3000/api/v2/plates/1/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/parents","related":"http://localhost:3000/api/v2/plates/1/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/children","related":"http://localhost:3000/api/v2/plates/1/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/child_plates","related":"http://localhost:3000/api/v2/plates/1/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/child_tubes","related":"http://localhost:3000/api/v2/plates/1/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/direct_submissions","related":"http://localhost:3000/api/v2/plates/1/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/state_changes","related":"http://localhost:3000/api/v2/plates/1/state_changes"}},"wells":{"links":{"self":"http://localhost:3000/api/v2/plates/1/relationships/wells","related":"http://localhost:3000/api/v2/plates/1/wells"},"data":[{"type":"wells","id":"1"},{"type":"wells","id":"2"},{"type":"wells","id":"3"},{"type":"wells","id":"4"},{"type":"wells","id":"5"},{"type":"wells","id":"6"},{"type":"wells","id":"7"},{"type":"wells","id":"8"},{"type":"wells","id":"9"},{"type":"wells","id":"10"},{"type":"wells","id":"11"},{"type":"wells","id":"12"},{"type":"wells","id":"13"},{"type":"wells","id":"14"},{"type":"wells","id":"15"},{"type":"wells","id":"16"},{"type":"wells","id":"17"},{"type":"wells","id":"18"},{"type":"wells","id":"19"},{"type":"wells","id":"20"},{"type":"wells","id":"21"},{"type":"wells","id":"22"},{"type":"wells","id":"23"},{"type":"wells","id":"24"},{"type":"wells","id":"25"},{"type":"wells","id":"26"},{"type":"wells","id":"27"},{"type":"wells","id":"28"},{"type":"wells","id":"29"},{"type":"wells","id":"30"},{"type":"wells","id":"31"},{"type":"wells","id":"32"},{"type":"wells","id":"33"},{"type":"wells","id":"34"},{"type":"wells","id":"35"},{"type":"wells","id":"36"},{"type":"wells","id":"37"},{"type":"wells","id":"38"},{"type":"wells","id":"39"},{"type":"wells","id":"40"},{"type":"wells","id":"41"},{"type":"wells","id":"42"},{"type":"wells","id":"43"},{"type":"wells","id":"44"},{"type":"wells","id":"45"},{"type":"wells","id":"46"},{"type":"wells","id":"47"},{"type":"wells","id":"48"},{"type":"wells","id":"49"},{"type":"wells","id":"50"},{"type":"wells","id":"51"},{"type":"wells","id":"52"},{"type":"wells","id":"53"},{"type":"wells","id":"54"},{"type":"wells","id":"55"},{"type":"wells","id":"56"},{"type":"wells","id":"57"},{"type":"wells","id":"58"},{"type":"wells","id":"59"},{"type":"wells","id":"60"},{"type":"wells","id":"61"},{"type":"wells","id":"62"},{"type":"wells","id":"63"},{"type":"wells","id":"64"},{"type":"wells","id":"65"},{"type":"wells","id":"66"},{"type":"wells","id":"67"},{"type":"wells","id":"68"},{"type":"wells","id":"69"},{"type":"wells","id":"70"},{"type":"wells","id":"71"},{"type":"wells","id":"72"},{"type":"wells","id":"73"},{"type":"wells","id":"74"},{"type":"wells","id":"75"},{"type":"wells","id":"76"},{"type":"wells","id":"77"},{"type":"wells","id":"78"},{"type":"wells","id":"79"},{"type":"wells","id":"80"},{"type":"wells","id":"81"},{"type":"wells","id":"82"},{"type":"wells","id":"83"},{"type":"wells","id":"84"},{"type":"wells","id":"85"},{"type":"wells","id":"86"},{"type":"wells","id":"87"},{"type":"wells","id":"88"},{"type":"wells","id":"89"},{"type":"wells","id":"90"},{"type":"wells","id":"91"},{"type":"wells","id":"92"},{"type":"wells","id":"93"},{"type":"wells","id":"94"},{"type":"wells","id":"95"},{"type":"wells","id":"96"}]}}}],"included":[{"id":"1","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/1"},"attributes":{"uuid":"76c222fa-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/samples","related":"http://localhost:3000/api/v2/wells/1/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/studies","related":"http://localhost:3000/api/v2/wells/1/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/projects","related":"http://localhost:3000/api/v2/wells/1/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/1/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/1/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/1/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/1/aliquots"},"data":[{"type":"aliquots","id":"1"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/1/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/1/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/1/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/1/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/1/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/1/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/1/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/1/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/1/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/1/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/1/transfer_requests_as_target"}}}},{"id":"2","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/2"},"attributes":{"uuid":"76c224d0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/samples","related":"http://localhost:3000/api/v2/wells/2/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/studies","related":"http://localhost:3000/api/v2/wells/2/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/projects","related":"http://localhost:3000/api/v2/wells/2/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/2/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/2/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/2/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/2/aliquots"},"data":[{"type":"aliquots","id":"2"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/2/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/2/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/2/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/2/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/2/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/2/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/2/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/2/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/2/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/2/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/2/transfer_requests_as_target"}}}},{"id":"3","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/3"},"attributes":{"uuid":"76c2278c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/samples","related":"http://localhost:3000/api/v2/wells/3/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/studies","related":"http://localhost:3000/api/v2/wells/3/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/projects","related":"http://localhost:3000/api/v2/wells/3/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/3/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/3/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/3/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/3/aliquots"},"data":[{"type":"aliquots","id":"3"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/3/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/3/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/3/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/3/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/3/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/3/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/3/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/3/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/3/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/3/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/3/transfer_requests_as_target"}}}},{"id":"4","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/4"},"attributes":{"uuid":"76c22a98-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/samples","related":"http://localhost:3000/api/v2/wells/4/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/studies","related":"http://localhost:3000/api/v2/wells/4/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/projects","related":"http://localhost:3000/api/v2/wells/4/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/4/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/4/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/4/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/4/aliquots"},"data":[{"type":"aliquots","id":"4"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/4/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/4/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/4/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/4/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/4/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/4/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/4/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/4/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/4/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/4/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/4/transfer_requests_as_target"}}}},{"id":"5","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/5"},"attributes":{"uuid":"76c22b1a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/samples","related":"http://localhost:3000/api/v2/wells/5/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/studies","related":"http://localhost:3000/api/v2/wells/5/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/projects","related":"http://localhost:3000/api/v2/wells/5/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/5/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/5/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/5/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/5/aliquots"},"data":[{"type":"aliquots","id":"5"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/5/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/5/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/5/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/5/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/5/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/5/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/5/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/5/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/5/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/5/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/5/transfer_requests_as_target"}}}},{"id":"6","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/6"},"attributes":{"uuid":"76c22c50-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/samples","related":"http://localhost:3000/api/v2/wells/6/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/studies","related":"http://localhost:3000/api/v2/wells/6/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/projects","related":"http://localhost:3000/api/v2/wells/6/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/6/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/6/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/6/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/6/aliquots"},"data":[{"type":"aliquots","id":"6"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/6/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/6/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/6/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/6/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/6/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/6/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/6/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/6/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/6/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/6/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/6/transfer_requests_as_target"}}}},{"id":"7","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/7"},"attributes":{"uuid":"76c22cc8-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/samples","related":"http://localhost:3000/api/v2/wells/7/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/studies","related":"http://localhost:3000/api/v2/wells/7/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/projects","related":"http://localhost:3000/api/v2/wells/7/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/7/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/7/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/7/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/7/aliquots"},"data":[{"type":"aliquots","id":"7"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/7/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/7/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/7/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/7/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/7/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/7/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/7/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/7/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/7/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/7/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/7/transfer_requests_as_target"}}}},{"id":"8","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/8"},"attributes":{"uuid":"76c22ebc-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/samples","related":"http://localhost:3000/api/v2/wells/8/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/studies","related":"http://localhost:3000/api/v2/wells/8/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/projects","related":"http://localhost:3000/api/v2/wells/8/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/8/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/8/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/8/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/8/aliquots"},"data":[{"type":"aliquots","id":"8"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/8/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/8/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/8/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/8/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/8/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/8/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/8/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/8/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/8/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/8/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/8/transfer_requests_as_target"}}}},{"id":"9","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/9"},"attributes":{"uuid":"76c22fde-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/samples","related":"http://localhost:3000/api/v2/wells/9/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/studies","related":"http://localhost:3000/api/v2/wells/9/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/projects","related":"http://localhost:3000/api/v2/wells/9/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/9/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/9/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/9/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/9/aliquots"},"data":[{"type":"aliquots","id":"9"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/9/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/9/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/9/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/9/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/9/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/9/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/9/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/9/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/9/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/9/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/9/transfer_requests_as_target"}}}},{"id":"10","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/10"},"attributes":{"uuid":"76c23592-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/samples","related":"http://localhost:3000/api/v2/wells/10/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/studies","related":"http://localhost:3000/api/v2/wells/10/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/projects","related":"http://localhost:3000/api/v2/wells/10/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/10/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/10/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/10/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/10/aliquots"},"data":[{"type":"aliquots","id":"10"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/10/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/10/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/10/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/10/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/10/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/10/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/10/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/10/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/10/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/10/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/10/transfer_requests_as_target"}}}},{"id":"11","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/11"},"attributes":{"uuid":"76c23808-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/samples","related":"http://localhost:3000/api/v2/wells/11/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/studies","related":"http://localhost:3000/api/v2/wells/11/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/projects","related":"http://localhost:3000/api/v2/wells/11/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/11/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/11/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/11/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/11/aliquots"},"data":[{"type":"aliquots","id":"11"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/11/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/11/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/11/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/11/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/11/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/11/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/11/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/11/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/11/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/11/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/11/transfer_requests_as_target"}}}},{"id":"12","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/12"},"attributes":{"uuid":"76c23ba0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:A12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"A12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/samples","related":"http://localhost:3000/api/v2/wells/12/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/studies","related":"http://localhost:3000/api/v2/wells/12/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/projects","related":"http://localhost:3000/api/v2/wells/12/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/12/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/12/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/12/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/12/aliquots"},"data":[{"type":"aliquots","id":"12"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/12/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/12/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/12/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/12/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/12/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/12/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/12/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/12/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/12/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/12/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/12/transfer_requests_as_target"}}}},{"id":"13","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/13"},"attributes":{"uuid":"76c23ccc-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/samples","related":"http://localhost:3000/api/v2/wells/13/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/studies","related":"http://localhost:3000/api/v2/wells/13/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/projects","related":"http://localhost:3000/api/v2/wells/13/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/13/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/13/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/13/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/13/aliquots"},"data":[{"type":"aliquots","id":"13"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/13/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/13/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/13/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/13/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/13/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/13/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/13/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/13/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/13/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/13/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/13/transfer_requests_as_target"}}}},{"id":"14","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/14"},"attributes":{"uuid":"76c23d4e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/samples","related":"http://localhost:3000/api/v2/wells/14/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/studies","related":"http://localhost:3000/api/v2/wells/14/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/projects","related":"http://localhost:3000/api/v2/wells/14/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/14/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/14/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/14/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/14/aliquots"},"data":[{"type":"aliquots","id":"14"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/14/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/14/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/14/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/14/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/14/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/14/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/14/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/14/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/14/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/14/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/14/transfer_requests_as_target"}}}},{"id":"15","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/15"},"attributes":{"uuid":"76c23dc6-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/samples","related":"http://localhost:3000/api/v2/wells/15/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/studies","related":"http://localhost:3000/api/v2/wells/15/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/projects","related":"http://localhost:3000/api/v2/wells/15/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/15/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/15/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/15/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/15/aliquots"},"data":[{"type":"aliquots","id":"15"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/15/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/15/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/15/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/15/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/15/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/15/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/15/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/15/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/15/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/15/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/15/transfer_requests_as_target"}}}},{"id":"16","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/16"},"attributes":{"uuid":"76c23f56-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/samples","related":"http://localhost:3000/api/v2/wells/16/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/studies","related":"http://localhost:3000/api/v2/wells/16/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/projects","related":"http://localhost:3000/api/v2/wells/16/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/16/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/16/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/16/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/16/aliquots"},"data":[{"type":"aliquots","id":"16"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/16/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/16/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/16/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/16/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/16/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/16/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/16/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/16/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/16/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/16/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/16/transfer_requests_as_target"}}}},{"id":"17","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/17"},"attributes":{"uuid":"76c23fce-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/samples","related":"http://localhost:3000/api/v2/wells/17/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/studies","related":"http://localhost:3000/api/v2/wells/17/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/projects","related":"http://localhost:3000/api/v2/wells/17/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/17/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/17/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/17/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/17/aliquots"},"data":[{"type":"aliquots","id":"17"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/17/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/17/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/17/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/17/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/17/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/17/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/17/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/17/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/17/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/17/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/17/transfer_requests_as_target"}}}},{"id":"18","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/18"},"attributes":{"uuid":"76c2403c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/samples","related":"http://localhost:3000/api/v2/wells/18/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/studies","related":"http://localhost:3000/api/v2/wells/18/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/projects","related":"http://localhost:3000/api/v2/wells/18/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/18/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/18/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/18/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/18/aliquots"},"data":[{"type":"aliquots","id":"18"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/18/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/18/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/18/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/18/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/18/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/18/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/18/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/18/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/18/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/18/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/18/transfer_requests_as_target"}}}},{"id":"19","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/19"},"attributes":{"uuid":"76c240aa-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/samples","related":"http://localhost:3000/api/v2/wells/19/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/studies","related":"http://localhost:3000/api/v2/wells/19/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/projects","related":"http://localhost:3000/api/v2/wells/19/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/19/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/19/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/19/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/19/aliquots"},"data":[{"type":"aliquots","id":"19"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/19/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/19/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/19/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/19/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/19/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/19/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/19/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/19/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/19/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/19/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/19/transfer_requests_as_target"}}}},{"id":"20","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/20"},"attributes":{"uuid":"76c241c2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/samples","related":"http://localhost:3000/api/v2/wells/20/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/studies","related":"http://localhost:3000/api/v2/wells/20/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/projects","related":"http://localhost:3000/api/v2/wells/20/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/20/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/20/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/20/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/20/aliquots"},"data":[{"type":"aliquots","id":"20"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/20/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/20/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/20/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/20/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/20/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/20/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/20/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/20/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/20/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/20/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/20/transfer_requests_as_target"}}}},{"id":"21","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/21"},"attributes":{"uuid":"76c24230-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/samples","related":"http://localhost:3000/api/v2/wells/21/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/studies","related":"http://localhost:3000/api/v2/wells/21/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/projects","related":"http://localhost:3000/api/v2/wells/21/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/21/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/21/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/21/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/21/aliquots"},"data":[{"type":"aliquots","id":"21"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/21/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/21/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/21/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/21/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/21/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/21/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/21/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/21/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/21/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/21/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/21/transfer_requests_as_target"}}}},{"id":"22","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/22"},"attributes":{"uuid":"76c2429e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/samples","related":"http://localhost:3000/api/v2/wells/22/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/studies","related":"http://localhost:3000/api/v2/wells/22/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/projects","related":"http://localhost:3000/api/v2/wells/22/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/22/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/22/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/22/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/22/aliquots"},"data":[{"type":"aliquots","id":"22"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/22/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/22/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/22/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/22/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/22/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/22/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/22/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/22/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/22/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/22/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/22/transfer_requests_as_target"}}}},{"id":"23","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/23"},"attributes":{"uuid":"76c2430c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/samples","related":"http://localhost:3000/api/v2/wells/23/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/studies","related":"http://localhost:3000/api/v2/wells/23/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/projects","related":"http://localhost:3000/api/v2/wells/23/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/23/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/23/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/23/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/23/aliquots"},"data":[{"type":"aliquots","id":"23"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/23/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/23/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/23/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/23/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/23/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/23/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/23/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/23/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/23/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/23/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/23/transfer_requests_as_target"}}}},{"id":"24","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/24"},"attributes":{"uuid":"76c244e2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:B12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"B12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/samples","related":"http://localhost:3000/api/v2/wells/24/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/studies","related":"http://localhost:3000/api/v2/wells/24/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/projects","related":"http://localhost:3000/api/v2/wells/24/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/24/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/24/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/24/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/24/aliquots"},"data":[{"type":"aliquots","id":"24"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/24/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/24/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/24/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/24/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/24/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/24/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/24/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/24/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/24/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/24/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/24/transfer_requests_as_target"}}}},{"id":"25","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/25"},"attributes":{"uuid":"76c2455a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/samples","related":"http://localhost:3000/api/v2/wells/25/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/studies","related":"http://localhost:3000/api/v2/wells/25/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/projects","related":"http://localhost:3000/api/v2/wells/25/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/25/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/25/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/25/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/25/aliquots"},"data":[{"type":"aliquots","id":"25"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/25/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/25/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/25/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/25/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/25/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/25/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/25/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/25/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/25/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/25/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/25/transfer_requests_as_target"}}}},{"id":"26","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/26"},"attributes":{"uuid":"76c245d2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/samples","related":"http://localhost:3000/api/v2/wells/26/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/studies","related":"http://localhost:3000/api/v2/wells/26/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/projects","related":"http://localhost:3000/api/v2/wells/26/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/26/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/26/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/26/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/26/aliquots"},"data":[{"type":"aliquots","id":"26"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/26/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/26/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/26/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/26/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/26/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/26/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/26/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/26/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/26/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/26/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/26/transfer_requests_as_target"}}}},{"id":"27","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/27"},"attributes":{"uuid":"76c24988-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/samples","related":"http://localhost:3000/api/v2/wells/27/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/studies","related":"http://localhost:3000/api/v2/wells/27/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/projects","related":"http://localhost:3000/api/v2/wells/27/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/27/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/27/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/27/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/27/aliquots"},"data":[{"type":"aliquots","id":"27"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/27/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/27/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/27/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/27/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/27/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/27/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/27/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/27/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/27/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/27/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/27/transfer_requests_as_target"}}}},{"id":"28","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/28"},"attributes":{"uuid":"76c24aa0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/samples","related":"http://localhost:3000/api/v2/wells/28/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/studies","related":"http://localhost:3000/api/v2/wells/28/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/projects","related":"http://localhost:3000/api/v2/wells/28/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/28/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/28/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/28/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/28/aliquots"},"data":[{"type":"aliquots","id":"28"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/28/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/28/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/28/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/28/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/28/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/28/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/28/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/28/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/28/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/28/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/28/transfer_requests_as_target"}}}},{"id":"29","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/29"},"attributes":{"uuid":"76c24b18-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/samples","related":"http://localhost:3000/api/v2/wells/29/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/studies","related":"http://localhost:3000/api/v2/wells/29/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/projects","related":"http://localhost:3000/api/v2/wells/29/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/29/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/29/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/29/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/29/aliquots"},"data":[{"type":"aliquots","id":"29"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/29/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/29/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/29/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/29/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/29/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/29/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/29/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/29/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/29/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/29/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/29/transfer_requests_as_target"}}}},{"id":"30","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/30"},"attributes":{"uuid":"76c24c44-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/samples","related":"http://localhost:3000/api/v2/wells/30/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/studies","related":"http://localhost:3000/api/v2/wells/30/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/projects","related":"http://localhost:3000/api/v2/wells/30/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/30/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/30/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/30/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/30/aliquots"},"data":[{"type":"aliquots","id":"30"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/30/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/30/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/30/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/30/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/30/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/30/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/30/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/30/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/30/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/30/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/30/transfer_requests_as_target"}}}},{"id":"31","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/31"},"attributes":{"uuid":"76c24e38-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/samples","related":"http://localhost:3000/api/v2/wells/31/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/studies","related":"http://localhost:3000/api/v2/wells/31/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/projects","related":"http://localhost:3000/api/v2/wells/31/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/31/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/31/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/31/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/31/aliquots"},"data":[{"type":"aliquots","id":"31"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/31/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/31/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/31/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/31/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/31/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/31/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/31/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/31/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/31/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/31/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/31/transfer_requests_as_target"}}}},{"id":"32","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/32"},"attributes":{"uuid":"76c24f78-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/samples","related":"http://localhost:3000/api/v2/wells/32/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/studies","related":"http://localhost:3000/api/v2/wells/32/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/projects","related":"http://localhost:3000/api/v2/wells/32/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/32/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/32/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/32/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/32/aliquots"},"data":[{"type":"aliquots","id":"32"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/32/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/32/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/32/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/32/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/32/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/32/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/32/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/32/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/32/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/32/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/32/transfer_requests_as_target"}}}},{"id":"33","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/33"},"attributes":{"uuid":"76c24fe6-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/samples","related":"http://localhost:3000/api/v2/wells/33/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/studies","related":"http://localhost:3000/api/v2/wells/33/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/projects","related":"http://localhost:3000/api/v2/wells/33/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/33/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/33/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/33/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/33/aliquots"},"data":[{"type":"aliquots","id":"33"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/33/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/33/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/33/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/33/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/33/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/33/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/33/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/33/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/33/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/33/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/33/transfer_requests_as_target"}}}},{"id":"34","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/34"},"attributes":{"uuid":"76c2537e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/samples","related":"http://localhost:3000/api/v2/wells/34/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/studies","related":"http://localhost:3000/api/v2/wells/34/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/projects","related":"http://localhost:3000/api/v2/wells/34/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/34/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/34/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/34/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/34/aliquots"},"data":[{"type":"aliquots","id":"34"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/34/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/34/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/34/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/34/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/34/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/34/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/34/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/34/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/34/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/34/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/34/transfer_requests_as_target"}}}},{"id":"35","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/35"},"attributes":{"uuid":"76c255a4-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/samples","related":"http://localhost:3000/api/v2/wells/35/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/studies","related":"http://localhost:3000/api/v2/wells/35/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/projects","related":"http://localhost:3000/api/v2/wells/35/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/35/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/35/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/35/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/35/aliquots"},"data":[{"type":"aliquots","id":"35"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/35/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/35/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/35/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/35/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/35/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/35/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/35/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/35/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/35/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/35/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/35/transfer_requests_as_target"}}}},{"id":"36","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/36"},"attributes":{"uuid":"76c2590a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:C12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"C12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/samples","related":"http://localhost:3000/api/v2/wells/36/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/studies","related":"http://localhost:3000/api/v2/wells/36/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/projects","related":"http://localhost:3000/api/v2/wells/36/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/36/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/36/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/36/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/36/aliquots"},"data":[{"type":"aliquots","id":"36"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/36/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/36/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/36/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/36/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/36/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/36/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/36/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/36/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/36/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/36/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/36/transfer_requests_as_target"}}}},{"id":"37","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/37"},"attributes":{"uuid":"76c25a86-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/samples","related":"http://localhost:3000/api/v2/wells/37/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/studies","related":"http://localhost:3000/api/v2/wells/37/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/projects","related":"http://localhost:3000/api/v2/wells/37/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/37/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/37/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/37/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/37/aliquots"},"data":[{"type":"aliquots","id":"37"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/37/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/37/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/37/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/37/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/37/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/37/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/37/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/37/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/37/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/37/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/37/transfer_requests_as_target"}}}},{"id":"38","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/38"},"attributes":{"uuid":"76c25cc0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/samples","related":"http://localhost:3000/api/v2/wells/38/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/studies","related":"http://localhost:3000/api/v2/wells/38/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/projects","related":"http://localhost:3000/api/v2/wells/38/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/38/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/38/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/38/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/38/aliquots"},"data":[{"type":"aliquots","id":"38"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/38/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/38/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/38/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/38/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/38/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/38/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/38/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/38/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/38/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/38/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/38/transfer_requests_as_target"}}}},{"id":"39","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/39"},"attributes":{"uuid":"76c25d4c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/samples","related":"http://localhost:3000/api/v2/wells/39/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/studies","related":"http://localhost:3000/api/v2/wells/39/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/projects","related":"http://localhost:3000/api/v2/wells/39/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/39/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/39/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/39/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/39/aliquots"},"data":[{"type":"aliquots","id":"39"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/39/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/39/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/39/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/39/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/39/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/39/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/39/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/39/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/39/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/39/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/39/transfer_requests_as_target"}}}},{"id":"40","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/40"},"attributes":{"uuid":"76c25dc4-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/samples","related":"http://localhost:3000/api/v2/wells/40/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/studies","related":"http://localhost:3000/api/v2/wells/40/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/projects","related":"http://localhost:3000/api/v2/wells/40/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/40/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/40/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/40/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/40/aliquots"},"data":[{"type":"aliquots","id":"40"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/40/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/40/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/40/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/40/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/40/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/40/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/40/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/40/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/40/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/40/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/40/transfer_requests_as_target"}}}},{"id":"41","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/41"},"attributes":{"uuid":"76c25e3c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/samples","related":"http://localhost:3000/api/v2/wells/41/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/studies","related":"http://localhost:3000/api/v2/wells/41/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/projects","related":"http://localhost:3000/api/v2/wells/41/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/41/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/41/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/41/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/41/aliquots"},"data":[{"type":"aliquots","id":"41"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/41/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/41/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/41/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/41/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/41/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/41/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/41/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/41/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/41/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/41/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/41/transfer_requests_as_target"}}}},{"id":"42","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/42"},"attributes":{"uuid":"76c25eb4-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/samples","related":"http://localhost:3000/api/v2/wells/42/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/studies","related":"http://localhost:3000/api/v2/wells/42/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/projects","related":"http://localhost:3000/api/v2/wells/42/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/42/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/42/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/42/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/42/aliquots"},"data":[{"type":"aliquots","id":"42"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/42/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/42/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/42/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/42/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/42/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/42/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/42/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/42/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/42/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/42/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/42/transfer_requests_as_target"}}}},{"id":"43","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/43"},"attributes":{"uuid":"76c2603a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/samples","related":"http://localhost:3000/api/v2/wells/43/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/studies","related":"http://localhost:3000/api/v2/wells/43/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/projects","related":"http://localhost:3000/api/v2/wells/43/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/43/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/43/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/43/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/43/aliquots"},"data":[{"type":"aliquots","id":"43"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/43/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/43/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/43/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/43/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/43/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/43/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/43/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/43/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/43/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/43/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/43/transfer_requests_as_target"}}}},{"id":"44","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/44"},"attributes":{"uuid":"76c260b2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/samples","related":"http://localhost:3000/api/v2/wells/44/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/studies","related":"http://localhost:3000/api/v2/wells/44/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/projects","related":"http://localhost:3000/api/v2/wells/44/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/44/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/44/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/44/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/44/aliquots"},"data":[{"type":"aliquots","id":"44"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/44/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/44/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/44/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/44/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/44/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/44/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/44/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/44/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/44/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/44/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/44/transfer_requests_as_target"}}}},{"id":"45","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/45"},"attributes":{"uuid":"76c2612a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/samples","related":"http://localhost:3000/api/v2/wells/45/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/studies","related":"http://localhost:3000/api/v2/wells/45/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/projects","related":"http://localhost:3000/api/v2/wells/45/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/45/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/45/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/45/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/45/aliquots"},"data":[{"type":"aliquots","id":"45"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/45/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/45/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/45/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/45/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/45/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/45/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/45/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/45/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/45/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/45/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/45/transfer_requests_as_target"}}}},{"id":"46","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/46"},"attributes":{"uuid":"76c26198-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/samples","related":"http://localhost:3000/api/v2/wells/46/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/studies","related":"http://localhost:3000/api/v2/wells/46/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/projects","related":"http://localhost:3000/api/v2/wells/46/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/46/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/46/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/46/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/46/aliquots"},"data":[{"type":"aliquots","id":"46"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/46/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/46/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/46/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/46/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/46/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/46/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/46/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/46/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/46/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/46/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/46/transfer_requests_as_target"}}}},{"id":"47","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/47"},"attributes":{"uuid":"76c262ec-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/samples","related":"http://localhost:3000/api/v2/wells/47/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/studies","related":"http://localhost:3000/api/v2/wells/47/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/projects","related":"http://localhost:3000/api/v2/wells/47/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/47/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/47/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/47/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/47/aliquots"},"data":[{"type":"aliquots","id":"47"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/47/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/47/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/47/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/47/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/47/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/47/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/47/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/47/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/47/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/47/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/47/transfer_requests_as_target"}}}},{"id":"48","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/48"},"attributes":{"uuid":"76c2635a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:D12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"D12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/samples","related":"http://localhost:3000/api/v2/wells/48/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/studies","related":"http://localhost:3000/api/v2/wells/48/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/projects","related":"http://localhost:3000/api/v2/wells/48/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/48/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/48/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/48/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/48/aliquots"},"data":[{"type":"aliquots","id":"48"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/48/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/48/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/48/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/48/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/48/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/48/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/48/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/48/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/48/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/48/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/48/transfer_requests_as_target"}}}},{"id":"49","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/49"},"attributes":{"uuid":"76c263d2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/samples","related":"http://localhost:3000/api/v2/wells/49/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/studies","related":"http://localhost:3000/api/v2/wells/49/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/projects","related":"http://localhost:3000/api/v2/wells/49/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/49/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/49/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/49/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/49/aliquots"},"data":[{"type":"aliquots","id":"49"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/49/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/49/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/49/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/49/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/49/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/49/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/49/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/49/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/49/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/49/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/49/transfer_requests_as_target"}}}},{"id":"50","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/50"},"attributes":{"uuid":"76c264ea-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/samples","related":"http://localhost:3000/api/v2/wells/50/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/studies","related":"http://localhost:3000/api/v2/wells/50/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/projects","related":"http://localhost:3000/api/v2/wells/50/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/50/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/50/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/50/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/50/aliquots"},"data":[{"type":"aliquots","id":"50"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/50/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/50/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/50/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/50/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/50/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/50/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/50/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/50/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/50/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/50/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/50/transfer_requests_as_target"}}}},{"id":"51","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/51"},"attributes":{"uuid":"76c26562-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/samples","related":"http://localhost:3000/api/v2/wells/51/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/studies","related":"http://localhost:3000/api/v2/wells/51/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/projects","related":"http://localhost:3000/api/v2/wells/51/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/51/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/51/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/51/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/51/aliquots"},"data":[{"type":"aliquots","id":"51"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/51/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/51/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/51/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/51/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/51/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/51/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/51/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/51/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/51/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/51/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/51/transfer_requests_as_target"}}}},{"id":"52","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/52"},"attributes":{"uuid":"76c265d0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/samples","related":"http://localhost:3000/api/v2/wells/52/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/studies","related":"http://localhost:3000/api/v2/wells/52/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/projects","related":"http://localhost:3000/api/v2/wells/52/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/52/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/52/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/52/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/52/aliquots"},"data":[{"type":"aliquots","id":"52"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/52/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/52/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/52/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/52/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/52/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/52/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/52/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/52/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/52/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/52/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/52/transfer_requests_as_target"}}}},{"id":"53","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/53"},"attributes":{"uuid":"76c26878-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/samples","related":"http://localhost:3000/api/v2/wells/53/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/studies","related":"http://localhost:3000/api/v2/wells/53/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/projects","related":"http://localhost:3000/api/v2/wells/53/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/53/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/53/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/53/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/53/aliquots"},"data":[{"type":"aliquots","id":"53"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/53/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/53/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/53/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/53/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/53/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/53/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/53/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/53/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/53/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/53/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/53/transfer_requests_as_target"}}}},{"id":"54","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/54"},"attributes":{"uuid":"76c26904-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/samples","related":"http://localhost:3000/api/v2/wells/54/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/studies","related":"http://localhost:3000/api/v2/wells/54/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/projects","related":"http://localhost:3000/api/v2/wells/54/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/54/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/54/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/54/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/54/aliquots"},"data":[{"type":"aliquots","id":"54"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/54/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/54/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/54/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/54/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/54/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/54/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/54/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/54/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/54/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/54/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/54/transfer_requests_as_target"}}}},{"id":"55","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/55"},"attributes":{"uuid":"76c26a3a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/samples","related":"http://localhost:3000/api/v2/wells/55/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/studies","related":"http://localhost:3000/api/v2/wells/55/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/projects","related":"http://localhost:3000/api/v2/wells/55/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/55/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/55/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/55/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/55/aliquots"},"data":[{"type":"aliquots","id":"55"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/55/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/55/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/55/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/55/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/55/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/55/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/55/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/55/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/55/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/55/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/55/transfer_requests_as_target"}}}},{"id":"56","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/56"},"attributes":{"uuid":"76c26bac-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/samples","related":"http://localhost:3000/api/v2/wells/56/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/studies","related":"http://localhost:3000/api/v2/wells/56/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/projects","related":"http://localhost:3000/api/v2/wells/56/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/56/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/56/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/56/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/56/aliquots"},"data":[{"type":"aliquots","id":"56"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/56/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/56/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/56/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/56/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/56/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/56/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/56/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/56/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/56/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/56/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/56/transfer_requests_as_target"}}}},{"id":"57","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/57"},"attributes":{"uuid":"76c26c2e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/samples","related":"http://localhost:3000/api/v2/wells/57/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/studies","related":"http://localhost:3000/api/v2/wells/57/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/projects","related":"http://localhost:3000/api/v2/wells/57/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/57/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/57/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/57/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/57/aliquots"},"data":[{"type":"aliquots","id":"57"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/57/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/57/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/57/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/57/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/57/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/57/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/57/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/57/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/57/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/57/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/57/transfer_requests_as_target"}}}},{"id":"58","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/58"},"attributes":{"uuid":"76c26c9c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/samples","related":"http://localhost:3000/api/v2/wells/58/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/studies","related":"http://localhost:3000/api/v2/wells/58/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/projects","related":"http://localhost:3000/api/v2/wells/58/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/58/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/58/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/58/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/58/aliquots"},"data":[{"type":"aliquots","id":"58"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/58/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/58/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/58/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/58/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/58/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/58/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/58/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/58/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/58/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/58/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/58/transfer_requests_as_target"}}}},{"id":"59","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/59"},"attributes":{"uuid":"76c26d0a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/samples","related":"http://localhost:3000/api/v2/wells/59/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/studies","related":"http://localhost:3000/api/v2/wells/59/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/projects","related":"http://localhost:3000/api/v2/wells/59/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/59/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/59/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/59/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/59/aliquots"},"data":[{"type":"aliquots","id":"59"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/59/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/59/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/59/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/59/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/59/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/59/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/59/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/59/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/59/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/59/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/59/transfer_requests_as_target"}}}},{"id":"60","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/60"},"attributes":{"uuid":"76c26e72-9a21-11ec-9a02-acde48001122","name":"DN9000001W:E12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"E12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/samples","related":"http://localhost:3000/api/v2/wells/60/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/studies","related":"http://localhost:3000/api/v2/wells/60/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/projects","related":"http://localhost:3000/api/v2/wells/60/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/60/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/60/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/60/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/60/aliquots"},"data":[{"type":"aliquots","id":"60"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/60/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/60/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/60/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/60/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/60/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/60/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/60/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/60/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/60/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/60/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/60/transfer_requests_as_target"}}}},{"id":"61","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/61"},"attributes":{"uuid":"76c26eea-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/samples","related":"http://localhost:3000/api/v2/wells/61/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/studies","related":"http://localhost:3000/api/v2/wells/61/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/projects","related":"http://localhost:3000/api/v2/wells/61/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/61/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/61/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/61/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/61/aliquots"},"data":[{"type":"aliquots","id":"61"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/61/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/61/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/61/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/61/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/61/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/61/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/61/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/61/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/61/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/61/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/61/transfer_requests_as_target"}}}},{"id":"62","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/62"},"attributes":{"uuid":"76c26f62-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/samples","related":"http://localhost:3000/api/v2/wells/62/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/studies","related":"http://localhost:3000/api/v2/wells/62/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/projects","related":"http://localhost:3000/api/v2/wells/62/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/62/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/62/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/62/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/62/aliquots"},"data":[{"type":"aliquots","id":"62"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/62/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/62/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/62/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/62/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/62/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/62/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/62/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/62/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/62/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/62/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/62/transfer_requests_as_target"}}}},{"id":"63","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/63"},"attributes":{"uuid":"76c27200-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/samples","related":"http://localhost:3000/api/v2/wells/63/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/studies","related":"http://localhost:3000/api/v2/wells/63/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/projects","related":"http://localhost:3000/api/v2/wells/63/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/63/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/63/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/63/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/63/aliquots"},"data":[{"type":"aliquots","id":"63"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/63/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/63/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/63/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/63/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/63/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/63/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/63/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/63/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/63/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/63/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/63/transfer_requests_as_target"}}}},{"id":"64","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/64"},"attributes":{"uuid":"76c273cc-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/samples","related":"http://localhost:3000/api/v2/wells/64/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/studies","related":"http://localhost:3000/api/v2/wells/64/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/projects","related":"http://localhost:3000/api/v2/wells/64/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/64/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/64/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/64/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/64/aliquots"},"data":[{"type":"aliquots","id":"64"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/64/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/64/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/64/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/64/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/64/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/64/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/64/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/64/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/64/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/64/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/64/transfer_requests_as_target"}}}},{"id":"65","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/65"},"attributes":{"uuid":"76c27494-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/samples","related":"http://localhost:3000/api/v2/wells/65/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/studies","related":"http://localhost:3000/api/v2/wells/65/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/projects","related":"http://localhost:3000/api/v2/wells/65/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/65/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/65/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/65/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/65/aliquots"},"data":[{"type":"aliquots","id":"65"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/65/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/65/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/65/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/65/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/65/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/65/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/65/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/65/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/65/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/65/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/65/transfer_requests_as_target"}}}},{"id":"66","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/66"},"attributes":{"uuid":"76c2750c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/samples","related":"http://localhost:3000/api/v2/wells/66/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/studies","related":"http://localhost:3000/api/v2/wells/66/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/projects","related":"http://localhost:3000/api/v2/wells/66/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/66/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/66/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/66/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/66/aliquots"},"data":[{"type":"aliquots","id":"66"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/66/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/66/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/66/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/66/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/66/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/66/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/66/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/66/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/66/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/66/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/66/transfer_requests_as_target"}}}},{"id":"67","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/67"},"attributes":{"uuid":"76c276a6-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/samples","related":"http://localhost:3000/api/v2/wells/67/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/studies","related":"http://localhost:3000/api/v2/wells/67/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/projects","related":"http://localhost:3000/api/v2/wells/67/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/67/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/67/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/67/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/67/aliquots"},"data":[{"type":"aliquots","id":"67"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/67/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/67/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/67/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/67/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/67/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/67/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/67/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/67/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/67/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/67/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/67/transfer_requests_as_target"}}}},{"id":"68","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/68"},"attributes":{"uuid":"76c278ea-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/samples","related":"http://localhost:3000/api/v2/wells/68/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/studies","related":"http://localhost:3000/api/v2/wells/68/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/projects","related":"http://localhost:3000/api/v2/wells/68/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/68/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/68/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/68/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/68/aliquots"},"data":[{"type":"aliquots","id":"68"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/68/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/68/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/68/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/68/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/68/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/68/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/68/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/68/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/68/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/68/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/68/transfer_requests_as_target"}}}},{"id":"69","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/69"},"attributes":{"uuid":"76c27980-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/samples","related":"http://localhost:3000/api/v2/wells/69/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/studies","related":"http://localhost:3000/api/v2/wells/69/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/projects","related":"http://localhost:3000/api/v2/wells/69/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/69/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/69/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/69/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/69/aliquots"},"data":[{"type":"aliquots","id":"69"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/69/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/69/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/69/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/69/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/69/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/69/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/69/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/69/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/69/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/69/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/69/transfer_requests_as_target"}}}},{"id":"70","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/70"},"attributes":{"uuid":"76c27a02-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/samples","related":"http://localhost:3000/api/v2/wells/70/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/studies","related":"http://localhost:3000/api/v2/wells/70/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/projects","related":"http://localhost:3000/api/v2/wells/70/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/70/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/70/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/70/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/70/aliquots"},"data":[{"type":"aliquots","id":"70"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/70/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/70/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/70/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/70/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/70/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/70/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/70/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/70/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/70/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/70/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/70/transfer_requests_as_target"}}}},{"id":"71","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/71"},"attributes":{"uuid":"76c27c6e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/samples","related":"http://localhost:3000/api/v2/wells/71/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/studies","related":"http://localhost:3000/api/v2/wells/71/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/projects","related":"http://localhost:3000/api/v2/wells/71/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/71/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/71/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/71/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/71/aliquots"},"data":[{"type":"aliquots","id":"71"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/71/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/71/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/71/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/71/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/71/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/71/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/71/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/71/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/71/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/71/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/71/transfer_requests_as_target"}}}},{"id":"72","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/72"},"attributes":{"uuid":"76c27d72-9a21-11ec-9a02-acde48001122","name":"DN9000001W:F12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"F12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/samples","related":"http://localhost:3000/api/v2/wells/72/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/studies","related":"http://localhost:3000/api/v2/wells/72/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/projects","related":"http://localhost:3000/api/v2/wells/72/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/72/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/72/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/72/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/72/aliquots"},"data":[{"type":"aliquots","id":"72"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/72/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/72/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/72/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/72/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/72/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/72/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/72/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/72/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/72/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/72/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/72/transfer_requests_as_target"}}}},{"id":"73","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/73"},"attributes":{"uuid":"76c27fde-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/samples","related":"http://localhost:3000/api/v2/wells/73/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/studies","related":"http://localhost:3000/api/v2/wells/73/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/projects","related":"http://localhost:3000/api/v2/wells/73/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/73/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/73/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/73/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/73/aliquots"},"data":[{"type":"aliquots","id":"73"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/73/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/73/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/73/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/73/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/73/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/73/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/73/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/73/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/73/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/73/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/73/transfer_requests_as_target"}}}},{"id":"74","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/74"},"attributes":{"uuid":"76c2810a-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/samples","related":"http://localhost:3000/api/v2/wells/74/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/studies","related":"http://localhost:3000/api/v2/wells/74/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/projects","related":"http://localhost:3000/api/v2/wells/74/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/74/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/74/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/74/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/74/aliquots"},"data":[{"type":"aliquots","id":"74"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/74/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/74/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/74/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/74/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/74/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/74/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/74/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/74/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/74/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/74/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/74/transfer_requests_as_target"}}}},{"id":"75","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/75"},"attributes":{"uuid":"76c282e0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/samples","related":"http://localhost:3000/api/v2/wells/75/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/studies","related":"http://localhost:3000/api/v2/wells/75/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/projects","related":"http://localhost:3000/api/v2/wells/75/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/75/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/75/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/75/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/75/aliquots"},"data":[{"type":"aliquots","id":"75"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/75/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/75/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/75/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/75/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/75/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/75/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/75/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/75/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/75/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/75/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/75/transfer_requests_as_target"}}}},{"id":"76","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/76"},"attributes":{"uuid":"76c28358-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/samples","related":"http://localhost:3000/api/v2/wells/76/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/studies","related":"http://localhost:3000/api/v2/wells/76/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/projects","related":"http://localhost:3000/api/v2/wells/76/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/76/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/76/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/76/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/76/aliquots"},"data":[{"type":"aliquots","id":"76"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/76/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/76/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/76/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/76/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/76/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/76/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/76/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/76/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/76/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/76/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/76/transfer_requests_as_target"}}}},{"id":"77","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/77"},"attributes":{"uuid":"76c283d0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/samples","related":"http://localhost:3000/api/v2/wells/77/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/studies","related":"http://localhost:3000/api/v2/wells/77/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/projects","related":"http://localhost:3000/api/v2/wells/77/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/77/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/77/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/77/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/77/aliquots"},"data":[{"type":"aliquots","id":"77"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/77/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/77/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/77/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/77/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/77/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/77/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/77/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/77/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/77/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/77/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/77/transfer_requests_as_target"}}}},{"id":"78","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/78"},"attributes":{"uuid":"76c284ac-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/samples","related":"http://localhost:3000/api/v2/wells/78/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/studies","related":"http://localhost:3000/api/v2/wells/78/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/projects","related":"http://localhost:3000/api/v2/wells/78/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/78/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/78/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/78/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/78/aliquots"},"data":[{"type":"aliquots","id":"78"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/78/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/78/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/78/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/78/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/78/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/78/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/78/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/78/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/78/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/78/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/78/transfer_requests_as_target"}}}},{"id":"79","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/79"},"attributes":{"uuid":"76c28524-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/samples","related":"http://localhost:3000/api/v2/wells/79/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/studies","related":"http://localhost:3000/api/v2/wells/79/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/projects","related":"http://localhost:3000/api/v2/wells/79/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/79/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/79/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/79/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/79/aliquots"},"data":[{"type":"aliquots","id":"79"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/79/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/79/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/79/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/79/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/79/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/79/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/79/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/79/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/79/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/79/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/79/transfer_requests_as_target"}}}},{"id":"80","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/80"},"attributes":{"uuid":"76c28592-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/samples","related":"http://localhost:3000/api/v2/wells/80/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/studies","related":"http://localhost:3000/api/v2/wells/80/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/projects","related":"http://localhost:3000/api/v2/wells/80/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/80/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/80/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/80/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/80/aliquots"},"data":[{"type":"aliquots","id":"80"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/80/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/80/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/80/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/80/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/80/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/80/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/80/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/80/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/80/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/80/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/80/transfer_requests_as_target"}}}},{"id":"81","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/81"},"attributes":{"uuid":"76c28632-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/samples","related":"http://localhost:3000/api/v2/wells/81/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/studies","related":"http://localhost:3000/api/v2/wells/81/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/projects","related":"http://localhost:3000/api/v2/wells/81/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/81/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/81/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/81/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/81/aliquots"},"data":[{"type":"aliquots","id":"81"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/81/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/81/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/81/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/81/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/81/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/81/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/81/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/81/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/81/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/81/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/81/transfer_requests_as_target"}}}},{"id":"82","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/82"},"attributes":{"uuid":"76c28736-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/samples","related":"http://localhost:3000/api/v2/wells/82/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/studies","related":"http://localhost:3000/api/v2/wells/82/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/projects","related":"http://localhost:3000/api/v2/wells/82/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/82/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/82/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/82/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/82/aliquots"},"data":[{"type":"aliquots","id":"82"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/82/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/82/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/82/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/82/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/82/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/82/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/82/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/82/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/82/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/82/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/82/transfer_requests_as_target"}}}},{"id":"83","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/83"},"attributes":{"uuid":"76c287ae-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/samples","related":"http://localhost:3000/api/v2/wells/83/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/studies","related":"http://localhost:3000/api/v2/wells/83/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/projects","related":"http://localhost:3000/api/v2/wells/83/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/83/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/83/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/83/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/83/aliquots"},"data":[{"type":"aliquots","id":"83"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/83/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/83/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/83/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/83/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/83/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/83/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/83/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/83/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/83/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/83/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/83/transfer_requests_as_target"}}}},{"id":"84","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/84"},"attributes":{"uuid":"76c2881c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:G12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"G12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/samples","related":"http://localhost:3000/api/v2/wells/84/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/studies","related":"http://localhost:3000/api/v2/wells/84/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/projects","related":"http://localhost:3000/api/v2/wells/84/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/84/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/84/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/84/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/84/aliquots"},"data":[{"type":"aliquots","id":"84"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/84/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/84/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/84/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/84/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/84/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/84/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/84/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/84/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/84/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/84/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/84/transfer_requests_as_target"}}}},{"id":"85","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/85"},"attributes":{"uuid":"76c28998-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H1","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H1"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/samples","related":"http://localhost:3000/api/v2/wells/85/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/studies","related":"http://localhost:3000/api/v2/wells/85/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/projects","related":"http://localhost:3000/api/v2/wells/85/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/85/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/85/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/85/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/85/aliquots"},"data":[{"type":"aliquots","id":"85"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/85/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/85/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/85/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/85/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/85/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/85/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/85/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/85/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/85/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/85/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/85/transfer_requests_as_target"}}}},{"id":"86","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/86"},"attributes":{"uuid":"76c28a06-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H2","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H2"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/samples","related":"http://localhost:3000/api/v2/wells/86/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/studies","related":"http://localhost:3000/api/v2/wells/86/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/projects","related":"http://localhost:3000/api/v2/wells/86/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/86/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/86/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/86/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/86/aliquots"},"data":[{"type":"aliquots","id":"86"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/86/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/86/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/86/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/86/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/86/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/86/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/86/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/86/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/86/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/86/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/86/transfer_requests_as_target"}}}},{"id":"87","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/87"},"attributes":{"uuid":"76c28ba0-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H3","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H3"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/samples","related":"http://localhost:3000/api/v2/wells/87/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/studies","related":"http://localhost:3000/api/v2/wells/87/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/projects","related":"http://localhost:3000/api/v2/wells/87/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/87/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/87/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/87/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/87/aliquots"},"data":[{"type":"aliquots","id":"87"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/87/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/87/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/87/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/87/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/87/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/87/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/87/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/87/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/87/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/87/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/87/transfer_requests_as_target"}}}},{"id":"88","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/88"},"attributes":{"uuid":"76c28c0e-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H4","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H4"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/samples","related":"http://localhost:3000/api/v2/wells/88/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/studies","related":"http://localhost:3000/api/v2/wells/88/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/projects","related":"http://localhost:3000/api/v2/wells/88/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/88/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/88/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/88/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/88/aliquots"},"data":[{"type":"aliquots","id":"88"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/88/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/88/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/88/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/88/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/88/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/88/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/88/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/88/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/88/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/88/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/88/transfer_requests_as_target"}}}},{"id":"89","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/89"},"attributes":{"uuid":"76c28c7c-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H5","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H5"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/samples","related":"http://localhost:3000/api/v2/wells/89/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/studies","related":"http://localhost:3000/api/v2/wells/89/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/projects","related":"http://localhost:3000/api/v2/wells/89/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/89/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/89/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/89/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/89/aliquots"},"data":[{"type":"aliquots","id":"89"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/89/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/89/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/89/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/89/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/89/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/89/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/89/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/89/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/89/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/89/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/89/transfer_requests_as_target"}}}},{"id":"90","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/90"},"attributes":{"uuid":"76c28cf4-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H6","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H6"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/samples","related":"http://localhost:3000/api/v2/wells/90/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/studies","related":"http://localhost:3000/api/v2/wells/90/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/projects","related":"http://localhost:3000/api/v2/wells/90/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/90/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/90/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/90/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/90/aliquots"},"data":[{"type":"aliquots","id":"90"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/90/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/90/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/90/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/90/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/90/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/90/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/90/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/90/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/90/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/90/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/90/transfer_requests_as_target"}}}},{"id":"91","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/91"},"attributes":{"uuid":"76c28e16-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H7","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H7"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/samples","related":"http://localhost:3000/api/v2/wells/91/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/studies","related":"http://localhost:3000/api/v2/wells/91/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/projects","related":"http://localhost:3000/api/v2/wells/91/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/91/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/91/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/91/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/91/aliquots"},"data":[{"type":"aliquots","id":"91"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/91/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/91/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/91/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/91/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/91/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/91/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/91/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/91/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/91/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/91/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/91/transfer_requests_as_target"}}}},{"id":"92","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/92"},"attributes":{"uuid":"76c28e84-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H8","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H8"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/samples","related":"http://localhost:3000/api/v2/wells/92/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/studies","related":"http://localhost:3000/api/v2/wells/92/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/projects","related":"http://localhost:3000/api/v2/wells/92/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/92/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/92/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/92/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/92/aliquots"},"data":[{"type":"aliquots","id":"92"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/92/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/92/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/92/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/92/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/92/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/92/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/92/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/92/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/92/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/92/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/92/transfer_requests_as_target"}}}},{"id":"93","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/93"},"attributes":{"uuid":"76c28ef2-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H9","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H9"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/samples","related":"http://localhost:3000/api/v2/wells/93/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/studies","related":"http://localhost:3000/api/v2/wells/93/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/projects","related":"http://localhost:3000/api/v2/wells/93/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/93/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/93/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/93/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/93/aliquots"},"data":[{"type":"aliquots","id":"93"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/93/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/93/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/93/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/93/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/93/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/93/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/93/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/93/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/93/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/93/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/93/transfer_requests_as_target"}}}},{"id":"94","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/94"},"attributes":{"uuid":"76c29028-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H10","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H10"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/samples","related":"http://localhost:3000/api/v2/wells/94/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/studies","related":"http://localhost:3000/api/v2/wells/94/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/projects","related":"http://localhost:3000/api/v2/wells/94/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/94/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/94/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/94/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/94/aliquots"},"data":[{"type":"aliquots","id":"94"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/94/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/94/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/94/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/94/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/94/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/94/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/94/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/94/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/94/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/94/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/94/transfer_requests_as_target"}}}},{"id":"95","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/95"},"attributes":{"uuid":"76c29096-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H11","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H11"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/samples","related":"http://localhost:3000/api/v2/wells/95/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/studies","related":"http://localhost:3000/api/v2/wells/95/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/projects","related":"http://localhost:3000/api/v2/wells/95/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/95/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/95/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/95/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/95/aliquots"},"data":[{"type":"aliquots","id":"95"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/95/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/95/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/95/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/95/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/95/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/95/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/95/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/95/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/95/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/95/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/95/transfer_requests_as_target"}}}},{"id":"96","type":"wells","links":{"self":"http://localhost:3000/api/v2/wells/96"},"attributes":{"uuid":"76c29104-9a21-11ec-9a02-acde48001122","name":"DN9000001W:H12","pcr_cycles":null,"submit_for_sequencing":null,"sub_pool":null,"coverage":null,"diluent_volume":null,"state":"unknown","position":{"name":"H12"}},"relationships":{"samples":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/samples","related":"http://localhost:3000/api/v2/wells/96/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/studies","related":"http://localhost:3000/api/v2/wells/96/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/projects","related":"http://localhost:3000/api/v2/wells/96/projects"}},"requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/requests_as_source","related":"http://localhost:3000/api/v2/wells/96/requests_as_source"}},"requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/requests_as_target","related":"http://localhost:3000/api/v2/wells/96/requests_as_target"}},"qc_results":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/qc_results","related":"http://localhost:3000/api/v2/wells/96/qc_results"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/aliquots","related":"http://localhost:3000/api/v2/wells/96/aliquots"},"data":[{"type":"aliquots","id":"96"}]},"downstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/downstream_assets","related":"http://localhost:3000/api/v2/wells/96/downstream_assets"}},"downstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/downstream_wells","related":"http://localhost:3000/api/v2/wells/96/downstream_wells"}},"downstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/downstream_plates","related":"http://localhost:3000/api/v2/wells/96/downstream_plates"}},"downstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/downstream_tubes","related":"http://localhost:3000/api/v2/wells/96/downstream_tubes"}},"upstream_assets":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/upstream_assets","related":"http://localhost:3000/api/v2/wells/96/upstream_assets"}},"upstream_wells":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/upstream_wells","related":"http://localhost:3000/api/v2/wells/96/upstream_wells"}},"upstream_plates":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/upstream_plates","related":"http://localhost:3000/api/v2/wells/96/upstream_plates"}},"upstream_tubes":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/upstream_tubes","related":"http://localhost:3000/api/v2/wells/96/upstream_tubes"}},"transfer_requests_as_source":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/transfer_requests_as_source","related":"http://localhost:3000/api/v2/wells/96/transfer_requests_as_source"}},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/wells/96/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/wells/96/transfer_requests_as_target"}}}},{"id":"1","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/1"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/1/relationships/study","related":"http://localhost:3000/api/v2/aliquots/1/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/1/relationships/project","related":"http://localhost:3000/api/v2/aliquots/1/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/1/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/1/sample"},"data":{"type":"samples","id":"2"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/1/relationships/request","related":"http://localhost:3000/api/v2/aliquots/1/request"}}}},{"id":"2","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/2"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/2/relationships/study","related":"http://localhost:3000/api/v2/aliquots/2/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/2/relationships/project","related":"http://localhost:3000/api/v2/aliquots/2/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/2/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/2/sample"},"data":{"type":"samples","id":"3"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/2/relationships/request","related":"http://localhost:3000/api/v2/aliquots/2/request"}}}},{"id":"3","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/3"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/3/relationships/study","related":"http://localhost:3000/api/v2/aliquots/3/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/3/relationships/project","related":"http://localhost:3000/api/v2/aliquots/3/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/3/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/3/sample"},"data":{"type":"samples","id":"4"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/3/relationships/request","related":"http://localhost:3000/api/v2/aliquots/3/request"}}}},{"id":"4","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/4"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/4/relationships/study","related":"http://localhost:3000/api/v2/aliquots/4/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/4/relationships/project","related":"http://localhost:3000/api/v2/aliquots/4/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/4/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/4/sample"},"data":{"type":"samples","id":"5"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/4/relationships/request","related":"http://localhost:3000/api/v2/aliquots/4/request"}}}},{"id":"5","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/5"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/5/relationships/study","related":"http://localhost:3000/api/v2/aliquots/5/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/5/relationships/project","related":"http://localhost:3000/api/v2/aliquots/5/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/5/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/5/sample"},"data":{"type":"samples","id":"6"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/5/relationships/request","related":"http://localhost:3000/api/v2/aliquots/5/request"}}}},{"id":"6","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/6"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/6/relationships/study","related":"http://localhost:3000/api/v2/aliquots/6/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/6/relationships/project","related":"http://localhost:3000/api/v2/aliquots/6/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/6/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/6/sample"},"data":{"type":"samples","id":"7"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/6/relationships/request","related":"http://localhost:3000/api/v2/aliquots/6/request"}}}},{"id":"7","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/7"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/7/relationships/study","related":"http://localhost:3000/api/v2/aliquots/7/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/7/relationships/project","related":"http://localhost:3000/api/v2/aliquots/7/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/7/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/7/sample"},"data":{"type":"samples","id":"8"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/7/relationships/request","related":"http://localhost:3000/api/v2/aliquots/7/request"}}}},{"id":"8","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/8"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/8/relationships/study","related":"http://localhost:3000/api/v2/aliquots/8/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/8/relationships/project","related":"http://localhost:3000/api/v2/aliquots/8/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/8/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/8/sample"},"data":{"type":"samples","id":"9"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/8/relationships/request","related":"http://localhost:3000/api/v2/aliquots/8/request"}}}},{"id":"9","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/9"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/9/relationships/study","related":"http://localhost:3000/api/v2/aliquots/9/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/9/relationships/project","related":"http://localhost:3000/api/v2/aliquots/9/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/9/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/9/sample"},"data":{"type":"samples","id":"10"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/9/relationships/request","related":"http://localhost:3000/api/v2/aliquots/9/request"}}}},{"id":"10","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/10"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/10/relationships/study","related":"http://localhost:3000/api/v2/aliquots/10/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/10/relationships/project","related":"http://localhost:3000/api/v2/aliquots/10/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/10/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/10/sample"},"data":{"type":"samples","id":"11"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/10/relationships/request","related":"http://localhost:3000/api/v2/aliquots/10/request"}}}},{"id":"11","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/11"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/11/relationships/study","related":"http://localhost:3000/api/v2/aliquots/11/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/11/relationships/project","related":"http://localhost:3000/api/v2/aliquots/11/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/11/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/11/sample"},"data":{"type":"samples","id":"12"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/11/relationships/request","related":"http://localhost:3000/api/v2/aliquots/11/request"}}}},{"id":"12","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/12"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/12/relationships/study","related":"http://localhost:3000/api/v2/aliquots/12/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/12/relationships/project","related":"http://localhost:3000/api/v2/aliquots/12/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/12/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/12/sample"},"data":{"type":"samples","id":"13"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/12/relationships/request","related":"http://localhost:3000/api/v2/aliquots/12/request"}}}},{"id":"13","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/13"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/13/relationships/study","related":"http://localhost:3000/api/v2/aliquots/13/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/13/relationships/project","related":"http://localhost:3000/api/v2/aliquots/13/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/13/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/13/sample"},"data":{"type":"samples","id":"14"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/13/relationships/request","related":"http://localhost:3000/api/v2/aliquots/13/request"}}}},{"id":"14","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/14"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/14/relationships/study","related":"http://localhost:3000/api/v2/aliquots/14/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/14/relationships/project","related":"http://localhost:3000/api/v2/aliquots/14/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/14/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/14/sample"},"data":{"type":"samples","id":"15"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/14/relationships/request","related":"http://localhost:3000/api/v2/aliquots/14/request"}}}},{"id":"15","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/15"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/15/relationships/study","related":"http://localhost:3000/api/v2/aliquots/15/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/15/relationships/project","related":"http://localhost:3000/api/v2/aliquots/15/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/15/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/15/sample"},"data":{"type":"samples","id":"16"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/15/relationships/request","related":"http://localhost:3000/api/v2/aliquots/15/request"}}}},{"id":"16","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/16"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/16/relationships/study","related":"http://localhost:3000/api/v2/aliquots/16/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/16/relationships/project","related":"http://localhost:3000/api/v2/aliquots/16/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/16/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/16/sample"},"data":{"type":"samples","id":"17"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/16/relationships/request","related":"http://localhost:3000/api/v2/aliquots/16/request"}}}},{"id":"17","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/17"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/17/relationships/study","related":"http://localhost:3000/api/v2/aliquots/17/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/17/relationships/project","related":"http://localhost:3000/api/v2/aliquots/17/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/17/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/17/sample"},"data":{"type":"samples","id":"18"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/17/relationships/request","related":"http://localhost:3000/api/v2/aliquots/17/request"}}}},{"id":"18","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/18"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/18/relationships/study","related":"http://localhost:3000/api/v2/aliquots/18/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/18/relationships/project","related":"http://localhost:3000/api/v2/aliquots/18/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/18/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/18/sample"},"data":{"type":"samples","id":"19"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/18/relationships/request","related":"http://localhost:3000/api/v2/aliquots/18/request"}}}},{"id":"19","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/19"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/19/relationships/study","related":"http://localhost:3000/api/v2/aliquots/19/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/19/relationships/project","related":"http://localhost:3000/api/v2/aliquots/19/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/19/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/19/sample"},"data":{"type":"samples","id":"20"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/19/relationships/request","related":"http://localhost:3000/api/v2/aliquots/19/request"}}}},{"id":"20","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/20"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/20/relationships/study","related":"http://localhost:3000/api/v2/aliquots/20/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/20/relationships/project","related":"http://localhost:3000/api/v2/aliquots/20/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/20/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/20/sample"},"data":{"type":"samples","id":"21"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/20/relationships/request","related":"http://localhost:3000/api/v2/aliquots/20/request"}}}},{"id":"21","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/21"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/21/relationships/study","related":"http://localhost:3000/api/v2/aliquots/21/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/21/relationships/project","related":"http://localhost:3000/api/v2/aliquots/21/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/21/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/21/sample"},"data":{"type":"samples","id":"22"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/21/relationships/request","related":"http://localhost:3000/api/v2/aliquots/21/request"}}}},{"id":"22","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/22"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/22/relationships/study","related":"http://localhost:3000/api/v2/aliquots/22/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/22/relationships/project","related":"http://localhost:3000/api/v2/aliquots/22/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/22/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/22/sample"},"data":{"type":"samples","id":"23"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/22/relationships/request","related":"http://localhost:3000/api/v2/aliquots/22/request"}}}},{"id":"23","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/23"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/23/relationships/study","related":"http://localhost:3000/api/v2/aliquots/23/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/23/relationships/project","related":"http://localhost:3000/api/v2/aliquots/23/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/23/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/23/sample"},"data":{"type":"samples","id":"24"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/23/relationships/request","related":"http://localhost:3000/api/v2/aliquots/23/request"}}}},{"id":"24","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/24"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/24/relationships/study","related":"http://localhost:3000/api/v2/aliquots/24/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/24/relationships/project","related":"http://localhost:3000/api/v2/aliquots/24/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/24/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/24/sample"},"data":{"type":"samples","id":"25"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/24/relationships/request","related":"http://localhost:3000/api/v2/aliquots/24/request"}}}},{"id":"25","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/25"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/25/relationships/study","related":"http://localhost:3000/api/v2/aliquots/25/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/25/relationships/project","related":"http://localhost:3000/api/v2/aliquots/25/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/25/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/25/sample"},"data":{"type":"samples","id":"26"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/25/relationships/request","related":"http://localhost:3000/api/v2/aliquots/25/request"}}}},{"id":"26","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/26"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/26/relationships/study","related":"http://localhost:3000/api/v2/aliquots/26/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/26/relationships/project","related":"http://localhost:3000/api/v2/aliquots/26/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/26/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/26/sample"},"data":{"type":"samples","id":"27"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/26/relationships/request","related":"http://localhost:3000/api/v2/aliquots/26/request"}}}},{"id":"27","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/27"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/27/relationships/study","related":"http://localhost:3000/api/v2/aliquots/27/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/27/relationships/project","related":"http://localhost:3000/api/v2/aliquots/27/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/27/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/27/sample"},"data":{"type":"samples","id":"28"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/27/relationships/request","related":"http://localhost:3000/api/v2/aliquots/27/request"}}}},{"id":"28","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/28"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/28/relationships/study","related":"http://localhost:3000/api/v2/aliquots/28/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/28/relationships/project","related":"http://localhost:3000/api/v2/aliquots/28/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/28/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/28/sample"},"data":{"type":"samples","id":"29"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/28/relationships/request","related":"http://localhost:3000/api/v2/aliquots/28/request"}}}},{"id":"29","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/29"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/29/relationships/study","related":"http://localhost:3000/api/v2/aliquots/29/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/29/relationships/project","related":"http://localhost:3000/api/v2/aliquots/29/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/29/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/29/sample"},"data":{"type":"samples","id":"30"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/29/relationships/request","related":"http://localhost:3000/api/v2/aliquots/29/request"}}}},{"id":"30","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/30"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/30/relationships/study","related":"http://localhost:3000/api/v2/aliquots/30/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/30/relationships/project","related":"http://localhost:3000/api/v2/aliquots/30/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/30/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/30/sample"},"data":{"type":"samples","id":"31"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/30/relationships/request","related":"http://localhost:3000/api/v2/aliquots/30/request"}}}},{"id":"31","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/31"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/31/relationships/study","related":"http://localhost:3000/api/v2/aliquots/31/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/31/relationships/project","related":"http://localhost:3000/api/v2/aliquots/31/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/31/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/31/sample"},"data":{"type":"samples","id":"32"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/31/relationships/request","related":"http://localhost:3000/api/v2/aliquots/31/request"}}}},{"id":"32","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/32"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/32/relationships/study","related":"http://localhost:3000/api/v2/aliquots/32/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/32/relationships/project","related":"http://localhost:3000/api/v2/aliquots/32/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/32/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/32/sample"},"data":{"type":"samples","id":"33"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/32/relationships/request","related":"http://localhost:3000/api/v2/aliquots/32/request"}}}},{"id":"33","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/33"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/33/relationships/study","related":"http://localhost:3000/api/v2/aliquots/33/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/33/relationships/project","related":"http://localhost:3000/api/v2/aliquots/33/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/33/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/33/sample"},"data":{"type":"samples","id":"34"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/33/relationships/request","related":"http://localhost:3000/api/v2/aliquots/33/request"}}}},{"id":"34","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/34"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/34/relationships/study","related":"http://localhost:3000/api/v2/aliquots/34/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/34/relationships/project","related":"http://localhost:3000/api/v2/aliquots/34/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/34/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/34/sample"},"data":{"type":"samples","id":"35"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/34/relationships/request","related":"http://localhost:3000/api/v2/aliquots/34/request"}}}},{"id":"35","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/35"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/35/relationships/study","related":"http://localhost:3000/api/v2/aliquots/35/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/35/relationships/project","related":"http://localhost:3000/api/v2/aliquots/35/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/35/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/35/sample"},"data":{"type":"samples","id":"36"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/35/relationships/request","related":"http://localhost:3000/api/v2/aliquots/35/request"}}}},{"id":"36","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/36"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/36/relationships/study","related":"http://localhost:3000/api/v2/aliquots/36/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/36/relationships/project","related":"http://localhost:3000/api/v2/aliquots/36/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/36/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/36/sample"},"data":{"type":"samples","id":"37"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/36/relationships/request","related":"http://localhost:3000/api/v2/aliquots/36/request"}}}},{"id":"37","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/37"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/37/relationships/study","related":"http://localhost:3000/api/v2/aliquots/37/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/37/relationships/project","related":"http://localhost:3000/api/v2/aliquots/37/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/37/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/37/sample"},"data":{"type":"samples","id":"38"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/37/relationships/request","related":"http://localhost:3000/api/v2/aliquots/37/request"}}}},{"id":"38","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/38"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/38/relationships/study","related":"http://localhost:3000/api/v2/aliquots/38/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/38/relationships/project","related":"http://localhost:3000/api/v2/aliquots/38/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/38/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/38/sample"},"data":{"type":"samples","id":"39"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/38/relationships/request","related":"http://localhost:3000/api/v2/aliquots/38/request"}}}},{"id":"39","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/39"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/39/relationships/study","related":"http://localhost:3000/api/v2/aliquots/39/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/39/relationships/project","related":"http://localhost:3000/api/v2/aliquots/39/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/39/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/39/sample"},"data":{"type":"samples","id":"40"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/39/relationships/request","related":"http://localhost:3000/api/v2/aliquots/39/request"}}}},{"id":"40","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/40"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/40/relationships/study","related":"http://localhost:3000/api/v2/aliquots/40/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/40/relationships/project","related":"http://localhost:3000/api/v2/aliquots/40/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/40/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/40/sample"},"data":{"type":"samples","id":"41"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/40/relationships/request","related":"http://localhost:3000/api/v2/aliquots/40/request"}}}},{"id":"41","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/41"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/41/relationships/study","related":"http://localhost:3000/api/v2/aliquots/41/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/41/relationships/project","related":"http://localhost:3000/api/v2/aliquots/41/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/41/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/41/sample"},"data":{"type":"samples","id":"42"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/41/relationships/request","related":"http://localhost:3000/api/v2/aliquots/41/request"}}}},{"id":"42","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/42"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/42/relationships/study","related":"http://localhost:3000/api/v2/aliquots/42/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/42/relationships/project","related":"http://localhost:3000/api/v2/aliquots/42/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/42/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/42/sample"},"data":{"type":"samples","id":"43"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/42/relationships/request","related":"http://localhost:3000/api/v2/aliquots/42/request"}}}},{"id":"43","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/43"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/43/relationships/study","related":"http://localhost:3000/api/v2/aliquots/43/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/43/relationships/project","related":"http://localhost:3000/api/v2/aliquots/43/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/43/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/43/sample"},"data":{"type":"samples","id":"44"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/43/relationships/request","related":"http://localhost:3000/api/v2/aliquots/43/request"}}}},{"id":"44","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/44"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/44/relationships/study","related":"http://localhost:3000/api/v2/aliquots/44/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/44/relationships/project","related":"http://localhost:3000/api/v2/aliquots/44/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/44/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/44/sample"},"data":{"type":"samples","id":"45"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/44/relationships/request","related":"http://localhost:3000/api/v2/aliquots/44/request"}}}},{"id":"45","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/45"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/45/relationships/study","related":"http://localhost:3000/api/v2/aliquots/45/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/45/relationships/project","related":"http://localhost:3000/api/v2/aliquots/45/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/45/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/45/sample"},"data":{"type":"samples","id":"46"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/45/relationships/request","related":"http://localhost:3000/api/v2/aliquots/45/request"}}}},{"id":"46","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/46"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/46/relationships/study","related":"http://localhost:3000/api/v2/aliquots/46/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/46/relationships/project","related":"http://localhost:3000/api/v2/aliquots/46/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/46/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/46/sample"},"data":{"type":"samples","id":"47"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/46/relationships/request","related":"http://localhost:3000/api/v2/aliquots/46/request"}}}},{"id":"47","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/47"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/47/relationships/study","related":"http://localhost:3000/api/v2/aliquots/47/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/47/relationships/project","related":"http://localhost:3000/api/v2/aliquots/47/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/47/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/47/sample"},"data":{"type":"samples","id":"48"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/47/relationships/request","related":"http://localhost:3000/api/v2/aliquots/47/request"}}}},{"id":"48","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/48"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/48/relationships/study","related":"http://localhost:3000/api/v2/aliquots/48/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/48/relationships/project","related":"http://localhost:3000/api/v2/aliquots/48/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/48/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/48/sample"},"data":{"type":"samples","id":"49"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/48/relationships/request","related":"http://localhost:3000/api/v2/aliquots/48/request"}}}},{"id":"49","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/49"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/49/relationships/study","related":"http://localhost:3000/api/v2/aliquots/49/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/49/relationships/project","related":"http://localhost:3000/api/v2/aliquots/49/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/49/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/49/sample"},"data":{"type":"samples","id":"50"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/49/relationships/request","related":"http://localhost:3000/api/v2/aliquots/49/request"}}}},{"id":"50","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/50"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/50/relationships/study","related":"http://localhost:3000/api/v2/aliquots/50/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/50/relationships/project","related":"http://localhost:3000/api/v2/aliquots/50/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/50/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/50/sample"},"data":{"type":"samples","id":"51"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/50/relationships/request","related":"http://localhost:3000/api/v2/aliquots/50/request"}}}},{"id":"51","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/51"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/51/relationships/study","related":"http://localhost:3000/api/v2/aliquots/51/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/51/relationships/project","related":"http://localhost:3000/api/v2/aliquots/51/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/51/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/51/sample"},"data":{"type":"samples","id":"52"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/51/relationships/request","related":"http://localhost:3000/api/v2/aliquots/51/request"}}}},{"id":"52","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/52"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/52/relationships/study","related":"http://localhost:3000/api/v2/aliquots/52/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/52/relationships/project","related":"http://localhost:3000/api/v2/aliquots/52/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/52/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/52/sample"},"data":{"type":"samples","id":"53"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/52/relationships/request","related":"http://localhost:3000/api/v2/aliquots/52/request"}}}},{"id":"53","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/53"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/53/relationships/study","related":"http://localhost:3000/api/v2/aliquots/53/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/53/relationships/project","related":"http://localhost:3000/api/v2/aliquots/53/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/53/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/53/sample"},"data":{"type":"samples","id":"54"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/53/relationships/request","related":"http://localhost:3000/api/v2/aliquots/53/request"}}}},{"id":"54","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/54"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/54/relationships/study","related":"http://localhost:3000/api/v2/aliquots/54/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/54/relationships/project","related":"http://localhost:3000/api/v2/aliquots/54/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/54/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/54/sample"},"data":{"type":"samples","id":"55"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/54/relationships/request","related":"http://localhost:3000/api/v2/aliquots/54/request"}}}},{"id":"55","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/55"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/55/relationships/study","related":"http://localhost:3000/api/v2/aliquots/55/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/55/relationships/project","related":"http://localhost:3000/api/v2/aliquots/55/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/55/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/55/sample"},"data":{"type":"samples","id":"56"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/55/relationships/request","related":"http://localhost:3000/api/v2/aliquots/55/request"}}}},{"id":"56","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/56"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/56/relationships/study","related":"http://localhost:3000/api/v2/aliquots/56/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/56/relationships/project","related":"http://localhost:3000/api/v2/aliquots/56/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/56/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/56/sample"},"data":{"type":"samples","id":"57"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/56/relationships/request","related":"http://localhost:3000/api/v2/aliquots/56/request"}}}},{"id":"57","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/57"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/57/relationships/study","related":"http://localhost:3000/api/v2/aliquots/57/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/57/relationships/project","related":"http://localhost:3000/api/v2/aliquots/57/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/57/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/57/sample"},"data":{"type":"samples","id":"58"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/57/relationships/request","related":"http://localhost:3000/api/v2/aliquots/57/request"}}}},{"id":"58","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/58"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/58/relationships/study","related":"http://localhost:3000/api/v2/aliquots/58/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/58/relationships/project","related":"http://localhost:3000/api/v2/aliquots/58/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/58/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/58/sample"},"data":{"type":"samples","id":"59"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/58/relationships/request","related":"http://localhost:3000/api/v2/aliquots/58/request"}}}},{"id":"59","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/59"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/59/relationships/study","related":"http://localhost:3000/api/v2/aliquots/59/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/59/relationships/project","related":"http://localhost:3000/api/v2/aliquots/59/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/59/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/59/sample"},"data":{"type":"samples","id":"60"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/59/relationships/request","related":"http://localhost:3000/api/v2/aliquots/59/request"}}}},{"id":"60","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/60"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/60/relationships/study","related":"http://localhost:3000/api/v2/aliquots/60/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/60/relationships/project","related":"http://localhost:3000/api/v2/aliquots/60/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/60/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/60/sample"},"data":{"type":"samples","id":"61"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/60/relationships/request","related":"http://localhost:3000/api/v2/aliquots/60/request"}}}},{"id":"61","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/61"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/61/relationships/study","related":"http://localhost:3000/api/v2/aliquots/61/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/61/relationships/project","related":"http://localhost:3000/api/v2/aliquots/61/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/61/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/61/sample"},"data":{"type":"samples","id":"62"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/61/relationships/request","related":"http://localhost:3000/api/v2/aliquots/61/request"}}}},{"id":"62","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/62"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/62/relationships/study","related":"http://localhost:3000/api/v2/aliquots/62/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/62/relationships/project","related":"http://localhost:3000/api/v2/aliquots/62/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/62/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/62/sample"},"data":{"type":"samples","id":"63"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/62/relationships/request","related":"http://localhost:3000/api/v2/aliquots/62/request"}}}},{"id":"63","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/63"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/63/relationships/study","related":"http://localhost:3000/api/v2/aliquots/63/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/63/relationships/project","related":"http://localhost:3000/api/v2/aliquots/63/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/63/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/63/sample"},"data":{"type":"samples","id":"64"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/63/relationships/request","related":"http://localhost:3000/api/v2/aliquots/63/request"}}}},{"id":"64","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/64"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/64/relationships/study","related":"http://localhost:3000/api/v2/aliquots/64/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/64/relationships/project","related":"http://localhost:3000/api/v2/aliquots/64/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/64/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/64/sample"},"data":{"type":"samples","id":"65"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/64/relationships/request","related":"http://localhost:3000/api/v2/aliquots/64/request"}}}},{"id":"65","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/65"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/65/relationships/study","related":"http://localhost:3000/api/v2/aliquots/65/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/65/relationships/project","related":"http://localhost:3000/api/v2/aliquots/65/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/65/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/65/sample"},"data":{"type":"samples","id":"66"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/65/relationships/request","related":"http://localhost:3000/api/v2/aliquots/65/request"}}}},{"id":"66","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/66"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/66/relationships/study","related":"http://localhost:3000/api/v2/aliquots/66/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/66/relationships/project","related":"http://localhost:3000/api/v2/aliquots/66/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/66/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/66/sample"},"data":{"type":"samples","id":"67"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/66/relationships/request","related":"http://localhost:3000/api/v2/aliquots/66/request"}}}},{"id":"67","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/67"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/67/relationships/study","related":"http://localhost:3000/api/v2/aliquots/67/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/67/relationships/project","related":"http://localhost:3000/api/v2/aliquots/67/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/67/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/67/sample"},"data":{"type":"samples","id":"68"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/67/relationships/request","related":"http://localhost:3000/api/v2/aliquots/67/request"}}}},{"id":"68","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/68"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/68/relationships/study","related":"http://localhost:3000/api/v2/aliquots/68/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/68/relationships/project","related":"http://localhost:3000/api/v2/aliquots/68/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/68/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/68/sample"},"data":{"type":"samples","id":"69"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/68/relationships/request","related":"http://localhost:3000/api/v2/aliquots/68/request"}}}},{"id":"69","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/69"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/69/relationships/study","related":"http://localhost:3000/api/v2/aliquots/69/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/69/relationships/project","related":"http://localhost:3000/api/v2/aliquots/69/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/69/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/69/sample"},"data":{"type":"samples","id":"70"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/69/relationships/request","related":"http://localhost:3000/api/v2/aliquots/69/request"}}}},{"id":"70","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/70"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/70/relationships/study","related":"http://localhost:3000/api/v2/aliquots/70/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/70/relationships/project","related":"http://localhost:3000/api/v2/aliquots/70/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/70/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/70/sample"},"data":{"type":"samples","id":"71"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/70/relationships/request","related":"http://localhost:3000/api/v2/aliquots/70/request"}}}},{"id":"71","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/71"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/71/relationships/study","related":"http://localhost:3000/api/v2/aliquots/71/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/71/relationships/project","related":"http://localhost:3000/api/v2/aliquots/71/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/71/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/71/sample"},"data":{"type":"samples","id":"72"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/71/relationships/request","related":"http://localhost:3000/api/v2/aliquots/71/request"}}}},{"id":"72","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/72"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/72/relationships/study","related":"http://localhost:3000/api/v2/aliquots/72/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/72/relationships/project","related":"http://localhost:3000/api/v2/aliquots/72/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/72/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/72/sample"},"data":{"type":"samples","id":"73"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/72/relationships/request","related":"http://localhost:3000/api/v2/aliquots/72/request"}}}},{"id":"73","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/73"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/73/relationships/study","related":"http://localhost:3000/api/v2/aliquots/73/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/73/relationships/project","related":"http://localhost:3000/api/v2/aliquots/73/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/73/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/73/sample"},"data":{"type":"samples","id":"74"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/73/relationships/request","related":"http://localhost:3000/api/v2/aliquots/73/request"}}}},{"id":"74","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/74"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/74/relationships/study","related":"http://localhost:3000/api/v2/aliquots/74/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/74/relationships/project","related":"http://localhost:3000/api/v2/aliquots/74/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/74/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/74/sample"},"data":{"type":"samples","id":"75"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/74/relationships/request","related":"http://localhost:3000/api/v2/aliquots/74/request"}}}},{"id":"75","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/75"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/75/relationships/study","related":"http://localhost:3000/api/v2/aliquots/75/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/75/relationships/project","related":"http://localhost:3000/api/v2/aliquots/75/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/75/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/75/sample"},"data":{"type":"samples","id":"76"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/75/relationships/request","related":"http://localhost:3000/api/v2/aliquots/75/request"}}}},{"id":"76","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/76"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/76/relationships/study","related":"http://localhost:3000/api/v2/aliquots/76/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/76/relationships/project","related":"http://localhost:3000/api/v2/aliquots/76/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/76/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/76/sample"},"data":{"type":"samples","id":"77"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/76/relationships/request","related":"http://localhost:3000/api/v2/aliquots/76/request"}}}},{"id":"77","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/77"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/77/relationships/study","related":"http://localhost:3000/api/v2/aliquots/77/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/77/relationships/project","related":"http://localhost:3000/api/v2/aliquots/77/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/77/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/77/sample"},"data":{"type":"samples","id":"78"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/77/relationships/request","related":"http://localhost:3000/api/v2/aliquots/77/request"}}}},{"id":"78","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/78"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/78/relationships/study","related":"http://localhost:3000/api/v2/aliquots/78/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/78/relationships/project","related":"http://localhost:3000/api/v2/aliquots/78/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/78/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/78/sample"},"data":{"type":"samples","id":"79"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/78/relationships/request","related":"http://localhost:3000/api/v2/aliquots/78/request"}}}},{"id":"79","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/79"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/79/relationships/study","related":"http://localhost:3000/api/v2/aliquots/79/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/79/relationships/project","related":"http://localhost:3000/api/v2/aliquots/79/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/79/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/79/sample"},"data":{"type":"samples","id":"80"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/79/relationships/request","related":"http://localhost:3000/api/v2/aliquots/79/request"}}}},{"id":"80","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/80"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/80/relationships/study","related":"http://localhost:3000/api/v2/aliquots/80/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/80/relationships/project","related":"http://localhost:3000/api/v2/aliquots/80/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/80/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/80/sample"},"data":{"type":"samples","id":"81"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/80/relationships/request","related":"http://localhost:3000/api/v2/aliquots/80/request"}}}},{"id":"81","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/81"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/81/relationships/study","related":"http://localhost:3000/api/v2/aliquots/81/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/81/relationships/project","related":"http://localhost:3000/api/v2/aliquots/81/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/81/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/81/sample"},"data":{"type":"samples","id":"82"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/81/relationships/request","related":"http://localhost:3000/api/v2/aliquots/81/request"}}}},{"id":"82","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/82"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/82/relationships/study","related":"http://localhost:3000/api/v2/aliquots/82/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/82/relationships/project","related":"http://localhost:3000/api/v2/aliquots/82/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/82/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/82/sample"},"data":{"type":"samples","id":"83"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/82/relationships/request","related":"http://localhost:3000/api/v2/aliquots/82/request"}}}},{"id":"83","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/83"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/83/relationships/study","related":"http://localhost:3000/api/v2/aliquots/83/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/83/relationships/project","related":"http://localhost:3000/api/v2/aliquots/83/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/83/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/83/sample"},"data":{"type":"samples","id":"84"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/83/relationships/request","related":"http://localhost:3000/api/v2/aliquots/83/request"}}}},{"id":"84","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/84"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/84/relationships/study","related":"http://localhost:3000/api/v2/aliquots/84/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/84/relationships/project","related":"http://localhost:3000/api/v2/aliquots/84/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/84/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/84/sample"},"data":{"type":"samples","id":"85"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/84/relationships/request","related":"http://localhost:3000/api/v2/aliquots/84/request"}}}},{"id":"85","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/85"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/85/relationships/study","related":"http://localhost:3000/api/v2/aliquots/85/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/85/relationships/project","related":"http://localhost:3000/api/v2/aliquots/85/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/85/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/85/sample"},"data":{"type":"samples","id":"86"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/85/relationships/request","related":"http://localhost:3000/api/v2/aliquots/85/request"}}}},{"id":"86","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/86"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/86/relationships/study","related":"http://localhost:3000/api/v2/aliquots/86/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/86/relationships/project","related":"http://localhost:3000/api/v2/aliquots/86/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/86/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/86/sample"},"data":{"type":"samples","id":"87"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/86/relationships/request","related":"http://localhost:3000/api/v2/aliquots/86/request"}}}},{"id":"87","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/87"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/87/relationships/study","related":"http://localhost:3000/api/v2/aliquots/87/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/87/relationships/project","related":"http://localhost:3000/api/v2/aliquots/87/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/87/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/87/sample"},"data":{"type":"samples","id":"88"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/87/relationships/request","related":"http://localhost:3000/api/v2/aliquots/87/request"}}}},{"id":"88","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/88"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/88/relationships/study","related":"http://localhost:3000/api/v2/aliquots/88/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/88/relationships/project","related":"http://localhost:3000/api/v2/aliquots/88/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/88/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/88/sample"},"data":{"type":"samples","id":"89"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/88/relationships/request","related":"http://localhost:3000/api/v2/aliquots/88/request"}}}},{"id":"89","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/89"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/89/relationships/study","related":"http://localhost:3000/api/v2/aliquots/89/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/89/relationships/project","related":"http://localhost:3000/api/v2/aliquots/89/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/89/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/89/sample"},"data":{"type":"samples","id":"90"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/89/relationships/request","related":"http://localhost:3000/api/v2/aliquots/89/request"}}}},{"id":"90","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/90"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/90/relationships/study","related":"http://localhost:3000/api/v2/aliquots/90/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/90/relationships/project","related":"http://localhost:3000/api/v2/aliquots/90/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/90/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/90/sample"},"data":{"type":"samples","id":"91"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/90/relationships/request","related":"http://localhost:3000/api/v2/aliquots/90/request"}}}},{"id":"91","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/91"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/91/relationships/study","related":"http://localhost:3000/api/v2/aliquots/91/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/91/relationships/project","related":"http://localhost:3000/api/v2/aliquots/91/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/91/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/91/sample"},"data":{"type":"samples","id":"92"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/91/relationships/request","related":"http://localhost:3000/api/v2/aliquots/91/request"}}}},{"id":"92","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/92"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/92/relationships/study","related":"http://localhost:3000/api/v2/aliquots/92/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/92/relationships/project","related":"http://localhost:3000/api/v2/aliquots/92/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/92/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/92/sample"},"data":{"type":"samples","id":"93"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/92/relationships/request","related":"http://localhost:3000/api/v2/aliquots/92/request"}}}},{"id":"93","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/93"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/93/relationships/study","related":"http://localhost:3000/api/v2/aliquots/93/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/93/relationships/project","related":"http://localhost:3000/api/v2/aliquots/93/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/93/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/93/sample"},"data":{"type":"samples","id":"94"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/93/relationships/request","related":"http://localhost:3000/api/v2/aliquots/93/request"}}}},{"id":"94","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/94"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/94/relationships/study","related":"http://localhost:3000/api/v2/aliquots/94/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/94/relationships/project","related":"http://localhost:3000/api/v2/aliquots/94/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/94/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/94/sample"},"data":{"type":"samples","id":"95"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/94/relationships/request","related":"http://localhost:3000/api/v2/aliquots/94/request"}}}},{"id":"95","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/95"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/95/relationships/study","related":"http://localhost:3000/api/v2/aliquots/95/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/95/relationships/project","related":"http://localhost:3000/api/v2/aliquots/95/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/95/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/95/sample"},"data":{"type":"samples","id":"96"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/95/relationships/request","related":"http://localhost:3000/api/v2/aliquots/95/request"}}}},{"id":"96","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/96"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/96/relationships/study","related":"http://localhost:3000/api/v2/aliquots/96/study"},"data":null},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/96/relationships/project","related":"http://localhost:3000/api/v2/aliquots/96/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/96/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/96/sample"},"data":{"type":"samples","id":"97"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/96/relationships/request","related":"http://localhost:3000/api/v2/aliquots/96/request"}}}},{"id":"2","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/2"},"attributes":{"name":"sample_DN9000001W_A1","sanger_sample_id":null,"uuid":"76c97050-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/2/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/2/sample_metadata"},"data":{"type":"sample_metadata","id":"2"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/2/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/2/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/2/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/2/component_samples"}}}},{"id":"3","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/3"},"attributes":{"name":"sample_DN9000001W_A2","sanger_sample_id":null,"uuid":"76d347a6-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/3/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/3/sample_metadata"},"data":{"type":"sample_metadata","id":"3"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/3/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/3/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/3/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/3/component_samples"}}}},{"id":"4","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/4"},"attributes":{"name":"sample_DN9000001W_A3","sanger_sample_id":null,"uuid":"76e0c2aa-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/4/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/4/sample_metadata"},"data":{"type":"sample_metadata","id":"4"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/4/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/4/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/4/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/4/component_samples"}}}},{"id":"5","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/5"},"attributes":{"name":"sample_DN9000001W_A4","sanger_sample_id":null,"uuid":"76ead326-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/5/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/5/sample_metadata"},"data":{"type":"sample_metadata","id":"5"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/5/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/5/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/5/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/5/component_samples"}}}},{"id":"6","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/6"},"attributes":{"name":"sample_DN9000001W_A5","sanger_sample_id":null,"uuid":"76f29340-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/6/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/6/sample_metadata"},"data":{"type":"sample_metadata","id":"6"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/6/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/6/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/6/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/6/component_samples"}}}},{"id":"7","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/7"},"attributes":{"name":"sample_DN9000001W_A6","sanger_sample_id":null,"uuid":"76fa2ed4-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/7/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/7/sample_metadata"},"data":{"type":"sample_metadata","id":"7"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/7/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/7/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/7/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/7/component_samples"}}}},{"id":"8","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/8"},"attributes":{"name":"sample_DN9000001W_A7","sanger_sample_id":null,"uuid":"77017158-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/8/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/8/sample_metadata"},"data":{"type":"sample_metadata","id":"8"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/8/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/8/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/8/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/8/component_samples"}}}},{"id":"9","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/9"},"attributes":{"name":"sample_DN9000001W_A8","sanger_sample_id":null,"uuid":"7708b58a-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/9/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/9/sample_metadata"},"data":{"type":"sample_metadata","id":"9"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/9/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/9/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/9/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/9/component_samples"}}}},{"id":"10","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/10"},"attributes":{"name":"sample_DN9000001W_A9","sanger_sample_id":null,"uuid":"771063fc-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/10/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/10/sample_metadata"},"data":{"type":"sample_metadata","id":"10"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/10/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/10/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/10/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/10/component_samples"}}}},{"id":"11","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/11"},"attributes":{"name":"sample_DN9000001W_A10","sanger_sample_id":null,"uuid":"7717deb6-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/11/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/11/sample_metadata"},"data":{"type":"sample_metadata","id":"11"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/11/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/11/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/11/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/11/component_samples"}}}},{"id":"12","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/12"},"attributes":{"name":"sample_DN9000001W_A11","sanger_sample_id":null,"uuid":"771f368e-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/12/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/12/sample_metadata"},"data":{"type":"sample_metadata","id":"12"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/12/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/12/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/12/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/12/component_samples"}}}},{"id":"13","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/13"},"attributes":{"name":"sample_DN9000001W_A12","sanger_sample_id":null,"uuid":"7726dd76-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/13/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/13/sample_metadata"},"data":{"type":"sample_metadata","id":"13"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/13/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/13/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/13/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/13/component_samples"}}}},{"id":"14","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/14"},"attributes":{"name":"sample_DN9000001W_B1","sanger_sample_id":null,"uuid":"772e9e12-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/14/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/14/sample_metadata"},"data":{"type":"sample_metadata","id":"14"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/14/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/14/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/14/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/14/component_samples"}}}},{"id":"15","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/15"},"attributes":{"name":"sample_DN9000001W_B2","sanger_sample_id":null,"uuid":"77351fee-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/15/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/15/sample_metadata"},"data":{"type":"sample_metadata","id":"15"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/15/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/15/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/15/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/15/component_samples"}}}},{"id":"16","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/16"},"attributes":{"name":"sample_DN9000001W_B3","sanger_sample_id":null,"uuid":"773b2d9e-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/16/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/16/sample_metadata"},"data":{"type":"sample_metadata","id":"16"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/16/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/16/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/16/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/16/component_samples"}}}},{"id":"17","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/17"},"attributes":{"name":"sample_DN9000001W_B4","sanger_sample_id":null,"uuid":"774d0bfe-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/17/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/17/sample_metadata"},"data":{"type":"sample_metadata","id":"17"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/17/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/17/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/17/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/17/component_samples"}}}},{"id":"18","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/18"},"attributes":{"name":"sample_DN9000001W_B5","sanger_sample_id":null,"uuid":"7758a09a-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/18/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/18/sample_metadata"},"data":{"type":"sample_metadata","id":"18"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/18/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/18/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/18/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/18/component_samples"}}}},{"id":"19","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/19"},"attributes":{"name":"sample_DN9000001W_B6","sanger_sample_id":null,"uuid":"7767bddc-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/19/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/19/sample_metadata"},"data":{"type":"sample_metadata","id":"19"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/19/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/19/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/19/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/19/component_samples"}}}},{"id":"20","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/20"},"attributes":{"name":"sample_DN9000001W_B7","sanger_sample_id":null,"uuid":"777214e4-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/20/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/20/sample_metadata"},"data":{"type":"sample_metadata","id":"20"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/20/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/20/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/20/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/20/component_samples"}}}},{"id":"21","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/21"},"attributes":{"name":"sample_DN9000001W_B8","sanger_sample_id":null,"uuid":"77841720-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/21/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/21/sample_metadata"},"data":{"type":"sample_metadata","id":"21"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/21/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/21/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/21/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/21/component_samples"}}}},{"id":"22","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/22"},"attributes":{"name":"sample_DN9000001W_B9","sanger_sample_id":null,"uuid":"778c55ac-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/22/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/22/sample_metadata"},"data":{"type":"sample_metadata","id":"22"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/22/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/22/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/22/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/22/component_samples"}}}},{"id":"23","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/23"},"attributes":{"name":"sample_DN9000001W_B10","sanger_sample_id":null,"uuid":"779931b4-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/23/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/23/sample_metadata"},"data":{"type":"sample_metadata","id":"23"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/23/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/23/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/23/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/23/component_samples"}}}},{"id":"24","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/24"},"attributes":{"name":"sample_DN9000001W_B11","sanger_sample_id":null,"uuid":"77a0e4ea-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/24/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/24/sample_metadata"},"data":{"type":"sample_metadata","id":"24"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/24/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/24/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/24/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/24/component_samples"}}}},{"id":"25","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/25"},"attributes":{"name":"sample_DN9000001W_B12","sanger_sample_id":null,"uuid":"77aa1646-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/25/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/25/sample_metadata"},"data":{"type":"sample_metadata","id":"25"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/25/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/25/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/25/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/25/component_samples"}}}},{"id":"26","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/26"},"attributes":{"name":"sample_DN9000001W_C1","sanger_sample_id":null,"uuid":"77b240fa-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/26/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/26/sample_metadata"},"data":{"type":"sample_metadata","id":"26"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/26/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/26/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/26/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/26/component_samples"}}}},{"id":"27","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/27"},"attributes":{"name":"sample_DN9000001W_C2","sanger_sample_id":null,"uuid":"77ba2068-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/27/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/27/sample_metadata"},"data":{"type":"sample_metadata","id":"27"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/27/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/27/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/27/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/27/component_samples"}}}},{"id":"28","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/28"},"attributes":{"name":"sample_DN9000001W_C3","sanger_sample_id":null,"uuid":"77c1d29a-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/28/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/28/sample_metadata"},"data":{"type":"sample_metadata","id":"28"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/28/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/28/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/28/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/28/component_samples"}}}},{"id":"29","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/29"},"attributes":{"name":"sample_DN9000001W_C4","sanger_sample_id":null,"uuid":"77c98166-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/29/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/29/sample_metadata"},"data":{"type":"sample_metadata","id":"29"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/29/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/29/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/29/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/29/component_samples"}}}},{"id":"30","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/30"},"attributes":{"name":"sample_DN9000001W_C5","sanger_sample_id":null,"uuid":"77d122cc-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/30/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/30/sample_metadata"},"data":{"type":"sample_metadata","id":"30"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/30/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/30/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/30/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/30/component_samples"}}}},{"id":"31","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/31"},"attributes":{"name":"sample_DN9000001W_C6","sanger_sample_id":null,"uuid":"77d85e3e-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/31/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/31/sample_metadata"},"data":{"type":"sample_metadata","id":"31"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/31/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/31/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/31/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/31/component_samples"}}}},{"id":"32","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/32"},"attributes":{"name":"sample_DN9000001W_C7","sanger_sample_id":null,"uuid":"77df9a00-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/32/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/32/sample_metadata"},"data":{"type":"sample_metadata","id":"32"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/32/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/32/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/32/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/32/component_samples"}}}},{"id":"33","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/33"},"attributes":{"name":"sample_DN9000001W_C8","sanger_sample_id":null,"uuid":"77e6fed0-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/33/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/33/sample_metadata"},"data":{"type":"sample_metadata","id":"33"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/33/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/33/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/33/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/33/component_samples"}}}},{"id":"34","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/34"},"attributes":{"name":"sample_DN9000001W_C9","sanger_sample_id":null,"uuid":"77ee42a8-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/34/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/34/sample_metadata"},"data":{"type":"sample_metadata","id":"34"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/34/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/34/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/34/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/34/component_samples"}}}},{"id":"35","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/35"},"attributes":{"name":"sample_DN9000001W_C10","sanger_sample_id":null,"uuid":"77f56eca-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/35/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/35/sample_metadata"},"data":{"type":"sample_metadata","id":"35"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/35/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/35/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/35/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/35/component_samples"}}}},{"id":"36","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/36"},"attributes":{"name":"sample_DN9000001W_C11","sanger_sample_id":null,"uuid":"77fd6d6e-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/36/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/36/sample_metadata"},"data":{"type":"sample_metadata","id":"36"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/36/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/36/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/36/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/36/component_samples"}}}},{"id":"37","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/37"},"attributes":{"name":"sample_DN9000001W_C12","sanger_sample_id":null,"uuid":"780ac018-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/37/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/37/sample_metadata"},"data":{"type":"sample_metadata","id":"37"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/37/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/37/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/37/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/37/component_samples"}}}},{"id":"38","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/38"},"attributes":{"name":"sample_DN9000001W_D1","sanger_sample_id":null,"uuid":"7811ced0-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/38/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/38/sample_metadata"},"data":{"type":"sample_metadata","id":"38"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/38/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/38/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/38/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/38/component_samples"}}}},{"id":"39","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/39"},"attributes":{"name":"sample_DN9000001W_D2","sanger_sample_id":null,"uuid":"78192216-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/39/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/39/sample_metadata"},"data":{"type":"sample_metadata","id":"39"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/39/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/39/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/39/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/39/component_samples"}}}},{"id":"40","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/40"},"attributes":{"name":"sample_DN9000001W_D3","sanger_sample_id":null,"uuid":"7822e08a-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/40/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/40/sample_metadata"},"data":{"type":"sample_metadata","id":"40"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/40/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/40/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/40/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/40/component_samples"}}}},{"id":"41","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/41"},"attributes":{"name":"sample_DN9000001W_D4","sanger_sample_id":null,"uuid":"782a1a26-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/41/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/41/sample_metadata"},"data":{"type":"sample_metadata","id":"41"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/41/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/41/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/41/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/41/component_samples"}}}},{"id":"42","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/42"},"attributes":{"name":"sample_DN9000001W_D5","sanger_sample_id":null,"uuid":"783160ba-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/42/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/42/sample_metadata"},"data":{"type":"sample_metadata","id":"42"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/42/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/42/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/42/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/42/component_samples"}}}},{"id":"43","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/43"},"attributes":{"name":"sample_DN9000001W_D6","sanger_sample_id":null,"uuid":"78411b36-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/43/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/43/sample_metadata"},"data":{"type":"sample_metadata","id":"43"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/43/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/43/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/43/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/43/component_samples"}}}},{"id":"44","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/44"},"attributes":{"name":"sample_DN9000001W_D7","sanger_sample_id":null,"uuid":"78531a7a-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/44/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/44/sample_metadata"},"data":{"type":"sample_metadata","id":"44"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/44/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/44/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/44/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/44/component_samples"}}}},{"id":"45","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/45"},"attributes":{"name":"sample_DN9000001W_D8","sanger_sample_id":null,"uuid":"785ca31a-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/45/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/45/sample_metadata"},"data":{"type":"sample_metadata","id":"45"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/45/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/45/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/45/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/45/component_samples"}}}},{"id":"46","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/46"},"attributes":{"name":"sample_DN9000001W_D9","sanger_sample_id":null,"uuid":"78643e22-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/46/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/46/sample_metadata"},"data":{"type":"sample_metadata","id":"46"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/46/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/46/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/46/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/46/component_samples"}}}},{"id":"47","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/47"},"attributes":{"name":"sample_DN9000001W_D10","sanger_sample_id":null,"uuid":"786bd72c-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/47/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/47/sample_metadata"},"data":{"type":"sample_metadata","id":"47"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/47/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/47/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/47/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/47/component_samples"}}}},{"id":"48","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/48"},"attributes":{"name":"sample_DN9000001W_D11","sanger_sample_id":null,"uuid":"7873aeb6-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/48/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/48/sample_metadata"},"data":{"type":"sample_metadata","id":"48"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/48/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/48/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/48/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/48/component_samples"}}}},{"id":"49","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/49"},"attributes":{"name":"sample_DN9000001W_D12","sanger_sample_id":null,"uuid":"787d84a4-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/49/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/49/sample_metadata"},"data":{"type":"sample_metadata","id":"49"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/49/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/49/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/49/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/49/component_samples"}}}},{"id":"50","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/50"},"attributes":{"name":"sample_DN9000001W_E1","sanger_sample_id":null,"uuid":"78849e10-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/50/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/50/sample_metadata"},"data":{"type":"sample_metadata","id":"50"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/50/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/50/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/50/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/50/component_samples"}}}},{"id":"51","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/51"},"attributes":{"name":"sample_DN9000001W_E2","sanger_sample_id":null,"uuid":"788b88f6-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/51/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/51/sample_metadata"},"data":{"type":"sample_metadata","id":"51"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/51/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/51/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/51/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/51/component_samples"}}}},{"id":"52","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/52"},"attributes":{"name":"sample_DN9000001W_E3","sanger_sample_id":null,"uuid":"7892a03c-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/52/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/52/sample_metadata"},"data":{"type":"sample_metadata","id":"52"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/52/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/52/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/52/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/52/component_samples"}}}},{"id":"53","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/53"},"attributes":{"name":"sample_DN9000001W_E4","sanger_sample_id":null,"uuid":"789f9184-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/53/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/53/sample_metadata"},"data":{"type":"sample_metadata","id":"53"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/53/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/53/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/53/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/53/component_samples"}}}},{"id":"54","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/54"},"attributes":{"name":"sample_DN9000001W_E5","sanger_sample_id":null,"uuid":"78b92bda-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/54/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/54/sample_metadata"},"data":{"type":"sample_metadata","id":"54"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/54/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/54/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/54/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/54/component_samples"}}}},{"id":"55","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/55"},"attributes":{"name":"sample_DN9000001W_E6","sanger_sample_id":null,"uuid":"78c23ec8-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/55/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/55/sample_metadata"},"data":{"type":"sample_metadata","id":"55"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/55/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/55/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/55/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/55/component_samples"}}}},{"id":"56","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/56"},"attributes":{"name":"sample_DN9000001W_E7","sanger_sample_id":null,"uuid":"78d934d4-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/56/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/56/sample_metadata"},"data":{"type":"sample_metadata","id":"56"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/56/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/56/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/56/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/56/component_samples"}}}},{"id":"57","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/57"},"attributes":{"name":"sample_DN9000001W_E8","sanger_sample_id":null,"uuid":"78e25dfc-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/57/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/57/sample_metadata"},"data":{"type":"sample_metadata","id":"57"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/57/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/57/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/57/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/57/component_samples"}}}},{"id":"58","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/58"},"attributes":{"name":"sample_DN9000001W_E9","sanger_sample_id":null,"uuid":"78ed8740-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/58/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/58/sample_metadata"},"data":{"type":"sample_metadata","id":"58"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/58/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/58/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/58/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/58/component_samples"}}}},{"id":"59","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/59"},"attributes":{"name":"sample_DN9000001W_E10","sanger_sample_id":null,"uuid":"78f6ce9a-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/59/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/59/sample_metadata"},"data":{"type":"sample_metadata","id":"59"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/59/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/59/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/59/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/59/component_samples"}}}},{"id":"60","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/60"},"attributes":{"name":"sample_DN9000001W_E11","sanger_sample_id":null,"uuid":"78fef296-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/60/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/60/sample_metadata"},"data":{"type":"sample_metadata","id":"60"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/60/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/60/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/60/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/60/component_samples"}}}},{"id":"61","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/61"},"attributes":{"name":"sample_DN9000001W_E12","sanger_sample_id":null,"uuid":"7906692c-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/61/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/61/sample_metadata"},"data":{"type":"sample_metadata","id":"61"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/61/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/61/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/61/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/61/component_samples"}}}},{"id":"62","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/62"},"attributes":{"name":"sample_DN9000001W_F1","sanger_sample_id":null,"uuid":"790db880-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/62/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/62/sample_metadata"},"data":{"type":"sample_metadata","id":"62"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/62/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/62/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/62/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/62/component_samples"}}}},{"id":"63","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/63"},"attributes":{"name":"sample_DN9000001W_F2","sanger_sample_id":null,"uuid":"7914f69a-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/63/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/63/sample_metadata"},"data":{"type":"sample_metadata","id":"63"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/63/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/63/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/63/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/63/component_samples"}}}},{"id":"64","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/64"},"attributes":{"name":"sample_DN9000001W_F3","sanger_sample_id":null,"uuid":"791c50c0-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/64/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/64/sample_metadata"},"data":{"type":"sample_metadata","id":"64"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/64/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/64/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/64/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/64/component_samples"}}}},{"id":"65","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/65"},"attributes":{"name":"sample_DN9000001W_F4","sanger_sample_id":null,"uuid":"7923e628-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/65/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/65/sample_metadata"},"data":{"type":"sample_metadata","id":"65"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/65/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/65/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/65/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/65/component_samples"}}}},{"id":"66","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/66"},"attributes":{"name":"sample_DN9000001W_F5","sanger_sample_id":null,"uuid":"7932f816-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/66/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/66/sample_metadata"},"data":{"type":"sample_metadata","id":"66"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/66/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/66/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/66/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/66/component_samples"}}}},{"id":"67","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/67"},"attributes":{"name":"sample_DN9000001W_F6","sanger_sample_id":null,"uuid":"793c21de-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/67/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/67/sample_metadata"},"data":{"type":"sample_metadata","id":"67"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/67/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/67/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/67/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/67/component_samples"}}}},{"id":"68","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/68"},"attributes":{"name":"sample_DN9000001W_F7","sanger_sample_id":null,"uuid":"79449cec-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/68/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/68/sample_metadata"},"data":{"type":"sample_metadata","id":"68"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/68/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/68/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/68/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/68/component_samples"}}}},{"id":"69","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/69"},"attributes":{"name":"sample_DN9000001W_F8","sanger_sample_id":null,"uuid":"794cb7b0-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/69/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/69/sample_metadata"},"data":{"type":"sample_metadata","id":"69"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/69/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/69/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/69/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/69/component_samples"}}}},{"id":"70","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/70"},"attributes":{"name":"sample_DN9000001W_F9","sanger_sample_id":null,"uuid":"7956ea00-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/70/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/70/sample_metadata"},"data":{"type":"sample_metadata","id":"70"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/70/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/70/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/70/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/70/component_samples"}}}},{"id":"71","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/71"},"attributes":{"name":"sample_DN9000001W_F10","sanger_sample_id":null,"uuid":"796952bc-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/71/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/71/sample_metadata"},"data":{"type":"sample_metadata","id":"71"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/71/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/71/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/71/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/71/component_samples"}}}},{"id":"72","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/72"},"attributes":{"name":"sample_DN9000001W_F11","sanger_sample_id":null,"uuid":"7972d026-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/72/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/72/sample_metadata"},"data":{"type":"sample_metadata","id":"72"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/72/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/72/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/72/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/72/component_samples"}}}},{"id":"73","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/73"},"attributes":{"name":"sample_DN9000001W_F12","sanger_sample_id":null,"uuid":"797a4d4c-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/73/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/73/sample_metadata"},"data":{"type":"sample_metadata","id":"73"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/73/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/73/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/73/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/73/component_samples"}}}},{"id":"74","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/74"},"attributes":{"name":"sample_DN9000001W_G1","sanger_sample_id":null,"uuid":"7981542a-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/74/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/74/sample_metadata"},"data":{"type":"sample_metadata","id":"74"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/74/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/74/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/74/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/74/component_samples"}}}},{"id":"75","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/75"},"attributes":{"name":"sample_DN9000001W_G2","sanger_sample_id":null,"uuid":"798950e4-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/75/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/75/sample_metadata"},"data":{"type":"sample_metadata","id":"75"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/75/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/75/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/75/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/75/component_samples"}}}},{"id":"76","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/76"},"attributes":{"name":"sample_DN9000001W_G3","sanger_sample_id":null,"uuid":"79916f18-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/76/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/76/sample_metadata"},"data":{"type":"sample_metadata","id":"76"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/76/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/76/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/76/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/76/component_samples"}}}},{"id":"77","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/77"},"attributes":{"name":"sample_DN9000001W_G4","sanger_sample_id":null,"uuid":"79993ef0-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/77/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/77/sample_metadata"},"data":{"type":"sample_metadata","id":"77"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/77/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/77/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/77/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/77/component_samples"}}}},{"id":"78","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/78"},"attributes":{"name":"sample_DN9000001W_G5","sanger_sample_id":null,"uuid":"79a144f6-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/78/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/78/sample_metadata"},"data":{"type":"sample_metadata","id":"78"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/78/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/78/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/78/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/78/component_samples"}}}},{"id":"79","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/79"},"attributes":{"name":"sample_DN9000001W_G6","sanger_sample_id":null,"uuid":"79a86a60-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/79/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/79/sample_metadata"},"data":{"type":"sample_metadata","id":"79"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/79/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/79/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/79/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/79/component_samples"}}}},{"id":"80","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/80"},"attributes":{"name":"sample_DN9000001W_G7","sanger_sample_id":null,"uuid":"79afc850-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/80/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/80/sample_metadata"},"data":{"type":"sample_metadata","id":"80"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/80/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/80/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/80/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/80/component_samples"}}}},{"id":"81","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/81"},"attributes":{"name":"sample_DN9000001W_G8","sanger_sample_id":null,"uuid":"79b73b08-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/81/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/81/sample_metadata"},"data":{"type":"sample_metadata","id":"81"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/81/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/81/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/81/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/81/component_samples"}}}},{"id":"82","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/82"},"attributes":{"name":"sample_DN9000001W_G9","sanger_sample_id":null,"uuid":"79c71032-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/82/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/82/sample_metadata"},"data":{"type":"sample_metadata","id":"82"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/82/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/82/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/82/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/82/component_samples"}}}},{"id":"83","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/83"},"attributes":{"name":"sample_DN9000001W_G10","sanger_sample_id":null,"uuid":"79ce40a0-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/83/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/83/sample_metadata"},"data":{"type":"sample_metadata","id":"83"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/83/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/83/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/83/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/83/component_samples"}}}},{"id":"84","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/84"},"attributes":{"name":"sample_DN9000001W_G11","sanger_sample_id":null,"uuid":"79d553f4-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/84/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/84/sample_metadata"},"data":{"type":"sample_metadata","id":"84"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/84/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/84/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/84/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/84/component_samples"}}}},{"id":"85","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/85"},"attributes":{"name":"sample_DN9000001W_G12","sanger_sample_id":null,"uuid":"79dcc076-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/85/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/85/sample_metadata"},"data":{"type":"sample_metadata","id":"85"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/85/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/85/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/85/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/85/component_samples"}}}},{"id":"86","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/86"},"attributes":{"name":"sample_DN9000001W_H1","sanger_sample_id":null,"uuid":"79e41ab0-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/86/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/86/sample_metadata"},"data":{"type":"sample_metadata","id":"86"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/86/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/86/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/86/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/86/component_samples"}}}},{"id":"87","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/87"},"attributes":{"name":"sample_DN9000001W_H2","sanger_sample_id":null,"uuid":"79f1f536-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/87/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/87/sample_metadata"},"data":{"type":"sample_metadata","id":"87"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/87/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/87/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/87/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/87/component_samples"}}}},{"id":"88","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/88"},"attributes":{"name":"sample_DN9000001W_H3","sanger_sample_id":null,"uuid":"79fa86ba-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/88/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/88/sample_metadata"},"data":{"type":"sample_metadata","id":"88"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/88/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/88/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/88/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/88/component_samples"}}}},{"id":"89","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/89"},"attributes":{"name":"sample_DN9000001W_H4","sanger_sample_id":null,"uuid":"7a0abe68-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/89/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/89/sample_metadata"},"data":{"type":"sample_metadata","id":"89"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/89/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/89/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/89/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/89/component_samples"}}}},{"id":"90","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/90"},"attributes":{"name":"sample_DN9000001W_H5","sanger_sample_id":null,"uuid":"7a129eb2-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/90/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/90/sample_metadata"},"data":{"type":"sample_metadata","id":"90"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/90/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/90/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/90/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/90/component_samples"}}}},{"id":"91","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/91"},"attributes":{"name":"sample_DN9000001W_H6","sanger_sample_id":null,"uuid":"7a1ac51a-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/91/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/91/sample_metadata"},"data":{"type":"sample_metadata","id":"91"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/91/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/91/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/91/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/91/component_samples"}}}},{"id":"92","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/92"},"attributes":{"name":"sample_DN9000001W_H7","sanger_sample_id":null,"uuid":"7a22a0b4-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/92/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/92/sample_metadata"},"data":{"type":"sample_metadata","id":"92"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/92/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/92/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/92/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/92/component_samples"}}}},{"id":"93","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/93"},"attributes":{"name":"sample_DN9000001W_H8","sanger_sample_id":null,"uuid":"7a2b6eb0-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/93/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/93/sample_metadata"},"data":{"type":"sample_metadata","id":"93"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/93/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/93/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/93/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/93/component_samples"}}}},{"id":"94","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/94"},"attributes":{"name":"sample_DN9000001W_H9","sanger_sample_id":null,"uuid":"7a3578d8-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/94/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/94/sample_metadata"},"data":{"type":"sample_metadata","id":"94"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/94/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/94/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/94/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/94/component_samples"}}}},{"id":"95","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/95"},"attributes":{"name":"sample_DN9000001W_H10","sanger_sample_id":null,"uuid":"7a3c7264-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/95/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/95/sample_metadata"},"data":{"type":"sample_metadata","id":"95"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/95/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/95/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/95/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/95/component_samples"}}}},{"id":"96","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/96"},"attributes":{"name":"sample_DN9000001W_H11","sanger_sample_id":null,"uuid":"7a445a56-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/96/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/96/sample_metadata"},"data":{"type":"sample_metadata","id":"96"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/96/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/96/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/96/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/96/component_samples"}}}},{"id":"97","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/97"},"attributes":{"name":"sample_DN9000001W_H12","sanger_sample_id":null,"uuid":"7a4de788-9a21-11ec-9a02-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/97/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/97/sample_metadata"},"data":{"type":"sample_metadata","id":"97"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/97/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/97/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/97/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/97/component_samples"}}}},{"id":"2","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/2"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"3","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/3"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"4","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/4"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"5","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/5"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"6","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/6"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"7","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/7"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"8","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/8"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"9","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/9"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"10","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/10"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"11","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/11"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"12","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/12"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"13","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/13"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"14","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/14"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"15","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/15"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"16","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/16"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"17","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/17"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"18","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/18"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"19","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/19"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"20","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/20"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"21","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/21"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"22","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/22"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"23","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/23"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"24","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/24"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"25","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/25"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"26","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/26"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"27","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/27"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"28","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/28"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"29","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/29"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"30","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/30"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"31","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/31"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"32","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/32"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"33","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/33"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"34","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/34"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"35","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/35"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"36","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/36"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"37","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/37"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"38","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/38"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"39","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/39"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"40","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/40"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"41","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/41"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"42","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/42"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"43","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/43"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"44","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/44"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"45","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/45"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"46","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/46"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"47","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/47"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"48","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/48"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"49","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/49"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"50","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/50"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"51","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/51"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"52","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/52"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"53","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/53"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"54","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/54"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"55","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/55"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"56","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/56"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"57","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/57"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"58","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/58"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"59","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/59"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"60","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/60"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"61","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/61"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"62","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/62"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"63","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/63"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"64","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/64"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"65","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/65"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"66","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/66"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"67","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/67"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"68","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/68"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"69","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/69"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"70","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/70"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"71","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/71"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"72","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/72"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"73","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/73"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"74","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/74"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"75","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/75"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"76","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/76"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"77","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/77"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"78","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/78"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"79","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/79"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"80","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/80"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"81","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/81"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"82","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/82"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"83","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/83"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"84","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/84"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"85","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/85"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"86","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/86"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"87","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/87"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"88","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/88"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"89","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/89"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"90","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/90"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"91","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/91"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"92","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/92"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"93","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/93"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"94","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/94"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"95","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/95"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"96","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/96"},"attributes":{"sample_common_name":null,"supplier_name":null}},{"id":"97","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/97"},"attributes":{"sample_common_name":null,"supplier_name":null}}],"links":{"first":"http://localhost:3000/api/v2/plates?filter%5Bbarcode%5D=DN9000001W&include=wells.aliquots.sample.sample_metadata%2Cwells.aliquots.study&page%5Bnumber%5D=1&page%5Bsize%5D=100","last":"http://localhost:3000/api/v2/plates?filter%5Bbarcode%5D=DN9000001W&include=wells.aliquots.sample.sample_metadata%2Cwells.aliquots.study&page%5Bnumber%5D=1&page%5Bsize%5D=100"}} \ No newline at end of file diff --git a/spec/support/responses/sequencescape/v2/tube_rack_response.txt b/spec/support/responses/sequencescape/v2/tube_rack_response.txt new file mode 100644 index 00000000..d7f6257c --- /dev/null +++ b/spec/support/responses/sequencescape/v2/tube_rack_response.txt @@ -0,0 +1,18 @@ +HTTP/1.1 200 OK +X-Frame-Options: SAMEORIGIN +X-XSS-Protection: 1; mode=block +X-Content-Type-Options: nosniff +X-Download-Options: noopen +X-Permitted-Cross-Domain-Policies: none +Referrer-Policy: strict-origin-when-cross-origin +Content-Type: application/vnd.api+json +Cache-Control: no-store, must-revalidate, private, max-age=0 +X-Request-Id: cfb52802-da5a-4417-ad04-54adafcd8071 +X-Runtime: 0.230121 +Vary: Origin +X-MiniProfiler-Original-Cache-Control: max-age=0, private, must-revalidate +X-MiniProfiler-Ids: uvj2z64xujm35luv0cv6,zefd3e9hcd9u3w0c0y3g,m6epucidfi055lx60z1z,kd9eqlh6f36or8r6gfav,vjl0yz1jnm9ki7arr1ej,wszgceac9sgn0jl5rx71,uo03fw227ne416z4s47p,g1waecks8hogp977ck3y,psonsyz3b2zjyfuh9z3r +Set-Cookie: __profilin=p%3Dt; path=/; HttpOnly; SameSite=Lax +Transfer-Encoding: chunked + +{"data":[{"id":"4","type":"tube_racks","links":{"self":"http://localhost:3000/api/v2/tube_racks/4"},"attributes":{"uuid":"f3834d5e-9fb3-11ec-a4f7-acde48001122","created_at":"2022-03-09T14:19:37+00:00","updated_at":"2022-03-09T14:19:37+00:00","labware_barcode":{"ean13_barcode":null,"machine_barcode":"AB42785517","human_barcode":"AB42785517"},"size":96,"number_of_rows":8,"number_of_columns":12,"name":null},"relationships":{"racked_tubes":{"links":{"self":"http://localhost:3000/api/v2/tube_racks/4/relationships/racked_tubes","related":"http://localhost:3000/api/v2/tube_racks/4/racked_tubes"},"data":[{"type":"racked_tubes","id":"1"},{"type":"racked_tubes","id":"2"},{"type":"racked_tubes","id":"3"},{"type":"racked_tubes","id":"4"},{"type":"racked_tubes","id":"5"},{"type":"racked_tubes","id":"6"},{"type":"racked_tubes","id":"7"},{"type":"racked_tubes","id":"8"},{"type":"racked_tubes","id":"9"},{"type":"racked_tubes","id":"10"},{"type":"racked_tubes","id":"11"},{"type":"racked_tubes","id":"12"},{"type":"racked_tubes","id":"13"},{"type":"racked_tubes","id":"14"},{"type":"racked_tubes","id":"15"},{"type":"racked_tubes","id":"16"},{"type":"racked_tubes","id":"17"},{"type":"racked_tubes","id":"18"},{"type":"racked_tubes","id":"19"},{"type":"racked_tubes","id":"20"},{"type":"racked_tubes","id":"21"},{"type":"racked_tubes","id":"22"},{"type":"racked_tubes","id":"23"},{"type":"racked_tubes","id":"24"},{"type":"racked_tubes","id":"25"},{"type":"racked_tubes","id":"26"},{"type":"racked_tubes","id":"27"},{"type":"racked_tubes","id":"28"},{"type":"racked_tubes","id":"29"},{"type":"racked_tubes","id":"30"},{"type":"racked_tubes","id":"31"},{"type":"racked_tubes","id":"32"},{"type":"racked_tubes","id":"33"},{"type":"racked_tubes","id":"34"},{"type":"racked_tubes","id":"35"},{"type":"racked_tubes","id":"36"},{"type":"racked_tubes","id":"37"},{"type":"racked_tubes","id":"38"},{"type":"racked_tubes","id":"39"},{"type":"racked_tubes","id":"40"},{"type":"racked_tubes","id":"41"},{"type":"racked_tubes","id":"42"},{"type":"racked_tubes","id":"43"},{"type":"racked_tubes","id":"44"},{"type":"racked_tubes","id":"45"},{"type":"racked_tubes","id":"46"},{"type":"racked_tubes","id":"47"},{"type":"racked_tubes","id":"48"},{"type":"racked_tubes","id":"49"},{"type":"racked_tubes","id":"50"},{"type":"racked_tubes","id":"51"},{"type":"racked_tubes","id":"52"},{"type":"racked_tubes","id":"53"},{"type":"racked_tubes","id":"54"},{"type":"racked_tubes","id":"55"},{"type":"racked_tubes","id":"56"},{"type":"racked_tubes","id":"57"},{"type":"racked_tubes","id":"58"},{"type":"racked_tubes","id":"59"},{"type":"racked_tubes","id":"60"},{"type":"racked_tubes","id":"61"},{"type":"racked_tubes","id":"62"},{"type":"racked_tubes","id":"63"},{"type":"racked_tubes","id":"64"},{"type":"racked_tubes","id":"65"},{"type":"racked_tubes","id":"66"},{"type":"racked_tubes","id":"67"},{"type":"racked_tubes","id":"68"},{"type":"racked_tubes","id":"69"},{"type":"racked_tubes","id":"70"},{"type":"racked_tubes","id":"71"},{"type":"racked_tubes","id":"72"},{"type":"racked_tubes","id":"73"},{"type":"racked_tubes","id":"74"},{"type":"racked_tubes","id":"75"},{"type":"racked_tubes","id":"76"},{"type":"racked_tubes","id":"77"},{"type":"racked_tubes","id":"78"},{"type":"racked_tubes","id":"79"},{"type":"racked_tubes","id":"80"},{"type":"racked_tubes","id":"81"},{"type":"racked_tubes","id":"82"},{"type":"racked_tubes","id":"83"},{"type":"racked_tubes","id":"84"},{"type":"racked_tubes","id":"85"},{"type":"racked_tubes","id":"86"},{"type":"racked_tubes","id":"87"},{"type":"racked_tubes","id":"88"},{"type":"racked_tubes","id":"89"},{"type":"racked_tubes","id":"90"},{"type":"racked_tubes","id":"91"},{"type":"racked_tubes","id":"92"},{"type":"racked_tubes","id":"93"},{"type":"racked_tubes","id":"94"},{"type":"racked_tubes","id":"95"},{"type":"racked_tubes","id":"96"}]},"comments":{"links":{"self":"http://localhost:3000/api/v2/tube_racks/4/relationships/comments","related":"http://localhost:3000/api/v2/tube_racks/4/comments"}},"purpose":{"links":{"self":"http://localhost:3000/api/v2/tube_racks/4/relationships/purpose","related":"http://localhost:3000/api/v2/tube_racks/4/purpose"}}}}],"included":[{"id":"1","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/1"},"attributes":{"coordinate":"A1"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/1/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/1/tube"},"data":{"type":"tubes","id":"5"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/1/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/1/tube_rack"}}}},{"id":"2","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/2"},"attributes":{"coordinate":"A2"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/2/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/2/tube"},"data":{"type":"tubes","id":"6"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/2/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/2/tube_rack"}}}},{"id":"3","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/3"},"attributes":{"coordinate":"A3"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/3/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/3/tube"},"data":{"type":"tubes","id":"7"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/3/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/3/tube_rack"}}}},{"id":"4","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/4"},"attributes":{"coordinate":"A4"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/4/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/4/tube"},"data":{"type":"tubes","id":"8"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/4/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/4/tube_rack"}}}},{"id":"5","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/5"},"attributes":{"coordinate":"A5"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/5/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/5/tube"},"data":{"type":"tubes","id":"9"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/5/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/5/tube_rack"}}}},{"id":"6","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/6"},"attributes":{"coordinate":"A6"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/6/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/6/tube"},"data":{"type":"tubes","id":"10"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/6/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/6/tube_rack"}}}},{"id":"7","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/7"},"attributes":{"coordinate":"A7"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/7/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/7/tube"},"data":{"type":"tubes","id":"11"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/7/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/7/tube_rack"}}}},{"id":"8","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/8"},"attributes":{"coordinate":"A8"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/8/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/8/tube"},"data":{"type":"tubes","id":"12"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/8/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/8/tube_rack"}}}},{"id":"9","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/9"},"attributes":{"coordinate":"A9"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/9/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/9/tube"},"data":{"type":"tubes","id":"13"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/9/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/9/tube_rack"}}}},{"id":"10","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/10"},"attributes":{"coordinate":"A10"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/10/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/10/tube"},"data":{"type":"tubes","id":"14"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/10/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/10/tube_rack"}}}},{"id":"11","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/11"},"attributes":{"coordinate":"A11"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/11/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/11/tube"},"data":{"type":"tubes","id":"15"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/11/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/11/tube_rack"}}}},{"id":"12","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/12"},"attributes":{"coordinate":"A12"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/12/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/12/tube"},"data":{"type":"tubes","id":"16"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/12/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/12/tube_rack"}}}},{"id":"13","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/13"},"attributes":{"coordinate":"B1"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/13/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/13/tube"},"data":{"type":"tubes","id":"17"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/13/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/13/tube_rack"}}}},{"id":"14","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/14"},"attributes":{"coordinate":"B2"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/14/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/14/tube"},"data":{"type":"tubes","id":"18"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/14/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/14/tube_rack"}}}},{"id":"15","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/15"},"attributes":{"coordinate":"B3"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/15/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/15/tube"},"data":{"type":"tubes","id":"19"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/15/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/15/tube_rack"}}}},{"id":"16","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/16"},"attributes":{"coordinate":"B4"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/16/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/16/tube"},"data":{"type":"tubes","id":"20"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/16/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/16/tube_rack"}}}},{"id":"17","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/17"},"attributes":{"coordinate":"B5"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/17/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/17/tube"},"data":{"type":"tubes","id":"21"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/17/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/17/tube_rack"}}}},{"id":"18","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/18"},"attributes":{"coordinate":"B6"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/18/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/18/tube"},"data":{"type":"tubes","id":"22"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/18/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/18/tube_rack"}}}},{"id":"19","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/19"},"attributes":{"coordinate":"B7"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/19/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/19/tube"},"data":{"type":"tubes","id":"23"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/19/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/19/tube_rack"}}}},{"id":"20","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/20"},"attributes":{"coordinate":"B8"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/20/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/20/tube"},"data":{"type":"tubes","id":"24"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/20/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/20/tube_rack"}}}},{"id":"21","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/21"},"attributes":{"coordinate":"B9"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/21/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/21/tube"},"data":{"type":"tubes","id":"25"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/21/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/21/tube_rack"}}}},{"id":"22","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/22"},"attributes":{"coordinate":"B10"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/22/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/22/tube"},"data":{"type":"tubes","id":"26"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/22/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/22/tube_rack"}}}},{"id":"23","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/23"},"attributes":{"coordinate":"B11"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/23/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/23/tube"},"data":{"type":"tubes","id":"27"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/23/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/23/tube_rack"}}}},{"id":"24","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/24"},"attributes":{"coordinate":"B12"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/24/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/24/tube"},"data":{"type":"tubes","id":"28"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/24/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/24/tube_rack"}}}},{"id":"25","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/25"},"attributes":{"coordinate":"C1"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/25/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/25/tube"},"data":{"type":"tubes","id":"29"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/25/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/25/tube_rack"}}}},{"id":"26","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/26"},"attributes":{"coordinate":"C2"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/26/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/26/tube"},"data":{"type":"tubes","id":"30"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/26/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/26/tube_rack"}}}},{"id":"27","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/27"},"attributes":{"coordinate":"C3"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/27/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/27/tube"},"data":{"type":"tubes","id":"31"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/27/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/27/tube_rack"}}}},{"id":"28","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/28"},"attributes":{"coordinate":"C4"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/28/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/28/tube"},"data":{"type":"tubes","id":"32"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/28/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/28/tube_rack"}}}},{"id":"29","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/29"},"attributes":{"coordinate":"C5"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/29/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/29/tube"},"data":{"type":"tubes","id":"33"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/29/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/29/tube_rack"}}}},{"id":"30","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/30"},"attributes":{"coordinate":"C6"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/30/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/30/tube"},"data":{"type":"tubes","id":"34"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/30/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/30/tube_rack"}}}},{"id":"31","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/31"},"attributes":{"coordinate":"C7"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/31/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/31/tube"},"data":{"type":"tubes","id":"35"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/31/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/31/tube_rack"}}}},{"id":"32","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/32"},"attributes":{"coordinate":"C8"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/32/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/32/tube"},"data":{"type":"tubes","id":"36"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/32/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/32/tube_rack"}}}},{"id":"33","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/33"},"attributes":{"coordinate":"C9"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/33/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/33/tube"},"data":{"type":"tubes","id":"37"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/33/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/33/tube_rack"}}}},{"id":"34","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/34"},"attributes":{"coordinate":"C10"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/34/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/34/tube"},"data":{"type":"tubes","id":"38"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/34/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/34/tube_rack"}}}},{"id":"35","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/35"},"attributes":{"coordinate":"C11"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/35/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/35/tube"},"data":{"type":"tubes","id":"39"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/35/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/35/tube_rack"}}}},{"id":"36","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/36"},"attributes":{"coordinate":"C12"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/36/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/36/tube"},"data":{"type":"tubes","id":"40"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/36/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/36/tube_rack"}}}},{"id":"37","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/37"},"attributes":{"coordinate":"D1"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/37/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/37/tube"},"data":{"type":"tubes","id":"41"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/37/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/37/tube_rack"}}}},{"id":"38","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/38"},"attributes":{"coordinate":"D2"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/38/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/38/tube"},"data":{"type":"tubes","id":"42"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/38/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/38/tube_rack"}}}},{"id":"39","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/39"},"attributes":{"coordinate":"D3"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/39/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/39/tube"},"data":{"type":"tubes","id":"43"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/39/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/39/tube_rack"}}}},{"id":"40","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/40"},"attributes":{"coordinate":"D4"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/40/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/40/tube"},"data":{"type":"tubes","id":"44"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/40/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/40/tube_rack"}}}},{"id":"41","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/41"},"attributes":{"coordinate":"D5"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/41/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/41/tube"},"data":{"type":"tubes","id":"45"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/41/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/41/tube_rack"}}}},{"id":"42","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/42"},"attributes":{"coordinate":"D6"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/42/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/42/tube"},"data":{"type":"tubes","id":"46"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/42/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/42/tube_rack"}}}},{"id":"43","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/43"},"attributes":{"coordinate":"D7"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/43/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/43/tube"},"data":{"type":"tubes","id":"47"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/43/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/43/tube_rack"}}}},{"id":"44","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/44"},"attributes":{"coordinate":"D8"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/44/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/44/tube"},"data":{"type":"tubes","id":"48"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/44/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/44/tube_rack"}}}},{"id":"45","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/45"},"attributes":{"coordinate":"D9"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/45/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/45/tube"},"data":{"type":"tubes","id":"49"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/45/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/45/tube_rack"}}}},{"id":"46","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/46"},"attributes":{"coordinate":"D10"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/46/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/46/tube"},"data":{"type":"tubes","id":"50"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/46/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/46/tube_rack"}}}},{"id":"47","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/47"},"attributes":{"coordinate":"D11"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/47/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/47/tube"},"data":{"type":"tubes","id":"51"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/47/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/47/tube_rack"}}}},{"id":"48","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/48"},"attributes":{"coordinate":"D12"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/48/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/48/tube"},"data":{"type":"tubes","id":"52"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/48/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/48/tube_rack"}}}},{"id":"49","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/49"},"attributes":{"coordinate":"E1"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/49/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/49/tube"},"data":{"type":"tubes","id":"53"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/49/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/49/tube_rack"}}}},{"id":"50","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/50"},"attributes":{"coordinate":"E2"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/50/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/50/tube"},"data":{"type":"tubes","id":"54"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/50/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/50/tube_rack"}}}},{"id":"51","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/51"},"attributes":{"coordinate":"E3"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/51/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/51/tube"},"data":{"type":"tubes","id":"55"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/51/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/51/tube_rack"}}}},{"id":"52","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/52"},"attributes":{"coordinate":"E4"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/52/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/52/tube"},"data":{"type":"tubes","id":"56"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/52/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/52/tube_rack"}}}},{"id":"53","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/53"},"attributes":{"coordinate":"E5"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/53/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/53/tube"},"data":{"type":"tubes","id":"57"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/53/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/53/tube_rack"}}}},{"id":"54","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/54"},"attributes":{"coordinate":"E6"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/54/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/54/tube"},"data":{"type":"tubes","id":"58"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/54/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/54/tube_rack"}}}},{"id":"55","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/55"},"attributes":{"coordinate":"E7"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/55/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/55/tube"},"data":{"type":"tubes","id":"59"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/55/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/55/tube_rack"}}}},{"id":"56","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/56"},"attributes":{"coordinate":"E8"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/56/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/56/tube"},"data":{"type":"tubes","id":"60"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/56/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/56/tube_rack"}}}},{"id":"57","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/57"},"attributes":{"coordinate":"E9"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/57/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/57/tube"},"data":{"type":"tubes","id":"61"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/57/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/57/tube_rack"}}}},{"id":"58","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/58"},"attributes":{"coordinate":"E10"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/58/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/58/tube"},"data":{"type":"tubes","id":"62"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/58/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/58/tube_rack"}}}},{"id":"59","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/59"},"attributes":{"coordinate":"E11"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/59/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/59/tube"},"data":{"type":"tubes","id":"63"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/59/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/59/tube_rack"}}}},{"id":"60","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/60"},"attributes":{"coordinate":"E12"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/60/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/60/tube"},"data":{"type":"tubes","id":"64"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/60/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/60/tube_rack"}}}},{"id":"61","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/61"},"attributes":{"coordinate":"F1"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/61/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/61/tube"},"data":{"type":"tubes","id":"65"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/61/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/61/tube_rack"}}}},{"id":"62","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/62"},"attributes":{"coordinate":"F2"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/62/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/62/tube"},"data":{"type":"tubes","id":"66"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/62/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/62/tube_rack"}}}},{"id":"63","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/63"},"attributes":{"coordinate":"F3"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/63/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/63/tube"},"data":{"type":"tubes","id":"67"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/63/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/63/tube_rack"}}}},{"id":"64","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/64"},"attributes":{"coordinate":"F4"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/64/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/64/tube"},"data":{"type":"tubes","id":"68"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/64/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/64/tube_rack"}}}},{"id":"65","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/65"},"attributes":{"coordinate":"F5"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/65/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/65/tube"},"data":{"type":"tubes","id":"69"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/65/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/65/tube_rack"}}}},{"id":"66","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/66"},"attributes":{"coordinate":"F6"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/66/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/66/tube"},"data":{"type":"tubes","id":"70"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/66/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/66/tube_rack"}}}},{"id":"67","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/67"},"attributes":{"coordinate":"F7"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/67/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/67/tube"},"data":{"type":"tubes","id":"71"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/67/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/67/tube_rack"}}}},{"id":"68","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/68"},"attributes":{"coordinate":"F8"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/68/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/68/tube"},"data":{"type":"tubes","id":"72"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/68/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/68/tube_rack"}}}},{"id":"69","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/69"},"attributes":{"coordinate":"F9"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/69/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/69/tube"},"data":{"type":"tubes","id":"73"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/69/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/69/tube_rack"}}}},{"id":"70","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/70"},"attributes":{"coordinate":"F10"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/70/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/70/tube"},"data":{"type":"tubes","id":"74"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/70/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/70/tube_rack"}}}},{"id":"71","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/71"},"attributes":{"coordinate":"F11"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/71/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/71/tube"},"data":{"type":"tubes","id":"75"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/71/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/71/tube_rack"}}}},{"id":"72","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/72"},"attributes":{"coordinate":"F12"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/72/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/72/tube"},"data":{"type":"tubes","id":"76"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/72/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/72/tube_rack"}}}},{"id":"73","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/73"},"attributes":{"coordinate":"G1"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/73/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/73/tube"},"data":{"type":"tubes","id":"77"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/73/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/73/tube_rack"}}}},{"id":"74","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/74"},"attributes":{"coordinate":"G2"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/74/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/74/tube"},"data":{"type":"tubes","id":"78"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/74/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/74/tube_rack"}}}},{"id":"75","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/75"},"attributes":{"coordinate":"G3"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/75/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/75/tube"},"data":{"type":"tubes","id":"79"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/75/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/75/tube_rack"}}}},{"id":"76","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/76"},"attributes":{"coordinate":"G4"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/76/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/76/tube"},"data":{"type":"tubes","id":"80"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/76/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/76/tube_rack"}}}},{"id":"77","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/77"},"attributes":{"coordinate":"G5"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/77/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/77/tube"},"data":{"type":"tubes","id":"81"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/77/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/77/tube_rack"}}}},{"id":"78","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/78"},"attributes":{"coordinate":"G6"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/78/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/78/tube"},"data":{"type":"tubes","id":"82"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/78/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/78/tube_rack"}}}},{"id":"79","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/79"},"attributes":{"coordinate":"G7"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/79/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/79/tube"},"data":{"type":"tubes","id":"83"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/79/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/79/tube_rack"}}}},{"id":"80","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/80"},"attributes":{"coordinate":"G8"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/80/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/80/tube"},"data":{"type":"tubes","id":"84"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/80/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/80/tube_rack"}}}},{"id":"81","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/81"},"attributes":{"coordinate":"G9"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/81/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/81/tube"},"data":{"type":"tubes","id":"85"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/81/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/81/tube_rack"}}}},{"id":"82","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/82"},"attributes":{"coordinate":"G10"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/82/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/82/tube"},"data":{"type":"tubes","id":"86"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/82/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/82/tube_rack"}}}},{"id":"83","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/83"},"attributes":{"coordinate":"G11"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/83/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/83/tube"},"data":{"type":"tubes","id":"87"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/83/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/83/tube_rack"}}}},{"id":"84","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/84"},"attributes":{"coordinate":"G12"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/84/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/84/tube"},"data":{"type":"tubes","id":"88"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/84/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/84/tube_rack"}}}},{"id":"85","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/85"},"attributes":{"coordinate":"H1"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/85/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/85/tube"},"data":{"type":"tubes","id":"89"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/85/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/85/tube_rack"}}}},{"id":"86","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/86"},"attributes":{"coordinate":"H2"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/86/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/86/tube"},"data":{"type":"tubes","id":"90"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/86/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/86/tube_rack"}}}},{"id":"87","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/87"},"attributes":{"coordinate":"H3"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/87/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/87/tube"},"data":{"type":"tubes","id":"91"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/87/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/87/tube_rack"}}}},{"id":"88","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/88"},"attributes":{"coordinate":"H4"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/88/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/88/tube"},"data":{"type":"tubes","id":"92"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/88/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/88/tube_rack"}}}},{"id":"89","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/89"},"attributes":{"coordinate":"H5"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/89/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/89/tube"},"data":{"type":"tubes","id":"93"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/89/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/89/tube_rack"}}}},{"id":"90","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/90"},"attributes":{"coordinate":"H6"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/90/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/90/tube"},"data":{"type":"tubes","id":"94"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/90/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/90/tube_rack"}}}},{"id":"91","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/91"},"attributes":{"coordinate":"H7"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/91/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/91/tube"},"data":{"type":"tubes","id":"95"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/91/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/91/tube_rack"}}}},{"id":"92","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/92"},"attributes":{"coordinate":"H8"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/92/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/92/tube"},"data":{"type":"tubes","id":"96"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/92/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/92/tube_rack"}}}},{"id":"93","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/93"},"attributes":{"coordinate":"H9"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/93/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/93/tube"},"data":{"type":"tubes","id":"97"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/93/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/93/tube_rack"}}}},{"id":"94","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/94"},"attributes":{"coordinate":"H10"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/94/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/94/tube"},"data":{"type":"tubes","id":"98"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/94/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/94/tube_rack"}}}},{"id":"95","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/95"},"attributes":{"coordinate":"H11"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/95/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/95/tube"},"data":{"type":"tubes","id":"99"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/95/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/95/tube_rack"}}}},{"id":"96","type":"racked_tubes","links":{"self":"http://localhost:3000/api/v2/racked_tubes/96"},"attributes":{"coordinate":"H12"},"relationships":{"tube":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/96/relationships/tube","related":"http://localhost:3000/api/v2/racked_tubes/96/tube"},"data":{"type":"tubes","id":"100"}},"tube_rack":{"links":{"self":"http://localhost:3000/api/v2/racked_tubes/96/relationships/tube_rack","related":"http://localhost:3000/api/v2/racked_tubes/96/tube_rack"}}}},{"id":"5","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/5"},"attributes":{"uuid":"f3ac29fe-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 5","labware_barcode":{"ean13_barcode":"3980000002808","machine_barcode":"3980000002808","human_barcode":"NT2P"},"state":"unknown","created_at":"2022-03-09T14:19:37+00:00","updated_at":"2022-03-09T14:19:37+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/5/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/5/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/samples","related":"http://localhost:3000/api/v2/tubes/5/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/studies","related":"http://localhost:3000/api/v2/tubes/5/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/projects","related":"http://localhost:3000/api/v2/tubes/5/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/comments","related":"http://localhost:3000/api/v2/tubes/5/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/5/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/5/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/5/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/parents","related":"http://localhost:3000/api/v2/tubes/5/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/children","related":"http://localhost:3000/api/v2/tubes/5/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/5/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/5/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/5/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/5/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/5/aliquots"},"data":[{"type":"aliquots","id":"97"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/5/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/5/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/5/receptacle"}}}},{"id":"6","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/6"},"attributes":{"uuid":"f40131b0-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 6","labware_barcode":{"ean13_barcode":"3980000003812","machine_barcode":"3980000003812","human_barcode":"NT3Q"},"state":"unknown","created_at":"2022-03-09T14:19:38+00:00","updated_at":"2022-03-09T14:19:38+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/6/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/6/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/samples","related":"http://localhost:3000/api/v2/tubes/6/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/studies","related":"http://localhost:3000/api/v2/tubes/6/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/projects","related":"http://localhost:3000/api/v2/tubes/6/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/comments","related":"http://localhost:3000/api/v2/tubes/6/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/6/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/6/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/6/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/parents","related":"http://localhost:3000/api/v2/tubes/6/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/children","related":"http://localhost:3000/api/v2/tubes/6/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/6/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/6/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/6/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/6/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/6/aliquots"},"data":[{"type":"aliquots","id":"98"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/6/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/6/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/6/receptacle"}}}},{"id":"7","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/7"},"attributes":{"uuid":"f41bc23c-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 7","labware_barcode":{"ean13_barcode":"3980000004826","machine_barcode":"3980000004826","human_barcode":"NT4R"},"state":"unknown","created_at":"2022-03-09T14:19:38+00:00","updated_at":"2022-03-09T14:19:38+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/7/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/7/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/samples","related":"http://localhost:3000/api/v2/tubes/7/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/studies","related":"http://localhost:3000/api/v2/tubes/7/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/projects","related":"http://localhost:3000/api/v2/tubes/7/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/comments","related":"http://localhost:3000/api/v2/tubes/7/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/7/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/7/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/7/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/parents","related":"http://localhost:3000/api/v2/tubes/7/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/children","related":"http://localhost:3000/api/v2/tubes/7/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/7/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/7/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/7/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/7/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/7/aliquots"},"data":[{"type":"aliquots","id":"99"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/7/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/7/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/7/receptacle"}}}},{"id":"8","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/8"},"attributes":{"uuid":"f44c537a-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 8","labware_barcode":{"ean13_barcode":"3980000005830","machine_barcode":"3980000005830","human_barcode":"NT5S"},"state":"unknown","created_at":"2022-03-09T14:19:38+00:00","updated_at":"2022-03-09T14:19:38+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/8/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/8/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/samples","related":"http://localhost:3000/api/v2/tubes/8/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/studies","related":"http://localhost:3000/api/v2/tubes/8/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/projects","related":"http://localhost:3000/api/v2/tubes/8/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/comments","related":"http://localhost:3000/api/v2/tubes/8/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/8/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/8/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/8/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/parents","related":"http://localhost:3000/api/v2/tubes/8/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/children","related":"http://localhost:3000/api/v2/tubes/8/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/8/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/8/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/8/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/8/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/8/aliquots"},"data":[{"type":"aliquots","id":"100"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/8/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/8/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/8/receptacle"}}}},{"id":"9","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/9"},"attributes":{"uuid":"f46228f8-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 9","labware_barcode":{"ean13_barcode":"3980000006844","machine_barcode":"3980000006844","human_barcode":"NT6T"},"state":"unknown","created_at":"2022-03-09T14:19:38+00:00","updated_at":"2022-03-09T14:19:38+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/9/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/9/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/samples","related":"http://localhost:3000/api/v2/tubes/9/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/studies","related":"http://localhost:3000/api/v2/tubes/9/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/projects","related":"http://localhost:3000/api/v2/tubes/9/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/comments","related":"http://localhost:3000/api/v2/tubes/9/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/9/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/9/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/9/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/parents","related":"http://localhost:3000/api/v2/tubes/9/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/children","related":"http://localhost:3000/api/v2/tubes/9/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/9/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/9/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/9/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/9/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/9/aliquots"},"data":[{"type":"aliquots","id":"101"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/9/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/9/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/9/receptacle"}}}},{"id":"10","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/10"},"attributes":{"uuid":"f477cf46-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 10","labware_barcode":{"ean13_barcode":"3980000007858","machine_barcode":"3980000007858","human_barcode":"NT7U"},"state":"unknown","created_at":"2022-03-09T14:19:39+00:00","updated_at":"2022-03-09T14:19:39+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/10/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/10/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/samples","related":"http://localhost:3000/api/v2/tubes/10/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/studies","related":"http://localhost:3000/api/v2/tubes/10/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/projects","related":"http://localhost:3000/api/v2/tubes/10/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/comments","related":"http://localhost:3000/api/v2/tubes/10/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/10/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/10/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/10/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/parents","related":"http://localhost:3000/api/v2/tubes/10/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/children","related":"http://localhost:3000/api/v2/tubes/10/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/10/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/10/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/10/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/10/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/10/aliquots"},"data":[{"type":"aliquots","id":"102"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/10/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/10/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/10/receptacle"}}}},{"id":"11","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/11"},"attributes":{"uuid":"f4951196-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 11","labware_barcode":{"ean13_barcode":"3980000008862","machine_barcode":"3980000008862","human_barcode":"NT8V"},"state":"unknown","created_at":"2022-03-09T14:19:39+00:00","updated_at":"2022-03-09T14:19:39+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/11/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/11/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/samples","related":"http://localhost:3000/api/v2/tubes/11/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/studies","related":"http://localhost:3000/api/v2/tubes/11/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/projects","related":"http://localhost:3000/api/v2/tubes/11/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/comments","related":"http://localhost:3000/api/v2/tubes/11/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/11/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/11/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/11/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/parents","related":"http://localhost:3000/api/v2/tubes/11/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/children","related":"http://localhost:3000/api/v2/tubes/11/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/11/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/11/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/11/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/11/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/11/aliquots"},"data":[{"type":"aliquots","id":"103"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/11/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/11/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/11/receptacle"}}}},{"id":"12","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/12"},"attributes":{"uuid":"f4aecf14-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 12","labware_barcode":{"ean13_barcode":"3980000009876","machine_barcode":"3980000009876","human_barcode":"NT9W"},"state":"unknown","created_at":"2022-03-09T14:19:39+00:00","updated_at":"2022-03-09T14:19:39+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/12/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/12/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/samples","related":"http://localhost:3000/api/v2/tubes/12/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/studies","related":"http://localhost:3000/api/v2/tubes/12/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/projects","related":"http://localhost:3000/api/v2/tubes/12/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/comments","related":"http://localhost:3000/api/v2/tubes/12/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/12/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/12/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/12/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/parents","related":"http://localhost:3000/api/v2/tubes/12/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/children","related":"http://localhost:3000/api/v2/tubes/12/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/12/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/12/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/12/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/12/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/12/aliquots"},"data":[{"type":"aliquots","id":"104"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/12/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/12/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/12/receptacle"}}}},{"id":"13","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/13"},"attributes":{"uuid":"f4cd1b04-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 13","labware_barcode":{"ean13_barcode":"3980000010858","machine_barcode":"3980000010858","human_barcode":"NT10U"},"state":"unknown","created_at":"2022-03-09T14:19:39+00:00","updated_at":"2022-03-09T14:19:39+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/13/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/13/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/samples","related":"http://localhost:3000/api/v2/tubes/13/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/studies","related":"http://localhost:3000/api/v2/tubes/13/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/projects","related":"http://localhost:3000/api/v2/tubes/13/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/comments","related":"http://localhost:3000/api/v2/tubes/13/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/13/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/13/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/13/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/parents","related":"http://localhost:3000/api/v2/tubes/13/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/children","related":"http://localhost:3000/api/v2/tubes/13/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/13/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/13/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/13/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/13/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/13/aliquots"},"data":[{"type":"aliquots","id":"105"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/13/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/13/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/13/receptacle"}}}},{"id":"14","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/14"},"attributes":{"uuid":"f4e1196a-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 14","labware_barcode":{"ean13_barcode":"3980000011862","machine_barcode":"3980000011862","human_barcode":"NT11V"},"state":"unknown","created_at":"2022-03-09T14:19:39+00:00","updated_at":"2022-03-09T14:19:39+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/14/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/14/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/samples","related":"http://localhost:3000/api/v2/tubes/14/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/studies","related":"http://localhost:3000/api/v2/tubes/14/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/projects","related":"http://localhost:3000/api/v2/tubes/14/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/comments","related":"http://localhost:3000/api/v2/tubes/14/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/14/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/14/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/14/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/parents","related":"http://localhost:3000/api/v2/tubes/14/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/children","related":"http://localhost:3000/api/v2/tubes/14/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/14/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/14/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/14/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/14/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/14/aliquots"},"data":[{"type":"aliquots","id":"106"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/14/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/14/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/14/receptacle"}}}},{"id":"15","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/15"},"attributes":{"uuid":"f4f97aaa-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 15","labware_barcode":{"ean13_barcode":"3980000012876","machine_barcode":"3980000012876","human_barcode":"NT12W"},"state":"unknown","created_at":"2022-03-09T14:19:39+00:00","updated_at":"2022-03-09T14:19:39+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/15/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/15/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/samples","related":"http://localhost:3000/api/v2/tubes/15/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/studies","related":"http://localhost:3000/api/v2/tubes/15/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/projects","related":"http://localhost:3000/api/v2/tubes/15/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/comments","related":"http://localhost:3000/api/v2/tubes/15/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/15/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/15/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/15/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/parents","related":"http://localhost:3000/api/v2/tubes/15/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/children","related":"http://localhost:3000/api/v2/tubes/15/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/15/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/15/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/15/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/15/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/15/aliquots"},"data":[{"type":"aliquots","id":"107"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/15/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/15/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/15/receptacle"}}}},{"id":"16","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/16"},"attributes":{"uuid":"f50b10b2-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 16","labware_barcode":{"ean13_barcode":"3980000013651","machine_barcode":"3980000013651","human_barcode":"NT13A"},"state":"unknown","created_at":"2022-03-09T14:19:40+00:00","updated_at":"2022-03-09T14:19:40+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/16/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/16/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/samples","related":"http://localhost:3000/api/v2/tubes/16/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/studies","related":"http://localhost:3000/api/v2/tubes/16/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/projects","related":"http://localhost:3000/api/v2/tubes/16/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/comments","related":"http://localhost:3000/api/v2/tubes/16/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/16/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/16/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/16/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/parents","related":"http://localhost:3000/api/v2/tubes/16/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/children","related":"http://localhost:3000/api/v2/tubes/16/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/16/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/16/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/16/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/16/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/16/aliquots"},"data":[{"type":"aliquots","id":"108"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/16/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/16/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/16/receptacle"}}}},{"id":"17","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/17"},"attributes":{"uuid":"f5201944-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 17","labware_barcode":{"ean13_barcode":"3980000014665","machine_barcode":"3980000014665","human_barcode":"NT14B"},"state":"unknown","created_at":"2022-03-09T14:19:40+00:00","updated_at":"2022-03-09T14:19:40+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/17/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/17/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/samples","related":"http://localhost:3000/api/v2/tubes/17/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/studies","related":"http://localhost:3000/api/v2/tubes/17/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/projects","related":"http://localhost:3000/api/v2/tubes/17/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/comments","related":"http://localhost:3000/api/v2/tubes/17/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/17/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/17/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/17/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/parents","related":"http://localhost:3000/api/v2/tubes/17/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/children","related":"http://localhost:3000/api/v2/tubes/17/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/17/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/17/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/17/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/17/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/17/aliquots"},"data":[{"type":"aliquots","id":"109"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/17/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/17/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/17/receptacle"}}}},{"id":"18","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/18"},"attributes":{"uuid":"f53a92ce-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 18","labware_barcode":{"ean13_barcode":"3980000015679","machine_barcode":"3980000015679","human_barcode":"NT15C"},"state":"unknown","created_at":"2022-03-09T14:19:40+00:00","updated_at":"2022-03-09T14:19:40+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/18/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/18/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/samples","related":"http://localhost:3000/api/v2/tubes/18/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/studies","related":"http://localhost:3000/api/v2/tubes/18/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/projects","related":"http://localhost:3000/api/v2/tubes/18/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/comments","related":"http://localhost:3000/api/v2/tubes/18/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/18/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/18/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/18/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/parents","related":"http://localhost:3000/api/v2/tubes/18/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/children","related":"http://localhost:3000/api/v2/tubes/18/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/18/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/18/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/18/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/18/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/18/aliquots"},"data":[{"type":"aliquots","id":"110"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/18/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/18/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/18/receptacle"}}}},{"id":"19","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/19"},"attributes":{"uuid":"f54b887c-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 19","labware_barcode":{"ean13_barcode":"3980000016683","machine_barcode":"3980000016683","human_barcode":"NT16D"},"state":"unknown","created_at":"2022-03-09T14:19:40+00:00","updated_at":"2022-03-09T14:19:40+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/19/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/19/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/samples","related":"http://localhost:3000/api/v2/tubes/19/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/studies","related":"http://localhost:3000/api/v2/tubes/19/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/projects","related":"http://localhost:3000/api/v2/tubes/19/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/comments","related":"http://localhost:3000/api/v2/tubes/19/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/19/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/19/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/19/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/parents","related":"http://localhost:3000/api/v2/tubes/19/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/children","related":"http://localhost:3000/api/v2/tubes/19/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/19/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/19/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/19/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/19/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/19/aliquots"},"data":[{"type":"aliquots","id":"111"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/19/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/19/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/19/receptacle"}}}},{"id":"20","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/20"},"attributes":{"uuid":"f55cb232-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 20","labware_barcode":{"ean13_barcode":"3980000017697","machine_barcode":"3980000017697","human_barcode":"NT17E"},"state":"unknown","created_at":"2022-03-09T14:19:40+00:00","updated_at":"2022-03-09T14:19:40+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/20/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/20/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/samples","related":"http://localhost:3000/api/v2/tubes/20/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/studies","related":"http://localhost:3000/api/v2/tubes/20/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/projects","related":"http://localhost:3000/api/v2/tubes/20/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/comments","related":"http://localhost:3000/api/v2/tubes/20/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/20/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/20/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/20/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/parents","related":"http://localhost:3000/api/v2/tubes/20/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/children","related":"http://localhost:3000/api/v2/tubes/20/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/20/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/20/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/20/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/20/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/20/aliquots"},"data":[{"type":"aliquots","id":"112"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/20/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/20/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/20/receptacle"}}}},{"id":"21","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/21"},"attributes":{"uuid":"f56f7b7e-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 21","labware_barcode":{"ean13_barcode":"3980000018700","machine_barcode":"3980000018700","human_barcode":"NT18F"},"state":"unknown","created_at":"2022-03-09T14:19:40+00:00","updated_at":"2022-03-09T14:19:40+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/21/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/21/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/samples","related":"http://localhost:3000/api/v2/tubes/21/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/studies","related":"http://localhost:3000/api/v2/tubes/21/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/projects","related":"http://localhost:3000/api/v2/tubes/21/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/comments","related":"http://localhost:3000/api/v2/tubes/21/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/21/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/21/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/21/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/parents","related":"http://localhost:3000/api/v2/tubes/21/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/children","related":"http://localhost:3000/api/v2/tubes/21/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/21/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/21/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/21/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/21/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/21/aliquots"},"data":[{"type":"aliquots","id":"113"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/21/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/21/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/21/receptacle"}}}},{"id":"22","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/22"},"attributes":{"uuid":"f58c8a8e-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 22","labware_barcode":{"ean13_barcode":"3980000019714","machine_barcode":"3980000019714","human_barcode":"NT19G"},"state":"unknown","created_at":"2022-03-09T14:19:40+00:00","updated_at":"2022-03-09T14:19:40+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/22/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/22/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/samples","related":"http://localhost:3000/api/v2/tubes/22/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/studies","related":"http://localhost:3000/api/v2/tubes/22/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/projects","related":"http://localhost:3000/api/v2/tubes/22/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/comments","related":"http://localhost:3000/api/v2/tubes/22/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/22/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/22/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/22/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/parents","related":"http://localhost:3000/api/v2/tubes/22/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/children","related":"http://localhost:3000/api/v2/tubes/22/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/22/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/22/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/22/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/22/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/22/aliquots"},"data":[{"type":"aliquots","id":"114"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/22/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/22/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/22/receptacle"}}}},{"id":"23","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/23"},"attributes":{"uuid":"f5a5b05e-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 23","labware_barcode":{"ean13_barcode":"3980000020871","machine_barcode":"3980000020871","human_barcode":"NT20W"},"state":"unknown","created_at":"2022-03-09T14:19:41+00:00","updated_at":"2022-03-09T14:19:41+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/23/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/23/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/samples","related":"http://localhost:3000/api/v2/tubes/23/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/studies","related":"http://localhost:3000/api/v2/tubes/23/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/projects","related":"http://localhost:3000/api/v2/tubes/23/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/comments","related":"http://localhost:3000/api/v2/tubes/23/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/23/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/23/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/23/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/parents","related":"http://localhost:3000/api/v2/tubes/23/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/children","related":"http://localhost:3000/api/v2/tubes/23/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/23/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/23/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/23/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/23/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/23/aliquots"},"data":[{"type":"aliquots","id":"115"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/23/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/23/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/23/receptacle"}}}},{"id":"24","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/24"},"attributes":{"uuid":"f5b66dc2-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 24","labware_barcode":{"ean13_barcode":"3980000021656","machine_barcode":"3980000021656","human_barcode":"NT21A"},"state":"unknown","created_at":"2022-03-09T14:19:41+00:00","updated_at":"2022-03-09T14:19:41+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/24/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/24/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/samples","related":"http://localhost:3000/api/v2/tubes/24/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/studies","related":"http://localhost:3000/api/v2/tubes/24/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/projects","related":"http://localhost:3000/api/v2/tubes/24/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/comments","related":"http://localhost:3000/api/v2/tubes/24/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/24/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/24/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/24/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/parents","related":"http://localhost:3000/api/v2/tubes/24/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/children","related":"http://localhost:3000/api/v2/tubes/24/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/24/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/24/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/24/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/24/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/24/aliquots"},"data":[{"type":"aliquots","id":"116"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/24/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/24/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/24/receptacle"}}}},{"id":"25","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/25"},"attributes":{"uuid":"f5c803b6-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 25","labware_barcode":{"ean13_barcode":"3980000022660","machine_barcode":"3980000022660","human_barcode":"NT22B"},"state":"unknown","created_at":"2022-03-09T14:19:41+00:00","updated_at":"2022-03-09T14:19:41+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/25/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/25/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/samples","related":"http://localhost:3000/api/v2/tubes/25/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/studies","related":"http://localhost:3000/api/v2/tubes/25/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/projects","related":"http://localhost:3000/api/v2/tubes/25/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/comments","related":"http://localhost:3000/api/v2/tubes/25/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/25/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/25/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/25/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/parents","related":"http://localhost:3000/api/v2/tubes/25/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/children","related":"http://localhost:3000/api/v2/tubes/25/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/25/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/25/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/25/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/25/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/25/aliquots"},"data":[{"type":"aliquots","id":"117"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/25/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/25/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/25/receptacle"}}}},{"id":"26","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/26"},"attributes":{"uuid":"f5d9cd30-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 26","labware_barcode":{"ean13_barcode":"3980000023674","machine_barcode":"3980000023674","human_barcode":"NT23C"},"state":"unknown","created_at":"2022-03-09T14:19:41+00:00","updated_at":"2022-03-09T14:19:41+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/26/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/26/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/samples","related":"http://localhost:3000/api/v2/tubes/26/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/studies","related":"http://localhost:3000/api/v2/tubes/26/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/projects","related":"http://localhost:3000/api/v2/tubes/26/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/comments","related":"http://localhost:3000/api/v2/tubes/26/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/26/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/26/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/26/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/parents","related":"http://localhost:3000/api/v2/tubes/26/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/children","related":"http://localhost:3000/api/v2/tubes/26/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/26/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/26/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/26/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/26/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/26/aliquots"},"data":[{"type":"aliquots","id":"118"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/26/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/26/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/26/receptacle"}}}},{"id":"27","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/27"},"attributes":{"uuid":"f5eef0ac-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 27","labware_barcode":{"ean13_barcode":"3980000024688","machine_barcode":"3980000024688","human_barcode":"NT24D"},"state":"unknown","created_at":"2022-03-09T14:19:41+00:00","updated_at":"2022-03-09T14:19:41+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/27/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/27/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/samples","related":"http://localhost:3000/api/v2/tubes/27/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/studies","related":"http://localhost:3000/api/v2/tubes/27/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/projects","related":"http://localhost:3000/api/v2/tubes/27/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/comments","related":"http://localhost:3000/api/v2/tubes/27/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/27/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/27/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/27/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/parents","related":"http://localhost:3000/api/v2/tubes/27/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/children","related":"http://localhost:3000/api/v2/tubes/27/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/27/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/27/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/27/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/27/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/27/aliquots"},"data":[{"type":"aliquots","id":"119"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/27/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/27/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/27/receptacle"}}}},{"id":"28","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/28"},"attributes":{"uuid":"f6026f74-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 28","labware_barcode":{"ean13_barcode":"3980000025692","machine_barcode":"3980000025692","human_barcode":"NT25E"},"state":"unknown","created_at":"2022-03-09T14:19:41+00:00","updated_at":"2022-03-09T14:19:41+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/28/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/28/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/samples","related":"http://localhost:3000/api/v2/tubes/28/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/studies","related":"http://localhost:3000/api/v2/tubes/28/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/projects","related":"http://localhost:3000/api/v2/tubes/28/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/comments","related":"http://localhost:3000/api/v2/tubes/28/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/28/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/28/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/28/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/parents","related":"http://localhost:3000/api/v2/tubes/28/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/children","related":"http://localhost:3000/api/v2/tubes/28/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/28/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/28/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/28/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/28/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/28/aliquots"},"data":[{"type":"aliquots","id":"120"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/28/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/28/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/28/receptacle"}}}},{"id":"29","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/29"},"attributes":{"uuid":"f61547e8-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 29","labware_barcode":{"ean13_barcode":"3980000026705","machine_barcode":"3980000026705","human_barcode":"NT26F"},"state":"unknown","created_at":"2022-03-09T14:19:41+00:00","updated_at":"2022-03-09T14:19:41+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/29/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/29/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/samples","related":"http://localhost:3000/api/v2/tubes/29/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/studies","related":"http://localhost:3000/api/v2/tubes/29/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/projects","related":"http://localhost:3000/api/v2/tubes/29/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/comments","related":"http://localhost:3000/api/v2/tubes/29/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/29/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/29/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/29/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/parents","related":"http://localhost:3000/api/v2/tubes/29/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/children","related":"http://localhost:3000/api/v2/tubes/29/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/29/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/29/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/29/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/29/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/29/aliquots"},"data":[{"type":"aliquots","id":"121"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/29/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/29/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/29/receptacle"}}}},{"id":"30","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/30"},"attributes":{"uuid":"f6250de0-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 30","labware_barcode":{"ean13_barcode":"3980000027719","machine_barcode":"3980000027719","human_barcode":"NT27G"},"state":"unknown","created_at":"2022-03-09T14:19:41+00:00","updated_at":"2022-03-09T14:19:41+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/30/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/30/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/samples","related":"http://localhost:3000/api/v2/tubes/30/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/studies","related":"http://localhost:3000/api/v2/tubes/30/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/projects","related":"http://localhost:3000/api/v2/tubes/30/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/comments","related":"http://localhost:3000/api/v2/tubes/30/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/30/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/30/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/30/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/parents","related":"http://localhost:3000/api/v2/tubes/30/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/children","related":"http://localhost:3000/api/v2/tubes/30/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/30/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/30/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/30/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/30/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/30/aliquots"},"data":[{"type":"aliquots","id":"122"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/30/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/30/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/30/receptacle"}}}},{"id":"31","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/31"},"attributes":{"uuid":"f63315ca-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 31","labware_barcode":{"ean13_barcode":"3980000028723","machine_barcode":"3980000028723","human_barcode":"NT28H"},"state":"unknown","created_at":"2022-03-09T14:19:42+00:00","updated_at":"2022-03-09T14:19:42+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/31/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/31/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/samples","related":"http://localhost:3000/api/v2/tubes/31/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/studies","related":"http://localhost:3000/api/v2/tubes/31/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/projects","related":"http://localhost:3000/api/v2/tubes/31/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/comments","related":"http://localhost:3000/api/v2/tubes/31/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/31/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/31/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/31/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/parents","related":"http://localhost:3000/api/v2/tubes/31/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/children","related":"http://localhost:3000/api/v2/tubes/31/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/31/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/31/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/31/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/31/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/31/aliquots"},"data":[{"type":"aliquots","id":"123"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/31/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/31/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/31/receptacle"}}}},{"id":"32","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/32"},"attributes":{"uuid":"f6455438-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 32","labware_barcode":{"ean13_barcode":"3980000029737","machine_barcode":"3980000029737","human_barcode":"NT29I"},"state":"unknown","created_at":"2022-03-09T14:19:42+00:00","updated_at":"2022-03-09T14:19:42+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/32/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/32/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/samples","related":"http://localhost:3000/api/v2/tubes/32/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/studies","related":"http://localhost:3000/api/v2/tubes/32/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/projects","related":"http://localhost:3000/api/v2/tubes/32/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/comments","related":"http://localhost:3000/api/v2/tubes/32/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/32/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/32/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/32/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/parents","related":"http://localhost:3000/api/v2/tubes/32/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/children","related":"http://localhost:3000/api/v2/tubes/32/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/32/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/32/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/32/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/32/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/32/aliquots"},"data":[{"type":"aliquots","id":"124"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/32/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/32/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/32/receptacle"}}}},{"id":"33","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/33"},"attributes":{"uuid":"f6571cc2-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 33","labware_barcode":{"ean13_barcode":"3980000030665","machine_barcode":"3980000030665","human_barcode":"NT30B"},"state":"unknown","created_at":"2022-03-09T14:19:42+00:00","updated_at":"2022-03-09T14:19:42+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/33/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/33/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/samples","related":"http://localhost:3000/api/v2/tubes/33/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/studies","related":"http://localhost:3000/api/v2/tubes/33/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/projects","related":"http://localhost:3000/api/v2/tubes/33/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/comments","related":"http://localhost:3000/api/v2/tubes/33/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/33/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/33/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/33/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/parents","related":"http://localhost:3000/api/v2/tubes/33/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/children","related":"http://localhost:3000/api/v2/tubes/33/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/33/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/33/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/33/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/33/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/33/aliquots"},"data":[{"type":"aliquots","id":"125"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/33/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/33/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/33/receptacle"}}}},{"id":"34","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/34"},"attributes":{"uuid":"f672a5be-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 34","labware_barcode":{"ean13_barcode":"3980000031679","machine_barcode":"3980000031679","human_barcode":"NT31C"},"state":"unknown","created_at":"2022-03-09T14:19:42+00:00","updated_at":"2022-03-09T14:19:42+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/34/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/34/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/samples","related":"http://localhost:3000/api/v2/tubes/34/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/studies","related":"http://localhost:3000/api/v2/tubes/34/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/projects","related":"http://localhost:3000/api/v2/tubes/34/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/comments","related":"http://localhost:3000/api/v2/tubes/34/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/34/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/34/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/34/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/parents","related":"http://localhost:3000/api/v2/tubes/34/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/children","related":"http://localhost:3000/api/v2/tubes/34/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/34/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/34/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/34/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/34/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/34/aliquots"},"data":[{"type":"aliquots","id":"126"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/34/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/34/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/34/receptacle"}}}},{"id":"35","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/35"},"attributes":{"uuid":"f68322d6-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 35","labware_barcode":{"ean13_barcode":"3980000032683","machine_barcode":"3980000032683","human_barcode":"NT32D"},"state":"unknown","created_at":"2022-03-09T14:19:42+00:00","updated_at":"2022-03-09T14:19:42+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/35/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/35/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/samples","related":"http://localhost:3000/api/v2/tubes/35/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/studies","related":"http://localhost:3000/api/v2/tubes/35/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/projects","related":"http://localhost:3000/api/v2/tubes/35/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/comments","related":"http://localhost:3000/api/v2/tubes/35/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/35/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/35/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/35/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/parents","related":"http://localhost:3000/api/v2/tubes/35/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/children","related":"http://localhost:3000/api/v2/tubes/35/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/35/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/35/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/35/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/35/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/35/aliquots"},"data":[{"type":"aliquots","id":"127"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/35/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/35/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/35/receptacle"}}}},{"id":"36","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/36"},"attributes":{"uuid":"f6a5612a-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 36","labware_barcode":{"ean13_barcode":"3980000033697","machine_barcode":"3980000033697","human_barcode":"NT33E"},"state":"unknown","created_at":"2022-03-09T14:19:42+00:00","updated_at":"2022-03-09T14:19:42+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/36/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/36/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/samples","related":"http://localhost:3000/api/v2/tubes/36/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/studies","related":"http://localhost:3000/api/v2/tubes/36/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/projects","related":"http://localhost:3000/api/v2/tubes/36/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/comments","related":"http://localhost:3000/api/v2/tubes/36/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/36/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/36/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/36/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/parents","related":"http://localhost:3000/api/v2/tubes/36/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/children","related":"http://localhost:3000/api/v2/tubes/36/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/36/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/36/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/36/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/36/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/36/aliquots"},"data":[{"type":"aliquots","id":"128"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/36/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/36/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/36/receptacle"}}}},{"id":"37","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/37"},"attributes":{"uuid":"f6ba694e-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 37","labware_barcode":{"ean13_barcode":"3980000034700","machine_barcode":"3980000034700","human_barcode":"NT34F"},"state":"unknown","created_at":"2022-03-09T14:19:42+00:00","updated_at":"2022-03-09T14:19:42+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/37/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/37/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/samples","related":"http://localhost:3000/api/v2/tubes/37/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/studies","related":"http://localhost:3000/api/v2/tubes/37/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/projects","related":"http://localhost:3000/api/v2/tubes/37/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/comments","related":"http://localhost:3000/api/v2/tubes/37/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/37/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/37/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/37/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/parents","related":"http://localhost:3000/api/v2/tubes/37/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/children","related":"http://localhost:3000/api/v2/tubes/37/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/37/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/37/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/37/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/37/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/37/aliquots"},"data":[{"type":"aliquots","id":"129"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/37/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/37/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/37/receptacle"}}}},{"id":"38","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/38"},"attributes":{"uuid":"f6ce125a-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 38","labware_barcode":{"ean13_barcode":"3980000035714","machine_barcode":"3980000035714","human_barcode":"NT35G"},"state":"unknown","created_at":"2022-03-09T14:19:43+00:00","updated_at":"2022-03-09T14:19:43+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/38/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/38/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/samples","related":"http://localhost:3000/api/v2/tubes/38/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/studies","related":"http://localhost:3000/api/v2/tubes/38/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/projects","related":"http://localhost:3000/api/v2/tubes/38/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/comments","related":"http://localhost:3000/api/v2/tubes/38/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/38/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/38/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/38/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/parents","related":"http://localhost:3000/api/v2/tubes/38/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/children","related":"http://localhost:3000/api/v2/tubes/38/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/38/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/38/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/38/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/38/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/38/aliquots"},"data":[{"type":"aliquots","id":"130"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/38/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/38/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/38/receptacle"}}}},{"id":"39","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/39"},"attributes":{"uuid":"f6dfe8f4-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 39","labware_barcode":{"ean13_barcode":"3980000036728","machine_barcode":"3980000036728","human_barcode":"NT36H"},"state":"unknown","created_at":"2022-03-09T14:19:43+00:00","updated_at":"2022-03-09T14:19:43+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/39/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/39/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/samples","related":"http://localhost:3000/api/v2/tubes/39/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/studies","related":"http://localhost:3000/api/v2/tubes/39/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/projects","related":"http://localhost:3000/api/v2/tubes/39/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/comments","related":"http://localhost:3000/api/v2/tubes/39/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/39/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/39/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/39/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/parents","related":"http://localhost:3000/api/v2/tubes/39/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/children","related":"http://localhost:3000/api/v2/tubes/39/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/39/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/39/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/39/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/39/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/39/aliquots"},"data":[{"type":"aliquots","id":"131"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/39/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/39/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/39/receptacle"}}}},{"id":"40","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/40"},"attributes":{"uuid":"f6f3830a-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 40","labware_barcode":{"ean13_barcode":"3980000037732","machine_barcode":"3980000037732","human_barcode":"NT37I"},"state":"unknown","created_at":"2022-03-09T14:19:43+00:00","updated_at":"2022-03-09T14:19:43+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/40/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/40/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/samples","related":"http://localhost:3000/api/v2/tubes/40/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/studies","related":"http://localhost:3000/api/v2/tubes/40/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/projects","related":"http://localhost:3000/api/v2/tubes/40/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/comments","related":"http://localhost:3000/api/v2/tubes/40/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/40/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/40/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/40/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/parents","related":"http://localhost:3000/api/v2/tubes/40/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/children","related":"http://localhost:3000/api/v2/tubes/40/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/40/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/40/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/40/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/40/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/40/aliquots"},"data":[{"type":"aliquots","id":"132"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/40/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/40/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/40/receptacle"}}}},{"id":"41","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/41"},"attributes":{"uuid":"f7044f46-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 41","labware_barcode":{"ean13_barcode":"3980000038746","machine_barcode":"3980000038746","human_barcode":"NT38J"},"state":"unknown","created_at":"2022-03-09T14:19:43+00:00","updated_at":"2022-03-09T14:19:43+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/41/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/41/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/samples","related":"http://localhost:3000/api/v2/tubes/41/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/studies","related":"http://localhost:3000/api/v2/tubes/41/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/projects","related":"http://localhost:3000/api/v2/tubes/41/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/comments","related":"http://localhost:3000/api/v2/tubes/41/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/41/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/41/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/41/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/parents","related":"http://localhost:3000/api/v2/tubes/41/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/children","related":"http://localhost:3000/api/v2/tubes/41/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/41/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/41/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/41/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/41/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/41/aliquots"},"data":[{"type":"aliquots","id":"133"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/41/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/41/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/41/receptacle"}}}},{"id":"42","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/42"},"attributes":{"uuid":"f71a7cb2-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 42","labware_barcode":{"ean13_barcode":"3980000039750","machine_barcode":"3980000039750","human_barcode":"NT39K"},"state":"unknown","created_at":"2022-03-09T14:19:43+00:00","updated_at":"2022-03-09T14:19:43+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/42/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/42/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/samples","related":"http://localhost:3000/api/v2/tubes/42/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/studies","related":"http://localhost:3000/api/v2/tubes/42/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/projects","related":"http://localhost:3000/api/v2/tubes/42/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/comments","related":"http://localhost:3000/api/v2/tubes/42/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/42/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/42/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/42/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/parents","related":"http://localhost:3000/api/v2/tubes/42/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/children","related":"http://localhost:3000/api/v2/tubes/42/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/42/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/42/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/42/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/42/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/42/aliquots"},"data":[{"type":"aliquots","id":"134"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/42/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/42/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/42/receptacle"}}}},{"id":"43","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/43"},"attributes":{"uuid":"f72c8236-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 43","labware_barcode":{"ean13_barcode":"3980000040688","machine_barcode":"3980000040688","human_barcode":"NT40D"},"state":"unknown","created_at":"2022-03-09T14:19:43+00:00","updated_at":"2022-03-09T14:19:43+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/43/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/43/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/samples","related":"http://localhost:3000/api/v2/tubes/43/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/studies","related":"http://localhost:3000/api/v2/tubes/43/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/projects","related":"http://localhost:3000/api/v2/tubes/43/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/comments","related":"http://localhost:3000/api/v2/tubes/43/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/43/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/43/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/43/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/parents","related":"http://localhost:3000/api/v2/tubes/43/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/children","related":"http://localhost:3000/api/v2/tubes/43/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/43/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/43/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/43/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/43/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/43/aliquots"},"data":[{"type":"aliquots","id":"135"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/43/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/43/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/43/receptacle"}}}},{"id":"44","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/44"},"attributes":{"uuid":"f73ebb22-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 44","labware_barcode":{"ean13_barcode":"3980000041692","machine_barcode":"3980000041692","human_barcode":"NT41E"},"state":"unknown","created_at":"2022-03-09T14:19:43+00:00","updated_at":"2022-03-09T14:19:43+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/44/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/44/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/samples","related":"http://localhost:3000/api/v2/tubes/44/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/studies","related":"http://localhost:3000/api/v2/tubes/44/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/projects","related":"http://localhost:3000/api/v2/tubes/44/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/comments","related":"http://localhost:3000/api/v2/tubes/44/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/44/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/44/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/44/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/parents","related":"http://localhost:3000/api/v2/tubes/44/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/children","related":"http://localhost:3000/api/v2/tubes/44/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/44/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/44/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/44/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/44/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/44/aliquots"},"data":[{"type":"aliquots","id":"136"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/44/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/44/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/44/receptacle"}}}},{"id":"45","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/45"},"attributes":{"uuid":"f756909e-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 45","labware_barcode":{"ean13_barcode":"3980000042705","machine_barcode":"3980000042705","human_barcode":"NT42F"},"state":"unknown","created_at":"2022-03-09T14:19:43+00:00","updated_at":"2022-03-09T14:19:43+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/45/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/45/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/samples","related":"http://localhost:3000/api/v2/tubes/45/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/studies","related":"http://localhost:3000/api/v2/tubes/45/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/projects","related":"http://localhost:3000/api/v2/tubes/45/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/comments","related":"http://localhost:3000/api/v2/tubes/45/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/45/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/45/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/45/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/parents","related":"http://localhost:3000/api/v2/tubes/45/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/children","related":"http://localhost:3000/api/v2/tubes/45/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/45/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/45/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/45/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/45/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/45/aliquots"},"data":[{"type":"aliquots","id":"137"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/45/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/45/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/45/receptacle"}}}},{"id":"46","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/46"},"attributes":{"uuid":"f7713836-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 46","labware_barcode":{"ean13_barcode":"3980000043719","machine_barcode":"3980000043719","human_barcode":"NT43G"},"state":"unknown","created_at":"2022-03-09T14:19:44+00:00","updated_at":"2022-03-09T14:19:44+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/46/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/46/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/samples","related":"http://localhost:3000/api/v2/tubes/46/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/studies","related":"http://localhost:3000/api/v2/tubes/46/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/projects","related":"http://localhost:3000/api/v2/tubes/46/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/comments","related":"http://localhost:3000/api/v2/tubes/46/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/46/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/46/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/46/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/parents","related":"http://localhost:3000/api/v2/tubes/46/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/children","related":"http://localhost:3000/api/v2/tubes/46/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/46/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/46/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/46/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/46/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/46/aliquots"},"data":[{"type":"aliquots","id":"138"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/46/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/46/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/46/receptacle"}}}},{"id":"47","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/47"},"attributes":{"uuid":"f7810fe0-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 47","labware_barcode":{"ean13_barcode":"3980000044723","machine_barcode":"3980000044723","human_barcode":"NT44H"},"state":"unknown","created_at":"2022-03-09T14:19:44+00:00","updated_at":"2022-03-09T14:19:44+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/47/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/47/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/samples","related":"http://localhost:3000/api/v2/tubes/47/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/studies","related":"http://localhost:3000/api/v2/tubes/47/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/projects","related":"http://localhost:3000/api/v2/tubes/47/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/comments","related":"http://localhost:3000/api/v2/tubes/47/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/47/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/47/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/47/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/parents","related":"http://localhost:3000/api/v2/tubes/47/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/children","related":"http://localhost:3000/api/v2/tubes/47/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/47/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/47/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/47/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/47/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/47/aliquots"},"data":[{"type":"aliquots","id":"139"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/47/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/47/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/47/receptacle"}}}},{"id":"48","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/48"},"attributes":{"uuid":"f7a3a78a-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 48","labware_barcode":{"ean13_barcode":"3980000045737","machine_barcode":"3980000045737","human_barcode":"NT45I"},"state":"unknown","created_at":"2022-03-09T14:19:44+00:00","updated_at":"2022-03-09T14:19:44+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/48/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/48/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/samples","related":"http://localhost:3000/api/v2/tubes/48/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/studies","related":"http://localhost:3000/api/v2/tubes/48/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/projects","related":"http://localhost:3000/api/v2/tubes/48/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/comments","related":"http://localhost:3000/api/v2/tubes/48/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/48/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/48/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/48/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/parents","related":"http://localhost:3000/api/v2/tubes/48/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/children","related":"http://localhost:3000/api/v2/tubes/48/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/48/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/48/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/48/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/48/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/48/aliquots"},"data":[{"type":"aliquots","id":"140"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/48/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/48/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/48/receptacle"}}}},{"id":"49","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/49"},"attributes":{"uuid":"f7b46dea-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 49","labware_barcode":{"ean13_barcode":"3980000046741","machine_barcode":"3980000046741","human_barcode":"NT46J"},"state":"unknown","created_at":"2022-03-09T14:19:44+00:00","updated_at":"2022-03-09T14:19:44+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/49/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/49/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/samples","related":"http://localhost:3000/api/v2/tubes/49/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/studies","related":"http://localhost:3000/api/v2/tubes/49/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/projects","related":"http://localhost:3000/api/v2/tubes/49/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/comments","related":"http://localhost:3000/api/v2/tubes/49/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/49/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/49/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/49/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/parents","related":"http://localhost:3000/api/v2/tubes/49/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/children","related":"http://localhost:3000/api/v2/tubes/49/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/49/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/49/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/49/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/49/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/49/aliquots"},"data":[{"type":"aliquots","id":"141"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/49/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/49/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/49/receptacle"}}}},{"id":"50","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/50"},"attributes":{"uuid":"f7c745a0-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 50","labware_barcode":{"ean13_barcode":"3980000047755","machine_barcode":"3980000047755","human_barcode":"NT47K"},"state":"unknown","created_at":"2022-03-09T14:19:44+00:00","updated_at":"2022-03-09T14:19:44+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/50/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/50/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/samples","related":"http://localhost:3000/api/v2/tubes/50/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/studies","related":"http://localhost:3000/api/v2/tubes/50/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/projects","related":"http://localhost:3000/api/v2/tubes/50/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/comments","related":"http://localhost:3000/api/v2/tubes/50/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/50/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/50/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/50/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/parents","related":"http://localhost:3000/api/v2/tubes/50/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/children","related":"http://localhost:3000/api/v2/tubes/50/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/50/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/50/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/50/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/50/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/50/aliquots"},"data":[{"type":"aliquots","id":"142"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/50/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/50/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/50/receptacle"}}}},{"id":"51","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/51"},"attributes":{"uuid":"f7d88d42-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 51","labware_barcode":{"ean13_barcode":"3980000048769","machine_barcode":"3980000048769","human_barcode":"NT48L"},"state":"unknown","created_at":"2022-03-09T14:19:44+00:00","updated_at":"2022-03-09T14:19:44+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/51/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/51/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/samples","related":"http://localhost:3000/api/v2/tubes/51/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/studies","related":"http://localhost:3000/api/v2/tubes/51/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/projects","related":"http://localhost:3000/api/v2/tubes/51/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/comments","related":"http://localhost:3000/api/v2/tubes/51/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/51/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/51/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/51/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/parents","related":"http://localhost:3000/api/v2/tubes/51/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/children","related":"http://localhost:3000/api/v2/tubes/51/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/51/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/51/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/51/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/51/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/51/aliquots"},"data":[{"type":"aliquots","id":"143"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/51/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/51/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/51/receptacle"}}}},{"id":"52","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/52"},"attributes":{"uuid":"f7ecebd4-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 52","labware_barcode":{"ean13_barcode":"3980000049773","machine_barcode":"3980000049773","human_barcode":"NT49M"},"state":"unknown","created_at":"2022-03-09T14:19:44+00:00","updated_at":"2022-03-09T14:19:44+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/52/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/52/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/samples","related":"http://localhost:3000/api/v2/tubes/52/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/studies","related":"http://localhost:3000/api/v2/tubes/52/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/projects","related":"http://localhost:3000/api/v2/tubes/52/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/comments","related":"http://localhost:3000/api/v2/tubes/52/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/52/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/52/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/52/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/parents","related":"http://localhost:3000/api/v2/tubes/52/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/children","related":"http://localhost:3000/api/v2/tubes/52/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/52/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/52/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/52/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/52/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/52/aliquots"},"data":[{"type":"aliquots","id":"144"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/52/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/52/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/52/receptacle"}}}},{"id":"53","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/53"},"attributes":{"uuid":"f800094e-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 53","labware_barcode":{"ean13_barcode":"3980000050700","machine_barcode":"3980000050700","human_barcode":"NT50F"},"state":"unknown","created_at":"2022-03-09T14:19:45+00:00","updated_at":"2022-03-09T14:19:45+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/53/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/53/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/samples","related":"http://localhost:3000/api/v2/tubes/53/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/studies","related":"http://localhost:3000/api/v2/tubes/53/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/projects","related":"http://localhost:3000/api/v2/tubes/53/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/comments","related":"http://localhost:3000/api/v2/tubes/53/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/53/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/53/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/53/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/parents","related":"http://localhost:3000/api/v2/tubes/53/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/children","related":"http://localhost:3000/api/v2/tubes/53/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/53/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/53/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/53/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/53/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/53/aliquots"},"data":[{"type":"aliquots","id":"145"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/53/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/53/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/53/receptacle"}}}},{"id":"54","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/54"},"attributes":{"uuid":"f8114b14-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 54","labware_barcode":{"ean13_barcode":"3980000051714","machine_barcode":"3980000051714","human_barcode":"NT51G"},"state":"unknown","created_at":"2022-03-09T14:19:45+00:00","updated_at":"2022-03-09T14:19:45+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/54/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/54/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/samples","related":"http://localhost:3000/api/v2/tubes/54/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/studies","related":"http://localhost:3000/api/v2/tubes/54/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/projects","related":"http://localhost:3000/api/v2/tubes/54/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/comments","related":"http://localhost:3000/api/v2/tubes/54/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/54/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/54/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/54/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/parents","related":"http://localhost:3000/api/v2/tubes/54/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/children","related":"http://localhost:3000/api/v2/tubes/54/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/54/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/54/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/54/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/54/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/54/aliquots"},"data":[{"type":"aliquots","id":"146"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/54/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/54/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/54/receptacle"}}}},{"id":"55","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/55"},"attributes":{"uuid":"f825f226-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 55","labware_barcode":{"ean13_barcode":"3980000052728","machine_barcode":"3980000052728","human_barcode":"NT52H"},"state":"unknown","created_at":"2022-03-09T14:19:45+00:00","updated_at":"2022-03-09T14:19:45+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/55/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/55/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/samples","related":"http://localhost:3000/api/v2/tubes/55/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/studies","related":"http://localhost:3000/api/v2/tubes/55/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/projects","related":"http://localhost:3000/api/v2/tubes/55/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/comments","related":"http://localhost:3000/api/v2/tubes/55/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/55/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/55/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/55/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/parents","related":"http://localhost:3000/api/v2/tubes/55/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/children","related":"http://localhost:3000/api/v2/tubes/55/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/55/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/55/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/55/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/55/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/55/aliquots"},"data":[{"type":"aliquots","id":"147"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/55/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/55/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/55/receptacle"}}}},{"id":"56","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/56"},"attributes":{"uuid":"f84161d2-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 56","labware_barcode":{"ean13_barcode":"3980000053732","machine_barcode":"3980000053732","human_barcode":"NT53I"},"state":"unknown","created_at":"2022-03-09T14:19:45+00:00","updated_at":"2022-03-09T14:19:45+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/56/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/56/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/samples","related":"http://localhost:3000/api/v2/tubes/56/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/studies","related":"http://localhost:3000/api/v2/tubes/56/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/projects","related":"http://localhost:3000/api/v2/tubes/56/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/comments","related":"http://localhost:3000/api/v2/tubes/56/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/56/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/56/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/56/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/parents","related":"http://localhost:3000/api/v2/tubes/56/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/children","related":"http://localhost:3000/api/v2/tubes/56/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/56/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/56/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/56/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/56/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/56/aliquots"},"data":[{"type":"aliquots","id":"148"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/56/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/56/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/56/receptacle"}}}},{"id":"57","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/57"},"attributes":{"uuid":"f8509684-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 57","labware_barcode":{"ean13_barcode":"3980000054746","machine_barcode":"3980000054746","human_barcode":"NT54J"},"state":"unknown","created_at":"2022-03-09T14:19:45+00:00","updated_at":"2022-03-09T14:19:45+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/57/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/57/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/samples","related":"http://localhost:3000/api/v2/tubes/57/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/studies","related":"http://localhost:3000/api/v2/tubes/57/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/projects","related":"http://localhost:3000/api/v2/tubes/57/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/comments","related":"http://localhost:3000/api/v2/tubes/57/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/57/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/57/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/57/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/parents","related":"http://localhost:3000/api/v2/tubes/57/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/children","related":"http://localhost:3000/api/v2/tubes/57/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/57/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/57/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/57/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/57/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/57/aliquots"},"data":[{"type":"aliquots","id":"149"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/57/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/57/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/57/receptacle"}}}},{"id":"58","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/58"},"attributes":{"uuid":"f863e658-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 58","labware_barcode":{"ean13_barcode":"3980000055750","machine_barcode":"3980000055750","human_barcode":"NT55K"},"state":"unknown","created_at":"2022-03-09T14:19:45+00:00","updated_at":"2022-03-09T14:19:45+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/58/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/58/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/samples","related":"http://localhost:3000/api/v2/tubes/58/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/studies","related":"http://localhost:3000/api/v2/tubes/58/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/projects","related":"http://localhost:3000/api/v2/tubes/58/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/comments","related":"http://localhost:3000/api/v2/tubes/58/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/58/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/58/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/58/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/parents","related":"http://localhost:3000/api/v2/tubes/58/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/children","related":"http://localhost:3000/api/v2/tubes/58/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/58/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/58/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/58/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/58/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/58/aliquots"},"data":[{"type":"aliquots","id":"150"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/58/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/58/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/58/receptacle"}}}},{"id":"59","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/59"},"attributes":{"uuid":"f875b40a-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 59","labware_barcode":{"ean13_barcode":"3980000056764","machine_barcode":"3980000056764","human_barcode":"NT56L"},"state":"unknown","created_at":"2022-03-09T14:19:45+00:00","updated_at":"2022-03-09T14:19:45+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/59/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/59/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/samples","related":"http://localhost:3000/api/v2/tubes/59/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/studies","related":"http://localhost:3000/api/v2/tubes/59/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/projects","related":"http://localhost:3000/api/v2/tubes/59/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/comments","related":"http://localhost:3000/api/v2/tubes/59/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/59/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/59/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/59/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/parents","related":"http://localhost:3000/api/v2/tubes/59/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/children","related":"http://localhost:3000/api/v2/tubes/59/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/59/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/59/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/59/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/59/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/59/aliquots"},"data":[{"type":"aliquots","id":"151"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/59/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/59/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/59/receptacle"}}}},{"id":"60","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/60"},"attributes":{"uuid":"f888ed36-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 60","labware_barcode":{"ean13_barcode":"3980000057778","machine_barcode":"3980000057778","human_barcode":"NT57M"},"state":"unknown","created_at":"2022-03-09T14:19:45+00:00","updated_at":"2022-03-09T14:19:45+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/60/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/60/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/samples","related":"http://localhost:3000/api/v2/tubes/60/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/studies","related":"http://localhost:3000/api/v2/tubes/60/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/projects","related":"http://localhost:3000/api/v2/tubes/60/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/comments","related":"http://localhost:3000/api/v2/tubes/60/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/60/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/60/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/60/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/parents","related":"http://localhost:3000/api/v2/tubes/60/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/children","related":"http://localhost:3000/api/v2/tubes/60/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/60/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/60/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/60/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/60/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/60/aliquots"},"data":[{"type":"aliquots","id":"152"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/60/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/60/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/60/receptacle"}}}},{"id":"61","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/61"},"attributes":{"uuid":"f89b4c24-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 61","labware_barcode":{"ean13_barcode":"3980000058782","machine_barcode":"3980000058782","human_barcode":"NT58N"},"state":"unknown","created_at":"2022-03-09T14:19:46+00:00","updated_at":"2022-03-09T14:19:46+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/61/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/61/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/samples","related":"http://localhost:3000/api/v2/tubes/61/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/studies","related":"http://localhost:3000/api/v2/tubes/61/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/projects","related":"http://localhost:3000/api/v2/tubes/61/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/comments","related":"http://localhost:3000/api/v2/tubes/61/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/61/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/61/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/61/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/parents","related":"http://localhost:3000/api/v2/tubes/61/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/children","related":"http://localhost:3000/api/v2/tubes/61/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/61/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/61/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/61/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/61/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/61/aliquots"},"data":[{"type":"aliquots","id":"153"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/61/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/61/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/61/receptacle"}}}},{"id":"62","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/62"},"attributes":{"uuid":"f8ac960a-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 62","labware_barcode":{"ean13_barcode":"3980000059796","machine_barcode":"3980000059796","human_barcode":"NT59O"},"state":"unknown","created_at":"2022-03-09T14:19:46+00:00","updated_at":"2022-03-09T14:19:46+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/62/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/62/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/samples","related":"http://localhost:3000/api/v2/tubes/62/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/studies","related":"http://localhost:3000/api/v2/tubes/62/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/projects","related":"http://localhost:3000/api/v2/tubes/62/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/comments","related":"http://localhost:3000/api/v2/tubes/62/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/62/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/62/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/62/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/parents","related":"http://localhost:3000/api/v2/tubes/62/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/children","related":"http://localhost:3000/api/v2/tubes/62/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/62/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/62/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/62/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/62/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/62/aliquots"},"data":[{"type":"aliquots","id":"154"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/62/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/62/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/62/receptacle"}}}},{"id":"63","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/63"},"attributes":{"uuid":"f8ce85da-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 63","labware_barcode":{"ean13_barcode":"3980000060723","machine_barcode":"3980000060723","human_barcode":"NT60H"},"state":"unknown","created_at":"2022-03-09T14:19:46+00:00","updated_at":"2022-03-09T14:19:46+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/63/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/63/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/samples","related":"http://localhost:3000/api/v2/tubes/63/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/studies","related":"http://localhost:3000/api/v2/tubes/63/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/projects","related":"http://localhost:3000/api/v2/tubes/63/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/comments","related":"http://localhost:3000/api/v2/tubes/63/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/63/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/63/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/63/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/parents","related":"http://localhost:3000/api/v2/tubes/63/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/children","related":"http://localhost:3000/api/v2/tubes/63/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/63/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/63/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/63/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/63/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/63/aliquots"},"data":[{"type":"aliquots","id":"155"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/63/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/63/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/63/receptacle"}}}},{"id":"64","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/64"},"attributes":{"uuid":"f8df0b4e-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 64","labware_barcode":{"ean13_barcode":"3980000061737","machine_barcode":"3980000061737","human_barcode":"NT61I"},"state":"unknown","created_at":"2022-03-09T14:19:46+00:00","updated_at":"2022-03-09T14:19:46+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/64/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/64/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/samples","related":"http://localhost:3000/api/v2/tubes/64/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/studies","related":"http://localhost:3000/api/v2/tubes/64/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/projects","related":"http://localhost:3000/api/v2/tubes/64/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/comments","related":"http://localhost:3000/api/v2/tubes/64/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/64/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/64/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/64/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/parents","related":"http://localhost:3000/api/v2/tubes/64/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/children","related":"http://localhost:3000/api/v2/tubes/64/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/64/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/64/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/64/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/64/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/64/aliquots"},"data":[{"type":"aliquots","id":"156"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/64/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/64/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/64/receptacle"}}}},{"id":"65","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/65"},"attributes":{"uuid":"f8f313e6-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 65","labware_barcode":{"ean13_barcode":"3980000062741","machine_barcode":"3980000062741","human_barcode":"NT62J"},"state":"unknown","created_at":"2022-03-09T14:19:46+00:00","updated_at":"2022-03-09T14:19:46+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/65/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/65/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/samples","related":"http://localhost:3000/api/v2/tubes/65/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/studies","related":"http://localhost:3000/api/v2/tubes/65/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/projects","related":"http://localhost:3000/api/v2/tubes/65/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/comments","related":"http://localhost:3000/api/v2/tubes/65/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/65/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/65/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/65/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/parents","related":"http://localhost:3000/api/v2/tubes/65/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/children","related":"http://localhost:3000/api/v2/tubes/65/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/65/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/65/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/65/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/65/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/65/aliquots"},"data":[{"type":"aliquots","id":"157"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/65/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/65/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/65/receptacle"}}}},{"id":"66","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/66"},"attributes":{"uuid":"f9044454-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 66","labware_barcode":{"ean13_barcode":"3980000063755","machine_barcode":"3980000063755","human_barcode":"NT63K"},"state":"unknown","created_at":"2022-03-09T14:19:46+00:00","updated_at":"2022-03-09T14:19:46+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/66/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/66/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/samples","related":"http://localhost:3000/api/v2/tubes/66/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/studies","related":"http://localhost:3000/api/v2/tubes/66/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/projects","related":"http://localhost:3000/api/v2/tubes/66/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/comments","related":"http://localhost:3000/api/v2/tubes/66/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/66/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/66/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/66/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/parents","related":"http://localhost:3000/api/v2/tubes/66/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/children","related":"http://localhost:3000/api/v2/tubes/66/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/66/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/66/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/66/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/66/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/66/aliquots"},"data":[{"type":"aliquots","id":"158"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/66/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/66/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/66/receptacle"}}}},{"id":"67","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/67"},"attributes":{"uuid":"f92005cc-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 67","labware_barcode":{"ean13_barcode":"3980000064769","machine_barcode":"3980000064769","human_barcode":"NT64L"},"state":"unknown","created_at":"2022-03-09T14:19:46+00:00","updated_at":"2022-03-09T14:19:46+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/67/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/67/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/samples","related":"http://localhost:3000/api/v2/tubes/67/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/studies","related":"http://localhost:3000/api/v2/tubes/67/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/projects","related":"http://localhost:3000/api/v2/tubes/67/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/comments","related":"http://localhost:3000/api/v2/tubes/67/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/67/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/67/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/67/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/parents","related":"http://localhost:3000/api/v2/tubes/67/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/children","related":"http://localhost:3000/api/v2/tubes/67/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/67/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/67/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/67/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/67/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/67/aliquots"},"data":[{"type":"aliquots","id":"159"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/67/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/67/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/67/receptacle"}}}},{"id":"68","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/68"},"attributes":{"uuid":"f92fee92-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 68","labware_barcode":{"ean13_barcode":"3980000065773","machine_barcode":"3980000065773","human_barcode":"NT65M"},"state":"unknown","created_at":"2022-03-09T14:19:47+00:00","updated_at":"2022-03-09T14:19:47+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/68/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/68/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/samples","related":"http://localhost:3000/api/v2/tubes/68/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/studies","related":"http://localhost:3000/api/v2/tubes/68/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/projects","related":"http://localhost:3000/api/v2/tubes/68/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/comments","related":"http://localhost:3000/api/v2/tubes/68/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/68/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/68/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/68/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/parents","related":"http://localhost:3000/api/v2/tubes/68/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/children","related":"http://localhost:3000/api/v2/tubes/68/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/68/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/68/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/68/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/68/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/68/aliquots"},"data":[{"type":"aliquots","id":"160"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/68/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/68/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/68/receptacle"}}}},{"id":"69","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/69"},"attributes":{"uuid":"f94108ee-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 69","labware_barcode":{"ean13_barcode":"3980000066787","machine_barcode":"3980000066787","human_barcode":"NT66N"},"state":"unknown","created_at":"2022-03-09T14:19:47+00:00","updated_at":"2022-03-09T14:19:47+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/69/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/69/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/samples","related":"http://localhost:3000/api/v2/tubes/69/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/studies","related":"http://localhost:3000/api/v2/tubes/69/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/projects","related":"http://localhost:3000/api/v2/tubes/69/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/comments","related":"http://localhost:3000/api/v2/tubes/69/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/69/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/69/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/69/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/parents","related":"http://localhost:3000/api/v2/tubes/69/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/children","related":"http://localhost:3000/api/v2/tubes/69/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/69/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/69/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/69/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/69/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/69/aliquots"},"data":[{"type":"aliquots","id":"161"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/69/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/69/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/69/receptacle"}}}},{"id":"70","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/70"},"attributes":{"uuid":"f950f5ec-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 70","labware_barcode":{"ean13_barcode":"3980000067791","machine_barcode":"3980000067791","human_barcode":"NT67O"},"state":"unknown","created_at":"2022-03-09T14:19:47+00:00","updated_at":"2022-03-09T14:19:47+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/70/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/70/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/samples","related":"http://localhost:3000/api/v2/tubes/70/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/studies","related":"http://localhost:3000/api/v2/tubes/70/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/projects","related":"http://localhost:3000/api/v2/tubes/70/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/comments","related":"http://localhost:3000/api/v2/tubes/70/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/70/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/70/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/70/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/parents","related":"http://localhost:3000/api/v2/tubes/70/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/children","related":"http://localhost:3000/api/v2/tubes/70/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/70/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/70/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/70/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/70/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/70/aliquots"},"data":[{"type":"aliquots","id":"162"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/70/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/70/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/70/receptacle"}}}},{"id":"71","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/71"},"attributes":{"uuid":"f961c62e-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 71","labware_barcode":{"ean13_barcode":"3980000068804","machine_barcode":"3980000068804","human_barcode":"NT68P"},"state":"unknown","created_at":"2022-03-09T14:19:47+00:00","updated_at":"2022-03-09T14:19:47+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/71/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/71/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/samples","related":"http://localhost:3000/api/v2/tubes/71/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/studies","related":"http://localhost:3000/api/v2/tubes/71/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/projects","related":"http://localhost:3000/api/v2/tubes/71/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/comments","related":"http://localhost:3000/api/v2/tubes/71/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/71/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/71/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/71/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/parents","related":"http://localhost:3000/api/v2/tubes/71/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/children","related":"http://localhost:3000/api/v2/tubes/71/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/71/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/71/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/71/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/71/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/71/aliquots"},"data":[{"type":"aliquots","id":"163"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/71/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/71/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/71/receptacle"}}}},{"id":"72","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/72"},"attributes":{"uuid":"f979c922-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 72","labware_barcode":{"ean13_barcode":"3980000069818","machine_barcode":"3980000069818","human_barcode":"NT69Q"},"state":"unknown","created_at":"2022-03-09T14:19:47+00:00","updated_at":"2022-03-09T14:19:47+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/72/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/72/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/samples","related":"http://localhost:3000/api/v2/tubes/72/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/studies","related":"http://localhost:3000/api/v2/tubes/72/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/projects","related":"http://localhost:3000/api/v2/tubes/72/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/comments","related":"http://localhost:3000/api/v2/tubes/72/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/72/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/72/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/72/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/parents","related":"http://localhost:3000/api/v2/tubes/72/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/children","related":"http://localhost:3000/api/v2/tubes/72/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/72/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/72/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/72/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/72/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/72/aliquots"},"data":[{"type":"aliquots","id":"164"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/72/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/72/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/72/receptacle"}}}},{"id":"73","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/73"},"attributes":{"uuid":"f992993e-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 73","labware_barcode":{"ean13_barcode":"3980000070746","machine_barcode":"3980000070746","human_barcode":"NT70J"},"state":"unknown","created_at":"2022-03-09T14:19:47+00:00","updated_at":"2022-03-09T14:19:47+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/73/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/73/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/samples","related":"http://localhost:3000/api/v2/tubes/73/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/studies","related":"http://localhost:3000/api/v2/tubes/73/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/projects","related":"http://localhost:3000/api/v2/tubes/73/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/comments","related":"http://localhost:3000/api/v2/tubes/73/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/73/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/73/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/73/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/parents","related":"http://localhost:3000/api/v2/tubes/73/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/children","related":"http://localhost:3000/api/v2/tubes/73/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/73/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/73/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/73/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/73/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/73/aliquots"},"data":[{"type":"aliquots","id":"165"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/73/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/73/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/73/receptacle"}}}},{"id":"74","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/74"},"attributes":{"uuid":"f9a507f4-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 74","labware_barcode":{"ean13_barcode":"3980000071750","machine_barcode":"3980000071750","human_barcode":"NT71K"},"state":"unknown","created_at":"2022-03-09T14:19:47+00:00","updated_at":"2022-03-09T14:19:47+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/74/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/74/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/samples","related":"http://localhost:3000/api/v2/tubes/74/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/studies","related":"http://localhost:3000/api/v2/tubes/74/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/projects","related":"http://localhost:3000/api/v2/tubes/74/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/comments","related":"http://localhost:3000/api/v2/tubes/74/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/74/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/74/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/74/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/parents","related":"http://localhost:3000/api/v2/tubes/74/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/children","related":"http://localhost:3000/api/v2/tubes/74/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/74/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/74/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/74/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/74/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/74/aliquots"},"data":[{"type":"aliquots","id":"166"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/74/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/74/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/74/receptacle"}}}},{"id":"75","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/75"},"attributes":{"uuid":"f9b649ba-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 75","labware_barcode":{"ean13_barcode":"3980000072764","machine_barcode":"3980000072764","human_barcode":"NT72L"},"state":"unknown","created_at":"2022-03-09T14:19:47+00:00","updated_at":"2022-03-09T14:19:47+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/75/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/75/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/samples","related":"http://localhost:3000/api/v2/tubes/75/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/studies","related":"http://localhost:3000/api/v2/tubes/75/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/projects","related":"http://localhost:3000/api/v2/tubes/75/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/comments","related":"http://localhost:3000/api/v2/tubes/75/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/75/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/75/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/75/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/parents","related":"http://localhost:3000/api/v2/tubes/75/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/children","related":"http://localhost:3000/api/v2/tubes/75/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/75/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/75/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/75/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/75/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/75/aliquots"},"data":[{"type":"aliquots","id":"167"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/75/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/75/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/75/receptacle"}}}},{"id":"76","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/76"},"attributes":{"uuid":"f9c711dc-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 76","labware_barcode":{"ean13_barcode":"3980000073778","machine_barcode":"3980000073778","human_barcode":"NT73M"},"state":"unknown","created_at":"2022-03-09T14:19:48+00:00","updated_at":"2022-03-09T14:19:48+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/76/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/76/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/samples","related":"http://localhost:3000/api/v2/tubes/76/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/studies","related":"http://localhost:3000/api/v2/tubes/76/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/projects","related":"http://localhost:3000/api/v2/tubes/76/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/comments","related":"http://localhost:3000/api/v2/tubes/76/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/76/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/76/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/76/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/parents","related":"http://localhost:3000/api/v2/tubes/76/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/children","related":"http://localhost:3000/api/v2/tubes/76/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/76/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/76/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/76/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/76/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/76/aliquots"},"data":[{"type":"aliquots","id":"168"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/76/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/76/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/76/receptacle"}}}},{"id":"77","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/77"},"attributes":{"uuid":"f9df765a-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 77","labware_barcode":{"ean13_barcode":"3980000074782","machine_barcode":"3980000074782","human_barcode":"NT74N"},"state":"unknown","created_at":"2022-03-09T14:19:48+00:00","updated_at":"2022-03-09T14:19:48+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/77/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/77/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/samples","related":"http://localhost:3000/api/v2/tubes/77/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/studies","related":"http://localhost:3000/api/v2/tubes/77/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/projects","related":"http://localhost:3000/api/v2/tubes/77/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/comments","related":"http://localhost:3000/api/v2/tubes/77/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/77/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/77/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/77/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/parents","related":"http://localhost:3000/api/v2/tubes/77/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/children","related":"http://localhost:3000/api/v2/tubes/77/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/77/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/77/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/77/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/77/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/77/aliquots"},"data":[{"type":"aliquots","id":"169"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/77/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/77/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/77/receptacle"}}}},{"id":"78","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/78"},"attributes":{"uuid":"f9f9782a-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 78","labware_barcode":{"ean13_barcode":"3980000075796","machine_barcode":"3980000075796","human_barcode":"NT75O"},"state":"unknown","created_at":"2022-03-09T14:19:48+00:00","updated_at":"2022-03-09T14:19:48+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/78/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/78/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/samples","related":"http://localhost:3000/api/v2/tubes/78/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/studies","related":"http://localhost:3000/api/v2/tubes/78/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/projects","related":"http://localhost:3000/api/v2/tubes/78/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/comments","related":"http://localhost:3000/api/v2/tubes/78/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/78/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/78/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/78/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/parents","related":"http://localhost:3000/api/v2/tubes/78/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/children","related":"http://localhost:3000/api/v2/tubes/78/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/78/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/78/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/78/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/78/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/78/aliquots"},"data":[{"type":"aliquots","id":"170"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/78/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/78/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/78/receptacle"}}}},{"id":"79","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/79"},"attributes":{"uuid":"fa0ff096-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 79","labware_barcode":{"ean13_barcode":"3980000076809","machine_barcode":"3980000076809","human_barcode":"NT76P"},"state":"unknown","created_at":"2022-03-09T14:19:48+00:00","updated_at":"2022-03-09T14:19:48+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/79/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/79/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/samples","related":"http://localhost:3000/api/v2/tubes/79/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/studies","related":"http://localhost:3000/api/v2/tubes/79/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/projects","related":"http://localhost:3000/api/v2/tubes/79/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/comments","related":"http://localhost:3000/api/v2/tubes/79/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/79/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/79/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/79/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/parents","related":"http://localhost:3000/api/v2/tubes/79/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/children","related":"http://localhost:3000/api/v2/tubes/79/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/79/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/79/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/79/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/79/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/79/aliquots"},"data":[{"type":"aliquots","id":"171"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/79/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/79/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/79/receptacle"}}}},{"id":"80","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/80"},"attributes":{"uuid":"fa2be6de-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 80","labware_barcode":{"ean13_barcode":"3980000077813","machine_barcode":"3980000077813","human_barcode":"NT77Q"},"state":"unknown","created_at":"2022-03-09T14:19:48+00:00","updated_at":"2022-03-09T14:19:48+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/80/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/80/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/samples","related":"http://localhost:3000/api/v2/tubes/80/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/studies","related":"http://localhost:3000/api/v2/tubes/80/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/projects","related":"http://localhost:3000/api/v2/tubes/80/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/comments","related":"http://localhost:3000/api/v2/tubes/80/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/80/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/80/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/80/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/parents","related":"http://localhost:3000/api/v2/tubes/80/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/children","related":"http://localhost:3000/api/v2/tubes/80/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/80/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/80/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/80/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/80/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/80/aliquots"},"data":[{"type":"aliquots","id":"172"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/80/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/80/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/80/receptacle"}}}},{"id":"81","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/81"},"attributes":{"uuid":"fa3cc922-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 81","labware_barcode":{"ean13_barcode":"3980000078827","machine_barcode":"3980000078827","human_barcode":"NT78R"},"state":"unknown","created_at":"2022-03-09T14:19:48+00:00","updated_at":"2022-03-09T14:19:48+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/81/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/81/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/samples","related":"http://localhost:3000/api/v2/tubes/81/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/studies","related":"http://localhost:3000/api/v2/tubes/81/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/projects","related":"http://localhost:3000/api/v2/tubes/81/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/comments","related":"http://localhost:3000/api/v2/tubes/81/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/81/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/81/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/81/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/parents","related":"http://localhost:3000/api/v2/tubes/81/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/children","related":"http://localhost:3000/api/v2/tubes/81/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/81/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/81/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/81/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/81/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/81/aliquots"},"data":[{"type":"aliquots","id":"173"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/81/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/81/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/81/receptacle"}}}},{"id":"82","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/82"},"attributes":{"uuid":"fa4e9148-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 82","labware_barcode":{"ean13_barcode":"3980000079831","machine_barcode":"3980000079831","human_barcode":"NT79S"},"state":"unknown","created_at":"2022-03-09T14:19:48+00:00","updated_at":"2022-03-09T14:19:48+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/82/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/82/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/samples","related":"http://localhost:3000/api/v2/tubes/82/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/studies","related":"http://localhost:3000/api/v2/tubes/82/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/projects","related":"http://localhost:3000/api/v2/tubes/82/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/comments","related":"http://localhost:3000/api/v2/tubes/82/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/82/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/82/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/82/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/parents","related":"http://localhost:3000/api/v2/tubes/82/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/children","related":"http://localhost:3000/api/v2/tubes/82/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/82/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/82/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/82/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/82/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/82/aliquots"},"data":[{"type":"aliquots","id":"174"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/82/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/82/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/82/receptacle"}}}},{"id":"83","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/83"},"attributes":{"uuid":"fa5d4698-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 83","labware_barcode":{"ean13_barcode":"3980000080769","machine_barcode":"3980000080769","human_barcode":"NT80L"},"state":"unknown","created_at":"2022-03-09T14:19:48+00:00","updated_at":"2022-03-09T14:19:48+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/83/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/83/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/samples","related":"http://localhost:3000/api/v2/tubes/83/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/studies","related":"http://localhost:3000/api/v2/tubes/83/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/projects","related":"http://localhost:3000/api/v2/tubes/83/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/comments","related":"http://localhost:3000/api/v2/tubes/83/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/83/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/83/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/83/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/parents","related":"http://localhost:3000/api/v2/tubes/83/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/children","related":"http://localhost:3000/api/v2/tubes/83/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/83/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/83/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/83/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/83/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/83/aliquots"},"data":[{"type":"aliquots","id":"175"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/83/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/83/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/83/receptacle"}}}},{"id":"84","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/84"},"attributes":{"uuid":"fa6bb34a-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 84","labware_barcode":{"ean13_barcode":"3980000081773","machine_barcode":"3980000081773","human_barcode":"NT81M"},"state":"unknown","created_at":"2022-03-09T14:19:49+00:00","updated_at":"2022-03-09T14:19:49+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/84/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/84/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/samples","related":"http://localhost:3000/api/v2/tubes/84/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/studies","related":"http://localhost:3000/api/v2/tubes/84/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/projects","related":"http://localhost:3000/api/v2/tubes/84/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/comments","related":"http://localhost:3000/api/v2/tubes/84/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/84/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/84/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/84/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/parents","related":"http://localhost:3000/api/v2/tubes/84/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/children","related":"http://localhost:3000/api/v2/tubes/84/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/84/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/84/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/84/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/84/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/84/aliquots"},"data":[{"type":"aliquots","id":"176"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/84/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/84/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/84/receptacle"}}}},{"id":"85","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/85"},"attributes":{"uuid":"fa7a6994-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 85","labware_barcode":{"ean13_barcode":"3980000082787","machine_barcode":"3980000082787","human_barcode":"NT82N"},"state":"unknown","created_at":"2022-03-09T14:19:49+00:00","updated_at":"2022-03-09T14:19:49+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/85/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/85/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/samples","related":"http://localhost:3000/api/v2/tubes/85/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/studies","related":"http://localhost:3000/api/v2/tubes/85/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/projects","related":"http://localhost:3000/api/v2/tubes/85/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/comments","related":"http://localhost:3000/api/v2/tubes/85/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/85/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/85/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/85/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/parents","related":"http://localhost:3000/api/v2/tubes/85/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/children","related":"http://localhost:3000/api/v2/tubes/85/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/85/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/85/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/85/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/85/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/85/aliquots"},"data":[{"type":"aliquots","id":"177"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/85/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/85/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/85/receptacle"}}}},{"id":"86","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/86"},"attributes":{"uuid":"fa88a93c-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 86","labware_barcode":{"ean13_barcode":"3980000083791","machine_barcode":"3980000083791","human_barcode":"NT83O"},"state":"unknown","created_at":"2022-03-09T14:19:49+00:00","updated_at":"2022-03-09T14:19:49+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/86/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/86/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/samples","related":"http://localhost:3000/api/v2/tubes/86/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/studies","related":"http://localhost:3000/api/v2/tubes/86/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/projects","related":"http://localhost:3000/api/v2/tubes/86/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/comments","related":"http://localhost:3000/api/v2/tubes/86/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/86/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/86/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/86/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/parents","related":"http://localhost:3000/api/v2/tubes/86/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/children","related":"http://localhost:3000/api/v2/tubes/86/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/86/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/86/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/86/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/86/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/86/aliquots"},"data":[{"type":"aliquots","id":"178"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/86/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/86/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/86/receptacle"}}}},{"id":"87","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/87"},"attributes":{"uuid":"fa9ae868-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 87","labware_barcode":{"ean13_barcode":"3980000084804","machine_barcode":"3980000084804","human_barcode":"NT84P"},"state":"unknown","created_at":"2022-03-09T14:19:49+00:00","updated_at":"2022-03-09T14:19:49+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/87/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/87/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/samples","related":"http://localhost:3000/api/v2/tubes/87/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/studies","related":"http://localhost:3000/api/v2/tubes/87/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/projects","related":"http://localhost:3000/api/v2/tubes/87/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/comments","related":"http://localhost:3000/api/v2/tubes/87/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/87/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/87/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/87/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/parents","related":"http://localhost:3000/api/v2/tubes/87/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/children","related":"http://localhost:3000/api/v2/tubes/87/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/87/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/87/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/87/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/87/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/87/aliquots"},"data":[{"type":"aliquots","id":"179"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/87/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/87/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/87/receptacle"}}}},{"id":"88","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/88"},"attributes":{"uuid":"faac2772-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 88","labware_barcode":{"ean13_barcode":"3980000085818","machine_barcode":"3980000085818","human_barcode":"NT85Q"},"state":"unknown","created_at":"2022-03-09T14:19:49+00:00","updated_at":"2022-03-09T14:19:49+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/88/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/88/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/samples","related":"http://localhost:3000/api/v2/tubes/88/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/studies","related":"http://localhost:3000/api/v2/tubes/88/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/projects","related":"http://localhost:3000/api/v2/tubes/88/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/comments","related":"http://localhost:3000/api/v2/tubes/88/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/88/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/88/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/88/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/parents","related":"http://localhost:3000/api/v2/tubes/88/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/children","related":"http://localhost:3000/api/v2/tubes/88/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/88/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/88/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/88/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/88/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/88/aliquots"},"data":[{"type":"aliquots","id":"180"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/88/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/88/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/88/receptacle"}}}},{"id":"89","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/89"},"attributes":{"uuid":"fabbe536-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 89","labware_barcode":{"ean13_barcode":"3980000086822","machine_barcode":"3980000086822","human_barcode":"NT86R"},"state":"unknown","created_at":"2022-03-09T14:19:49+00:00","updated_at":"2022-03-09T14:19:49+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/89/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/89/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/samples","related":"http://localhost:3000/api/v2/tubes/89/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/studies","related":"http://localhost:3000/api/v2/tubes/89/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/projects","related":"http://localhost:3000/api/v2/tubes/89/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/comments","related":"http://localhost:3000/api/v2/tubes/89/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/89/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/89/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/89/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/parents","related":"http://localhost:3000/api/v2/tubes/89/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/children","related":"http://localhost:3000/api/v2/tubes/89/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/89/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/89/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/89/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/89/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/89/aliquots"},"data":[{"type":"aliquots","id":"181"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/89/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/89/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/89/receptacle"}}}},{"id":"90","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/90"},"attributes":{"uuid":"fad2fde8-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 90","labware_barcode":{"ean13_barcode":"3980000087836","machine_barcode":"3980000087836","human_barcode":"NT87S"},"state":"unknown","created_at":"2022-03-09T14:19:49+00:00","updated_at":"2022-03-09T14:19:49+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/90/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/90/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/samples","related":"http://localhost:3000/api/v2/tubes/90/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/studies","related":"http://localhost:3000/api/v2/tubes/90/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/projects","related":"http://localhost:3000/api/v2/tubes/90/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/comments","related":"http://localhost:3000/api/v2/tubes/90/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/90/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/90/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/90/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/parents","related":"http://localhost:3000/api/v2/tubes/90/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/children","related":"http://localhost:3000/api/v2/tubes/90/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/90/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/90/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/90/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/90/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/90/aliquots"},"data":[{"type":"aliquots","id":"182"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/90/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/90/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/90/receptacle"}}}},{"id":"91","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/91"},"attributes":{"uuid":"faebc710-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 91","labware_barcode":{"ean13_barcode":"3980000088840","machine_barcode":"3980000088840","human_barcode":"NT88T"},"state":"unknown","created_at":"2022-03-09T14:19:49+00:00","updated_at":"2022-03-09T14:19:49+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/91/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/91/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/samples","related":"http://localhost:3000/api/v2/tubes/91/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/studies","related":"http://localhost:3000/api/v2/tubes/91/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/projects","related":"http://localhost:3000/api/v2/tubes/91/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/comments","related":"http://localhost:3000/api/v2/tubes/91/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/91/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/91/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/91/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/parents","related":"http://localhost:3000/api/v2/tubes/91/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/children","related":"http://localhost:3000/api/v2/tubes/91/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/91/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/91/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/91/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/91/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/91/aliquots"},"data":[{"type":"aliquots","id":"183"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/91/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/91/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/91/receptacle"}}}},{"id":"92","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/92"},"attributes":{"uuid":"fafa3a70-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 92","labware_barcode":{"ean13_barcode":"3980000089854","machine_barcode":"3980000089854","human_barcode":"NT89U"},"state":"unknown","created_at":"2022-03-09T14:19:50+00:00","updated_at":"2022-03-09T14:19:50+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/92/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/92/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/samples","related":"http://localhost:3000/api/v2/tubes/92/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/studies","related":"http://localhost:3000/api/v2/tubes/92/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/projects","related":"http://localhost:3000/api/v2/tubes/92/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/comments","related":"http://localhost:3000/api/v2/tubes/92/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/92/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/92/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/92/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/parents","related":"http://localhost:3000/api/v2/tubes/92/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/children","related":"http://localhost:3000/api/v2/tubes/92/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/92/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/92/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/92/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/92/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/92/aliquots"},"data":[{"type":"aliquots","id":"184"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/92/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/92/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/92/receptacle"}}}},{"id":"93","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/93"},"attributes":{"uuid":"fb156d2c-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 93","labware_barcode":{"ean13_barcode":"3980000090782","machine_barcode":"3980000090782","human_barcode":"NT90N"},"state":"unknown","created_at":"2022-03-09T14:19:50+00:00","updated_at":"2022-03-09T14:19:50+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/93/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/93/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/samples","related":"http://localhost:3000/api/v2/tubes/93/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/studies","related":"http://localhost:3000/api/v2/tubes/93/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/projects","related":"http://localhost:3000/api/v2/tubes/93/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/comments","related":"http://localhost:3000/api/v2/tubes/93/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/93/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/93/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/93/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/parents","related":"http://localhost:3000/api/v2/tubes/93/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/children","related":"http://localhost:3000/api/v2/tubes/93/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/93/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/93/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/93/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/93/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/93/aliquots"},"data":[{"type":"aliquots","id":"185"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/93/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/93/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/93/receptacle"}}}},{"id":"94","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/94"},"attributes":{"uuid":"fb25866c-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 94","labware_barcode":{"ean13_barcode":"3980000091796","machine_barcode":"3980000091796","human_barcode":"NT91O"},"state":"unknown","created_at":"2022-03-09T14:19:50+00:00","updated_at":"2022-03-09T14:19:50+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/94/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/94/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/samples","related":"http://localhost:3000/api/v2/tubes/94/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/studies","related":"http://localhost:3000/api/v2/tubes/94/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/projects","related":"http://localhost:3000/api/v2/tubes/94/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/comments","related":"http://localhost:3000/api/v2/tubes/94/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/94/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/94/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/94/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/parents","related":"http://localhost:3000/api/v2/tubes/94/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/children","related":"http://localhost:3000/api/v2/tubes/94/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/94/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/94/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/94/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/94/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/94/aliquots"},"data":[{"type":"aliquots","id":"186"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/94/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/94/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/94/receptacle"}}}},{"id":"95","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/95"},"attributes":{"uuid":"fb353760-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 95","labware_barcode":{"ean13_barcode":"3980000092809","machine_barcode":"3980000092809","human_barcode":"NT92P"},"state":"unknown","created_at":"2022-03-09T14:19:50+00:00","updated_at":"2022-03-09T14:19:50+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/95/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/95/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/samples","related":"http://localhost:3000/api/v2/tubes/95/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/studies","related":"http://localhost:3000/api/v2/tubes/95/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/projects","related":"http://localhost:3000/api/v2/tubes/95/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/comments","related":"http://localhost:3000/api/v2/tubes/95/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/95/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/95/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/95/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/parents","related":"http://localhost:3000/api/v2/tubes/95/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/children","related":"http://localhost:3000/api/v2/tubes/95/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/95/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/95/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/95/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/95/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/95/aliquots"},"data":[{"type":"aliquots","id":"187"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/95/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/95/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/95/receptacle"}}}},{"id":"96","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/96"},"attributes":{"uuid":"fb4547ae-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 96","labware_barcode":{"ean13_barcode":"3980000093813","machine_barcode":"3980000093813","human_barcode":"NT93Q"},"state":"unknown","created_at":"2022-03-09T14:19:50+00:00","updated_at":"2022-03-09T14:19:50+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/96/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/96/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/samples","related":"http://localhost:3000/api/v2/tubes/96/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/studies","related":"http://localhost:3000/api/v2/tubes/96/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/projects","related":"http://localhost:3000/api/v2/tubes/96/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/comments","related":"http://localhost:3000/api/v2/tubes/96/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/96/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/96/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/96/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/parents","related":"http://localhost:3000/api/v2/tubes/96/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/children","related":"http://localhost:3000/api/v2/tubes/96/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/96/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/96/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/96/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/96/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/96/aliquots"},"data":[{"type":"aliquots","id":"188"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/96/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/96/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/96/receptacle"}}}},{"id":"97","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/97"},"attributes":{"uuid":"fb54a7e4-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 97","labware_barcode":{"ean13_barcode":"3980000094827","machine_barcode":"3980000094827","human_barcode":"NT94R"},"state":"unknown","created_at":"2022-03-09T14:19:50+00:00","updated_at":"2022-03-09T14:19:50+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/97/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/97/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/samples","related":"http://localhost:3000/api/v2/tubes/97/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/studies","related":"http://localhost:3000/api/v2/tubes/97/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/projects","related":"http://localhost:3000/api/v2/tubes/97/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/comments","related":"http://localhost:3000/api/v2/tubes/97/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/97/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/97/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/97/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/parents","related":"http://localhost:3000/api/v2/tubes/97/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/children","related":"http://localhost:3000/api/v2/tubes/97/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/97/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/97/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/97/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/97/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/97/aliquots"},"data":[{"type":"aliquots","id":"189"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/97/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/97/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/97/receptacle"}}}},{"id":"98","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/98"},"attributes":{"uuid":"fb653046-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 98","labware_barcode":{"ean13_barcode":"3980000095831","machine_barcode":"3980000095831","human_barcode":"NT95S"},"state":"unknown","created_at":"2022-03-09T14:19:50+00:00","updated_at":"2022-03-09T14:19:50+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/98/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/98/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/samples","related":"http://localhost:3000/api/v2/tubes/98/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/studies","related":"http://localhost:3000/api/v2/tubes/98/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/projects","related":"http://localhost:3000/api/v2/tubes/98/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/comments","related":"http://localhost:3000/api/v2/tubes/98/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/98/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/98/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/98/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/parents","related":"http://localhost:3000/api/v2/tubes/98/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/children","related":"http://localhost:3000/api/v2/tubes/98/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/98/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/98/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/98/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/98/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/98/aliquots"},"data":[{"type":"aliquots","id":"190"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/98/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/98/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/98/receptacle"}}}},{"id":"99","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/99"},"attributes":{"uuid":"fb77ec72-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 99","labware_barcode":{"ean13_barcode":"3980000096845","machine_barcode":"3980000096845","human_barcode":"NT96T"},"state":"unknown","created_at":"2022-03-09T14:19:50+00:00","updated_at":"2022-03-09T14:19:50+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/99/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/99/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/samples","related":"http://localhost:3000/api/v2/tubes/99/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/studies","related":"http://localhost:3000/api/v2/tubes/99/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/projects","related":"http://localhost:3000/api/v2/tubes/99/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/comments","related":"http://localhost:3000/api/v2/tubes/99/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/99/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/99/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/99/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/parents","related":"http://localhost:3000/api/v2/tubes/99/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/children","related":"http://localhost:3000/api/v2/tubes/99/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/99/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/99/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/99/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/99/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/99/aliquots"},"data":[{"type":"aliquots","id":"191"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/99/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/99/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/99/receptacle"}}}},{"id":"100","type":"tubes","links":{"self":"http://localhost:3000/api/v2/tubes/100"},"attributes":{"uuid":"fb8d5daa-9fb3-11ec-a4f7-acde48001122","name":"SampleTube 100","labware_barcode":{"ean13_barcode":"3980000097859","machine_barcode":"3980000097859","human_barcode":"NT97U"},"state":"unknown","created_at":"2022-03-09T14:19:50+00:00","updated_at":"2022-03-09T14:19:50+00:00"},"relationships":{"purpose":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/purpose","related":"http://localhost:3000/api/v2/tubes/100/purpose"}},"custom_metadatum_collection":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/custom_metadatum_collection","related":"http://localhost:3000/api/v2/tubes/100/custom_metadatum_collection"}},"samples":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/samples","related":"http://localhost:3000/api/v2/tubes/100/samples"}},"studies":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/studies","related":"http://localhost:3000/api/v2/tubes/100/studies"}},"projects":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/projects","related":"http://localhost:3000/api/v2/tubes/100/projects"}},"comments":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/comments","related":"http://localhost:3000/api/v2/tubes/100/comments"}},"receptacles":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/receptacles","related":"http://localhost:3000/api/v2/tubes/100/receptacles"}},"ancestors":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/ancestors","related":"http://localhost:3000/api/v2/tubes/100/ancestors"}},"descendants":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/descendants","related":"http://localhost:3000/api/v2/tubes/100/descendants"}},"parents":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/parents","related":"http://localhost:3000/api/v2/tubes/100/parents"}},"children":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/children","related":"http://localhost:3000/api/v2/tubes/100/children"}},"child_plates":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/child_plates","related":"http://localhost:3000/api/v2/tubes/100/child_plates"}},"child_tubes":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/child_tubes","related":"http://localhost:3000/api/v2/tubes/100/child_tubes"}},"direct_submissions":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/direct_submissions","related":"http://localhost:3000/api/v2/tubes/100/direct_submissions"}},"state_changes":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/state_changes","related":"http://localhost:3000/api/v2/tubes/100/state_changes"}},"aliquots":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/aliquots","related":"http://localhost:3000/api/v2/tubes/100/aliquots"},"data":[{"type":"aliquots","id":"192"}]},"transfer_requests_as_target":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/transfer_requests_as_target","related":"http://localhost:3000/api/v2/tubes/100/transfer_requests_as_target"}},"receptacle":{"links":{"self":"http://localhost:3000/api/v2/tubes/100/relationships/receptacle","related":"http://localhost:3000/api/v2/tubes/100/receptacle"}}}},{"id":"97","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/97"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/97/relationships/study","related":"http://localhost:3000/api/v2/aliquots/97/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/97/relationships/project","related":"http://localhost:3000/api/v2/aliquots/97/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/97/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/97/sample"},"data":{"type":"samples","id":"98"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/97/relationships/request","related":"http://localhost:3000/api/v2/aliquots/97/request"}}}},{"id":"98","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/98"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/98/relationships/study","related":"http://localhost:3000/api/v2/aliquots/98/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/98/relationships/project","related":"http://localhost:3000/api/v2/aliquots/98/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/98/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/98/sample"},"data":{"type":"samples","id":"99"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/98/relationships/request","related":"http://localhost:3000/api/v2/aliquots/98/request"}}}},{"id":"99","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/99"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/99/relationships/study","related":"http://localhost:3000/api/v2/aliquots/99/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/99/relationships/project","related":"http://localhost:3000/api/v2/aliquots/99/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/99/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/99/sample"},"data":{"type":"samples","id":"100"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/99/relationships/request","related":"http://localhost:3000/api/v2/aliquots/99/request"}}}},{"id":"100","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/100"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/100/relationships/study","related":"http://localhost:3000/api/v2/aliquots/100/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/100/relationships/project","related":"http://localhost:3000/api/v2/aliquots/100/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/100/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/100/sample"},"data":{"type":"samples","id":"101"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/100/relationships/request","related":"http://localhost:3000/api/v2/aliquots/100/request"}}}},{"id":"101","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/101"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/101/relationships/study","related":"http://localhost:3000/api/v2/aliquots/101/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/101/relationships/project","related":"http://localhost:3000/api/v2/aliquots/101/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/101/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/101/sample"},"data":{"type":"samples","id":"102"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/101/relationships/request","related":"http://localhost:3000/api/v2/aliquots/101/request"}}}},{"id":"102","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/102"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/102/relationships/study","related":"http://localhost:3000/api/v2/aliquots/102/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/102/relationships/project","related":"http://localhost:3000/api/v2/aliquots/102/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/102/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/102/sample"},"data":{"type":"samples","id":"103"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/102/relationships/request","related":"http://localhost:3000/api/v2/aliquots/102/request"}}}},{"id":"103","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/103"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/103/relationships/study","related":"http://localhost:3000/api/v2/aliquots/103/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/103/relationships/project","related":"http://localhost:3000/api/v2/aliquots/103/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/103/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/103/sample"},"data":{"type":"samples","id":"104"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/103/relationships/request","related":"http://localhost:3000/api/v2/aliquots/103/request"}}}},{"id":"104","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/104"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/104/relationships/study","related":"http://localhost:3000/api/v2/aliquots/104/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/104/relationships/project","related":"http://localhost:3000/api/v2/aliquots/104/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/104/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/104/sample"},"data":{"type":"samples","id":"105"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/104/relationships/request","related":"http://localhost:3000/api/v2/aliquots/104/request"}}}},{"id":"105","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/105"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/105/relationships/study","related":"http://localhost:3000/api/v2/aliquots/105/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/105/relationships/project","related":"http://localhost:3000/api/v2/aliquots/105/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/105/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/105/sample"},"data":{"type":"samples","id":"106"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/105/relationships/request","related":"http://localhost:3000/api/v2/aliquots/105/request"}}}},{"id":"106","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/106"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/106/relationships/study","related":"http://localhost:3000/api/v2/aliquots/106/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/106/relationships/project","related":"http://localhost:3000/api/v2/aliquots/106/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/106/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/106/sample"},"data":{"type":"samples","id":"107"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/106/relationships/request","related":"http://localhost:3000/api/v2/aliquots/106/request"}}}},{"id":"107","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/107"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/107/relationships/study","related":"http://localhost:3000/api/v2/aliquots/107/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/107/relationships/project","related":"http://localhost:3000/api/v2/aliquots/107/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/107/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/107/sample"},"data":{"type":"samples","id":"108"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/107/relationships/request","related":"http://localhost:3000/api/v2/aliquots/107/request"}}}},{"id":"108","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/108"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/108/relationships/study","related":"http://localhost:3000/api/v2/aliquots/108/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/108/relationships/project","related":"http://localhost:3000/api/v2/aliquots/108/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/108/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/108/sample"},"data":{"type":"samples","id":"109"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/108/relationships/request","related":"http://localhost:3000/api/v2/aliquots/108/request"}}}},{"id":"109","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/109"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/109/relationships/study","related":"http://localhost:3000/api/v2/aliquots/109/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/109/relationships/project","related":"http://localhost:3000/api/v2/aliquots/109/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/109/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/109/sample"},"data":{"type":"samples","id":"110"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/109/relationships/request","related":"http://localhost:3000/api/v2/aliquots/109/request"}}}},{"id":"110","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/110"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/110/relationships/study","related":"http://localhost:3000/api/v2/aliquots/110/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/110/relationships/project","related":"http://localhost:3000/api/v2/aliquots/110/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/110/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/110/sample"},"data":{"type":"samples","id":"111"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/110/relationships/request","related":"http://localhost:3000/api/v2/aliquots/110/request"}}}},{"id":"111","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/111"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/111/relationships/study","related":"http://localhost:3000/api/v2/aliquots/111/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/111/relationships/project","related":"http://localhost:3000/api/v2/aliquots/111/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/111/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/111/sample"},"data":{"type":"samples","id":"112"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/111/relationships/request","related":"http://localhost:3000/api/v2/aliquots/111/request"}}}},{"id":"112","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/112"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/112/relationships/study","related":"http://localhost:3000/api/v2/aliquots/112/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/112/relationships/project","related":"http://localhost:3000/api/v2/aliquots/112/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/112/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/112/sample"},"data":{"type":"samples","id":"113"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/112/relationships/request","related":"http://localhost:3000/api/v2/aliquots/112/request"}}}},{"id":"113","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/113"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/113/relationships/study","related":"http://localhost:3000/api/v2/aliquots/113/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/113/relationships/project","related":"http://localhost:3000/api/v2/aliquots/113/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/113/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/113/sample"},"data":{"type":"samples","id":"114"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/113/relationships/request","related":"http://localhost:3000/api/v2/aliquots/113/request"}}}},{"id":"114","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/114"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/114/relationships/study","related":"http://localhost:3000/api/v2/aliquots/114/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/114/relationships/project","related":"http://localhost:3000/api/v2/aliquots/114/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/114/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/114/sample"},"data":{"type":"samples","id":"115"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/114/relationships/request","related":"http://localhost:3000/api/v2/aliquots/114/request"}}}},{"id":"115","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/115"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/115/relationships/study","related":"http://localhost:3000/api/v2/aliquots/115/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/115/relationships/project","related":"http://localhost:3000/api/v2/aliquots/115/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/115/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/115/sample"},"data":{"type":"samples","id":"116"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/115/relationships/request","related":"http://localhost:3000/api/v2/aliquots/115/request"}}}},{"id":"116","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/116"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/116/relationships/study","related":"http://localhost:3000/api/v2/aliquots/116/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/116/relationships/project","related":"http://localhost:3000/api/v2/aliquots/116/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/116/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/116/sample"},"data":{"type":"samples","id":"117"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/116/relationships/request","related":"http://localhost:3000/api/v2/aliquots/116/request"}}}},{"id":"117","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/117"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/117/relationships/study","related":"http://localhost:3000/api/v2/aliquots/117/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/117/relationships/project","related":"http://localhost:3000/api/v2/aliquots/117/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/117/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/117/sample"},"data":{"type":"samples","id":"118"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/117/relationships/request","related":"http://localhost:3000/api/v2/aliquots/117/request"}}}},{"id":"118","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/118"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/118/relationships/study","related":"http://localhost:3000/api/v2/aliquots/118/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/118/relationships/project","related":"http://localhost:3000/api/v2/aliquots/118/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/118/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/118/sample"},"data":{"type":"samples","id":"119"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/118/relationships/request","related":"http://localhost:3000/api/v2/aliquots/118/request"}}}},{"id":"119","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/119"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/119/relationships/study","related":"http://localhost:3000/api/v2/aliquots/119/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/119/relationships/project","related":"http://localhost:3000/api/v2/aliquots/119/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/119/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/119/sample"},"data":{"type":"samples","id":"120"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/119/relationships/request","related":"http://localhost:3000/api/v2/aliquots/119/request"}}}},{"id":"120","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/120"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/120/relationships/study","related":"http://localhost:3000/api/v2/aliquots/120/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/120/relationships/project","related":"http://localhost:3000/api/v2/aliquots/120/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/120/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/120/sample"},"data":{"type":"samples","id":"121"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/120/relationships/request","related":"http://localhost:3000/api/v2/aliquots/120/request"}}}},{"id":"121","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/121"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/121/relationships/study","related":"http://localhost:3000/api/v2/aliquots/121/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/121/relationships/project","related":"http://localhost:3000/api/v2/aliquots/121/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/121/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/121/sample"},"data":{"type":"samples","id":"122"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/121/relationships/request","related":"http://localhost:3000/api/v2/aliquots/121/request"}}}},{"id":"122","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/122"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/122/relationships/study","related":"http://localhost:3000/api/v2/aliquots/122/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/122/relationships/project","related":"http://localhost:3000/api/v2/aliquots/122/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/122/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/122/sample"},"data":{"type":"samples","id":"123"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/122/relationships/request","related":"http://localhost:3000/api/v2/aliquots/122/request"}}}},{"id":"123","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/123"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/123/relationships/study","related":"http://localhost:3000/api/v2/aliquots/123/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/123/relationships/project","related":"http://localhost:3000/api/v2/aliquots/123/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/123/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/123/sample"},"data":{"type":"samples","id":"124"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/123/relationships/request","related":"http://localhost:3000/api/v2/aliquots/123/request"}}}},{"id":"124","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/124"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/124/relationships/study","related":"http://localhost:3000/api/v2/aliquots/124/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/124/relationships/project","related":"http://localhost:3000/api/v2/aliquots/124/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/124/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/124/sample"},"data":{"type":"samples","id":"125"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/124/relationships/request","related":"http://localhost:3000/api/v2/aliquots/124/request"}}}},{"id":"125","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/125"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/125/relationships/study","related":"http://localhost:3000/api/v2/aliquots/125/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/125/relationships/project","related":"http://localhost:3000/api/v2/aliquots/125/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/125/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/125/sample"},"data":{"type":"samples","id":"126"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/125/relationships/request","related":"http://localhost:3000/api/v2/aliquots/125/request"}}}},{"id":"126","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/126"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/126/relationships/study","related":"http://localhost:3000/api/v2/aliquots/126/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/126/relationships/project","related":"http://localhost:3000/api/v2/aliquots/126/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/126/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/126/sample"},"data":{"type":"samples","id":"127"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/126/relationships/request","related":"http://localhost:3000/api/v2/aliquots/126/request"}}}},{"id":"127","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/127"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/127/relationships/study","related":"http://localhost:3000/api/v2/aliquots/127/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/127/relationships/project","related":"http://localhost:3000/api/v2/aliquots/127/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/127/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/127/sample"},"data":{"type":"samples","id":"128"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/127/relationships/request","related":"http://localhost:3000/api/v2/aliquots/127/request"}}}},{"id":"128","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/128"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/128/relationships/study","related":"http://localhost:3000/api/v2/aliquots/128/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/128/relationships/project","related":"http://localhost:3000/api/v2/aliquots/128/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/128/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/128/sample"},"data":{"type":"samples","id":"129"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/128/relationships/request","related":"http://localhost:3000/api/v2/aliquots/128/request"}}}},{"id":"129","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/129"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/129/relationships/study","related":"http://localhost:3000/api/v2/aliquots/129/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/129/relationships/project","related":"http://localhost:3000/api/v2/aliquots/129/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/129/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/129/sample"},"data":{"type":"samples","id":"130"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/129/relationships/request","related":"http://localhost:3000/api/v2/aliquots/129/request"}}}},{"id":"130","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/130"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/130/relationships/study","related":"http://localhost:3000/api/v2/aliquots/130/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/130/relationships/project","related":"http://localhost:3000/api/v2/aliquots/130/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/130/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/130/sample"},"data":{"type":"samples","id":"131"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/130/relationships/request","related":"http://localhost:3000/api/v2/aliquots/130/request"}}}},{"id":"131","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/131"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/131/relationships/study","related":"http://localhost:3000/api/v2/aliquots/131/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/131/relationships/project","related":"http://localhost:3000/api/v2/aliquots/131/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/131/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/131/sample"},"data":{"type":"samples","id":"132"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/131/relationships/request","related":"http://localhost:3000/api/v2/aliquots/131/request"}}}},{"id":"132","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/132"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/132/relationships/study","related":"http://localhost:3000/api/v2/aliquots/132/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/132/relationships/project","related":"http://localhost:3000/api/v2/aliquots/132/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/132/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/132/sample"},"data":{"type":"samples","id":"133"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/132/relationships/request","related":"http://localhost:3000/api/v2/aliquots/132/request"}}}},{"id":"133","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/133"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/133/relationships/study","related":"http://localhost:3000/api/v2/aliquots/133/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/133/relationships/project","related":"http://localhost:3000/api/v2/aliquots/133/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/133/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/133/sample"},"data":{"type":"samples","id":"134"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/133/relationships/request","related":"http://localhost:3000/api/v2/aliquots/133/request"}}}},{"id":"134","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/134"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/134/relationships/study","related":"http://localhost:3000/api/v2/aliquots/134/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/134/relationships/project","related":"http://localhost:3000/api/v2/aliquots/134/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/134/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/134/sample"},"data":{"type":"samples","id":"135"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/134/relationships/request","related":"http://localhost:3000/api/v2/aliquots/134/request"}}}},{"id":"135","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/135"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/135/relationships/study","related":"http://localhost:3000/api/v2/aliquots/135/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/135/relationships/project","related":"http://localhost:3000/api/v2/aliquots/135/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/135/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/135/sample"},"data":{"type":"samples","id":"136"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/135/relationships/request","related":"http://localhost:3000/api/v2/aliquots/135/request"}}}},{"id":"136","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/136"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/136/relationships/study","related":"http://localhost:3000/api/v2/aliquots/136/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/136/relationships/project","related":"http://localhost:3000/api/v2/aliquots/136/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/136/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/136/sample"},"data":{"type":"samples","id":"137"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/136/relationships/request","related":"http://localhost:3000/api/v2/aliquots/136/request"}}}},{"id":"137","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/137"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/137/relationships/study","related":"http://localhost:3000/api/v2/aliquots/137/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/137/relationships/project","related":"http://localhost:3000/api/v2/aliquots/137/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/137/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/137/sample"},"data":{"type":"samples","id":"138"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/137/relationships/request","related":"http://localhost:3000/api/v2/aliquots/137/request"}}}},{"id":"138","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/138"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/138/relationships/study","related":"http://localhost:3000/api/v2/aliquots/138/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/138/relationships/project","related":"http://localhost:3000/api/v2/aliquots/138/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/138/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/138/sample"},"data":{"type":"samples","id":"139"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/138/relationships/request","related":"http://localhost:3000/api/v2/aliquots/138/request"}}}},{"id":"139","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/139"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/139/relationships/study","related":"http://localhost:3000/api/v2/aliquots/139/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/139/relationships/project","related":"http://localhost:3000/api/v2/aliquots/139/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/139/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/139/sample"},"data":{"type":"samples","id":"140"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/139/relationships/request","related":"http://localhost:3000/api/v2/aliquots/139/request"}}}},{"id":"140","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/140"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/140/relationships/study","related":"http://localhost:3000/api/v2/aliquots/140/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/140/relationships/project","related":"http://localhost:3000/api/v2/aliquots/140/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/140/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/140/sample"},"data":{"type":"samples","id":"141"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/140/relationships/request","related":"http://localhost:3000/api/v2/aliquots/140/request"}}}},{"id":"141","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/141"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/141/relationships/study","related":"http://localhost:3000/api/v2/aliquots/141/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/141/relationships/project","related":"http://localhost:3000/api/v2/aliquots/141/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/141/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/141/sample"},"data":{"type":"samples","id":"142"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/141/relationships/request","related":"http://localhost:3000/api/v2/aliquots/141/request"}}}},{"id":"142","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/142"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/142/relationships/study","related":"http://localhost:3000/api/v2/aliquots/142/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/142/relationships/project","related":"http://localhost:3000/api/v2/aliquots/142/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/142/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/142/sample"},"data":{"type":"samples","id":"143"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/142/relationships/request","related":"http://localhost:3000/api/v2/aliquots/142/request"}}}},{"id":"143","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/143"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/143/relationships/study","related":"http://localhost:3000/api/v2/aliquots/143/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/143/relationships/project","related":"http://localhost:3000/api/v2/aliquots/143/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/143/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/143/sample"},"data":{"type":"samples","id":"144"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/143/relationships/request","related":"http://localhost:3000/api/v2/aliquots/143/request"}}}},{"id":"144","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/144"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/144/relationships/study","related":"http://localhost:3000/api/v2/aliquots/144/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/144/relationships/project","related":"http://localhost:3000/api/v2/aliquots/144/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/144/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/144/sample"},"data":{"type":"samples","id":"145"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/144/relationships/request","related":"http://localhost:3000/api/v2/aliquots/144/request"}}}},{"id":"145","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/145"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/145/relationships/study","related":"http://localhost:3000/api/v2/aliquots/145/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/145/relationships/project","related":"http://localhost:3000/api/v2/aliquots/145/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/145/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/145/sample"},"data":{"type":"samples","id":"146"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/145/relationships/request","related":"http://localhost:3000/api/v2/aliquots/145/request"}}}},{"id":"146","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/146"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/146/relationships/study","related":"http://localhost:3000/api/v2/aliquots/146/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/146/relationships/project","related":"http://localhost:3000/api/v2/aliquots/146/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/146/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/146/sample"},"data":{"type":"samples","id":"147"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/146/relationships/request","related":"http://localhost:3000/api/v2/aliquots/146/request"}}}},{"id":"147","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/147"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/147/relationships/study","related":"http://localhost:3000/api/v2/aliquots/147/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/147/relationships/project","related":"http://localhost:3000/api/v2/aliquots/147/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/147/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/147/sample"},"data":{"type":"samples","id":"148"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/147/relationships/request","related":"http://localhost:3000/api/v2/aliquots/147/request"}}}},{"id":"148","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/148"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/148/relationships/study","related":"http://localhost:3000/api/v2/aliquots/148/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/148/relationships/project","related":"http://localhost:3000/api/v2/aliquots/148/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/148/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/148/sample"},"data":{"type":"samples","id":"149"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/148/relationships/request","related":"http://localhost:3000/api/v2/aliquots/148/request"}}}},{"id":"149","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/149"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/149/relationships/study","related":"http://localhost:3000/api/v2/aliquots/149/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/149/relationships/project","related":"http://localhost:3000/api/v2/aliquots/149/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/149/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/149/sample"},"data":{"type":"samples","id":"150"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/149/relationships/request","related":"http://localhost:3000/api/v2/aliquots/149/request"}}}},{"id":"150","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/150"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/150/relationships/study","related":"http://localhost:3000/api/v2/aliquots/150/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/150/relationships/project","related":"http://localhost:3000/api/v2/aliquots/150/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/150/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/150/sample"},"data":{"type":"samples","id":"151"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/150/relationships/request","related":"http://localhost:3000/api/v2/aliquots/150/request"}}}},{"id":"151","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/151"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/151/relationships/study","related":"http://localhost:3000/api/v2/aliquots/151/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/151/relationships/project","related":"http://localhost:3000/api/v2/aliquots/151/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/151/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/151/sample"},"data":{"type":"samples","id":"152"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/151/relationships/request","related":"http://localhost:3000/api/v2/aliquots/151/request"}}}},{"id":"152","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/152"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/152/relationships/study","related":"http://localhost:3000/api/v2/aliquots/152/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/152/relationships/project","related":"http://localhost:3000/api/v2/aliquots/152/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/152/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/152/sample"},"data":{"type":"samples","id":"153"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/152/relationships/request","related":"http://localhost:3000/api/v2/aliquots/152/request"}}}},{"id":"153","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/153"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/153/relationships/study","related":"http://localhost:3000/api/v2/aliquots/153/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/153/relationships/project","related":"http://localhost:3000/api/v2/aliquots/153/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/153/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/153/sample"},"data":{"type":"samples","id":"154"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/153/relationships/request","related":"http://localhost:3000/api/v2/aliquots/153/request"}}}},{"id":"154","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/154"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/154/relationships/study","related":"http://localhost:3000/api/v2/aliquots/154/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/154/relationships/project","related":"http://localhost:3000/api/v2/aliquots/154/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/154/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/154/sample"},"data":{"type":"samples","id":"155"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/154/relationships/request","related":"http://localhost:3000/api/v2/aliquots/154/request"}}}},{"id":"155","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/155"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/155/relationships/study","related":"http://localhost:3000/api/v2/aliquots/155/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/155/relationships/project","related":"http://localhost:3000/api/v2/aliquots/155/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/155/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/155/sample"},"data":{"type":"samples","id":"156"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/155/relationships/request","related":"http://localhost:3000/api/v2/aliquots/155/request"}}}},{"id":"156","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/156"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/156/relationships/study","related":"http://localhost:3000/api/v2/aliquots/156/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/156/relationships/project","related":"http://localhost:3000/api/v2/aliquots/156/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/156/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/156/sample"},"data":{"type":"samples","id":"157"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/156/relationships/request","related":"http://localhost:3000/api/v2/aliquots/156/request"}}}},{"id":"157","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/157"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/157/relationships/study","related":"http://localhost:3000/api/v2/aliquots/157/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/157/relationships/project","related":"http://localhost:3000/api/v2/aliquots/157/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/157/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/157/sample"},"data":{"type":"samples","id":"158"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/157/relationships/request","related":"http://localhost:3000/api/v2/aliquots/157/request"}}}},{"id":"158","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/158"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/158/relationships/study","related":"http://localhost:3000/api/v2/aliquots/158/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/158/relationships/project","related":"http://localhost:3000/api/v2/aliquots/158/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/158/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/158/sample"},"data":{"type":"samples","id":"159"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/158/relationships/request","related":"http://localhost:3000/api/v2/aliquots/158/request"}}}},{"id":"159","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/159"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/159/relationships/study","related":"http://localhost:3000/api/v2/aliquots/159/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/159/relationships/project","related":"http://localhost:3000/api/v2/aliquots/159/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/159/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/159/sample"},"data":{"type":"samples","id":"160"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/159/relationships/request","related":"http://localhost:3000/api/v2/aliquots/159/request"}}}},{"id":"160","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/160"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/160/relationships/study","related":"http://localhost:3000/api/v2/aliquots/160/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/160/relationships/project","related":"http://localhost:3000/api/v2/aliquots/160/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/160/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/160/sample"},"data":{"type":"samples","id":"161"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/160/relationships/request","related":"http://localhost:3000/api/v2/aliquots/160/request"}}}},{"id":"161","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/161"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/161/relationships/study","related":"http://localhost:3000/api/v2/aliquots/161/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/161/relationships/project","related":"http://localhost:3000/api/v2/aliquots/161/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/161/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/161/sample"},"data":{"type":"samples","id":"162"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/161/relationships/request","related":"http://localhost:3000/api/v2/aliquots/161/request"}}}},{"id":"162","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/162"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/162/relationships/study","related":"http://localhost:3000/api/v2/aliquots/162/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/162/relationships/project","related":"http://localhost:3000/api/v2/aliquots/162/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/162/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/162/sample"},"data":{"type":"samples","id":"163"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/162/relationships/request","related":"http://localhost:3000/api/v2/aliquots/162/request"}}}},{"id":"163","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/163"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/163/relationships/study","related":"http://localhost:3000/api/v2/aliquots/163/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/163/relationships/project","related":"http://localhost:3000/api/v2/aliquots/163/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/163/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/163/sample"},"data":{"type":"samples","id":"164"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/163/relationships/request","related":"http://localhost:3000/api/v2/aliquots/163/request"}}}},{"id":"164","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/164"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/164/relationships/study","related":"http://localhost:3000/api/v2/aliquots/164/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/164/relationships/project","related":"http://localhost:3000/api/v2/aliquots/164/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/164/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/164/sample"},"data":{"type":"samples","id":"165"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/164/relationships/request","related":"http://localhost:3000/api/v2/aliquots/164/request"}}}},{"id":"165","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/165"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/165/relationships/study","related":"http://localhost:3000/api/v2/aliquots/165/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/165/relationships/project","related":"http://localhost:3000/api/v2/aliquots/165/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/165/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/165/sample"},"data":{"type":"samples","id":"166"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/165/relationships/request","related":"http://localhost:3000/api/v2/aliquots/165/request"}}}},{"id":"166","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/166"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/166/relationships/study","related":"http://localhost:3000/api/v2/aliquots/166/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/166/relationships/project","related":"http://localhost:3000/api/v2/aliquots/166/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/166/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/166/sample"},"data":{"type":"samples","id":"167"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/166/relationships/request","related":"http://localhost:3000/api/v2/aliquots/166/request"}}}},{"id":"167","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/167"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/167/relationships/study","related":"http://localhost:3000/api/v2/aliquots/167/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/167/relationships/project","related":"http://localhost:3000/api/v2/aliquots/167/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/167/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/167/sample"},"data":{"type":"samples","id":"168"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/167/relationships/request","related":"http://localhost:3000/api/v2/aliquots/167/request"}}}},{"id":"168","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/168"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/168/relationships/study","related":"http://localhost:3000/api/v2/aliquots/168/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/168/relationships/project","related":"http://localhost:3000/api/v2/aliquots/168/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/168/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/168/sample"},"data":{"type":"samples","id":"169"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/168/relationships/request","related":"http://localhost:3000/api/v2/aliquots/168/request"}}}},{"id":"169","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/169"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/169/relationships/study","related":"http://localhost:3000/api/v2/aliquots/169/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/169/relationships/project","related":"http://localhost:3000/api/v2/aliquots/169/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/169/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/169/sample"},"data":{"type":"samples","id":"170"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/169/relationships/request","related":"http://localhost:3000/api/v2/aliquots/169/request"}}}},{"id":"170","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/170"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/170/relationships/study","related":"http://localhost:3000/api/v2/aliquots/170/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/170/relationships/project","related":"http://localhost:3000/api/v2/aliquots/170/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/170/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/170/sample"},"data":{"type":"samples","id":"171"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/170/relationships/request","related":"http://localhost:3000/api/v2/aliquots/170/request"}}}},{"id":"171","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/171"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/171/relationships/study","related":"http://localhost:3000/api/v2/aliquots/171/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/171/relationships/project","related":"http://localhost:3000/api/v2/aliquots/171/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/171/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/171/sample"},"data":{"type":"samples","id":"172"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/171/relationships/request","related":"http://localhost:3000/api/v2/aliquots/171/request"}}}},{"id":"172","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/172"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/172/relationships/study","related":"http://localhost:3000/api/v2/aliquots/172/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/172/relationships/project","related":"http://localhost:3000/api/v2/aliquots/172/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/172/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/172/sample"},"data":{"type":"samples","id":"173"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/172/relationships/request","related":"http://localhost:3000/api/v2/aliquots/172/request"}}}},{"id":"173","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/173"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/173/relationships/study","related":"http://localhost:3000/api/v2/aliquots/173/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/173/relationships/project","related":"http://localhost:3000/api/v2/aliquots/173/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/173/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/173/sample"},"data":{"type":"samples","id":"174"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/173/relationships/request","related":"http://localhost:3000/api/v2/aliquots/173/request"}}}},{"id":"174","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/174"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/174/relationships/study","related":"http://localhost:3000/api/v2/aliquots/174/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/174/relationships/project","related":"http://localhost:3000/api/v2/aliquots/174/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/174/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/174/sample"},"data":{"type":"samples","id":"175"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/174/relationships/request","related":"http://localhost:3000/api/v2/aliquots/174/request"}}}},{"id":"175","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/175"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/175/relationships/study","related":"http://localhost:3000/api/v2/aliquots/175/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/175/relationships/project","related":"http://localhost:3000/api/v2/aliquots/175/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/175/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/175/sample"},"data":{"type":"samples","id":"176"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/175/relationships/request","related":"http://localhost:3000/api/v2/aliquots/175/request"}}}},{"id":"176","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/176"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/176/relationships/study","related":"http://localhost:3000/api/v2/aliquots/176/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/176/relationships/project","related":"http://localhost:3000/api/v2/aliquots/176/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/176/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/176/sample"},"data":{"type":"samples","id":"177"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/176/relationships/request","related":"http://localhost:3000/api/v2/aliquots/176/request"}}}},{"id":"177","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/177"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/177/relationships/study","related":"http://localhost:3000/api/v2/aliquots/177/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/177/relationships/project","related":"http://localhost:3000/api/v2/aliquots/177/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/177/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/177/sample"},"data":{"type":"samples","id":"178"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/177/relationships/request","related":"http://localhost:3000/api/v2/aliquots/177/request"}}}},{"id":"178","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/178"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/178/relationships/study","related":"http://localhost:3000/api/v2/aliquots/178/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/178/relationships/project","related":"http://localhost:3000/api/v2/aliquots/178/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/178/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/178/sample"},"data":{"type":"samples","id":"179"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/178/relationships/request","related":"http://localhost:3000/api/v2/aliquots/178/request"}}}},{"id":"179","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/179"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/179/relationships/study","related":"http://localhost:3000/api/v2/aliquots/179/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/179/relationships/project","related":"http://localhost:3000/api/v2/aliquots/179/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/179/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/179/sample"},"data":{"type":"samples","id":"180"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/179/relationships/request","related":"http://localhost:3000/api/v2/aliquots/179/request"}}}},{"id":"180","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/180"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/180/relationships/study","related":"http://localhost:3000/api/v2/aliquots/180/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/180/relationships/project","related":"http://localhost:3000/api/v2/aliquots/180/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/180/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/180/sample"},"data":{"type":"samples","id":"181"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/180/relationships/request","related":"http://localhost:3000/api/v2/aliquots/180/request"}}}},{"id":"181","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/181"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/181/relationships/study","related":"http://localhost:3000/api/v2/aliquots/181/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/181/relationships/project","related":"http://localhost:3000/api/v2/aliquots/181/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/181/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/181/sample"},"data":{"type":"samples","id":"182"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/181/relationships/request","related":"http://localhost:3000/api/v2/aliquots/181/request"}}}},{"id":"182","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/182"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/182/relationships/study","related":"http://localhost:3000/api/v2/aliquots/182/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/182/relationships/project","related":"http://localhost:3000/api/v2/aliquots/182/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/182/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/182/sample"},"data":{"type":"samples","id":"183"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/182/relationships/request","related":"http://localhost:3000/api/v2/aliquots/182/request"}}}},{"id":"183","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/183"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/183/relationships/study","related":"http://localhost:3000/api/v2/aliquots/183/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/183/relationships/project","related":"http://localhost:3000/api/v2/aliquots/183/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/183/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/183/sample"},"data":{"type":"samples","id":"184"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/183/relationships/request","related":"http://localhost:3000/api/v2/aliquots/183/request"}}}},{"id":"184","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/184"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/184/relationships/study","related":"http://localhost:3000/api/v2/aliquots/184/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/184/relationships/project","related":"http://localhost:3000/api/v2/aliquots/184/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/184/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/184/sample"},"data":{"type":"samples","id":"185"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/184/relationships/request","related":"http://localhost:3000/api/v2/aliquots/184/request"}}}},{"id":"185","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/185"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/185/relationships/study","related":"http://localhost:3000/api/v2/aliquots/185/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/185/relationships/project","related":"http://localhost:3000/api/v2/aliquots/185/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/185/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/185/sample"},"data":{"type":"samples","id":"186"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/185/relationships/request","related":"http://localhost:3000/api/v2/aliquots/185/request"}}}},{"id":"186","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/186"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/186/relationships/study","related":"http://localhost:3000/api/v2/aliquots/186/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/186/relationships/project","related":"http://localhost:3000/api/v2/aliquots/186/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/186/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/186/sample"},"data":{"type":"samples","id":"187"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/186/relationships/request","related":"http://localhost:3000/api/v2/aliquots/186/request"}}}},{"id":"187","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/187"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/187/relationships/study","related":"http://localhost:3000/api/v2/aliquots/187/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/187/relationships/project","related":"http://localhost:3000/api/v2/aliquots/187/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/187/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/187/sample"},"data":{"type":"samples","id":"188"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/187/relationships/request","related":"http://localhost:3000/api/v2/aliquots/187/request"}}}},{"id":"188","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/188"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/188/relationships/study","related":"http://localhost:3000/api/v2/aliquots/188/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/188/relationships/project","related":"http://localhost:3000/api/v2/aliquots/188/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/188/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/188/sample"},"data":{"type":"samples","id":"189"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/188/relationships/request","related":"http://localhost:3000/api/v2/aliquots/188/request"}}}},{"id":"189","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/189"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/189/relationships/study","related":"http://localhost:3000/api/v2/aliquots/189/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/189/relationships/project","related":"http://localhost:3000/api/v2/aliquots/189/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/189/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/189/sample"},"data":{"type":"samples","id":"190"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/189/relationships/request","related":"http://localhost:3000/api/v2/aliquots/189/request"}}}},{"id":"190","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/190"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/190/relationships/study","related":"http://localhost:3000/api/v2/aliquots/190/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/190/relationships/project","related":"http://localhost:3000/api/v2/aliquots/190/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/190/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/190/sample"},"data":{"type":"samples","id":"191"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/190/relationships/request","related":"http://localhost:3000/api/v2/aliquots/190/request"}}}},{"id":"191","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/191"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/191/relationships/study","related":"http://localhost:3000/api/v2/aliquots/191/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/191/relationships/project","related":"http://localhost:3000/api/v2/aliquots/191/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/191/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/191/sample"},"data":{"type":"samples","id":"192"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/191/relationships/request","related":"http://localhost:3000/api/v2/aliquots/191/request"}}}},{"id":"192","type":"aliquots","links":{"self":"http://localhost:3000/api/v2/aliquots/192"},"attributes":{"tag_oligo":null,"tag_index":null,"tag2_oligo":null,"tag2_index":null,"suboptimal":false,"library_type":null},"relationships":{"study":{"links":{"self":"http://localhost:3000/api/v2/aliquots/192/relationships/study","related":"http://localhost:3000/api/v2/aliquots/192/study"},"data":{"type":"studies","id":"1"}},"project":{"links":{"self":"http://localhost:3000/api/v2/aliquots/192/relationships/project","related":"http://localhost:3000/api/v2/aliquots/192/project"}},"sample":{"links":{"self":"http://localhost:3000/api/v2/aliquots/192/relationships/sample","related":"http://localhost:3000/api/v2/aliquots/192/sample"},"data":{"type":"samples","id":"193"}},"request":{"links":{"self":"http://localhost:3000/api/v2/aliquots/192/relationships/request","related":"http://localhost:3000/api/v2/aliquots/192/request"}}}},{"id":"1","type":"studies","links":{"self":"http://localhost:3000/api/v2/studies/1"},"attributes":{"name":"UAT Study","uuid":"6d4617ea-9a21-11ec-9a02-acde48001122"}},{"id":"98","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/98"},"attributes":{"name":"sample_AB42785517_A1","sanger_sample_id":null,"uuid":"f3ec112c-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/98/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/98/sample_metadata"},"data":{"type":"sample_metadata","id":"98"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/98/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/98/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/98/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/98/component_samples"}}}},{"id":"99","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/99"},"attributes":{"name":"sample_AB42785517_A2","sanger_sample_id":null,"uuid":"f40d1aac-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/99/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/99/sample_metadata"},"data":{"type":"sample_metadata","id":"99"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/99/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/99/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/99/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/99/component_samples"}}}},{"id":"100","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/100"},"attributes":{"name":"sample_AB42785517_A3","sanger_sample_id":null,"uuid":"f430acce-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/100/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/100/sample_metadata"},"data":{"type":"sample_metadata","id":"100"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/100/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/100/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/100/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/100/component_samples"}}}},{"id":"101","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/101"},"attributes":{"name":"sample_AB42785517_A4","sanger_sample_id":null,"uuid":"f4553d14-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/101/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/101/sample_metadata"},"data":{"type":"sample_metadata","id":"101"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/101/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/101/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/101/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/101/component_samples"}}}},{"id":"102","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/102"},"attributes":{"name":"sample_AB42785517_A5","sanger_sample_id":null,"uuid":"f46c7286-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/102/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/102/sample_metadata"},"data":{"type":"sample_metadata","id":"102"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/102/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/102/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/102/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/102/component_samples"}}}},{"id":"103","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/103"},"attributes":{"name":"sample_AB42785517_A6","sanger_sample_id":null,"uuid":"f482c658-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/103/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/103/sample_metadata"},"data":{"type":"sample_metadata","id":"103"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/103/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/103/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/103/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/103/component_samples"}}}},{"id":"104","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/104"},"attributes":{"name":"sample_AB42785517_A7","sanger_sample_id":null,"uuid":"f4a0ae70-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/104/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/104/sample_metadata"},"data":{"type":"sample_metadata","id":"104"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/104/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/104/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/104/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/104/component_samples"}}}},{"id":"105","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/105"},"attributes":{"name":"sample_AB42785517_A8","sanger_sample_id":null,"uuid":"f4c4fece-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/105/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/105/sample_metadata"},"data":{"type":"sample_metadata","id":"105"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/105/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/105/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/105/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/105/component_samples"}}}},{"id":"106","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/106"},"attributes":{"name":"sample_AB42785517_A9","sanger_sample_id":null,"uuid":"f4d604e4-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/106/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/106/sample_metadata"},"data":{"type":"sample_metadata","id":"106"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/106/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/106/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/106/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/106/component_samples"}}}},{"id":"107","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/107"},"attributes":{"name":"sample_AB42785517_A10","sanger_sample_id":null,"uuid":"f4eb3468-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/107/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/107/sample_metadata"},"data":{"type":"sample_metadata","id":"107"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/107/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/107/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/107/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/107/component_samples"}}}},{"id":"108","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/108"},"attributes":{"name":"sample_AB42785517_A11","sanger_sample_id":null,"uuid":"f501dc36-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/108/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/108/sample_metadata"},"data":{"type":"sample_metadata","id":"108"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/108/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/108/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/108/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/108/component_samples"}}}},{"id":"109","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/109"},"attributes":{"name":"sample_AB42785517_A12","sanger_sample_id":null,"uuid":"f5148354-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/109/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/109/sample_metadata"},"data":{"type":"sample_metadata","id":"109"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/109/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/109/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/109/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/109/component_samples"}}}},{"id":"110","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/110"},"attributes":{"name":"sample_AB42785517_B1","sanger_sample_id":null,"uuid":"f52ebcec-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/110/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/110/sample_metadata"},"data":{"type":"sample_metadata","id":"110"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/110/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/110/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/110/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/110/component_samples"}}}},{"id":"111","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/111"},"attributes":{"name":"sample_AB42785517_B2","sanger_sample_id":null,"uuid":"f542dbd2-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/111/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/111/sample_metadata"},"data":{"type":"sample_metadata","id":"111"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/111/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/111/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/111/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/111/component_samples"}}}},{"id":"112","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/112"},"attributes":{"name":"sample_AB42785517_B3","sanger_sample_id":null,"uuid":"f5552c38-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/112/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/112/sample_metadata"},"data":{"type":"sample_metadata","id":"112"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/112/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/112/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/112/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/112/component_samples"}}}},{"id":"113","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/113"},"attributes":{"name":"sample_AB42785517_B4","sanger_sample_id":null,"uuid":"f563d2b0-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/113/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/113/sample_metadata"},"data":{"type":"sample_metadata","id":"113"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/113/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/113/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/113/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/113/component_samples"}}}},{"id":"114","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/114"},"attributes":{"name":"sample_AB42785517_B5","sanger_sample_id":null,"uuid":"f576d22a-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/114/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/114/sample_metadata"},"data":{"type":"sample_metadata","id":"114"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/114/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/114/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/114/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/114/component_samples"}}}},{"id":"115","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/115"},"attributes":{"name":"sample_AB42785517_B6","sanger_sample_id":null,"uuid":"f5942cb2-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/115/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/115/sample_metadata"},"data":{"type":"sample_metadata","id":"115"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/115/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/115/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/115/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/115/component_samples"}}}},{"id":"116","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/116"},"attributes":{"name":"sample_AB42785517_B7","sanger_sample_id":null,"uuid":"f5ae0308-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/116/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/116/sample_metadata"},"data":{"type":"sample_metadata","id":"116"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/116/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/116/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/116/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/116/component_samples"}}}},{"id":"117","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/117"},"attributes":{"name":"sample_AB42785517_B8","sanger_sample_id":null,"uuid":"f5bfb472-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/117/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/117/sample_metadata"},"data":{"type":"sample_metadata","id":"117"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/117/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/117/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/117/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/117/component_samples"}}}},{"id":"118","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/118"},"attributes":{"name":"sample_AB42785517_B9","sanger_sample_id":null,"uuid":"f5d061e6-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/118/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/118/sample_metadata"},"data":{"type":"sample_metadata","id":"118"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/118/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/118/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/118/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/118/component_samples"}}}},{"id":"119","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/119"},"attributes":{"name":"sample_AB42785517_B10","sanger_sample_id":null,"uuid":"f5e25f22-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/119/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/119/sample_metadata"},"data":{"type":"sample_metadata","id":"119"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/119/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/119/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/119/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/119/component_samples"}}}},{"id":"120","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/120"},"attributes":{"name":"sample_AB42785517_B11","sanger_sample_id":null,"uuid":"f5f8622c-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/120/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/120/sample_metadata"},"data":{"type":"sample_metadata","id":"120"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/120/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/120/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/120/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/120/component_samples"}}}},{"id":"121","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/121"},"attributes":{"name":"sample_AB42785517_B12","sanger_sample_id":null,"uuid":"f60af7de-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/121/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/121/sample_metadata"},"data":{"type":"sample_metadata","id":"121"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/121/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/121/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/121/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/121/component_samples"}}}},{"id":"122","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/122"},"attributes":{"name":"sample_AB42785517_C1","sanger_sample_id":null,"uuid":"f61c7e1e-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/122/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/122/sample_metadata"},"data":{"type":"sample_metadata","id":"122"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/122/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/122/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/122/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/122/component_samples"}}}},{"id":"123","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/123"},"attributes":{"name":"sample_AB42785517_C2","sanger_sample_id":null,"uuid":"f62be00c-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/123/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/123/sample_metadata"},"data":{"type":"sample_metadata","id":"123"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/123/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/123/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/123/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/123/component_samples"}}}},{"id":"124","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/124"},"attributes":{"name":"sample_AB42785517_C3","sanger_sample_id":null,"uuid":"f63aeb4c-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/124/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/124/sample_metadata"},"data":{"type":"sample_metadata","id":"124"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/124/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/124/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/124/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/124/component_samples"}}}},{"id":"125","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/125"},"attributes":{"name":"sample_AB42785517_C4","sanger_sample_id":null,"uuid":"f64eccd4-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/125/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/125/sample_metadata"},"data":{"type":"sample_metadata","id":"125"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/125/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/125/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/125/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/125/component_samples"}}}},{"id":"126","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/126"},"attributes":{"name":"sample_AB42785517_C5","sanger_sample_id":null,"uuid":"f668f37a-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/126/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/126/sample_metadata"},"data":{"type":"sample_metadata","id":"126"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/126/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/126/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/126/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/126/component_samples"}}}},{"id":"127","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/127"},"attributes":{"name":"sample_AB42785517_C6","sanger_sample_id":null,"uuid":"f67aa9b2-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/127/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/127/sample_metadata"},"data":{"type":"sample_metadata","id":"127"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/127/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/127/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/127/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/127/component_samples"}}}},{"id":"128","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/128"},"attributes":{"name":"sample_AB42785517_C7","sanger_sample_id":null,"uuid":"f68b567c-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/128/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/128/sample_metadata"},"data":{"type":"sample_metadata","id":"128"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/128/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/128/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/128/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/128/component_samples"}}}},{"id":"129","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/129"},"attributes":{"name":"sample_AB42785517_C8","sanger_sample_id":null,"uuid":"f6afd524-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/129/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/129/sample_metadata"},"data":{"type":"sample_metadata","id":"129"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/129/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/129/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/129/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/129/component_samples"}}}},{"id":"130","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/130"},"attributes":{"name":"sample_AB42785517_C9","sanger_sample_id":null,"uuid":"f6c3ab44-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/130/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/130/sample_metadata"},"data":{"type":"sample_metadata","id":"130"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/130/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/130/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/130/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/130/component_samples"}}}},{"id":"131","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/131"},"attributes":{"name":"sample_AB42785517_C10","sanger_sample_id":null,"uuid":"f6d6d732-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/131/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/131/sample_metadata"},"data":{"type":"sample_metadata","id":"131"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/131/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/131/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/131/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/131/component_samples"}}}},{"id":"132","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/132"},"attributes":{"name":"sample_AB42785517_C11","sanger_sample_id":null,"uuid":"f6e9cec8-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/132/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/132/sample_metadata"},"data":{"type":"sample_metadata","id":"132"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/132/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/132/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/132/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/132/component_samples"}}}},{"id":"133","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/133"},"attributes":{"name":"sample_AB42785517_C12","sanger_sample_id":null,"uuid":"f6fb8eba-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/133/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/133/sample_metadata"},"data":{"type":"sample_metadata","id":"133"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/133/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/133/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/133/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/133/component_samples"}}}},{"id":"134","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/134"},"attributes":{"name":"sample_AB42785517_D1","sanger_sample_id":null,"uuid":"f70d47f4-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/134/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/134/sample_metadata"},"data":{"type":"sample_metadata","id":"134"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/134/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/134/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/134/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/134/component_samples"}}}},{"id":"135","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/135"},"attributes":{"name":"sample_AB42785517_D2","sanger_sample_id":null,"uuid":"f72440ee-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/135/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/135/sample_metadata"},"data":{"type":"sample_metadata","id":"135"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/135/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/135/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/135/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/135/component_samples"}}}},{"id":"136","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/136"},"attributes":{"name":"sample_AB42785517_D3","sanger_sample_id":null,"uuid":"f734ca68-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/136/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/136/sample_metadata"},"data":{"type":"sample_metadata","id":"136"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/136/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/136/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/136/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/136/component_samples"}}}},{"id":"137","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/137"},"attributes":{"name":"sample_AB42785517_D4","sanger_sample_id":null,"uuid":"f7487f90-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/137/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/137/sample_metadata"},"data":{"type":"sample_metadata","id":"137"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/137/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/137/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/137/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/137/component_samples"}}}},{"id":"138","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/138"},"attributes":{"name":"sample_AB42785517_D5","sanger_sample_id":null,"uuid":"f7682214-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/138/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/138/sample_metadata"},"data":{"type":"sample_metadata","id":"138"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/138/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/138/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/138/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/138/component_samples"}}}},{"id":"139","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/139"},"attributes":{"name":"sample_AB42785517_D6","sanger_sample_id":null,"uuid":"f778cf88-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/139/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/139/sample_metadata"},"data":{"type":"sample_metadata","id":"139"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/139/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/139/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/139/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/139/component_samples"}}}},{"id":"140","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/140"},"attributes":{"name":"sample_AB42785517_D7","sanger_sample_id":null,"uuid":"f789ca0e-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/140/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/140/sample_metadata"},"data":{"type":"sample_metadata","id":"140"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/140/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/140/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/140/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/140/component_samples"}}}},{"id":"141","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/141"},"attributes":{"name":"sample_AB42785517_D8","sanger_sample_id":null,"uuid":"f7abad40-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/141/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/141/sample_metadata"},"data":{"type":"sample_metadata","id":"141"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/141/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/141/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/141/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/141/component_samples"}}}},{"id":"142","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/142"},"attributes":{"name":"sample_AB42785517_D9","sanger_sample_id":null,"uuid":"f7be2132-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/142/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/142/sample_metadata"},"data":{"type":"sample_metadata","id":"142"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/142/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/142/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/142/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/142/component_samples"}}}},{"id":"143","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/143"},"attributes":{"name":"sample_AB42785517_D10","sanger_sample_id":null,"uuid":"f7cfbb86-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/143/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/143/sample_metadata"},"data":{"type":"sample_metadata","id":"143"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/143/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/143/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/143/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/143/component_samples"}}}},{"id":"144","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/144"},"attributes":{"name":"sample_AB42785517_D11","sanger_sample_id":null,"uuid":"f7e2785c-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/144/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/144/sample_metadata"},"data":{"type":"sample_metadata","id":"144"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/144/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/144/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/144/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/144/component_samples"}}}},{"id":"145","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/145"},"attributes":{"name":"sample_AB42785517_D12","sanger_sample_id":null,"uuid":"f7f55a12-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/145/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/145/sample_metadata"},"data":{"type":"sample_metadata","id":"145"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/145/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/145/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/145/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/145/component_samples"}}}},{"id":"146","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/146"},"attributes":{"name":"sample_AB42785517_E1","sanger_sample_id":null,"uuid":"f808ff86-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/146/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/146/sample_metadata"},"data":{"type":"sample_metadata","id":"146"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/146/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/146/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/146/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/146/component_samples"}}}},{"id":"147","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/147"},"attributes":{"name":"sample_AB42785517_E2","sanger_sample_id":null,"uuid":"f81e681c-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/147/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/147/sample_metadata"},"data":{"type":"sample_metadata","id":"147"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/147/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/147/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/147/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/147/component_samples"}}}},{"id":"148","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/148"},"attributes":{"name":"sample_AB42785517_E3","sanger_sample_id":null,"uuid":"f82e13c0-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/148/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/148/sample_metadata"},"data":{"type":"sample_metadata","id":"148"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/148/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/148/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/148/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/148/component_samples"}}}},{"id":"149","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/149"},"attributes":{"name":"sample_AB42785517_E4","sanger_sample_id":null,"uuid":"f8482e72-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/149/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/149/sample_metadata"},"data":{"type":"sample_metadata","id":"149"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/149/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/149/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/149/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/149/component_samples"}}}},{"id":"150","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/150"},"attributes":{"name":"sample_AB42785517_E5","sanger_sample_id":null,"uuid":"f85a5566-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/150/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/150/sample_metadata"},"data":{"type":"sample_metadata","id":"150"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/150/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/150/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/150/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/150/component_samples"}}}},{"id":"151","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/151"},"attributes":{"name":"sample_AB42785517_E6","sanger_sample_id":null,"uuid":"f86c01b2-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/151/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/151/sample_metadata"},"data":{"type":"sample_metadata","id":"151"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/151/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/151/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/151/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/151/component_samples"}}}},{"id":"152","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/152"},"attributes":{"name":"sample_AB42785517_E7","sanger_sample_id":null,"uuid":"f88021a6-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/152/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/152/sample_metadata"},"data":{"type":"sample_metadata","id":"152"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/152/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/152/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/152/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/152/component_samples"}}}},{"id":"153","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/153"},"attributes":{"name":"sample_AB42785517_E8","sanger_sample_id":null,"uuid":"f8917744-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/153/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/153/sample_metadata"},"data":{"type":"sample_metadata","id":"153"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/153/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/153/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/153/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/153/component_samples"}}}},{"id":"154","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/154"},"attributes":{"name":"sample_AB42785517_E9","sanger_sample_id":null,"uuid":"f8a37e1c-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/154/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/154/sample_metadata"},"data":{"type":"sample_metadata","id":"154"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/154/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/154/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/154/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/154/component_samples"}}}},{"id":"155","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/155"},"attributes":{"name":"sample_AB42785517_E10","sanger_sample_id":null,"uuid":"f8b36386-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/155/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/155/sample_metadata"},"data":{"type":"sample_metadata","id":"155"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/155/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/155/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/155/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/155/component_samples"}}}},{"id":"156","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/156"},"attributes":{"name":"sample_AB42785517_E11","sanger_sample_id":null,"uuid":"f8d66a98-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/156/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/156/sample_metadata"},"data":{"type":"sample_metadata","id":"156"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/156/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/156/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/156/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/156/component_samples"}}}},{"id":"157","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/157"},"attributes":{"name":"sample_AB42785517_E12","sanger_sample_id":null,"uuid":"f8e9e2d0-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/157/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/157/sample_metadata"},"data":{"type":"sample_metadata","id":"157"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/157/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/157/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/157/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/157/component_samples"}}}},{"id":"158","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/158"},"attributes":{"name":"sample_AB42785517_F1","sanger_sample_id":null,"uuid":"f8fb3f30-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/158/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/158/sample_metadata"},"data":{"type":"sample_metadata","id":"158"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/158/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/158/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/158/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/158/component_samples"}}}},{"id":"159","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/159"},"attributes":{"name":"sample_AB42785517_F2","sanger_sample_id":null,"uuid":"f917de42-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/159/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/159/sample_metadata"},"data":{"type":"sample_metadata","id":"159"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/159/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/159/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/159/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/159/component_samples"}}}},{"id":"160","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/160"},"attributes":{"name":"sample_AB42785517_F3","sanger_sample_id":null,"uuid":"f927aad4-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/160/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/160/sample_metadata"},"data":{"type":"sample_metadata","id":"160"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/160/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/160/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/160/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/160/component_samples"}}}},{"id":"161","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/161"},"attributes":{"name":"sample_AB42785517_F4","sanger_sample_id":null,"uuid":"f938abfe-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/161/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/161/sample_metadata"},"data":{"type":"sample_metadata","id":"161"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/161/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/161/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/161/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/161/component_samples"}}}},{"id":"162","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/162"},"attributes":{"name":"sample_AB42785517_F5","sanger_sample_id":null,"uuid":"f9489b36-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/162/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/162/sample_metadata"},"data":{"type":"sample_metadata","id":"162"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/162/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/162/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/162/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/162/component_samples"}}}},{"id":"163","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/163"},"attributes":{"name":"sample_AB42785517_F6","sanger_sample_id":null,"uuid":"f959c78a-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/163/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/163/sample_metadata"},"data":{"type":"sample_metadata","id":"163"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/163/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/163/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/163/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/163/component_samples"}}}},{"id":"164","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/164"},"attributes":{"name":"sample_AB42785517_F7","sanger_sample_id":null,"uuid":"f9707b92-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/164/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/164/sample_metadata"},"data":{"type":"sample_metadata","id":"164"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/164/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/164/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/164/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/164/component_samples"}}}},{"id":"165","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/165"},"attributes":{"name":"sample_AB42785517_F8","sanger_sample_id":null,"uuid":"f985c9c0-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/165/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/165/sample_metadata"},"data":{"type":"sample_metadata","id":"165"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/165/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/165/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/165/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/165/component_samples"}}}},{"id":"166","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/166"},"attributes":{"name":"sample_AB42785517_F9","sanger_sample_id":null,"uuid":"f99c97cc-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/166/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/166/sample_metadata"},"data":{"type":"sample_metadata","id":"166"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/166/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/166/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/166/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/166/component_samples"}}}},{"id":"167","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/167"},"attributes":{"name":"sample_AB42785517_F10","sanger_sample_id":null,"uuid":"f9ac9c62-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/167/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/167/sample_metadata"},"data":{"type":"sample_metadata","id":"167"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/167/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/167/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/167/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/167/component_samples"}}}},{"id":"168","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/168"},"attributes":{"name":"sample_AB42785517_F11","sanger_sample_id":null,"uuid":"f9be0272-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/168/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/168/sample_metadata"},"data":{"type":"sample_metadata","id":"168"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/168/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/168/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/168/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/168/component_samples"}}}},{"id":"169","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/169"},"attributes":{"name":"sample_AB42785517_F12","sanger_sample_id":null,"uuid":"f9ce39d0-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/169/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/169/sample_metadata"},"data":{"type":"sample_metadata","id":"169"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/169/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/169/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/169/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/169/component_samples"}}}},{"id":"170","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/170"},"attributes":{"name":"sample_AB42785517_G1","sanger_sample_id":null,"uuid":"f9e8504a-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/170/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/170/sample_metadata"},"data":{"type":"sample_metadata","id":"170"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/170/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/170/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/170/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/170/component_samples"}}}},{"id":"171","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/171"},"attributes":{"name":"sample_AB42785517_G2","sanger_sample_id":null,"uuid":"fa04818e-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/171/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/171/sample_metadata"},"data":{"type":"sample_metadata","id":"171"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/171/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/171/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/171/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/171/component_samples"}}}},{"id":"172","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/172"},"attributes":{"name":"sample_AB42785517_G3","sanger_sample_id":null,"uuid":"fa1b5242-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/172/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/172/sample_metadata"},"data":{"type":"sample_metadata","id":"172"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/172/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/172/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/172/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/172/component_samples"}}}},{"id":"173","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/173"},"attributes":{"name":"sample_AB42785517_G4","sanger_sample_id":null,"uuid":"fa34736c-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/173/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/173/sample_metadata"},"data":{"type":"sample_metadata","id":"173"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/173/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/173/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/173/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/173/component_samples"}}}},{"id":"174","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/174"},"attributes":{"name":"sample_AB42785517_G5","sanger_sample_id":null,"uuid":"fa45af2e-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/174/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/174/sample_metadata"},"data":{"type":"sample_metadata","id":"174"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/174/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/174/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/174/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/174/component_samples"}}}},{"id":"175","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/175"},"attributes":{"name":"sample_AB42785517_G6","sanger_sample_id":null,"uuid":"fa55b69e-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/175/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/175/sample_metadata"},"data":{"type":"sample_metadata","id":"175"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/175/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/175/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/175/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/175/component_samples"}}}},{"id":"176","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/176"},"attributes":{"name":"sample_AB42785517_G7","sanger_sample_id":null,"uuid":"fa64cb34-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/176/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/176/sample_metadata"},"data":{"type":"sample_metadata","id":"176"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/176/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/176/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/176/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/176/component_samples"}}}},{"id":"177","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/177"},"attributes":{"name":"sample_AB42785517_G8","sanger_sample_id":null,"uuid":"fa72a5ce-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/177/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/177/sample_metadata"},"data":{"type":"sample_metadata","id":"177"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/177/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/177/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/177/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/177/component_samples"}}}},{"id":"178","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/178"},"attributes":{"name":"sample_AB42785517_G9","sanger_sample_id":null,"uuid":"fa81c2d4-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/178/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/178/sample_metadata"},"data":{"type":"sample_metadata","id":"178"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/178/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/178/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/178/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/178/component_samples"}}}},{"id":"179","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/179"},"attributes":{"name":"sample_AB42785517_G10","sanger_sample_id":null,"uuid":"fa91ba5e-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/179/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/179/sample_metadata"},"data":{"type":"sample_metadata","id":"179"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/179/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/179/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/179/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/179/component_samples"}}}},{"id":"180","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/180"},"attributes":{"name":"sample_AB42785517_G11","sanger_sample_id":null,"uuid":"faa2f224-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/180/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/180/sample_metadata"},"data":{"type":"sample_metadata","id":"180"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/180/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/180/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/180/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/180/component_samples"}}}},{"id":"181","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/181"},"attributes":{"name":"sample_AB42785517_G12","sanger_sample_id":null,"uuid":"fab3aa6a-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/181/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/181/sample_metadata"},"data":{"type":"sample_metadata","id":"181"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/181/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/181/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/181/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/181/component_samples"}}}},{"id":"182","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/182"},"attributes":{"name":"sample_AB42785517_H1","sanger_sample_id":null,"uuid":"fac3826e-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/182/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/182/sample_metadata"},"data":{"type":"sample_metadata","id":"182"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/182/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/182/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/182/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/182/component_samples"}}}},{"id":"183","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/183"},"attributes":{"name":"sample_AB42785517_H2","sanger_sample_id":null,"uuid":"fae44eb8-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/183/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/183/sample_metadata"},"data":{"type":"sample_metadata","id":"183"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/183/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/183/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/183/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/183/component_samples"}}}},{"id":"184","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/184"},"attributes":{"name":"sample_AB42785517_H3","sanger_sample_id":null,"uuid":"faf24e64-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/184/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/184/sample_metadata"},"data":{"type":"sample_metadata","id":"184"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/184/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/184/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/184/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/184/component_samples"}}}},{"id":"185","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/185"},"attributes":{"name":"sample_AB42785517_H4","sanger_sample_id":null,"uuid":"fb019162-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/185/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/185/sample_metadata"},"data":{"type":"sample_metadata","id":"185"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/185/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/185/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/185/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/185/component_samples"}}}},{"id":"186","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/186"},"attributes":{"name":"sample_AB42785517_H5","sanger_sample_id":null,"uuid":"fb1d0924-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/186/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/186/sample_metadata"},"data":{"type":"sample_metadata","id":"186"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/186/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/186/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/186/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/186/component_samples"}}}},{"id":"187","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/187"},"attributes":{"name":"sample_AB42785517_H6","sanger_sample_id":null,"uuid":"fb2d6ee0-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/187/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/187/sample_metadata"},"data":{"type":"sample_metadata","id":"187"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/187/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/187/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/187/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/187/component_samples"}}}},{"id":"188","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/188"},"attributes":{"name":"sample_AB42785517_H7","sanger_sample_id":null,"uuid":"fb3c8fa6-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/188/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/188/sample_metadata"},"data":{"type":"sample_metadata","id":"188"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/188/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/188/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/188/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/188/component_samples"}}}},{"id":"189","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/189"},"attributes":{"name":"sample_AB42785517_H8","sanger_sample_id":null,"uuid":"fb4cefe0-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/189/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/189/sample_metadata"},"data":{"type":"sample_metadata","id":"189"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/189/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/189/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/189/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/189/component_samples"}}}},{"id":"190","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/190"},"attributes":{"name":"sample_AB42785517_H9","sanger_sample_id":null,"uuid":"fb5c2316-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/190/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/190/sample_metadata"},"data":{"type":"sample_metadata","id":"190"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/190/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/190/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/190/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/190/component_samples"}}}},{"id":"191","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/191"},"attributes":{"name":"sample_AB42785517_H10","sanger_sample_id":null,"uuid":"fb6db400-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/191/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/191/sample_metadata"},"data":{"type":"sample_metadata","id":"191"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/191/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/191/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/191/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/191/component_samples"}}}},{"id":"192","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/192"},"attributes":{"name":"sample_AB42785517_H11","sanger_sample_id":null,"uuid":"fb85173a-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/192/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/192/sample_metadata"},"data":{"type":"sample_metadata","id":"192"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/192/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/192/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/192/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/192/component_samples"}}}},{"id":"193","type":"samples","links":{"self":"http://localhost:3000/api/v2/samples/193"},"attributes":{"name":"sample_AB42785517_H12","sanger_sample_id":null,"uuid":"fb93b560-9fb3-11ec-a4f7-acde48001122","control":null,"control_type":null},"relationships":{"sample_metadata":{"links":{"self":"http://localhost:3000/api/v2/samples/193/relationships/sample_metadata","related":"http://localhost:3000/api/v2/samples/193/sample_metadata"},"data":{"type":"sample_metadata","id":"193"}},"sample_manifest":{"links":{"self":"http://localhost:3000/api/v2/samples/193/relationships/sample_manifest","related":"http://localhost:3000/api/v2/samples/193/sample_manifest"}},"component_samples":{"links":{"self":"http://localhost:3000/api/v2/samples/193/relationships/component_samples","related":"http://localhost:3000/api/v2/samples/193/component_samples"}}}},{"id":"98","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/98"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A1"}},{"id":"99","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/99"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A2"}},{"id":"100","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/100"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A3"}},{"id":"101","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/101"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A4"}},{"id":"102","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/102"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A5"}},{"id":"103","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/103"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A6"}},{"id":"104","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/104"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A7"}},{"id":"105","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/105"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A8"}},{"id":"106","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/106"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A9"}},{"id":"107","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/107"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A10"}},{"id":"108","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/108"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A11"}},{"id":"109","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/109"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_A12"}},{"id":"110","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/110"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B1"}},{"id":"111","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/111"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B2"}},{"id":"112","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/112"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B3"}},{"id":"113","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/113"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B4"}},{"id":"114","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/114"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B5"}},{"id":"115","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/115"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B6"}},{"id":"116","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/116"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B7"}},{"id":"117","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/117"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B8"}},{"id":"118","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/118"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B9"}},{"id":"119","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/119"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B10"}},{"id":"120","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/120"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B11"}},{"id":"121","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/121"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_B12"}},{"id":"122","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/122"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C1"}},{"id":"123","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/123"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C2"}},{"id":"124","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/124"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C3"}},{"id":"125","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/125"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C4"}},{"id":"126","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/126"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C5"}},{"id":"127","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/127"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C6"}},{"id":"128","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/128"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C7"}},{"id":"129","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/129"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C8"}},{"id":"130","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/130"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C9"}},{"id":"131","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/131"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C10"}},{"id":"132","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/132"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C11"}},{"id":"133","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/133"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_C12"}},{"id":"134","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/134"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D1"}},{"id":"135","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/135"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D2"}},{"id":"136","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/136"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D3"}},{"id":"137","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/137"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D4"}},{"id":"138","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/138"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D5"}},{"id":"139","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/139"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D6"}},{"id":"140","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/140"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D7"}},{"id":"141","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/141"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D8"}},{"id":"142","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/142"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D9"}},{"id":"143","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/143"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D10"}},{"id":"144","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/144"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D11"}},{"id":"145","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/145"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_D12"}},{"id":"146","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/146"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E1"}},{"id":"147","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/147"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E2"}},{"id":"148","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/148"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E3"}},{"id":"149","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/149"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E4"}},{"id":"150","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/150"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E5"}},{"id":"151","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/151"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E6"}},{"id":"152","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/152"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E7"}},{"id":"153","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/153"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E8"}},{"id":"154","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/154"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E9"}},{"id":"155","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/155"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E10"}},{"id":"156","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/156"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E11"}},{"id":"157","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/157"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_E12"}},{"id":"158","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/158"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F1"}},{"id":"159","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/159"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F2"}},{"id":"160","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/160"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F3"}},{"id":"161","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/161"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F4"}},{"id":"162","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/162"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F5"}},{"id":"163","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/163"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F6"}},{"id":"164","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/164"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F7"}},{"id":"165","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/165"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F8"}},{"id":"166","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/166"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F9"}},{"id":"167","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/167"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F10"}},{"id":"168","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/168"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F11"}},{"id":"169","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/169"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_F12"}},{"id":"170","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/170"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G1"}},{"id":"171","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/171"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G2"}},{"id":"172","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/172"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G3"}},{"id":"173","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/173"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G4"}},{"id":"174","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/174"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G5"}},{"id":"175","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/175"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G6"}},{"id":"176","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/176"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G7"}},{"id":"177","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/177"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G8"}},{"id":"178","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/178"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G9"}},{"id":"179","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/179"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G10"}},{"id":"180","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/180"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G11"}},{"id":"181","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/181"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_G12"}},{"id":"182","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/182"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H1"}},{"id":"183","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/183"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H2"}},{"id":"184","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/184"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H3"}},{"id":"185","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/185"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H4"}},{"id":"186","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/186"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H5"}},{"id":"187","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/187"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H6"}},{"id":"188","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/188"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H7"}},{"id":"189","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/189"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H8"}},{"id":"190","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/190"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H9"}},{"id":"191","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/191"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H10"}},{"id":"192","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/192"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H11"}},{"id":"193","type":"sample_metadata","links":{"self":"http://localhost:3000/api/v2/sample_metadata/193"},"attributes":{"sample_common_name":null,"supplier_name":"sample_AB42785517_H12"}}],"links":{"first":"http://localhost:3000/api/v2/tube_racks?filter%5Bbarcode%5D=AB42785517&include=racked_tubes.tube.aliquots.sample.sample_metadata%2Cracked_tubes.tube.aliquots.study&page%5Bnumber%5D=1&page%5Bsize%5D=100","last":"http://localhost:3000/api/v2/tube_racks?filter%5Bbarcode%5D=AB42785517&include=racked_tubes.tube.aliquots.sample.sample_metadata%2Cracked_tubes.tube.aliquots.study&page%5Bnumber%5D=1&page%5Bsize%5D=100"}} \ No newline at end of file From 22e0e8c32779b2091782f3c5598479e5626bb902 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 1 Apr 2022 13:43:08 +0100 Subject: [PATCH 148/303] Simplify uuid generation --- app/models/concerns/uuidable.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/models/concerns/uuidable.rb b/app/models/concerns/uuidable.rb index 5ba27cab..61979b5f 100644 --- a/app/models/concerns/uuidable.rb +++ b/app/models/concerns/uuidable.rb @@ -1,12 +1,6 @@ module Uuidable extend ActiveSupport::Concern included do - before_save :uuid - - alias_method :generate_uuid!, :uuid - end - - def uuid - self[:uuid] ||= SecureRandom.uuid + attribute :uuid, default: -> { SecureRandom.uuid } end end From 7e3bfc19b3e5ea4f64b25a5dcdb02698d7223e8f Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 1 Apr 2022 14:29:48 +0100 Subject: [PATCH 149/303] Index uuid --- db/migrate/20220401124332_index_and_constrain_uuid.rb | 11 +++++++++++ db/schema.rb | 7 ++++--- 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 db/migrate/20220401124332_index_and_constrain_uuid.rb diff --git a/db/migrate/20220401124332_index_and_constrain_uuid.rb b/db/migrate/20220401124332_index_and_constrain_uuid.rb new file mode 100644 index 00000000..e945a516 --- /dev/null +++ b/db/migrate/20220401124332_index_and_constrain_uuid.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +# Ensures the uuid column is required and indexed +# Ideally this would be a unique constraint, but there are current data integrity +# issues preventing this. +class IndexAndConstrainUuid < ActiveRecord::Migration[5.2] + def change + change_column_null :assets, :uuid, false + add_index :assets, :uuid + end +end diff --git a/db/schema.rb b/db/schema.rb index 7f4bc40f..57d55eb3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_03_30_123815) do +ActiveRecord::Schema.define(version: 2022_04_01_124332) do create_table "actions", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| t.string "action_type", null: false @@ -96,14 +96,15 @@ t.index ["asset_id"], name: "index_asset_groups_assets_on_asset_id" end - create_table "assets", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| - t.string "uuid" + create_table "assets", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + t.string "uuid", null: false t.string "barcode" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "facts_count" t.string "remote_digest" t.index ["barcode"], name: "index_assets_on_barcode" + t.index ["uuid"], name: "index_assets_on_uuid" end create_table "condition_groups", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t| From fa1fde5cbaad5079a9694dba484487864d9b3ca1 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 1 Apr 2022 14:30:11 +0100 Subject: [PATCH 150/303] Improve robustness of racking --- lib/actions/racking.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/actions/racking.rb b/lib/actions/racking.rb index 8cf3a2eb..51ca7060 100644 --- a/lib/actions/racking.rb +++ b/lib/actions/racking.rb @@ -68,10 +68,12 @@ def fact_changes_for_unrack_tubes(list_layout, destination_rack = nil) # tubes_list = Asset.where(id: tubes_ids).includes(facts: { object_asset: { facts: :object_asset } }) tubes.each_with_index do |tube, index| location_facts = tube.facts.with_predicate('location') - unless location_facts.empty? + + if location_facts.present? location = location_facts.first.object - updates.remove(tube.facts.with_predicate('location')) + updates.remove(location_facts) end + tube.facts.with_predicate('parent').each do |parent_fact| previous_rack = parent_fact.object_asset unless (previous_racks.include?(previous_rack)) @@ -93,8 +95,8 @@ def fact_changes_for_unrack_tubes(list_layout, destination_rack = nil) updates.add(rerack, 'a', 'Rerack') updates.add(rerack, 'tube', tube) updates.add(rerack, 'barcodeType', 'NoBarcode') - updates.add(rerack, 'previousParent', previous_rack) - updates.add(rerack, 'previousLocation', location) + updates.add(rerack, 'previousParent', previous_rack) if previous_rack.present? + updates.add(rerack, 'previousLocation', location) if location.present? updates.add(rerack, 'location', list_layout[index][:location]) updates.add(rerackGroup, 'rerack', rerack) @@ -216,7 +218,7 @@ def check_collisions(rack, list_layout, error_messages, error_locations) end end end - unless (list_layout.map { |obj| obj[:asset] }.include?(tube)) + if list_layout.none? { |obj| obj[:asset] == tube } # Remember that the tubes needs to be always in a rack. They cannot be interchanged # in between racks error_messages.push( From afeb483f2661251f3316cdc7561023d87ec5ce44 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 1 Apr 2022 14:37:30 +0100 Subject: [PATCH 151/303] Remove redundanct generate_uuid --- lib/parsers/csv_layout/barcode_creatable_parser.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/parsers/csv_layout/barcode_creatable_parser.rb b/lib/parsers/csv_layout/barcode_creatable_parser.rb index 886580b5..01b30e34 100644 --- a/lib/parsers/csv_layout/barcode_creatable_parser.rb +++ b/lib/parsers/csv_layout/barcode_creatable_parser.rb @@ -17,7 +17,6 @@ def asset # in that context. However, this is definitely the more sensible way of handling this. @instance = Asset.new(barcode: barcode) - @instance.generate_uuid! updater.create_assets([@instance]) updater.add(@instance, 'barcode', barcode) updater.add(@instance, 'a', 'Tube') From 5134f6695318e8162f564ed614abf913e6774085 Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 1 Apr 2022 14:47:45 +0100 Subject: [PATCH 152/303] Clear up temporary code The comment here had been rendered inaccurate via the changes I had been making. So this refactors the existing code and ensures we create the same facts as the previous path. --- .../csv_layout/barcode_creatable_parser.rb | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/parsers/csv_layout/barcode_creatable_parser.rb b/lib/parsers/csv_layout/barcode_creatable_parser.rb index 01b30e34..ce2a16db 100644 --- a/lib/parsers/csv_layout/barcode_creatable_parser.rb +++ b/lib/parsers/csv_layout/barcode_creatable_parser.rb @@ -8,19 +8,17 @@ def updater end def asset - @instance ||= @parser.find_or_import_asset_with_barcode(barcode) # || Asset.create_local_asset(barcode, updater) - - return @instance if @instance - - # In reality I don't think we ever get here, as Asset.find_or_import_asset_with_barcode - # will actually create assets for valid fluidx barcodes, and this is only used - # in that context. However, this is definitely the more sensible way of handling this. + @asset ||= @parser.find_or_import_asset_with_barcode(barcode) || generate_asset + end - @instance = Asset.new(barcode: barcode) - updater.create_assets([@instance]) - updater.add(@instance, 'barcode', barcode) - updater.add(@instance, 'a', 'Tube') - @instance + def generate_asset + Asset.new(barcode: barcode).tap do |tube| + updater.create_assets([tube]) + updater.add(tube, 'barcode', barcode) + updater.add(tube, 'a', 'Tube') + updater.add(tube, 'barcodeType', 'Code2D') if TokenUtil.is_valid_fluidx_barcode?(barcode) + updater.add(tube, 'is', 'Empty') + end end end end From af9f085a816c9d71a0df423fec3f63e573d88edf Mon Sep 17 00:00:00 2001 From: James Glover Date: Fri, 1 Apr 2022 15:25:30 +0100 Subject: [PATCH 153/303] Restore unseeded database on CI --- bin/setup | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/bin/setup b/bin/setup index 94fd4d79..35729777 100755 --- a/bin/setup +++ b/bin/setup @@ -18,7 +18,7 @@ chdir APP_ROOT do system('bundle check') || system!('bundle install') # Install JavaScript dependencies if using Yarn - # system('bin/yarn') + system!('bin/yarn') # puts "\n== Copying sample files ==" # unless File.exist?('config/database.yml') @@ -26,7 +26,16 @@ chdir APP_ROOT do # end puts "\n== Preparing database ==" - system! 'bin/rails db:setup' + if ENV['RAILS_ENV'] == 'test' + # If the RAILS_ENV is already set to test (such as on the CI server) then + # not only will rake db:setup generate the test database, but will also seed + # it. This differs from the test database created when an environment is + # unspecified, which is unseeded. We avoid using rake db:setup in this case + # and just create the database and load the schema instead. + system! 'bin/rake db:create db:schema:load' + else + system! 'bin/rake db:setup' + end puts "\n== Removing old logs and tempfiles ==" system! 'bin/rails log:clear tmp:clear' From 089dbfe0f63a851d5de3b29aa96ab7c95f3e44ad Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Fri, 1 Apr 2022 16:40:36 +0000 Subject: [PATCH 154/303] Update puma to version 5.6.4 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index fcc21daf..304511fc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -200,7 +200,7 @@ GEM coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (4.0.6) - puma (5.6.2) + puma (5.6.4) nio4r (~> 2.0) pusher-client (0.6.2) json From 975cd34b5a2223cd00749c5367c76d8fd726c5bf Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 5 Apr 2022 08:18:05 +0100 Subject: [PATCH 155/303] Remove irrelevant bits of rubocop.yml --- .rubocop.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index dd149680..b87fb717 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -12,17 +12,14 @@ AllCops: Exclude: - 'db/views_schema.rb' -# Blocks are used to structure tests and are part of the shoulda dsl. +# Blocks are used to structure tests and are part of the rspec dsl. # The standard BlockLength limits are too stringent for this purpose. # Block DSL is also used in routes # We should be careful keeping rake tasks here, as large tasks are still an issue. # Not sure if we need to split namespaces across several files though. -# We exclude builders, as the are concerned with rendering xml Metrics/BlockLength: Exclude: - Gemfile - - 'db/seeds/**/*' - - '**/*.builder' IgnoredMethods: - describe - context From fbad29a7682ba39e05e30871a5c97f549161bb37 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 5 Apr 2022 08:18:55 +0100 Subject: [PATCH 156/303] Update node version --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 95c177cc..20f0988a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,10 +53,10 @@ jobs: - name: Setup node uses: actions/setup-node@v2 with: - node-version: '14' + node-version: '16' - name: Install run: yarn install - name: Run yarn test - run: yarn test \ No newline at end of file + run: yarn test From 223ec99e76404ebff2fd46fcb97421eefe1ad268 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 5 Apr 2022 08:26:58 +0100 Subject: [PATCH 157/303] Update webmock comment in light of actually using it fully --- Gemfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index e6069917..87530c19 100644 --- a/Gemfile +++ b/Gemfile @@ -90,9 +90,7 @@ group :development do gem 'rubocop', require: false gem 'rubocop-performance' gem 'rubocop-rails' - # Lets mocking of HTTP requests, but importantly also prevents unintentional outbound connections - # I had tests connecting to my dev copy of SS and passing, and only noticed the failures on the CI. - # Suspect we'll also end up using it properly, especially for integration tests + # Mocks APi connections, and also prevents inadvertent network connections being made. gem 'webmock' end From 183979c5afdc05959cd430da63c95aee2b0741ad Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 5 Apr 2022 09:55:52 +0100 Subject: [PATCH 158/303] Fix potential selection of wrong fact --- app/models/asset.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index d822bf06..eba9705b 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -257,7 +257,7 @@ def self.class_type(facts) return 'Tube' if class_types.include?('Tube') return 'SampleTube' if class_types.include?('SampleTube') - facts.first&.object || '' + class_types.first&.object || '' end def kind_of_plate? From f2f5acdcb6045cc248633c4d83123efb36472c8a Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 5 Apr 2022 10:33:31 +0100 Subject: [PATCH 159/303] Revert accidental change of default database --- config/database.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/database.yml b/config/database.yml index a630d4d1..62ef88fa 100644 --- a/config/database.yml +++ b/config/database.yml @@ -20,7 +20,7 @@ default: &default development: <<: *default - database: <%= ENV.fetch('DBNAME','uat_se_dump') %> + database: <%= ENV.fetch('DBNAME','samples_extraction_development') %> debug: <<: *default From e28d68e0b3b0caabce8757fcc7b254f0b068f167 Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Sat, 9 Apr 2022 00:10:34 +0000 Subject: [PATCH 160/303] Update moment to version 2.29.2 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 56199769..42e3c0d8 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "fine-uploader": "^5.16.2", "fine-uploader-wrappers": "^1.0.1", "jquery": "^3.4.1", - "moment": "^2.22.2", + "moment": "^2.29.2", "node": "^10.0.0", "prop-types": "^15.6.0", "react": "^16.2.0", diff --git a/yarn.lock b/yarn.lock index 59871142..1eaee68c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5886,10 +5886,10 @@ mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: dependencies: minimist "0.0.8" -moment@^2.22.2: - version "2.24.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" - integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== +moment@^2.29.2: + version "2.29.2" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.2.tgz#00910c60b20843bcba52d37d58c628b47b1f20e4" + integrity sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg== moo@^0.4.3: version "0.4.3" From 9d82d9ff3941f7404d227db5455757da24f608e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Apr 2022 10:22:52 +0000 Subject: [PATCH 161/303] Bump nokogiri from 1.13.3 to 1.13.4 Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.13.3 to 1.13.4. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/v1.13.4/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.13.3...v1.13.4) --- updated-dependencies: - dependency-name: nokogiri dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index fcc21daf..fdbc3abd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -189,7 +189,7 @@ GEM net-http-pipeline (1.0.1) netrc (0.11.0) nio4r (2.5.8) - nokogiri (1.13.3) + nokogiri (1.13.4) mini_portile2 (~> 2.8.0) racc (~> 1.4) os (0.9.6) From 8c6285219619e26fcc7b0221abf05c887a32c3eb Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 13 Apr 2022 15:13:16 +0100 Subject: [PATCH 162/303] Update and unify node versions --- .github/workflows/test.yml | 5 ++++- .nvmrc | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 20f0988a..60541883 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -50,10 +50,13 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Export node version + id: node_version + run: echo ::set-output name=NODE_VERSION::$(cat .nvmrc) - name: Setup node uses: actions/setup-node@v2 with: - node-version: '16' + node-version: ${{ steps.node_version.outputs.NODE_VERSION }} - name: Install run: yarn install diff --git a/.nvmrc b/.nvmrc index 4ec320b2..6276cf12 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v14.17.6 +v16.14.2 From 650abd229c5b043a1aa22f256bc957109b8349bb Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 13 Apr 2022 15:40:58 +0100 Subject: [PATCH 163/303] Remove fluidgx registration This was actually undersired behaviour here, so can be removed. I have added an error for missing barcodes to improve communication. --- app/channels/activity_channel.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/channels/activity_channel.rb b/app/channels/activity_channel.rb index 0856f0d0..ef20d1a3 100644 --- a/app/channels/activity_channel.rb +++ b/app/channels/activity_channel.rb @@ -47,10 +47,9 @@ def process_asset_group(strong_params) # Maintaining existing behaviour: register previously unknown fluidx barcodes fluidx_barcodes = asset_barcodes.select { |bc| TokenUtil.is_valid_fluidx_barcode?(bc) } missing_barcodes = fluidx_barcodes - barcode_assets.map(&:barcode) - facts = FactChanges.new - generated_assets = missing_barcodes.map { |bc| Asset.create_local_asset(bc, facts) } + asset_group.update_with_assets(uuid_assets + barcode_assets) - asset_group.update_with_assets(uuid_assets + barcode_assets + generated_assets) + asset_group.activity.send_wss_event({ error: { type: 'danger', msg: "Could not find barcodes: #{missing_barcodes.join(', ')}" } }) if missing_barcodes.present? rescue Errno::ECONNREFUSED => e asset_group.activity.send_wss_event({ error: { type: 'danger', msg: 'Cannot connect with sequencescape' } }) rescue StandardError => e From 181b00d7ec596c323c07e5a39934e5f6189a7d5f Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 13 Apr 2022 15:45:36 +0100 Subject: [PATCH 164/303] =?UTF-8?q?Use=20the=20actual=20method=20arguments?= =?UTF-8?q?=20=F0=9F=A4=A6=E2=80=8D=E2=99=82=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Should not have made this mistake, and should definitely caught it in proofreading. --- app/models/asset.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index eba9705b..e9fa8e81 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -30,7 +30,7 @@ def predicate_matching?(predicate, value) if loaded? with_predicate(predicate).any? { |fact| fact.object == value } else - exists?(predicate: 'a', object: 'Plate') + exists?(predicate: predicate, object: value) end end end From 085d190411ddab8fab099cd14ba488f1765d28de Mon Sep 17 00:00:00 2001 From: James Glover Date: Wed, 13 Apr 2022 16:08:44 +0100 Subject: [PATCH 165/303] Clean up barcode parser - Ensure no_read_barcode? returns a bool - Remove unused instance variable --- lib/parsers/csv_layout/barcode_parser.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/parsers/csv_layout/barcode_parser.rb b/lib/parsers/csv_layout/barcode_parser.rb index d3793a74..a36ae19a 100644 --- a/lib/parsers/csv_layout/barcode_parser.rb +++ b/lib/parsers/csv_layout/barcode_parser.rb @@ -18,12 +18,11 @@ def validations def initialize(line, parser) @parser = parser - @parsing_error = nil parse(line) end def no_read_barcode? - barcode&.downcase&.start_with?(NO_READ_BARCODE) + !!barcode&.downcase&.start_with?(NO_READ_BARCODE) end def asset From 6157de59348c77eaeb31bd7da625156fb1837b57 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 14 Apr 2022 13:03:46 +0100 Subject: [PATCH 166/303] Fix fallback class --- app/models/asset.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index e9fa8e81..2367da43 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -257,7 +257,7 @@ def self.class_type(facts) return 'Tube' if class_types.include?('Tube') return 'SampleTube' if class_types.include?('SampleTube') - class_types.first&.object || '' + facts.with_predicate('a').first&.object || '' end def kind_of_plate? From 034992babd25dd8ee9283218f5b55698b2adb2b7 Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Thu, 14 Apr 2022 12:30:25 +0000 Subject: [PATCH 167/303] Update jquery to version 3.6.0 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b2d94248..12089df1 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "eslint": "^4.19.1", "fine-uploader": "^5.16.2", "fine-uploader-wrappers": "^1.0.1", - "jquery": "^3.4.1", + "jquery": "^3.6.0", "moment": "^2.29.2", "node": "^10.0.0", "prop-types": "^15.6.0", diff --git a/yarn.lock b/yarn.lock index 41f6288b..ac507ebc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5063,10 +5063,10 @@ jest@^24.9.0: import-local "^2.0.0" jest-cli "^24.9.0" -jquery@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2" - integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw== +jquery@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470" + integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" From b8a742528321c76f0011337d1764cc3d073790fa Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 14 Apr 2022 13:43:47 +0100 Subject: [PATCH 168/303] Sync ruby versions in docker build --- .ruby-version | 2 +- Dockerfile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.ruby-version b/.ruby-version index 849c0c47..49cdd668 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-2.7.5 +2.7.6 diff --git a/Dockerfile b/Dockerfile index e14f1238..dc0180a8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -FROM ruby:2.6 -ENV BUNDLER_VERSION=2.1.4 +FROM ruby:2.7 +ENV BUNDLER_VERSION=2.2.26 RUN apt-get update -qq && apt-get install -y # Install node and Yarn RUN curl -sL https://deb.nodesource.com/setup_15.x | bash - From 29f45001f844d5458eb0871cf03be5fe057fb737 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 14 Apr 2022 13:52:00 +0100 Subject: [PATCH 169/303] Sync node versions in dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index dc0180a8..5e2823ef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM ruby:2.7 ENV BUNDLER_VERSION=2.2.26 RUN apt-get update -qq && apt-get install -y # Install node and Yarn -RUN curl -sL https://deb.nodesource.com/setup_15.x | bash - +RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - RUN apt-get install -y nodejs RUN apt-get install -y python2 RUN npm install -g yarn From a9e84b81f0eb0244e5018dfeaa8ba6089f307a69 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 14 Apr 2022 14:01:51 +0100 Subject: [PATCH 170/303] Do not try to initialize warren to build assets --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5e2823ef..6966ba00 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ RUN yarn install ADD . /samples_extraction/ # Compiling assets -RUN RAILS_ENV=production bundle exec rake assets:precompile +RUN WARREN_TYPE=log RAILS_ENV=production bundle exec rake assets:precompile # Generating sha RUN git rev-parse HEAD > REVISION From fb79d81746a8b6e51f61e3ff9993437026712430 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 14 Apr 2022 14:21:51 +0100 Subject: [PATCH 171/303] Fix version number handling --- lib/deployed_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/deployed_version.rb b/lib/deployed_version.rb index 80ea8269..327399fe 100644 --- a/lib/deployed_version.rb +++ b/lib/deployed_version.rb @@ -45,7 +45,7 @@ def extra end def version_hash - @version_hash ||= /\Arelease-(?\d+)\.(?\d+)\.?(?\S*)\z/.match(label) + @version_hash ||= /\A(?:release-|v){0,1}(?\d+)\.(?\d+)\.?(?\S*)\z/.match(label) end def version_label From 6a9e3dfc77c4122a5269227e14cc98b3658310e5 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 14 Apr 2022 14:57:40 +0100 Subject: [PATCH 172/303] Fix warren config preventing docker build --- config/warren.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/config/warren.yml b/config/warren.yml index fed6438c..9e39b049 100644 --- a/config/warren.yml +++ b/config/warren.yml @@ -13,3 +13,16 @@ development: exchange: psd.sequencescape test: type: test +production: + type: <%= ENV['WARREN_TYPE'] %> + config: + routing_key_prefix: <%= ENV['WARREN_ROUTING_KEY']||ENV['RAILS_ENV'] %> + server: + host: <%= ENV['WARREN_HOST'] %> + port: <%= ENV['WARREN_PORT'] %> + username: <%= ENV['WARREN_USERNAME'] %> + password: <%= ENV['WARREN_PASSWORD'] %> + vhost: <%= ENV['WARREN_VHOST'] %> + frame_max: 0 + heartbeat: 30 + exchange: <%= ENV['WARREN_EXCHANGE'] %> From 92747f666a34f1cd0ff021418350f7a288ed97ea Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 14 Apr 2022 15:13:01 +0100 Subject: [PATCH 173/303] Generate temporary secret key for asset compilation --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6966ba00..35261583 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ RUN yarn install ADD . /samples_extraction/ # Compiling assets -RUN WARREN_TYPE=log RAILS_ENV=production bundle exec rake assets:precompile +RUN SECRET_KEY_BASE=`bin/rake secret` WARREN_TYPE=log RAILS_ENV=production bundle exec rake assets:precompile # Generating sha RUN git rev-parse HEAD > REVISION From eedce3526f6750d5984dba4a1fd8fb5599e6da21 Mon Sep 17 00:00:00 2001 From: James Glover Date: Thu, 14 Apr 2022 16:24:53 +0100 Subject: [PATCH 174/303] Move preset-environments into production group This probably shouldn't be necessary, as the instructions for @babel/preset-react suggest iut should be a dev dependency. However this caused rake assets:precompile to fail when in production mode. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b2d94248..021190b9 100644 --- a/package.json +++ b/package.json @@ -25,14 +25,14 @@ "react_ujs": "^2.4.4", "turbolinks": "^5.1.1", "upath": "^1.0.5", + "@babel/preset-env": "^7.5.5", + "@babel/preset-react": "^7.0.0", "webpacker-react": "^0.3.2" }, "devDependencies": { "@babel/cli": "^7.5.5", "@babel/core": "^7.5.5", "@babel/plugin-proposal-object-rest-spread": "^7.5.5", - "@babel/preset-env": "^7.5.5", - "@babel/preset-react": "^7.0.0", "babel-jest": "^24.9.0", "babel-loader": "^8.0.6", "babel-plugin-react-transform": "^3.0.0", From c9e8853dea65fc9cebbe49aa83130a9900beba5e Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Fri, 22 Apr 2022 14:02:51 +0100 Subject: [PATCH 175/303] Raise error with message when not finding the template --- app/models/label_template.rb | 8 +++++- spec/models/label_template_spec.rb | 43 ++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 spec/models/label_template_spec.rb diff --git a/app/models/label_template.rb b/app/models/label_template.rb index c5bc6e81..79bf90f7 100644 --- a/app/models/label_template.rb +++ b/app/models/label_template.rb @@ -1,7 +1,7 @@ class LabelTemplate < ApplicationRecord CLASS_TYPE_TEMPLATE_ALIASES = { 'TubeRack' => 'Plate', - 'Tube' => 'SampleTube' + 'SampleTube' => 'Tube' }.freeze validates_presence_of :name, :external_id @@ -12,6 +12,12 @@ def self.for_type(class_type, barcodetype = 'ean13') templates = where(template_type: type) + unless templates.count.positive? + raise %( + Could not find any label template for type \'#{type}\'. Please contact LIMS support to fix the problem + ) + end + templates_by_barcodetype = templates.select { |t| t.name.include?(barcodetype) } templates_by_barcodetype.presence || templates diff --git a/spec/models/label_template_spec.rb b/spec/models/label_template_spec.rb new file mode 100644 index 00000000..855a7c6f --- /dev/null +++ b/spec/models/label_template_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe LabelTemplate, type: :model do + context '#for_type' do + let!(:templates) do + [ + create(:label_template, name: 'se_ean13_96plate', template_type: 'DEPRECATED_PLATE', external_id: 1), + create(:label_template, name: 'se_code128_96plate', template_type: 'Plate', external_id: 2), + create(:label_template, name: 'se_ean13_1dtube', template_type: 'DEPRECATED_TUBE', external_id: 3), + create(:label_template, name: 'se_code128_1dtube', template_type: 'Tube', external_id: 4), + create(:label_template, name: 'sqsc_96plate_label_template_code39', template_type: 'Plate', external_id: 5), + create(:label_template, name: 'se_vertical_code39_1dtube', template_type: 'Tube', external_id: 6) + ] + end + context 'when obtaining a template' do + it 'returns a valid template for each case' do + expect(LabelTemplate.for_type('Tube', 'ean13')).to eq([templates[3], templates[5]]) + expect(LabelTemplate.for_type('Tube', 'code128')).to eq([templates[3]]) + expect(LabelTemplate.for_type('Tube', 'code39')).to eq([templates[5]]) + expect(LabelTemplate.for_type('Plate', 'ean13')).to eq([templates[1], templates[4]]) + expect(LabelTemplate.for_type('Plate', 'code128')).to eq([templates[1]]) + expect(LabelTemplate.for_type('Plate', 'code39')).to eq([templates[4]]) + end + end + context 'when using the wrong template' do + it 'raise error' do + expect { LabelTemplate.for_type('Bubidibu', 'ean13') }.to raise_error + end + end + context 'when using the template of an alias labware type' do + it 'returns a valid template for each case' do + expect(LabelTemplate.for_type('SampleTube', 'ean13')).to eq([templates[3], templates[5]]) + expect(LabelTemplate.for_type('SampleTube', 'code128')).to eq([templates[3]]) + expect(LabelTemplate.for_type('SampleTube', 'code39')).to eq([templates[5]]) + expect(LabelTemplate.for_type('TubeRack', 'ean13')).to eq([templates[1], templates[4]]) + expect(LabelTemplate.for_type('TubeRack', 'code128')).to eq([templates[1]]) + expect(LabelTemplate.for_type('TubeRack', 'code39')).to eq([templates[4]]) + end + end + end +end From 21c8ccd4a4dc91e0632823d58d81d26d8f6121d2 Mon Sep 17 00:00:00 2001 From: Eduardo Martin Rojo Date: Mon, 25 Apr 2022 20:07:22 +0100 Subject: [PATCH 176/303] Added test to fix printing error --- app/models/asset.rb | 1 + app/models/printables/group.rb | 12 +- app/models/printer.rb | 2 +- spec/controllers/assets_controller_spec.rb | 2 - spec/models/asset_spec.rb | 39 ++++- spec/models/printables/group_spec.rb | 179 +++++++++++++++++++++ spec/models/printer_spec.rb | 14 ++ 7 files changed, 237 insertions(+), 12 deletions(-) create mode 100644 spec/models/printables/group_spec.rb create mode 100644 spec/models/printer_spec.rb diff --git a/app/models/asset.rb b/app/models/asset.rb index 2367da43..bfd6690f 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -252,6 +252,7 @@ def self.class_type(facts) # We do seem to have some assets which are both 'Tube' and 'Well'. This # may be due to the representation of some tube racks in SS as plates. class_types = facts.with_predicate('a').map(&:object) + return 'TubeRack' if class_types.include?('TubeRack') return 'Plate' if class_types.include?('Plate') return 'Tube' if class_types.include?('Tube') diff --git a/app/models/printables/group.rb b/app/models/printables/group.rb index 6f00b599..5b87e3e4 100644 --- a/app/models/printables/group.rb +++ b/app/models/printables/group.rb @@ -1,8 +1,10 @@ module Printables::Group - def classify_for_printing(assets, printer_config) + def classify_for_printing(printer_config) assets.reduce({}) do |memo, asset| class_type = asset.class_type printer_name = printer_config[Printer.printer_type_for(class_type)] + raise "There is no defined Printer for asset with type #{class_type}" unless printer_name + label_template = LabelTemplate.for_type(class_type, asset.barcode_type).first [asset, label_template, printer_name] memo[printer_name] = {} unless memo[printer_name] @@ -13,13 +15,9 @@ def classify_for_printing(assets, printer_config) end def print(printer_config, user) - print_assets(assets, printer_config, user) - end - - def print_assets(assets, printer_config, user) return if Rails.configuration.printing_disabled - classify_for_printing(assets, printer_config).each do |printer_name, info_for_template| + classify_for_printing(printer_config).each do |printer_name, info_for_template| info_for_template.each do |label_template, assets| body_print = assets.filter_map { |a| a.printable_object(user) }.reverse next if body_print.empty? @@ -32,6 +30,4 @@ def print_assets(assets, printer_config, user) end end end - - module_function :print_assets end diff --git a/app/models/printer.rb b/app/models/printer.rb index cf81a570..e51438d3 100644 --- a/app/models/printer.rb +++ b/app/models/printer.rb @@ -1,7 +1,7 @@ class Printer < ApplicationRecord CLASS_TYPE_PRINTER_ALIASES = { 'TubeRack' => 'Plate', - 'Tube' => 'SampleTube' + 'SampleTube' => 'Tube' }.freeze scope :for_tube, ->() { where(:printer_type => 'Tube') } diff --git a/spec/controllers/assets_controller_spec.rb b/spec/controllers/assets_controller_spec.rb index bc809ed0..a49c80ec 100644 --- a/spec/controllers/assets_controller_spec.rb +++ b/spec/controllers/assets_controller_spec.rb @@ -38,8 +38,6 @@ it_behaves_like 'a search action from a controller' it 'prints the barcodes of the assets from the query' do - allow(Printables::Group).to receive(:print_assets) - asset = create :asset, barcode: 'S1234' search = Asset.where(barcode: 'S1234') diff --git a/spec/models/asset_spec.rb b/spec/models/asset_spec.rb index fa1a10af..d3d8f9dd 100644 --- a/spec/models/asset_spec.rb +++ b/spec/models/asset_spec.rb @@ -1,5 +1,42 @@ require 'rails_helper' -RSpec.describe Asset do +RSpec.describe Asset, type: :model do + context '#class_type' do + context 'when having several valid types' do + let(:props) do + [ + create(:fact, predicate: 'a', object: 'Tube'), + create(:fact, predicate: 'a', object: 'Well') + ] + end + let(:asset) { create :asset, facts: props } + + it 'returns the right prioritised class type' do + expect(asset.class_type).to eq('Tube') + end + end + context 'when not having any valid types' do + let(:props) do + [ + create(:fact, predicate: 'a', object: 'Something'), + create(:fact, predicate: 'a', object: 'Another') + ] + end + let(:asset) { create :asset, facts: props } + + it 'returns the first value when not recognised' do + expect(asset.class_type).to eq('Something') + end + end + + context 'when not having anything' do + let(:props) { [] } + let(:asset) { create :asset, facts: props } + + it 'returns empty string' do + expect(asset.class_type).to eq('') + end + end + end context '#has_wells?' do it 'returns true when it is a plate with wells' do plate = create(:asset) diff --git a/spec/models/printables/group_spec.rb b/spec/models/printables/group_spec.rb new file mode 100644 index 00000000..699b3095 --- /dev/null +++ b/spec/models/printables/group_spec.rb @@ -0,0 +1,179 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Printables::Group do + context '#classify_for_printing' do + context 'when all asset are for the same printer and template' do + let!(:template1) do + create(:label_template, name: 'se_ean13_96tube', template_type: 'Tube', external_id: 1) + end + let(:props1) do + [ + create(:fact, predicate: 'a', object: 'Tube') + ] + end + let(:asset1) { create(:asset, facts: props1) } + let(:asset2) { create(:asset, facts: props1) } + let(:assets) { [asset1, asset2] } + let(:group) { create :asset_group, assets: assets } + let(:config) { { 'Tube' => 'printer1', 'Plate' => 'printer2' } } + let!(:printer1) { create :printer, name: 'printer1' } + let!(:printer2) { create :printer, name: 'printer2' } + + it 'classifies all assets to use the right printer' do + expect(group.classify_for_printing(config)).to eq( + { + 'printer1' => { template1 => [asset1, asset2] } + } + ) + end + end + context 'when each asset is for a different template and printer' do + let!(:template1) do + create(:label_template, name: 'se_ean13_96tube', template_type: 'Tube', external_id: 1) + end + let!(:template2) do + create(:label_template, name: 'se_ean13_96plate', template_type: 'Plate', external_id: 2) + end + let(:props1) do + [ + create(:fact, predicate: 'a', object: 'Tube') + ] + end + let(:props2) do + [ + create(:fact, predicate: 'a', object: 'Plate') + ] + end + let(:asset1) { create(:asset, facts: props1) } + let(:asset2) { create(:asset, facts: props2) } + let(:assets) { [asset1, asset2] } + let(:group) { create :asset_group, assets: assets } + let(:config) { { 'Tube' => 'printer1', 'Plate' => 'printer2' } } + let(:printer1) { create :printer, name: 'printer1' } + let(:printer2) { create :printer, name: 'printer2' } + + it 'classifies all assets to use the right printer' do + expect(group.classify_for_printing(config)).to eq( + { + 'printer1' => { template1 => [asset1] }, + 'printer2' => { template2 => [asset2] } + } + ) + end + end + + context 'when there is no template to print the asset' do + let!(:template1) do + create(:label_template, name: 'se_ean13_96tube', template_type: 'Tube', external_id: 1) + end + let!(:template2) do + create(:label_template, name: 'se_ean13_96plate', template_type: 'DEPRECATED_PLATE', external_id: 2) + end + let(:props1) do + [ + create(:fact, predicate: 'a', object: 'Tube') + ] + end + let(:props2) do + [ + create(:fact, predicate: 'a', object: 'Plate') + ] + end + let(:asset1) { create(:asset, facts: props1) } + let(:asset2) { create(:asset, facts: props2) } + let(:assets) { [asset1, asset2] } + let(:group) { create :asset_group, assets: assets } + let(:config) { { 'Tube' => 'printer1', 'Plate' => 'printer2' } } + let(:printer1) { create :printer, name: 'printer1' } + let(:printer2) { create :printer, name: 'printer2' } + + it 'raises error' do + expect { group.classify_for_printing(config) }.to raise_error + end + end + + context 'when there is no printer to print the asset' do + let!(:template1) do + create(:label_template, name: 'se_ean13_96tube', template_type: 'Tube', external_id: 1) + end + let!(:template2) do + create(:label_template, name: 'se_ean13_96plate', template_type: 'Plate', external_id: 2) + end + let(:props1) do + [ + create(:fact, predicate: 'a', object: 'Tube') + ] + end + let(:props2) do + [ + create(:fact, predicate: 'a', object: 'Plate') + ] + end + let(:asset1) { create(:asset, facts: props1) } + let(:asset2) { create(:asset, facts: props2) } + let(:assets) { [asset1, asset2] } + let(:group) { create :asset_group, assets: assets } + let(:config) { { 'Tube' => 'printer1' } } + let(:printer1) { create :printer, name: 'printer1' } + let(:printer2) { create :printer, name: 'printer2' } + + it 'raises error' do + expect { group.classify_for_printing(config) }.to raise_error + end + end + end + + context '#print' do + let!(:template1) do + create(:label_template, name: 'se_ean13_96tube', template_type: 'Tube', external_id: 1) + end + let(:props1) do + [ + create(:fact, predicate: 'a', object: 'Tube') + ] + end + let(:asset1) { create(:asset, facts: props1, barcode: '1') } + let(:asset2) { create(:asset, facts: props1, barcode: '2') } + let(:assets) { [asset1, asset2] } + let(:group) { create :asset_group, assets: assets } + let(:config) { { 'Tube' => 'printer1', 'Plate' => 'printer2' } } + let!(:printer1) { create :printer, name: 'printer1' } + let!(:printer2) { create :printer, name: 'printer2' } + + let(:saveable_mock) { double('saveable') } + + before do + allow(Rails.configuration).to receive(:printing_disabled).and_return(false) + end + + it 'sends the right message to PMB' do + body_print = assets.filter_map { |a| a.printable_object('user1') }.reverse + + expect(PMB::PrintJob).to receive(:new).with( + printer_name: 'printer1', + label_template_id: 1, + labels: { body: body_print } + ).and_return(saveable_mock) + expect(saveable_mock).to receive(:save) + group.print(config, 'user1') + end + + context 'when an asset does not have barcode' do + let(:asset1) { create(:asset, facts: props1, barcode: nil) } + it 'does not print it' do + body_print = [asset2.printable_object('user1')] + + expect(PMB::PrintJob).to receive(:new).with( + printer_name: 'printer1', + label_template_id: 1, + labels: { body: body_print } + ).and_return(saveable_mock) + expect(saveable_mock).to receive(:save) + + group.print(config, 'user1') + end + end + end +end diff --git a/spec/models/printer_spec.rb b/spec/models/printer_spec.rb new file mode 100644 index 00000000..51f6da0e --- /dev/null +++ b/spec/models/printer_spec.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Printer, type: :model do + context 'self.printer_type_for' do + it 'returns the right printer type' do + expect(Printer.printer_type_for('Tube')).to eq('Tube') + expect(Printer.printer_type_for('SampleTube')).to eq('Tube') + expect(Printer.printer_type_for('Plate')).to eq('Plate') + expect(Printer.printer_type_for('TubeRack')).to eq('Plate') + end + end +end From eeca99fa4b5fb92f08a7836a84aad428aaacdeaa Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 26 Apr 2022 13:26:21 +0100 Subject: [PATCH 177/303] Avoid hitting database once per asset - Remove unused username parameter from `printable_object` In theory we can remove username from `print` as well, but this cascades through a lot of the code so I stopped short. - LabelTemplate#for_type returns the first LabelTemplate as we were calling first on it consistently. While numbers aren't significant enough that it will make a major difference, this lets us use detect rather than select. - Switch `count.positive?` for `blank?` `count.positive?` is rarely what you want, as a count query is surprisingly slow. Usually `exists?` is a much better option. However here we use `blank?` which pulls back all the records. Ideal, as we immediately use them later on in the method. One DB query, rather than two. - Add template cache to classify_for_printing The previous behaviour was running the same query per asset. While the query cache should nuke the worst of this impact, it still results in generation of new objects and lots of repeated logic. - Use assets `group_by`. This is mostly a code clarity thing --- app/models/asset.rb | 2 +- app/models/label_template.rb | 11 +++---- app/models/printables/group.rb | 45 ++++++++++++++++------------ app/models/printables/instance.rb | 16 ++++++++-- spec/models/label_template_spec.rb | 26 ++++++++-------- spec/models/printables/group_spec.rb | 14 ++++----- 6 files changed, 64 insertions(+), 50 deletions(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index bfd6690f..71ba4ecb 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -197,7 +197,7 @@ def barcode_formatted_for_printing barcode end - def printable_object(username = 'unknown') + def printable_object return nil if barcode.nil? if (kind_of_plate?) diff --git a/app/models/label_template.rb b/app/models/label_template.rb index 79bf90f7..d44c7d28 100644 --- a/app/models/label_template.rb +++ b/app/models/label_template.rb @@ -12,14 +12,11 @@ def self.for_type(class_type, barcodetype = 'ean13') templates = where(template_type: type) - unless templates.count.positive? - raise %( - Could not find any label template for type \'#{type}\'. Please contact LIMS support to fix the problem - ) + if templates.blank? + raise "Could not find any label template for type \'#{type}\'. "\ + 'Please contact LIMS support to fix the problem' end - templates_by_barcodetype = templates.select { |t| t.name.include?(barcodetype) } - - templates_by_barcodetype.presence || templates + templates.detect { |t| t.name.include?(barcodetype) } || templates.first end end diff --git a/app/models/printables/group.rb b/app/models/printables/group.rb index 5b87e3e4..4d3aefbe 100644 --- a/app/models/printables/group.rb +++ b/app/models/printables/group.rb @@ -1,33 +1,40 @@ module Printables::Group def classify_for_printing(printer_config) - assets.reduce({}) do |memo, asset| + template_cache = Hash.new { |store, types| store[types] = LabelTemplate.for_type(*types).external_id } + + assets.group_by do |asset| class_type = asset.class_type printer_name = printer_config[Printer.printer_type_for(class_type)] - raise "There is no defined Printer for asset with type #{class_type}" unless printer_name - label_template = LabelTemplate.for_type(class_type, asset.barcode_type).first - [asset, label_template, printer_name] - memo[printer_name] = {} unless memo[printer_name] - memo[printer_name][label_template] = [] unless memo[printer_name][label_template] - memo[printer_name][label_template].push(asset) - memo + raise "There is no defined printer for asset with type #{class_type}" unless printer_name + + label_template_external_id = template_cache[[class_type, asset.barcode_type]] + [printer_name, label_template_external_id] end end - def print(printer_config, user) + # + # Print labels for the current Printables::Group (eg. Assets in an Asset + # Group) using the default printers defined in printer_config + # + # @param printer_config [Hash] Typically returned bu the `User` maps a printer + # type, 'Plate' or 'Tube' to a printer name. + # @param _username [Void] Unused. Formerly the username. + # + # @return [Void] + # + def print(printer_config, _username = nil) return if Rails.configuration.printing_disabled - classify_for_printing(printer_config).each do |printer_name, info_for_template| - info_for_template.each do |label_template, assets| - body_print = assets.filter_map { |a| a.printable_object(user) }.reverse - next if body_print.empty? + classify_for_printing(printer_config).each do |(printer_name, external_id), assets| + body_print = assets.filter_map(&:printable_object).reverse + next if body_print.empty? - PMB::PrintJob.new( - printer_name: printer_name, - label_template_id: label_template.external_id, - labels: { body: body_print } - ).save - end + PMB::PrintJob.new( + printer_name: printer_name, + label_template_id: external_id, + labels: { body: body_print } + ).save end end end diff --git a/app/models/printables/instance.rb b/app/models/printables/instance.rb index cf8342c3..1d230be5 100644 --- a/app/models/printables/instance.rb +++ b/app/models/printables/instance.rb @@ -1,13 +1,23 @@ module Printables::Instance - def print(printer_config, user) - body_print = [printable_object(user)].compact + # + # Print labels for the current Printables::Instance (eg. Asset) using the + # default printers defined in printer_config + # + # @param printer_config [Hash] Typically returned bu the `User` maps a printer + # type, 'Plate' or 'Tube' to a printer name. + # @param _username [Void] Unused. Formerly the username. + # + # @return [Void] + # + def print(printer_config, _username) + body_print = [printable_object].compact return if Rails.configuration.printing_disabled || body_print.empty? if !printer_config raise 'No printer config provided' end printer_name = printer_config[Printer.printer_type_for(class_type)] - label_template = LabelTemplate.for_type(class_type, barcode_type).first + label_template = LabelTemplate.for_type(class_type, barcode_type) PMB::PrintJob.new( printer_name: printer_name, label_template_id: label_template.external_id, diff --git a/spec/models/label_template_spec.rb b/spec/models/label_template_spec.rb index 855a7c6f..b4c2c88f 100644 --- a/spec/models/label_template_spec.rb +++ b/spec/models/label_template_spec.rb @@ -16,27 +16,27 @@ end context 'when obtaining a template' do it 'returns a valid template for each case' do - expect(LabelTemplate.for_type('Tube', 'ean13')).to eq([templates[3], templates[5]]) - expect(LabelTemplate.for_type('Tube', 'code128')).to eq([templates[3]]) - expect(LabelTemplate.for_type('Tube', 'code39')).to eq([templates[5]]) - expect(LabelTemplate.for_type('Plate', 'ean13')).to eq([templates[1], templates[4]]) - expect(LabelTemplate.for_type('Plate', 'code128')).to eq([templates[1]]) - expect(LabelTemplate.for_type('Plate', 'code39')).to eq([templates[4]]) + expect(LabelTemplate.for_type('Tube', 'ean13')).to eq(templates[3]) + expect(LabelTemplate.for_type('Tube', 'code128')).to eq(templates[3]) + expect(LabelTemplate.for_type('Tube', 'code39')).to eq(templates[5]) + expect(LabelTemplate.for_type('Plate', 'ean13')).to eq(templates[1]) + expect(LabelTemplate.for_type('Plate', 'code128')).to eq(templates[1]) + expect(LabelTemplate.for_type('Plate', 'code39')).to eq(templates[4]) end end context 'when using the wrong template' do it 'raise error' do - expect { LabelTemplate.for_type('Bubidibu', 'ean13') }.to raise_error + expect { LabelTemplate.for_type('Bubidibu', 'ean13') }.to raise_error RuntimeError, "Could not find any label template for type 'Bubidibu'. Please contact LIMS support to fix the problem" end end context 'when using the template of an alias labware type' do it 'returns a valid template for each case' do - expect(LabelTemplate.for_type('SampleTube', 'ean13')).to eq([templates[3], templates[5]]) - expect(LabelTemplate.for_type('SampleTube', 'code128')).to eq([templates[3]]) - expect(LabelTemplate.for_type('SampleTube', 'code39')).to eq([templates[5]]) - expect(LabelTemplate.for_type('TubeRack', 'ean13')).to eq([templates[1], templates[4]]) - expect(LabelTemplate.for_type('TubeRack', 'code128')).to eq([templates[1]]) - expect(LabelTemplate.for_type('TubeRack', 'code39')).to eq([templates[4]]) + expect(LabelTemplate.for_type('SampleTube', 'ean13')).to eq(templates[3]) + expect(LabelTemplate.for_type('SampleTube', 'code128')).to eq(templates[3]) + expect(LabelTemplate.for_type('SampleTube', 'code39')).to eq(templates[5]) + expect(LabelTemplate.for_type('TubeRack', 'ean13')).to eq(templates[1]) + expect(LabelTemplate.for_type('TubeRack', 'code128')).to eq(templates[1]) + expect(LabelTemplate.for_type('TubeRack', 'code39')).to eq(templates[4]) end end end diff --git a/spec/models/printables/group_spec.rb b/spec/models/printables/group_spec.rb index 699b3095..ecc1b5d3 100644 --- a/spec/models/printables/group_spec.rb +++ b/spec/models/printables/group_spec.rb @@ -24,7 +24,7 @@ it 'classifies all assets to use the right printer' do expect(group.classify_for_printing(config)).to eq( { - 'printer1' => { template1 => [asset1, asset2] } + ['printer1', template1.external_id] => [asset1, asset2] } ) end @@ -57,8 +57,8 @@ it 'classifies all assets to use the right printer' do expect(group.classify_for_printing(config)).to eq( { - 'printer1' => { template1 => [asset1] }, - 'printer2' => { template2 => [asset2] } + ['printer1', template1.external_id] => [asset1], + ['printer2', template2.external_id] => [asset2] } ) end @@ -90,7 +90,7 @@ let(:printer2) { create :printer, name: 'printer2' } it 'raises error' do - expect { group.classify_for_printing(config) }.to raise_error + expect { group.classify_for_printing(config) }.to raise_error RuntimeError, "Could not find any label template for type 'Plate'. Please contact LIMS support to fix the problem" end end @@ -120,7 +120,7 @@ let(:printer2) { create :printer, name: 'printer2' } it 'raises error' do - expect { group.classify_for_printing(config) }.to raise_error + expect { group.classify_for_printing(config) }.to raise_error RuntimeError, 'There is no defined printer for asset with type Plate' end end end @@ -149,7 +149,7 @@ end it 'sends the right message to PMB' do - body_print = assets.filter_map { |a| a.printable_object('user1') }.reverse + body_print = assets.filter_map(&:printable_object).reverse expect(PMB::PrintJob).to receive(:new).with( printer_name: 'printer1', @@ -163,7 +163,7 @@ context 'when an asset does not have barcode' do let(:asset1) { create(:asset, facts: props1, barcode: nil) } it 'does not print it' do - body_print = [asset2.printable_object('user1')] + body_print = [asset2.printable_object] expect(PMB::PrintJob).to receive(:new).with( printer_name: 'printer1', From 60c425281867b24d0c4d1d4893fdd9a287a31e25 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 26 Apr 2022 14:17:38 +0100 Subject: [PATCH 178/303] Rubocop - autocorrects I've also added in a few links to issues where I spotted somethign worth more attention. --- .rubocop_todo.yml | 88 ------------------- Gemfile | 50 +++++------ app/controllers/application_controller.rb | 2 +- app/helpers/activities_helper.rb | 2 +- app/helpers/application_helper.rb | 2 +- app/models/action.rb | 6 +- app/models/asset.rb | 2 +- app/models/assets/export.rb | 6 +- app/models/printables/instance.rb | 6 ++ app/models/printables/print_asset.rb | 3 +- ...028122148_add_action_type_to_operations.rb | 2 +- ...61028134840_add_connect_by_to_step_type.rb | 2 +- ...70122001651_add_active_step_to_activity.rb | 2 +- .../20170122173205_add_state_to_step.rb | 2 +- ...8170039_add_namespace_to_fact_predicate.rb | 2 +- ...1416_migrate_operations_to_object_asset.rb | 2 +- lefthook.yml | 4 +- lib/actions/plate_transfer.rb | 2 +- lib/actions/racking.rb | 4 +- lib/changes_support/disjoint_list.rb | 2 +- lib/fact_changes.rb | 20 ++--- lib/inference_engines/cwm/step_execution.rb | 8 +- .../runner/step_execution.rb | 2 +- lib/sequencescape_client.rb | 2 +- lib/support_n3.rb | 16 ++-- script/fix_duplicated_tubes.rb | 2 +- script/remove_duplicates.rb | 2 +- script/runners/create_12_tubes.rb | 10 +-- script/runners/create_file.rb | 2 +- script/runners/create_layout.rb | 2 +- script/runners/full_rack_generator.rb | 2 +- script/runners/load_metadata.rb | 6 +- script/runners/rack_layout.rb | 4 +- script/runners/rack_layout_any_barcode.rb | 4 +- script/runners/transfer_samples.rb | 2 +- ...transfer_tubes_to_tube_rack_by_position.rb | 2 +- .../barcode_creatable_parser_spec.rb | 2 +- .../parsers/csv_layout/barcode_parser_spec.rb | 2 +- .../activities/background_tasks_spec.rb | 2 +- spec/models/step_spec.rb | 8 +- spec/models/step_type_spec.rb | 14 +-- spec/remote_assets_helper.rb | 2 +- 42 files changed, 114 insertions(+), 193 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index d6932791..be35d1f6 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -6,14 +6,6 @@ # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 19 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. -# Include: **/*.gemfile, **/Gemfile, **/gems.rb -Bundler/OrderedGems: - Exclude: - - 'Gemfile' - # Offense count: 16 # Configuration parameters: IgnoredMethods. Lint/AmbiguousBlockAssociation: @@ -44,27 +36,6 @@ Lint/NonDeterministicRequireOrder: - 'lib/tasks/setup_templates.rake' - 'spec/rails_helper.rb' -# Offense count: 6 -# This cop supports safe auto-correction (--auto-correct). -Lint/ParenthesesAsGroupedExpression: - Exclude: - - 'script/runners/load_metadata.rb' - - 'script/runners/rack_layout.rb' - - 'script/runners/rack_layout_any_barcode.rb' - -# Offense count: 10 -# This cop supports safe auto-correction (--auto-correct). -Lint/RedundantStringCoercion: - Exclude: - - 'app/helpers/activities_helper.rb' - - 'app/models/asset.rb' - - 'lib/changes_support/disjoint_list.rb' - - 'lib/fact_changes.rb' - - 'script/runners/create_file.rb' - - 'script/runners/create_layout.rb' - - 'script/runners/full_rack_generator.rb' - - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - # Offense count: 9 Lint/ShadowingOuterLocalVariable: Exclude: @@ -79,57 +50,6 @@ Lint/SuppressedException: Exclude: - 'spec/controllers/steps_controller_spec.rb' -# Offense count: 1 -# This cop supports safe auto-correction (--auto-correct). -Lint/ToJSON: - Exclude: - - 'lib/fact_changes.rb' - -# Offense count: 49 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. -Lint/UnusedBlockArgument: - Exclude: - - 'app/models/action.rb' - - 'app/models/printables/print_asset.rb' - - 'db/migrate/20161028122148_add_action_type_to_operations.rb' - - 'db/migrate/20161028134840_add_connect_by_to_step_type.rb' - - 'db/migrate/20170122001651_add_active_step_to_activity.rb' - - 'db/migrate/20170122173205_add_state_to_step.rb' - - 'db/migrate/20170128170039_add_namespace_to_fact_predicate.rb' - - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' - - 'lib/actions/plate_transfer.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'lib/inference_engines/runner/step_execution.rb' - - 'lib/support_n3.rb' - - 'script/fix_duplicated_tubes.rb' - - 'script/runners/create_12_tubes.rb' - - 'script/runners/load_metadata.rb' - - 'spec/models/activities/background_tasks_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - -# Offense count: 18 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. -Lint/UnusedMethodArgument: - Exclude: - - 'app/controllers/application_controller.rb' - - 'app/helpers/application_helper.rb' - - 'app/models/action.rb' - - 'app/models/asset.rb' - - 'app/models/assets/export.rb' - - 'lib/actions/racking.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'lib/support_n3.rb' - - 'script/remove_duplicates.rb' - - 'script/runners/transfer_samples.rb' - - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' - - 'spec/remote_assets_helper.rb' - # Offense count: 56 Lint/UselessAssignment: Exclude: @@ -266,14 +186,6 @@ Naming/PredicateName: - 'lib/support_n3.rb' - 'lib/token_util.rb' -# Offense count: 2 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: PreferredName. -Naming/RescuedExceptionsVariableName: - Exclude: - - 'app/models/assets/export.rb' - - 'lib/sequencescape_client.rb' - # Offense count: 36 # Configuration parameters: EnforcedStyle, AllowedIdentifiers. # SupportedStyles: snake_case, camelCase diff --git a/Gemfile b/Gemfile index 87530c19..2e751162 100644 --- a/Gemfile +++ b/Gemfile @@ -1,58 +1,58 @@ source 'http://rubygems.org' # Service libraries -gem 'sanger_warren' # Wraps bunny and manages connection pools and configuration -gem 'puma' +gem 'bootsnap', require: false gem 'daemons' -gem 'redis' gem 'delayed_job_active_record' gem 'mysql2' -gem 'bootsnap', require: false +gem 'puma' +gem 'redis' +gem 'sanger_warren' # Wraps bunny and manages connection pools and configuration # Rails and framework libraries -gem 'rails', '~> 5.2' -gem 'tzinfo-data' +gem 'aasm' +gem 'activerecord-import' gem 'activerecord-session_store' gem 'micro_token' -gem 'activerecord-import' -gem 'aasm' +gem 'rails', '~> 5.2' +gem 'tzinfo-data' # Rails views and UI -gem 'turbolinks' gem 'bootstrap_form' -gem 'sprockets-rails' -gem 'js_cookie_rails' -gem 'webpacker' -gem 'webpacker-react' +gem 'bootstrap-sass' gem 'jquery-rails' +gem 'js_cookie_rails' gem 'react-rails' gem 'sass-rails' -gem 'bootstrap-sass' +gem 'sprockets-rails' +gem 'turbolinks' +gem 'webpacker' +gem 'webpacker-react' gem 'will_paginate' gem 'will_paginate-bootstrap' # Javascript UI -gem 'ejs' +gem 'ace-rails-ap' gem 'dropzonejs-rails' +gem 'ejs' gem 'rails-assets-tether' -gem 'ace-rails-ap' # Serializers -gem 'rdf-n3' gem 'jbuilder' gem 'oj' +gem 'rdf-n3' # Traction endpoints -gem 'jsonapi-resources' gem 'json_api_client' +gem 'jsonapi-resources' # Tools -gem 'sanger_barcode_format', git: 'https://github.com/sanger/sanger_barcode_format.git' gem 'pmb-client', git: 'https://github.com/sanger/pmb-client.git' +gem 'sanger_barcode_format', git: 'https://github.com/sanger/sanger_barcode_format.git' # Sequencescspae -gem 'rest-client' gem 'faraday' +gem 'rest-client' gem 'sequencescape-client-api', require: 'sequencescape' # Debugging @@ -69,15 +69,15 @@ group :development, :test do end group :test do - gem 'factory_bot_rails' - gem 'rspec-rails' - gem 'shoulda-matchers' - gem 'simplecov', require: false - gem 'rails-controller-testing' gem 'database_cleaner' + gem 'factory_bot_rails' gem 'json-schema' gem 'launchy' gem 'rack_session_access' + gem 'rails-controller-testing' + gem 'rspec-rails' + gem 'shoulda-matchers' + gem 'simplecov', require: false end group :development do diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1cd8dfec..3ac19b8d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -9,7 +9,7 @@ class ApplicationController < ActionController::Base attr_reader :current_user - def record_not_found(exception) + def record_not_found(_exception) flash.now[:error] = 'No record found' redirect_to :action => 'index' end diff --git a/app/helpers/activities_helper.rb b/app/helpers/activities_helper.rb index 977c7d47..81c3c34a 100644 --- a/app/helpers/activities_helper.rb +++ b/app/helpers/activities_helper.rb @@ -130,7 +130,7 @@ def step_type_templates_data_for_step_types(activity, step_types, asset_group) createStepUrl: Rails.application.routes.url_helpers.activity_steps_path(activity), stepType: st, name: st.name, - id: "step-type-id-#{rand(9999).to_s}-#{st.id}" + id: "step-type-id-#{rand(9999)}-#{st.id}" } end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index ecfb94f6..8b649b55 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -7,7 +7,7 @@ def empty_well_aliquot_type 'empty-well-aliquot' end - def bootstrap_link_to(name = nil, options = nil, html_options = nil, &block) + def bootstrap_link_to(name = nil, options = nil, html_options = nil) modified_options = { :class => 'btn btn-default' } modified_options.merge!(html_options) if html_options link_to(name, options, modified_options) diff --git a/app/models/action.rb b/app/models/action.rb index 6b53860a..c498e1d0 100644 --- a/app/models/action.rb +++ b/app/models/action.rb @@ -13,7 +13,7 @@ def self.types # Given the current action (that defines a relation between 2 conditional groups) # and the list of assets classified into 2 groups: sources or destinations, this method # will generate a list of pairs [source, destination] that can be connected. - def each_connected_asset(sources, destinations, wildcard_values = {}, &block) + def each_connected_asset(sources, destinations, wildcard_values = {}) unless (wildcard_values.nil? || wildcard_values.empty?) if (object_condition_group) if (wildcard_values[object_condition_group.id]) @@ -83,7 +83,9 @@ def run(asset_group, wildcard_values = {}) asset_group.classify_assets_in_condition_group(assets, subject_condition_group) end destinations = destinations(asset_group) - assets.each do |asset| + + # @todo: https://github.com/sanger/samples_extraction/issues/183 + assets.each do |_asset| each_connected_asset(assets, destinations, wildcard_values) do |s, d| updates.add(s, predicate, d) end diff --git a/app/models/asset.rb b/app/models/asset.rb index 71ba4ecb..7e49aa91 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -228,7 +228,7 @@ def position_value val = facts.filter_map(&:position).first return "" if val.nil? - "_#{(val.to_i + 1).to_s}" + "_#{(val.to_i + 1)}" end def info_line diff --git a/app/models/assets/export.rb b/app/models/assets/export.rb index 4c3a3b35..fd04340c 100644 --- a/app/models/assets/export.rb +++ b/app/models/assets/export.rb @@ -30,8 +30,8 @@ def update_sequencescape(user) updates.set_errors(['Sequencescape connection - The server is down.']) rescue Timeout::Error => e updates.set_errors(['Sequencescape connection - Timeout error occurred.']) - rescue StandardError => err - updates.set_errors(['Sequencescape connection - There was an error while updating Sequencescape', err.message, err.backtrace.to_s]) + rescue StandardError => e + updates.set_errors(['Sequencescape connection - There was an error while updating Sequencescape', e.message, e.backtrace.to_s]) end end end @@ -55,7 +55,7 @@ def code39_barcode(instance) SBCF::SangerBarcode.new(prefix: prefix, number: number).human_barcode end - def update_wells(remote_plate, updates) + def update_wells(remote_plate, _updates) remote_plate.wells.each do |remote_well| fact = fact_well_at(remote_well.location) if fact diff --git a/app/models/printables/instance.rb b/app/models/printables/instance.rb index 1d230be5..28f6477d 100644 --- a/app/models/printables/instance.rb +++ b/app/models/printables/instance.rb @@ -1,4 +1,5 @@ module Printables::Instance +<<<<<<< HEAD # # Print labels for the current Printables::Instance (eg. Asset) using the # default printers defined in printer_config @@ -11,6 +12,11 @@ module Printables::Instance # def print(printer_config, _username) body_print = [printable_object].compact +======= + # @todo Remove user: https://github.com/sanger/samples_extraction/issues/184 + def print(printer_config, user) + body_print = [printable_object(user)].compact +>>>>>>> e4b24de (Rubocop - autocorrects) return if Rails.configuration.printing_disabled || body_print.empty? if !printer_config raise 'No printer config provided' diff --git a/app/models/printables/print_asset.rb b/app/models/printables/print_asset.rb index 5e4ee855..af084e22 100644 --- a/app/models/printables/print_asset.rb +++ b/app/models/printables/print_asset.rb @@ -1,5 +1,6 @@ +# @todo This should not be on Object, and can probably be removed https://github.com/sanger/samples_extraction/issues/185 def print_list(user, printer_config, barcodes) - ActiveRecord::Base.transaction do |t| + ActiveRecord::Base.transaction do |_t| assets = barcodes.map do |barcode| asset = Asset.create(barcode: barcode) asset.facts << Fact.create(predicate: 'a', object: 'Tube') diff --git a/db/migrate/20161028122148_add_action_type_to_operations.rb b/db/migrate/20161028122148_add_action_type_to_operations.rb index 81262ed1..57acd146 100644 --- a/db/migrate/20161028122148_add_action_type_to_operations.rb +++ b/db/migrate/20161028122148_add_action_type_to_operations.rb @@ -1,6 +1,6 @@ class AddActionTypeToOperations < ActiveRecord::Migration def change - ActiveRecord::Base.transaction do |t| + ActiveRecord::Base.transaction do |_t| add_column :operations, :action_type, :string end end diff --git a/db/migrate/20161028134840_add_connect_by_to_step_type.rb b/db/migrate/20161028134840_add_connect_by_to_step_type.rb index 169aecf9..f268d687 100644 --- a/db/migrate/20161028134840_add_connect_by_to_step_type.rb +++ b/db/migrate/20161028134840_add_connect_by_to_step_type.rb @@ -1,6 +1,6 @@ class AddConnectByToStepType < ActiveRecord::Migration def change - ActiveRecord::Base.transaction do |t| + ActiveRecord::Base.transaction do |_t| add_column :step_types, :connect_by, :string end end diff --git a/db/migrate/20170122001651_add_active_step_to_activity.rb b/db/migrate/20170122001651_add_active_step_to_activity.rb index c8c97979..dbdefd36 100644 --- a/db/migrate/20170122001651_add_active_step_to_activity.rb +++ b/db/migrate/20170122001651_add_active_step_to_activity.rb @@ -1,6 +1,6 @@ class AddActiveStepToActivity < ActiveRecord::Migration def change - ActiveRecord::Base.transaction do |t| + ActiveRecord::Base.transaction do |_t| add_column :activities, :active_step_id, :integer add_index :activities, :active_step_id end diff --git a/db/migrate/20170122173205_add_state_to_step.rb b/db/migrate/20170122173205_add_state_to_step.rb index 49a6858b..54ee459d 100644 --- a/db/migrate/20170122173205_add_state_to_step.rb +++ b/db/migrate/20170122173205_add_state_to_step.rb @@ -1,6 +1,6 @@ class AddStateToStep < ActiveRecord::Migration def change - ActiveRecord::Base.transaction do |t| + ActiveRecord::Base.transaction do |_t| add_column :steps, :state, :string end end diff --git a/db/migrate/20170128170039_add_namespace_to_fact_predicate.rb b/db/migrate/20170128170039_add_namespace_to_fact_predicate.rb index d3f2f8f1..2ed4ea2a 100644 --- a/db/migrate/20170128170039_add_namespace_to_fact_predicate.rb +++ b/db/migrate/20170128170039_add_namespace_to_fact_predicate.rb @@ -1,6 +1,6 @@ class AddNamespaceToFactPredicate < ActiveRecord::Migration def change - ActiveRecord::Base.transaction do |t| + ActiveRecord::Base.transaction do |_t| add_column :facts, :ns_predicate, :string end end diff --git a/db/migrate/20170225191416_migrate_operations_to_object_asset.rb b/db/migrate/20170225191416_migrate_operations_to_object_asset.rb index f046cb07..262b0636 100644 --- a/db/migrate/20170225191416_migrate_operations_to_object_asset.rb +++ b/db/migrate/20170225191416_migrate_operations_to_object_asset.rb @@ -1,6 +1,6 @@ class MigrateOperationsToObjectAsset < ActiveRecord::Migration def change - ActiveRecord::Base.transaction do |t| + ActiveRecord::Base.transaction do |_t| Operation.where("object is not null").each do |oper| obj_asset = Asset.find_by(:uuid => oper.object) if obj_asset diff --git a/lefthook.yml b/lefthook.yml index 1078fe10..d84491c0 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -9,7 +9,7 @@ pre-commit: # run: yarn prettier --check {staged_files} --ignore-unknown rubocop: glob: "{*.{rb,arb,axlsx,builder,fcgi,gemfile,gemspec,god,jb,jbuilder,mspec,opal,pluginspec,podspec,rabl,rake,rbuild,rbw,rbx,ru,ruby,spec,thor,watchr},.irbrc,.pryrc,.simplecov,buildfile,Appraisals,Berksfile,Brewfile,Buildfile,Capfile,Cheffile,Dangerfile,Deliverfile,Fastfile,*Fastfile,Gemfile,Guardfile,Jarfile,Mavenfile,Podfile,Puppetfile,Rakefile,rakefile,Snapfile,Steepfile,Thorfile,Vagabondfile,Vagrantfile}" - run: rubocop --display-style-guide --extra-details --force-exclusion --parallel {staged_files} || (echo 'Run `lefthook run fix` to run autocorrect on staged files only'; exit 1) + run: bundle exec rubocop --display-style-guide --extra-details --force-exclusion --parallel {staged_files} || (echo 'Run `lefthook run fix` to run autocorrect on staged files only'; exit 1) # eslint: # glob: "app/javascript/**/*.{vue,js}" # run: yarn lintOnly {staged_files} || (echo 'Run `lefthook run fix` to run autocrrect on staged files only'; exit 1) @@ -21,7 +21,7 @@ fix: # run: yarn prettier --write {staged_files} --ignore-unknown rubocop: glob: "{*.{rb,arb,axlsx,builder,fcgi,gemfile,gemspec,god,jb,jbuilder,mspec,opal,pluginspec,podspec,rabl,rake,rbuild,rbw,rbx,ru,ruby,spec,thor,watchr},.irbrc,.pryrc,.simplecov,buildfile,Appraisals,Berksfile,Brewfile,Buildfile,Capfile,Cheffile,Dangerfile,Deliverfile,Fastfile,*Fastfile,Gemfile,Guardfile,Jarfile,Mavenfile,Podfile,Puppetfile,Rakefile,rakefile,Snapfile,Steepfile,Thorfile,Vagabondfile,Vagrantfile}" - run: rubocop --display-style-guide --extra-details --auto-correct --force-exclusion {staged_files} + run: bundle exec rubocop --display-style-guide --extra-details --auto-correct --force-exclusion {staged_files} # eslint: # glob: "app/javascript/**/*.{vue,js}" # run: yarn lintOnly {staged_files} --fix diff --git a/lib/actions/plate_transfer.rb b/lib/actions/plate_transfer.rb index 63459528..1ff1197d 100644 --- a/lib/actions/plate_transfer.rb +++ b/lib/actions/plate_transfer.rb @@ -57,7 +57,7 @@ def self.transfer_by_location(plate, destination, updates = nil) memo[location].push(f.object_asset) memo end - value.each do |location, assets| + value.each do |_location, assets| asset1, asset2 = assets if asset2 return updates unless validate_tube_is_compatible_with_aliquot(updates, asset2, aliquot.object) if aliquot diff --git a/lib/actions/racking.rb b/lib/actions/racking.rb index 51ca7060..4d740e87 100644 --- a/lib/actions/racking.rb +++ b/lib/actions/racking.rb @@ -197,13 +197,13 @@ def check_racking_barcodes(list_layout, error_messages, error_locations) end end - def check_tuberacks(asset_group, list_layout, error_messages, error_locations) + def check_tuberacks(asset_group, _list_layout, error_messages, _error_locations) if asset_group.assets.with_fact('a', 'TubeRack').empty? error_messages.push("No TubeRacks found to perform the racking process") end end - def check_collisions(rack, list_layout, error_messages, error_locations) + def check_collisions(rack, list_layout, error_messages, _error_locations) tubes_for_rack = rack.facts.with_predicate('contains').map(&:object_asset) tubes_for_rack.each do |tube| tube_location = tube.facts.with_predicate('location').first.object diff --git a/lib/changes_support/disjoint_list.rb b/lib/changes_support/disjoint_list.rb index 70ab61fb..96fdb148 100644 --- a/lib/changes_support/disjoint_list.rb +++ b/lib/changes_support/disjoint_list.rb @@ -199,7 +199,7 @@ def _unique_id_for_element(element, deep = 0) elsif element.try(:uuid) sum_function_for(element.uuid) elsif element.try(:id) - sum_function_for("#{element.class.to_s}_#{element.id.to_s}") + sum_function_for("#{element.class}_#{element.id}") elsif element.kind_of?(Hash) if (element.has_key?(:uuid) && (!element[:uuid].nil?)) sum_function_for(element[:uuid]) diff --git a/lib/fact_changes.rb b/lib/fact_changes.rb index 8090859a..a899531b 100644 --- a/lib/fact_changes.rb +++ b/lib/fact_changes.rb @@ -42,8 +42,8 @@ def build_disjoint_lists(list, opposite) list1.add_disjoint_list(list2) - send("#{list.to_s}=", list1) - send("#{opposite.to_s}=", list2) + send("#{list}=", list1) + send("#{opposite}=", list2) end def asset_group_asset_to_h(asset_group_asset_str) @@ -85,10 +85,10 @@ def to_h end, add_assets: asset_group_asset_to_h(@assets_to_add), remove_assets: asset_group_asset_to_h(@assets_to_remove) - }.reject { |k, v| v.length == 0 } + }.reject { |_k, v| v.length == 0 } end - def to_json + def to_json(*_args) JSON.pretty_generate(to_h) end @@ -200,7 +200,7 @@ def merge(fact_changes) def apply(step, with_operations = true) _handle_errors(step) if errors_added.length > 0 - ActiveRecord::Base.transaction do |t| + ActiveRecord::Base.transaction do |_t| _set_remote_facts(facts_to_set_to_remote) operations = [ _create_asset_groups(step, asset_groups_to_create, with_operations), @@ -416,7 +416,7 @@ def _create_assets(step, assets, with_operations = true) _build_barcode(asset, count + barcode_index) asset end - _instance_builder_for_import(Asset, assets) do |instances| + _instance_builder_for_import(Asset, assets) do |_instances| _asset_operations('createAssets', step, assets) if with_operations end end @@ -447,7 +447,7 @@ def _detach_assets(step, assets, with_operations = true) def _create_asset_groups(step, asset_groups, with_operations = true) return unless asset_groups - asset_groups.each_with_index do |asset_group, index| + asset_groups.each do |asset_group| asset_group.update_attributes( name: TokenUtil.to_asset_group_name(wildcard_for_uuid(asset_group.uuid)), activity_owner: step.activity @@ -500,14 +500,14 @@ def _asset_group_building_operations(action_type, step, asset_groups) end def _asset_group_operations(action_type, step, asset_group_assets) - asset_group_assets.map do |asset_group_asset, index| + asset_group_assets.map do |asset_group_asset, _index| Operation.new(:action_type => action_type, :step => step, :asset => asset_group_asset.asset, object: asset_group_asset.asset_group.uuid) end end def _asset_operations(action_type, step, assets) - assets.map do |asset, index| + assets.map do |asset, _index| # refer = (action_type == 'deleteAsset' ? nil : asset) Operation.new(:action_type => action_type, :step => step, object: asset.uuid) end @@ -533,7 +533,7 @@ def any_values_are_new_records(hash) hash.values.any? { |value| value.try(:new_record?) } end - def _instance_builder_for_import(klass, params_list, &block) + def _instance_builder_for_import(klass, params_list) instances = params_list.filter_map do |params_for_instance| if params_for_instance.kind_of?(klass) params_for_instance if params_for_instance.new_record? diff --git a/lib/inference_engines/cwm/step_execution.rb b/lib/inference_engines/cwm/step_execution.rb index bd6475a8..db849acf 100644 --- a/lib/inference_engines/cwm/step_execution.rb +++ b/lib/inference_engines/cwm/step_execution.rb @@ -55,7 +55,7 @@ def generate_plan proxy = Rails.configuration.cwm_proxy env_vars = { 'http_proxy' => proxy, 'https_proxy' => proxy } - Open3.popen3(*[env_vars, call_list].flatten) do |stdin, stdout, stderror, thr| + Open3.popen3(*[env_vars, call_list].flatten) do |_stdin, stdout, stderror, thr| content = stdout.read output = [line, content].join("\n") step.update_attributes(output: output) @@ -120,7 +120,7 @@ def remove_facts(graphs) end end - def add_quad_to_asset(quad, asset, action_type = "addFacts") + def add_quad_to_asset(quad, asset, _action_type = "addFacts") object = fragment(quad[2]) object_asset = nil literal = true @@ -148,11 +148,11 @@ def create_asset(graphs) @step.created_asset_group.add_assets(created_assets.values.flatten.compact.uniq) end - def select_asset(assets, quads) + def select_asset(assets, _quads) @step.asset_group.add_assets(assets) end - def unselect_asset(assets, quads) + def unselect_asset(assets, _quads) @step.asset_group.remove_assets(assets) end end diff --git a/lib/inference_engines/runner/step_execution.rb b/lib/inference_engines/runner/step_execution.rb index 98fb624d..f253f6aa 100644 --- a/lib/inference_engines/runner/step_execution.rb +++ b/lib/inference_engines/runner/step_execution.rb @@ -67,7 +67,7 @@ def generate_plan_from_external_process call_str = call_list.join(" ") line = "# EXECUTING: #{call_str}" - Open3.popen3(*[call_list].flatten) do |stdin, stdout, stderror, thr| + Open3.popen3(*[call_list].flatten) do |_stdin, stdout, stderror, thr| @content = stdout.read output = [line, content].join("\n") step.update_attributes(output: output) diff --git a/lib/sequencescape_client.rb b/lib/sequencescape_client.rb index 7768686e..c1b92c49 100644 --- a/lib/sequencescape_client.rb +++ b/lib/sequencescape_client.rb @@ -24,7 +24,7 @@ def self.client def self.version_1_find_by_uuid(uuid, type = :plate) client.send(type).find(uuid) - rescue Sequencescape::Api::ResourceNotFound => exception + rescue Sequencescape::Api::ResourceNotFound => e return nil end diff --git a/lib/support_n3.rb b/lib/support_n3.rb index 63379103..da26ef8d 100644 --- a/lib/support_n3.rb +++ b/lib/support_n3.rb @@ -164,15 +164,15 @@ def self.rules(quads) def self.parse_rules(quads, enforce_step_type = nil) self.activity_type = nil - deprecate_class_by_name(ActivityType, activity_type_name(quads), activity_type(quads)) do |old_instances| - RuleGraphAccessor.rules(quads).each do |k, p, v, g| + deprecate_class_by_name(ActivityType, activity_type_name(quads), activity_type(quads)) do |_old_instances| + RuleGraphAccessor.rules(quads).each do |k, _p, v, _g| accessor = RuleGraphAccessor.new(enforce_step_type, quads, k, v) accessor.execute end end end - def self.deprecate_class_by_name(class_type, name, new_instance, &block) + def self.deprecate_class_by_name(class_type, name, new_instance) if name && !name.empty? old_instances = class_type.where(:name => name).not_deprecated old_instances = nil if (old_instances.count > 1) && (old_instances.first == new_instance) @@ -254,7 +254,7 @@ def find_or_create_condition_group_for(node, params) def keep_selected_list actions.select { |quad| fragment(quad[1]) == 'unselectAsset' }.map do |q| if q[2].class == RDF::Node - fragment(@quads.select { |k, p, v, g| g == q[2] }.flatten[0]) + fragment(@quads.select { |_k, _p, _v, g| g == q[2] }.flatten[0]) else fragment(q[2]) end @@ -288,14 +288,14 @@ def is_wildcard?(v) def build_condition_groups # Left side of the rule - conditions.each do |k, p, v, g| + conditions.each do |k, _p, _v, _g| # Finds the condition group (or creates it) condition_group = find_or_create_condition_group_for(k, { :step_type => @step_type, :keep_selected => check_keep_selected_asset(k) }) end cgr = [] - conditions.each do |k, p, v, g| + conditions.each do |k, p, v, _g| if is_wildcard?(v) vcgroup = find_or_create_condition_group_for(v, { :step_type => @step_type, @@ -373,10 +373,10 @@ def execute def build_actions # Right side of the rule - actions.each do |k, p, v, g| + actions.each do |_k, p, v, _g| action = fragment(p) unless v.literal? - @quads.select { |quad| quad.last == v }.each do |k, p, v, g| + @quads.select { |quad| quad.last == v }.each do |k, p, v, _g| # Updates cardinality for the condition group if fragment(p) == 'maxCardinality' @c_groups_cardinalities[fragment(k)] = fragment(v) diff --git a/script/fix_duplicated_tubes.rb b/script/fix_duplicated_tubes.rb index 1a06fab7..ee66da38 100644 --- a/script/fix_duplicated_tubes.rb +++ b/script/fix_duplicated_tubes.rb @@ -12,6 +12,6 @@ memo end -duplicateds2 = duplicateds.map do |key, values| +duplicateds2 = duplicateds.map do |_key, values| values[1] end diff --git a/script/remove_duplicates.rb b/script/remove_duplicates.rb index 3023627c..5d59187b 100644 --- a/script/remove_duplicates.rb +++ b/script/remove_duplicates.rb @@ -1,4 +1,4 @@ -def remove_duplicates(plate) +def remove_duplicates(_plate) ActiveRecord::Base.transaction do # wells = plate.facts.where(predicate: 'contains').map(&:object_asset) wells.each do |well| diff --git a/script/runners/create_12_tubes.rb b/script/runners/create_12_tubes.rb index 4dd0285f..f82b5e7c 100755 --- a/script/runners/create_12_tubes.rb +++ b/script/runners/create_12_tubes.rb @@ -7,13 +7,13 @@ sanger_sample_id = Array.new(TOTAL_NUMBER) { |i| "SAMPLE#{i}" } study_name = "STDY1" -f1 = tubes.each_with_index.map { |t, i| [t, 'a', 'SampleTube'] } -f2 = tubes.each_with_index.map { |t, i| [t, 'is', 'NotStarted'] } +f1 = tubes.each_with_index.map { |t, _i| [t, 'a', 'SampleTube'] } +f2 = tubes.each_with_index.map { |t, _i| [t, 'is', 'NotStarted'] } f3 = tubes.each_with_index.map { |t, i| [t, 'sample_tube', samples[i]] } f4 = tubes.each_with_index.map { |t, i| [t, 'sanger_sample_id', sanger_sample_id[i]] } -f5 = tubes.each_with_index.map { |t, i| [t, 'study_name', study_name] } -f6 = tubes.each_with_index.map { |t, i| [t, 'transferVolume', 20] } -f7 = tubes.each_with_index.map { |t, i| [t, 'volume', 100] } +f5 = tubes.each_with_index.map { |t, _i| [t, 'study_name', study_name] } +f6 = tubes.each_with_index.map { |t, _i| [t, 'transferVolume', 20] } +f7 = tubes.each_with_index.map { |t, _i| [t, 'volume', 100] } all_assets = tubes + samples obj = { diff --git a/script/runners/create_file.rb b/script/runners/create_file.rb index 51900ef8..60cc5d85 100755 --- a/script/runners/create_file.rb +++ b/script/runners/create_file.rb @@ -19,7 +19,7 @@ letters = ("A".."H").to_a columns = (1..12).to_a location_for_position = Array.new(NUM_BARCODES) do |i| - "#{letters[(i / columns.length).floor]}#{(columns[i % columns.length]).to_s}" + "#{letters[(i / columns.length).floor]}#{columns[i % columns.length]}" end temp_file = Tempfile.new diff --git a/script/runners/create_layout.rb b/script/runners/create_layout.rb index 9b862999..d38c000b 100755 --- a/script/runners/create_layout.rb +++ b/script/runners/create_layout.rb @@ -19,7 +19,7 @@ letters = ("A".."H").to_a columns = (1..12).to_a location_for_position = Array.new(NUM_BARCODES) do |i| - "#{letters[(i / columns.length).floor]}#{(columns[i % columns.length]).to_s}" + "#{letters[(i / columns.length).floor]}#{columns[i % columns.length]}" end temp_file = Tempfile.new diff --git a/script/runners/full_rack_generator.rb b/script/runners/full_rack_generator.rb index c012ca9a..24823a83 100644 --- a/script/runners/full_rack_generator.rb +++ b/script/runners/full_rack_generator.rb @@ -16,7 +16,7 @@ letters = ("A".."H").to_a columns = (1..12).to_a location_for_position = Array.new(96) do |i| - "#{letters[(i / columns.length).floor]}#{(columns[i % columns.length]).to_s}" + "#{letters[(i / columns.length).floor]}#{columns[i % columns.length]}" end facts_to_add = (location_for_position - locations_with_tube).reduce([]) do |memo, location| diff --git a/script/runners/load_metadata.rb b/script/runners/load_metadata.rb index 9ef0f591..7e660960 100644 --- a/script/runners/load_metadata.rb +++ b/script/runners/load_metadata.rb @@ -26,7 +26,7 @@ def find_asset(line_parsed) end def filter_unneeded_data(line_parsed) - line_parsed.reject { |k, v| k == 'location' || k == 'barcode' } + line_parsed.reject { |k, _v| k == 'location' || k == 'barcode' } end def metadata_updates(asset_group) @@ -68,7 +68,7 @@ def process JSON.parse(json) puts json rescue InvalidDataParams => e - puts ({ set_errors: e.errors }.to_json) + puts({ set_errors: e.errors }.to_json) rescue StandardError => e - puts ({ set_errors: ['Unknown error while parsing file' + e.backtrace.to_s] }.to_json) + puts({ set_errors: ['Unknown error while parsing file' + e.backtrace.to_s] }.to_json) end diff --git a/script/runners/rack_layout.rb b/script/runners/rack_layout.rb index 70caeeaa..9195caf6 100644 --- a/script/runners/rack_layout.rb +++ b/script/runners/rack_layout.rb @@ -34,7 +34,7 @@ def process JSON.parse(json) puts json rescue InvalidDataParams => e - puts ({ set_errors: e.errors }.to_json) + puts({ set_errors: e.errors }.to_json) rescue StandardError => e - puts ({ set_errors: ['Unknown error while parsing file' + e] }.to_json) + puts({ set_errors: ['Unknown error while parsing file' + e] }.to_json) end diff --git a/script/runners/rack_layout_any_barcode.rb b/script/runners/rack_layout_any_barcode.rb index f0acacce..fecb4931 100644 --- a/script/runners/rack_layout_any_barcode.rb +++ b/script/runners/rack_layout_any_barcode.rb @@ -35,7 +35,7 @@ def process JSON.parse(json) puts json rescue InvalidDataParams => e - puts ({ set_errors: e.errors }.to_json) + puts({ set_errors: e.errors }.to_json) rescue StandardError => e - puts ({ set_errors: ['Unknown error while parsing file' + e.to_json + e.backtrace.join] }.to_json) + puts({ set_errors: ['Unknown error while parsing file' + e.to_json + e.backtrace.join] }.to_json) end diff --git a/script/runners/transfer_samples.rb b/script/runners/transfer_samples.rb index 4f038fb3..ed0e7929 100644 --- a/script/runners/transfer_samples.rb +++ b/script/runners/transfer_samples.rb @@ -18,7 +18,7 @@ def asset_group_for_execution asset_group end - def each_asset_and_modified_asset(&block) + def each_asset_and_modified_asset asset_group.assets.with_predicate('transfer').each do |asset| asset.facts.with_predicate('transfer').each do |fact| modified_asset = fact.object_asset diff --git a/script/runners/transfer_tubes_to_tube_rack_by_position.rb b/script/runners/transfer_tubes_to_tube_rack_by_position.rb index 7e73a37f..755caff1 100644 --- a/script/runners/transfer_tubes_to_tube_rack_by_position.rb +++ b/script/runners/transfer_tubes_to_tube_rack_by_position.rb @@ -53,7 +53,7 @@ def validate_tube_are_not_in_rack(rack, tubes, updates) tubes_already_ids = previous_tubes_ids & tubes.map(&:id) if (tubes_already_ids.length > 0) tubes_already = Asset.where(id: tubes_already_ids).map(&:barcode) - updates.set_errors(["This rack already contains the tubes #{tubes_already.to_s}"]) + updates.set_errors(["This rack already contains the tubes #{tubes_already}"]) return false end true diff --git a/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb b/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb index 5b1ff271..bc813fdb 100644 --- a/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb @@ -17,7 +17,7 @@ end class ValidatorSuccess < ActiveModel::Validator - def validate(record) + def validate(_record) true end end diff --git a/spec/lib/parsers/csv_layout/barcode_parser_spec.rb b/spec/lib/parsers/csv_layout/barcode_parser_spec.rb index bcc9522f..762e48d5 100644 --- a/spec/lib/parsers/csv_layout/barcode_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/barcode_parser_spec.rb @@ -12,7 +12,7 @@ let(:success_validator) do Class.new(ActiveModel::Validator) do - def validate(record) + def validate(_record) true end end diff --git a/spec/models/activities/background_tasks_spec.rb b/spec/models/activities/background_tasks_spec.rb index 3b20d609..73c8b051 100644 --- a/spec/models/activities/background_tasks_spec.rb +++ b/spec/models/activities/background_tasks_spec.rb @@ -53,7 +53,7 @@ def self.update_attributes!(params) context '#background_tasks' do it 'returns the list of inference tasks sorted by priority' do - step_types = 5.times.each_with_index.map { |i| create :step_type } + step_types = 5.times.each_with_index.map { |_i| create :step_type } reasoning_step_types = 4.times.each_with_index.map { |i| create :step_type, { for_reasoning: true, priority: i } } activity.activity_type.update_attributes(step_types: step_types.concat(reasoning_step_types)) diff --git a/spec/models/step_spec.rb b/spec/models/step_spec.rb index b329fd7a..b544c11f 100644 --- a/spec/models/step_spec.rb +++ b/spec/models/step_spec.rb @@ -95,13 +95,13 @@ def create_assets(num, type) }) @step_type.condition_groups << @cg1 @step_type.condition_groups << @cg2 - @tubes = Array.new(7) { |i| + @tubes = Array.new(7) { |_i| FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') ] }) } - @racks = Array.new(5) { |i| + @racks = Array.new(5) { |_i| FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') @@ -245,10 +245,10 @@ def create_assets(num, type) @racks.each(&:reload) @tubes.each(&:reload) - @tubes.each_with_index do |tube, pos| + @tubes.each_with_index do |tube, _pos| assert_equal true, tube.facts.with_predicate('relates').count == 0 end - @racks.each_with_index do |rack, pos| + @racks.each_with_index do |rack, _pos| assert_equal true, rack.facts.with_predicate('relates').count != 0 end @racks.zip(@tubes).each do |list| diff --git a/spec/models/step_type_spec.rb b/spec/models/step_type_spec.rb index ce7f921b..4dd69b3f 100644 --- a/spec/models/step_type_spec.rb +++ b/spec/models/step_type_spec.rb @@ -116,7 +116,7 @@ def assert_equal(a, b) describe "with special configuration" do describe "related with cardinality" do setup do - @assets = Array.new(5) { |i| + @assets = Array.new(5) { |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') @@ -150,7 +150,7 @@ def assert_equal(a, b) describe 'matching more than one asset' do describe 'for the same condition group' do setup do - @assets = Array.new(5) { |i| + @assets = Array.new(5) { |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') @@ -190,14 +190,14 @@ def assert_equal(a, b) @step_type.condition_groups << @cg2 - @assets = Array.new(5) { |i| + @assets = Array.new(5) { |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') ] } } - @racks = Array.new(5) { |i| + @racks = Array.new(5) { |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), ] } @@ -264,13 +264,13 @@ def assert_equal(a, b) :object_condition_group_id => @cg2.id }) - @racks = Array.new(5) { |i| + @racks = Array.new(5) { |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack') ] } } - @bad_racks = Array.new(5) { |i| + @bad_racks = Array.new(5) { |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack') ] } @@ -288,7 +288,7 @@ def assert_equal(a, b) assert_equal true, @step_type.compatible_with?([@assets, @racks].flatten) end it 'is not compatible when the relation is not matching the conditions required' do - @bad_racks = Array.new(5) { |i| + @bad_racks = Array.new(5) { |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'BadRack') ] } diff --git a/spec/remote_assets_helper.rb b/spec/remote_assets_helper.rb index 5664addf..6ce8ec06 100644 --- a/spec/remote_assets_helper.rb +++ b/spec/remote_assets_helper.rb @@ -89,7 +89,7 @@ def build_remote_aliquot(opts = {}) double('aliquot', { sample: build_remote_sample, study: build_study }.merge(opts)) end - def build_study(opts = {}) + def build_study(_opts = {}) double('study', { name: 'STDY', uuid: SecureRandom.uuid }) end From 1f1203582d4794e7fdf3ce06acebcfab468fb383 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 26 Apr 2022 14:26:08 +0100 Subject: [PATCH 179/303] Annotate runners with todo --- script/runners/create_12_tubes.rb | 2 ++ script/runners/create_file.rb | 2 ++ script/runners/create_layout.rb | 2 ++ script/runners/create_stamped_plate.rb | 2 ++ script/runners/full_rack_generator.rb | 2 ++ script/runners/load_metadata.rb | 2 ++ script/runners/print_barcodes.rb | 2 ++ script/runners/put_tubes_into_rack_by_column_order.rb | 2 ++ script/runners/rack_layout.rb | 2 ++ script/runners/rack_layout_any_barcode.rb | 2 ++ script/runners/transfer_plate_to_plate.rb | 2 ++ .../runners/transfer_plate_to_plate_and_update_sequencescape.rb | 2 ++ script/runners/transfer_samples.rb | 2 ++ script/runners/transfer_tubes_to_tube_rack_by_position.rb | 2 ++ script/runners/update_sequencescape.rb | 2 ++ 15 files changed, 30 insertions(+) diff --git a/script/runners/create_12_tubes.rb b/script/runners/create_12_tubes.rb index f82b5e7c..6472b8dd 100755 --- a/script/runners/create_12_tubes.rb +++ b/script/runners/create_12_tubes.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + return unless ARGV.any? { |s| s.match(".json") } TOTAL_NUMBER = 12 diff --git a/script/runners/create_file.rb b/script/runners/create_file.rb index 60cc5d85..676f07e4 100755 --- a/script/runners/create_file.rb +++ b/script/runners/create_file.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + require 'tempfile' require 'csv' require 'rest_client' diff --git a/script/runners/create_layout.rb b/script/runners/create_layout.rb index d38c000b..8c452b17 100755 --- a/script/runners/create_layout.rb +++ b/script/runners/create_layout.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + require 'tempfile' require 'csv' require 'rest_client' diff --git a/script/runners/create_stamped_plate.rb b/script/runners/create_stamped_plate.rb index 190db3e2..5d43a4df 100644 --- a/script/runners/create_stamped_plate.rb +++ b/script/runners/create_stamped_plate.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + require 'actions/plate_transfer' class CreateStampedPlate diff --git a/script/runners/full_rack_generator.rb b/script/runners/full_rack_generator.rb index 24823a83..0b63a350 100644 --- a/script/runners/full_rack_generator.rb +++ b/script/runners/full_rack_generator.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] diff --git a/script/runners/load_metadata.rb b/script/runners/load_metadata.rb index 7e660960..7368ad61 100644 --- a/script/runners/load_metadata.rb +++ b/script/runners/load_metadata.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + require 'actions/racking' require 'parsers/csv_metadata/csv_parser' diff --git a/script/runners/print_barcodes.rb b/script/runners/print_barcodes.rb index bc264c16..4145c72a 100644 --- a/script/runners/print_barcodes.rb +++ b/script/runners/print_barcodes.rb @@ -1,3 +1,5 @@ +# Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + class PrintBarcodes attr_reader :asset_group, :step diff --git a/script/runners/put_tubes_into_rack_by_column_order.rb b/script/runners/put_tubes_into_rack_by_column_order.rb index 9a27c65f..b2ef96c7 100644 --- a/script/runners/put_tubes_into_rack_by_column_order.rb +++ b/script/runners/put_tubes_into_rack_by_column_order.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + require 'actions/racking' require 'token_util' include Actions::Racking diff --git a/script/runners/rack_layout.rb b/script/runners/rack_layout.rb index 9195caf6..3554f028 100644 --- a/script/runners/rack_layout.rb +++ b/script/runners/rack_layout.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + require 'actions/racking' class RackLayout diff --git a/script/runners/rack_layout_any_barcode.rb b/script/runners/rack_layout_any_barcode.rb index fecb4931..478519cc 100644 --- a/script/runners/rack_layout_any_barcode.rb +++ b/script/runners/rack_layout_any_barcode.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + require 'actions/racking' class RackLayoutAnyBarcode diff --git a/script/runners/transfer_plate_to_plate.rb b/script/runners/transfer_plate_to_plate.rb index 096d260e..5ca20ecf 100644 --- a/script/runners/transfer_plate_to_plate.rb +++ b/script/runners/transfer_plate_to_plate.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + require 'actions/plate_transfer' # Stamps an Asset (plate or tube rack) to another Asset diff --git a/script/runners/transfer_plate_to_plate_and_update_sequencescape.rb b/script/runners/transfer_plate_to_plate_and_update_sequencescape.rb index a8e471f3..864f3b87 100644 --- a/script/runners/transfer_plate_to_plate_and_update_sequencescape.rb +++ b/script/runners/transfer_plate_to_plate_and_update_sequencescape.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + return unless ARGV.any? { |s| s.match(".json") } args = ARGV[0] diff --git a/script/runners/transfer_samples.rb b/script/runners/transfer_samples.rb index ed0e7929..8586b865 100644 --- a/script/runners/transfer_samples.rb +++ b/script/runners/transfer_samples.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + require 'actions/tube_transfer' class TransferSamples diff --git a/script/runners/transfer_tubes_to_tube_rack_by_position.rb b/script/runners/transfer_tubes_to_tube_rack_by_position.rb index 755caff1..eee955aa 100644 --- a/script/runners/transfer_tubes_to_tube_rack_by_position.rb +++ b/script/runners/transfer_tubes_to_tube_rack_by_position.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + require 'actions/tube_transfer' class TransferTubesToTubeRackByPosition diff --git a/script/runners/update_sequencescape.rb b/script/runners/update_sequencescape.rb index 84f25f65..1beca339 100644 --- a/script/runners/update_sequencescape.rb +++ b/script/runners/update_sequencescape.rb @@ -1,3 +1,5 @@ +# @todo Migrate to StepPlanner https://github.com/sanger/samples_extraction/issues/193 + # Creates or updates a plate in Sequencescape corresponding to the Samples Extraction Asset # At time of writing, 'update' function is limited to 're-racking' # Only works if the Asset has a fact 'pushTo:Sequencescape' From b73cc769155bf4232d06c64c90f9f26867fdc04e Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 26 Apr 2022 14:37:35 +0100 Subject: [PATCH 180/303] Rubocop: Style/AccessorGrouping --- .rubocop_todo.yml | 10 ---------- lib/changes_support/disjoint_list.rb | 4 +--- lib/inference_engines/default/step_execution.rb | 4 +--- lib/support_n3.rb | 11 +---------- 4 files changed, 3 insertions(+), 26 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index be35d1f6..be66a157 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -474,16 +474,6 @@ Rails/WhereNot: - 'app/models/step_type.rb' - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' -# Offense count: 14 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: separated, grouped -Style/AccessorGrouping: - Exclude: - - 'lib/changes_support/disjoint_list.rb' - - 'lib/inference_engines/default/step_execution.rb' - - 'lib/support_n3.rb' - # Offense count: 1 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. diff --git a/lib/changes_support/disjoint_list.rb b/lib/changes_support/disjoint_list.rb index 96fdb148..e98e776a 100644 --- a/lib/changes_support/disjoint_list.rb +++ b/lib/changes_support/disjoint_list.rb @@ -7,9 +7,7 @@ class ChangesSupport::DisjointList include Enumerable - attr_accessor :location_for_unique_id - attr_accessor :disjoint_lists - attr_accessor :list + attr_accessor :location_for_unique_id, :disjoint_lists, :list attr_reader :name DISABLED_NAME = "DISABLED" diff --git a/lib/inference_engines/default/step_execution.rb b/lib/inference_engines/default/step_execution.rb index 94f50b40..b71830b7 100644 --- a/lib/inference_engines/default/step_execution.rb +++ b/lib/inference_engines/default/step_execution.rb @@ -6,9 +6,7 @@ module Default class StepExecution include StepExecutionProcess - attr_accessor :step - attr_accessor :asset_group - attr_accessor :updates + attr_accessor :step, :asset_group, :updates def initialize(params) @step = params[:step] diff --git a/lib/support_n3.rb b/lib/support_n3.rb index da26ef8d..9046a767 100644 --- a/lib/support_n3.rb +++ b/lib/support_n3.rb @@ -147,16 +147,7 @@ def self.parse_facts(input, options = {}, create_assets = true) end class RuleGraphAccessor - attr_reader :quads - attr_reader :graph_conditions - attr_reader :graph_consequences - attr_reader :c_groups - attr_reader :c_groups_cardinalities - - attr_reader :conditions - attr_reader :actions - - attr_reader :step_type + attr_reader :quads, :graph_conditions, :graph_consequences, :c_groups, :c_groups_cardinalities, :conditions, :actions, :step_type def self.rules(quads) quads.select { |quad| fragment(quad[1]) == 'implies' } From cb3ab30cfafbc863cf4508da3689afee2f10bbc4 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 26 Apr 2022 14:42:21 +0100 Subject: [PATCH 181/303] Rubocop: Style/Alias --- .rubocop_todo.yml | 8 -------- app/models/asset_group.rb | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index be66a157..e1d1f16e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -474,14 +474,6 @@ Rails/WhereNot: - 'app/models/step_type.rb' - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' -# Offense count: 1 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: prefer_alias, prefer_alias_method -Style/Alias: - Exclude: - - 'app/models/asset_group.rb' - # Offense count: 82 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. diff --git a/app/models/asset_group.rb b/app/models/asset_group.rb index 4d6b093c..a552b7bf 100644 --- a/app/models/asset_group.rb +++ b/app/models/asset_group.rb @@ -11,7 +11,7 @@ class AssetGroup < ApplicationRecord belongs_to :activity_owner, :class_name => 'Activity' belongs_to :condition_group, :class_name => 'ConditionGroup' - alias_method :activity, :activity_owner + alias activity activity_owner include Printables::Group From e7922e233fed032bda7bf7adceab4c2b290bcba7 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 26 Apr 2022 14:47:46 +0100 Subject: [PATCH 182/303] Rubocop: Style/BarePercentLiterals --- .rubocop_todo.yml | 18 ---- db/seeds.rb | 18 ++-- script/aliquot_type_inference.rb | 2 +- script/container_inferences.rb | 2 +- script/purpose_name_inference.rb | 4 +- script/recreate_steptypes.rb | 18 ++-- script/study_name_inference.rb | 2 +- .../tasks/runners/aliquot_type_inference.rb | 2 +- spec/integration/inferences_data.rb | 98 +++++++++---------- spec/lib/support_n3_spec.rb | 2 +- spec/models/assets/export_spec.rb | 12 +-- spec/models/steps/cancellable_spec.rb | 2 +- 12 files changed, 81 insertions(+), 99 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index e1d1f16e..5d1d6d69 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -474,24 +474,6 @@ Rails/WhereNot: - 'app/models/step_type.rb' - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' -# Offense count: 82 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: percent_q, bare_percent -Style/BarePercentLiterals: - Exclude: - - 'db/seeds.rb' - - 'script/aliquot_type_inference.rb' - - 'script/container_inferences.rb' - - 'script/purpose_name_inference.rb' - - 'script/recreate_steptypes.rb' - - 'script/study_name_inference.rb' - - 'script/tasks/runners/aliquot_type_inference.rb' - - 'spec/integration/inferences_data.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/assets/export_spec.rb' - - 'spec/models/steps/cancellable_spec.rb' - # Offense count: 1 # This cop supports safe auto-correction (--auto-correct). Style/BlockComments: diff --git a/db/seeds.rb b/db/seeds.rb index ba03ab5c..c543fa4d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -34,40 +34,40 @@ runners = [ ['[DEMO] Create 12 tubes', 'create_12_tubes.rb'], ['[DEMO] Generate plate layout file', 'create_layout.rb'], - ['Aliquot type inference', 'aliquot_type_inference.rb', %Q{ + ['Aliquot type inference', 'aliquot_type_inference.rb', %{ { ?p :contains ?q . ?q :aliquotType ?_aliquot . }=>{}. }], ['Print barcodes', 'print_barcodes.rb'], - ['Purpose name inference', 'purpose_name_inference.rb', %Q{ + ['Purpose name inference', 'purpose_name_inference.rb', %{ { ?p :contains ?q . ?q :aliquotType ?_aliquot . }=>{}. }], - ['Rack Layout', 'rack_layout.rb', %Q{ + ['Rack Layout', 'rack_layout.rb', %{ { ?p :contains ?q . ?p :a :TubeRack . ?q :a :File . }=>{}. }], - ['Rack Layout creating tubes', 'StepPlanner::RackLayoutCreatingTubes', %Q{ + ['Rack Layout creating tubes', 'StepPlanner::RackLayoutCreatingTubes', %{ { ?p :contains ?q . ?p :a :TubeRack . ?q :a :File . }=>{}. }], - ['Study name inference', 'study_name_inference.rb', %Q{ + ['Study name inference', 'study_name_inference.rb', %{ { ?p :contains ?q . ?q :study_name ?_aliquot . }=>{}. }], - ['Transfer plate to plate', 'transfer_plate_to_plate.rb', %Q{ + ['Transfer plate to plate', 'transfer_plate_to_plate.rb', %{ { ?p :a :Plate . @@ -75,16 +75,16 @@ ?p :transfer ?q . ?p :contains ?tube . } => {} . }], - ['Transfer samples', 'transfer_samples.rb', %Q{ + ['Transfer samples', 'transfer_samples.rb', %{ { ?p :transfer ?q .}=> {}. }], - ['Transfer tubes to tube rack by position', 'transfer_tubes_to_tube_rack_by_position.rb', %Q{ + ['Transfer tubes to tube rack by position', 'transfer_tubes_to_tube_rack_by_position.rb', %{ { ?p :a :TubeRack . ?q :a :Tube . }=>{}. }], - ['Update Sequencescape', 'update_sequencescape.rb', %Q{ + ['Update Sequencescape', 'update_sequencescape.rb', %{ { ?p :a :TubeRack .}=>{}. }] ].map { |l| StepType.create(name: l[0], step_action: l[1], n3_definition: l[2]) } diff --git a/script/aliquot_type_inference.rb b/script/aliquot_type_inference.rb index acfcf2aa..d0d4d5c4 100644 --- a/script/aliquot_type_inference.rb +++ b/script/aliquot_type_inference.rb @@ -7,7 +7,7 @@ def initialize(params) # rubocop:todo Naming/MethodName def _CODE - %Q{ + %{ { ?asset :aliquotType ?aliquot . ?asset :contains ?anotherAsset . diff --git a/script/container_inferences.rb b/script/container_inferences.rb index 456ed532..fc5109ae 100644 --- a/script/container_inferences.rb +++ b/script/container_inferences.rb @@ -6,7 +6,7 @@ def initialize(params) end def containers - asset_group.assets.joins(%Q{ + asset_group.assets.joins(%{ INNER JOIN facts as plate_facts on plate_facts.asset_id=assets.id AND plate_facts.predicate='contains' INNER JOIN assets as tubes on tubes.id=plate_facts.object_asset_id INNER JOIN facts as tubes_facts on tubes_facts.asset_id=tubes.id AND (tubes_facts.predicate='aliquotType' OR tubes_facts.predicate='study_name') diff --git a/script/purpose_name_inference.rb b/script/purpose_name_inference.rb index 8b74a252..9255358b 100644 --- a/script/purpose_name_inference.rb +++ b/script/purpose_name_inference.rb @@ -7,7 +7,7 @@ def initialize(params) # rubocop:todo Naming/MethodName def _CODE - %Q{ + %{ { ?asset :contains ?anotherAsset . ?anotherAsset :aliquotType """DNA""" . @@ -38,7 +38,7 @@ def containers2 end def containers - asset_group.assets.joins(%Q{ + asset_group.assets.joins(%{ INNER JOIN facts as plate_facts on plate_facts.asset_id=assets.id AND plate_facts.predicate='contains' INNER JOIN assets as tubes on tubes.id=plate_facts.object_asset_id INNER JOIN facts as tubes_facts on tubes_facts.asset_id=tubes.id AND tubes_facts.predicate='aliquotType' diff --git a/script/recreate_steptypes.rb b/script/recreate_steptypes.rb index 46a1fe8a..279445b4 100755 --- a/script/recreate_steptypes.rb +++ b/script/recreate_steptypes.rb @@ -1,38 +1,38 @@ [ - ['Aliquot type inference', 'aliquot_type_inference.rb', %Q{ + ['Aliquot type inference', 'aliquot_type_inference.rb', %{ { ?p :contains ?q . ?q :aliquotType ?_aliquot . }=>{}. }], ['Print barcodes', 'print_barcodes.rb'], - ['Purpose name inference', 'purpose_name_inference.rb', %Q{ + ['Purpose name inference', 'purpose_name_inference.rb', %{ { ?p :contains ?q . ?q :aliquotType ?_aliquot . }=>{}. }], - ['Rack Layout', 'rack_layout.rb', %Q{ + ['Rack Layout', 'rack_layout.rb', %{ { ?p :contains ?q . ?p :a :TubeRack . ?q :a :File . }=>{}. }], - ['Rack Layout creating tubes', 'StepPlanner::RackLayoutCreatingTubes', %Q{ + ['Rack Layout creating tubes', 'StepPlanner::RackLayoutCreatingTubes', %{ { ?p :contains ?q . ?p :a :TubeRack . ?q :a :File . }=>{}. }], - ['Study name inference', 'study_name_inference.rb', %Q{ + ['Study name inference', 'study_name_inference.rb', %{ { ?p :contains ?q . ?q :study_name ?_aliquot . }=>{}. }], - ['Transfer plate to plate', 'transfer_plate_to_plate.rb', %Q{ + ['Transfer plate to plate', 'transfer_plate_to_plate.rb', %{ { ?p :a :Plate . @@ -40,16 +40,16 @@ ?p :transfer ?q . ?p :contains ?tube . } => {} . }], - ['Transfer samples', 'transfer_samples.rb', %Q{ + ['Transfer samples', 'transfer_samples.rb', %{ { ?p :transfer ?q .}=> {}. }], - ['Transfer tubes to tube rack by position', 'transfer_tubes_to_tube_rack_by_position.rb', %Q{ + ['Transfer tubes to tube rack by position', 'transfer_tubes_to_tube_rack_by_position.rb', %{ { ?p :a :TubeRack . ?q :a :Tube . }=>{}. }], - ['Update Sequencescape', 'update_sequencescape.rb', %Q{ + ['Update Sequencescape', 'update_sequencescape.rb', %{ { ?p :a :TubeRack .}=>{}. }] ].map { |l| diff --git a/script/study_name_inference.rb b/script/study_name_inference.rb index 43a73d88..4a23b6e9 100644 --- a/script/study_name_inference.rb +++ b/script/study_name_inference.rb @@ -7,7 +7,7 @@ def initialize(params) # rubocop:todo Naming/MethodName def _CODE - %Q{ + %{ { ?asset :contains ?anotherAsset . ?anotherAsset :study_name ?study . diff --git a/script/tasks/runners/aliquot_type_inference.rb b/script/tasks/runners/aliquot_type_inference.rb index 4fd41259..7c654e91 100755 --- a/script/tasks/runners/aliquot_type_inference.rb +++ b/script/tasks/runners/aliquot_type_inference.rb @@ -7,7 +7,7 @@ def initialize(params) # rubocop:todo Naming/MethodName def _CODE - %Q{ + %{ { ?asset :aliquotType ?aliquot . ?asset :contains ?anotherAsset . diff --git a/spec/integration/inferences_data.rb b/spec/integration/inferences_data.rb index 39c015b7..7b7a3eac 100644 --- a/spec/integration/inferences_data.rb +++ b/spec/integration/inferences_data.rb @@ -1,28 +1,28 @@ def inferences_data [ { - :it => %Q{keeps elements the way they are when there is no changes}, - :rule => %Q{ { ?x :t ?_y .} => { :step :addFacts {?x :t ?_y .}. }. }, - :inputs => %Q{ :a :t "1" . }, - :outputs => %Q{ :a :t "1" .} + :it => %{keeps elements the way they are when there is no changes}, + :rule => %{ { ?x :t ?_y .} => { :step :addFacts {?x :t ?_y .}. }. }, + :inputs => %{ :a :t "1" . }, + :outputs => %{ :a :t "1" .} }, { - :it => %Q{keeps elements the way they are when there is no changes}, - :rule => %Q{ { ?x :t ?_y .} => { :step :addFacts {?x :t ?_y .}. }. }, - :inputs => %Q{ :a :t "1" . :b :t "2".}, - :outputs => %Q{ :a :t "1" . :b :t "2".} + :it => %{keeps elements the way they are when there is no changes}, + :rule => %{ { ?x :t ?_y .} => { :step :addFacts {?x :t ?_y .}. }. }, + :inputs => %{ :a :t "1" . :b :t "2".}, + :outputs => %{ :a :t "1" . :b :t "2".} }, { - :it => %Q{keeps elements the way they are when there is no changes}, - :rule => %Q{ { ?x :relation_r ?_y .} => { :step :addFacts { ?x :relation_r ?_y . }. }. }, - :inputs => %Q{ :a :relation_r """1""" . :b :relation_r :a .}, - :outputs => %Q{ :a :relation_r """1""" . :b :relation_r :a .} + :it => %{keeps elements the way they are when there is no changes}, + :rule => %{ { ?x :relation_r ?_y .} => { :step :addFacts { ?x :relation_r ?_y . }. }. }, + :inputs => %{ :a :relation_r """1""" . :b :relation_r :a .}, + :outputs => %{ :a :relation_r """1""" . :b :relation_r :a .} }, { - :it => %Q{relates elements with wildcard and with literal}, - :rule => %Q{ + :it => %{relates elements with wildcard and with literal}, + :rule => %{ { ?x :s """1""" . ?y :t ?_val . @@ -31,14 +31,14 @@ def inferences_data } }, - :inputs => %Q{ + :inputs => %{ :tube1 :s """1""" . :tube2 :t """2""" . :tube3 :s """1""" . :tube4 :t """2""" . }, - :outputs => %Q{ + :outputs => %{ :tube1 :s """1""" . :tube1 :val """2""" . :tube2 :t """2""" . @@ -49,8 +49,8 @@ def inferences_data } }, { - :it => %Q{relates elements with wildcard}, - :rule => %Q{ + :it => %{relates elements with wildcard}, + :rule => %{ { ?x :t ?_pos . ?y :t ?_pos . @@ -58,14 +58,14 @@ def inferences_data :step :addFacts {?x :relates_with ?y }. } }, - :inputs => %Q{ + :inputs => %{ :tube1 :t """1""" . :tube2 :t """2""" . :tube3 :t """1""" . :tube4 :t """2""" . }, - :outputs => %Q{ + :outputs => %{ :tube1 :t """1""" . :tube2 :t """2""" . :tube3 :t """1""" . @@ -82,9 +82,9 @@ def inferences_data }, { - :it => %Q{relates elements with relation}, + :it => %{relates elements with relation}, :tags => :testing, - :rule => %Q{ + :rule => %{ { ?x :a "TubeA" . ?x :transfer ?y . @@ -93,13 +93,13 @@ def inferences_data :step :addFacts { ?y :transferredFrom ?x . }. } }, - :inputs => %Q{ + :inputs => %{ :tube1 :a "TubeA" . :tube1 :transfer :tube2 . :tube2 :a "TubeB" . }, - :outputs => %Q{ + :outputs => %{ :tube1 :a """TubeA""" . :tube2 :a """TubeB""" . @@ -108,9 +108,9 @@ def inferences_data } }, { - :it => %Q{set the value if the destination does not have the value}, + :it => %{set the value if the destination does not have the value}, :unless => :cwm_engine?, - :rule => %Q{ + :rule => %{ { ?x :a :Tube . ?y :a :Tube . @@ -121,13 +121,13 @@ def inferences_data :step :addFacts {?y :aliquotType ?_aliquot .}. }. }, - :inputs => %Q{ + :inputs => %{ :tube1 :a :Tube . :tube1 :transfer :tube2 . :tube2 :a :Tube . :tube1 :aliquotType "DNA" . }, - :outputs => %Q{ + :outputs => %{ :tube1 :a :Tube . :tube1 :transfer :tube2 . :tube2 :a :Tube . @@ -136,8 +136,8 @@ def inferences_data } }, { - :it => %Q{only set the value if the destination does not have the value already}, - :rule => %Q{ + :it => %{only set the value if the destination does not have the value already}, + :rule => %{ { ?x :a :Tube . ?y :a :Tube . @@ -148,14 +148,14 @@ def inferences_data :step :addFacts {?y :aliquotType ?_aliquot .}. }. }, - :inputs => %Q{ + :inputs => %{ :tube1 :a :Tube . :tube1 :transfer :tube2 . :tube2 :a :Tube . :tube1 :aliquotType """DNA""" . :tube2 :aliquotType """RNA""" . }, - :outputs => %Q{ + :outputs => %{ :tube1 :a :Tube . :tube1 :transfer :tube2 . :tube2 :a :Tube . @@ -164,9 +164,9 @@ def inferences_data } }, { - :it => %Q{transfer between plates}, + :it => %{transfer between plates}, :unless => :cwm_engine?, - :rule => %Q{ + :rule => %{ { ?plate :a :Plate . ?plate2 :a :Plate . @@ -184,7 +184,7 @@ def inferences_data :step :addFacts {?tube1 :transfer ?tube2 .}. }. }, - :inputs => %Q{ + :inputs => %{ :plate1 :a :Plate . :plate2 :a :Plate . :tube1 :a :Tube . @@ -199,7 +199,7 @@ def inferences_data :tube3 :location "D9" . :plate1 :contains :tube3 . }, - :outputs => %Q{ + :outputs => %{ :plate1 :a :Plate . :plate2 :a :Plate . :tube1 :a :Tube . @@ -219,8 +219,8 @@ def inferences_data }, { - :xit => %Q{perform math operations}, - :rule => %Q{ + :xit => %{perform math operations}, + :rule => %{ { ?plate :a :Plate . @@ -235,7 +235,7 @@ def inferences_data :step :addFacts {?aliquot :currentVolume ?newVolume .}. }. }, - :inputs => %Q{ + :inputs => %{ :plate1 :a """Plate""" . :well1 :a """Well""" . @@ -244,7 +244,7 @@ def inferences_data :aliquot1 :currentVolume """20""". }, - :outputs => %Q{ + :outputs => %{ :plate1 :a """Plate""" . :well1 :a """Well""" . @@ -255,7 +255,7 @@ def inferences_data }, { :it => 'moves the value of a wildcard using a relation between two cgroups', - :rule => %Q{ + :rule => %{ { ?tube :is "Tube" . ?tube :location ?_position . @@ -268,7 +268,7 @@ def inferences_data :step :addFacts {?rack :location ?_position .} . } }, - :inputs => %Q{ + :inputs => %{ :tube1 :is "Tube" , :Full ; :location "1". :tube2 :is "Tube" , :Full ; :location "2". :tube3 :is "Tube" , :Full ; :location "3". @@ -283,7 +283,7 @@ def inferences_data :rack4 :is "Rack" , :Full ; :contains :tube4 ; :position "4" ; :relates :tube4 . :rack5 :is "Rack" , :Full ; :contains :tube5 ; :position "5" ; :relates :tube5 . }, - :outputs => %Q{ + :outputs => %{ :tube1 :is "Tube" , :Full ; :location "1". :tube2 :is "Tube" , :Full ; :location "2". :tube3 :is "Tube" , :Full ; :location "3". @@ -301,7 +301,7 @@ def inferences_data }, { :it => 'Bug 1: Not transferring tube contents to tube rack', - :rule => %Q{ + :rule => %{ { ?tuberack :a :TubeRack . ?tuberack :layout :Complete . @@ -309,7 +309,7 @@ def inferences_data ?tube :sanger_sample_id ?_sample . } => { :step :addFacts {?tube :transferToTubeRackByPosition ?tuberack . } . } . }, - :inputs => %Q{ + :inputs => %{ :tube :a "Tube" . :tube :aliquotType "RNA" . :tube :is "Used" . @@ -323,7 +323,7 @@ def inferences_data :tubeRack :contains :tube2 . :tubeRack :contains :tube3 . :tubeRack :layout "Complete" . }, - :outputs => %Q{ + :outputs => %{ :tube :transferToTubeRackByPosition :tubeRack . :tube :a "Tube" . :tube :aliquotType "RNA" . @@ -342,13 +342,13 @@ def inferences_data }, { :it => 'creates new assets from scratch', - :rule => %Q{ + :rule => %{ {?p :maxCardinality "1" .} => { :step :createAsset {?p :a :Tube . ?p :uuid "tube" .} } . }, - :inputs => %Q{}, - :outputs => %Q{ + :inputs => %{}, + :outputs => %{ :tube :a :Tube . :tube :uuid "tube" . } diff --git a/spec/lib/support_n3_spec.rb b/spec/lib/support_n3_spec.rb index 674908a7..b6b05f0f 100644 --- a/spec/lib/support_n3_spec.rb +++ b/spec/lib/support_n3_spec.rb @@ -43,7 +43,7 @@ def validates_rule_with(parsed_obj) @activity_type = FactoryBot.create :activity_type, { :name => testing_name } @activity_type.reload expect(@activity_type.deprecated?).to eq(false) - SupportN3.parse_string(%Q{ + SupportN3.parse_string(%{ :activity :activityTypeName "#{testing_name}" . {} => {:step :stepTypeName \"\"\"#{testing_name}\"\"\" .}. {} => {:step :stepTypeName \"\"\"#{testing_name}\"\"\" .}. diff --git a/spec/models/assets/export_spec.rb b/spec/models/assets/export_spec.rb index ee9b16f9..101036df 100644 --- a/spec/models/assets/export_spec.rb +++ b/spec/models/assets/export_spec.rb @@ -35,7 +35,7 @@ end it 'generates an attribute object for a well' do - facts = %Q{ + facts = %{ :s1 :a :SampleTube . :s2 :a :SampleTube . :s3 :a :SampleTube . @@ -125,13 +125,13 @@ context '#attributes_to_send' do it 'can convert location to Sequencescape location format' do - %Q{ + %{ I have a tube rack that contains 4 tubes with names tube1, tube2, tube3 and tube4. tube1 is in location A01, tube2 in B01, tube3 in C01 and tube4 in D1. Each tube has a sample tube inside, with names s1, s2, s3 and s4. } - facts = %Q{ + facts = %{ :s1 :a :SampleTube . :s2 :a :SampleTube . :s3 :a :SampleTube . @@ -163,7 +163,7 @@ end it 'generates the attributes when the locations are not duplicated' do - facts = %Q{ + facts = %{ :s1 :a :SampleTube . :s2 :a :SampleTube . :s3 :a :SampleTube . @@ -195,7 +195,7 @@ end it 'fails when trying to generate attributes when the locations are duplicated' do - facts = %Q{ + facts = %{ :s1 :a :SampleTube . :s2 :a :SampleTube . :s3 :a :SampleTube . @@ -221,7 +221,7 @@ end it 'does not export locations without a sample in it' do - facts = %Q{ + facts = %{ :s1 :a :SampleTube . :s2 :a :SampleTube . :s3 :a :SampleTube . diff --git a/spec/models/steps/cancellable_spec.rb b/spec/models/steps/cancellable_spec.rb index 41ba4a1f..ab738693 100644 --- a/spec/models/steps/cancellable_spec.rb +++ b/spec/models/steps/cancellable_spec.rb @@ -12,7 +12,7 @@ @activity_type = FactoryBot.create :activity_type @activity = FactoryBot.create :activity, activity_type: @activity_type, asset_group: @asset_group @steps = Array.new(10) do - step = build_step(%Q{{?p :a :Rack.} => {:step :addFacts {?p :a :TubeRack .}.} .}, %Q{}, activity: @activity, asset_group: @asset_group) + step = build_step(%{{?p :a :Rack.} => {:step :addFacts {?p :a :TubeRack .}.} .}, %{}, activity: @activity, asset_group: @asset_group) step.run! step end From ae6e860d227a82299a408e8630388d97aab8c922 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 26 Apr 2022 14:49:57 +0100 Subject: [PATCH 183/303] Rubocop: Style/BlockComments --- .rubocop_todo.yml | 6 ---- spec/spec_helper.rb | 76 ++++++++++++++++++++++----------------------- 2 files changed, 37 insertions(+), 45 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 5d1d6d69..ede0d40e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -474,12 +474,6 @@ Rails/WhereNot: - 'app/models/step_type.rb' - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' -# Offense count: 1 -# This cop supports safe auto-correction (--auto-correct). -Style/BlockComments: - Exclude: - - 'spec/spec_helper.rb' - # Offense count: 120 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, IgnoredMethods, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c7099a8d..ba82ca24 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -69,43 +69,41 @@ # you configure your source control system to ignore this file. config.example_status_persistence_file_path = 'tmp/spec_failures.txt' -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # This allows you to limit a spec run to individual examples or groups - # you care about by tagging them with `:focus` metadata. When nothing - # is tagged with `:focus`, all examples get run. RSpec also provides - # aliases for `it`, `describe`, and `context` that include `:focus` - # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_when_matching :focus - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ - # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - config.disable_monkey_patching! - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = 'doc' - end - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end + # The settings below are suggested to provide a good initial experience + # with RSpec, but feel free to customize to your heart's content. + # # This allows you to limit a spec run to individual examples or groups + # # you care about by tagging them with `:focus` metadata. When nothing + # # is tagged with `:focus`, all examples get run. RSpec also provides + # # aliases for `it`, `describe`, and `context` that include `:focus` + # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + # config.filter_run_when_matching :focus + # + # # Limits the available syntax to the non-monkey patched syntax that is + # # recommended. For more details, see: + # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + # config.disable_monkey_patching! + # + # # Many RSpec users commonly either run the entire suite or an individual + # # file, and it's useful to allow more verbose output when running an + # # individual spec file. + # if config.files_to_run.one? + # # Use the documentation formatter for detailed output, + # # unless a formatter has already been configured + # # (e.g. via a command-line flag). + # config.default_formatter = 'doc' + # end + # + # # Run specs in random order to surface order dependencies. If you find an + # # order dependency and want to debug it, you can fix the order by providing + # # the seed, which is printed after each run. + # # --seed 1234 + # config.order = :random + # + # # Seed global randomization in this process using the `--seed` CLI option. + # # Setting this allows you to use `--seed` to deterministically reproduce + # # test failures related to randomization by passing the same `--seed` value + # # as the one that triggered the failure. + # Kernel.srand config.seed end From 30c9737355ec35ce9188a1aa2860b32e0635b963 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 26 Apr 2022 14:54:10 +0100 Subject: [PATCH 184/303] Rubocop: Style/BlockDelimiters --- .rubocop_todo.yml | 46 ----------------- app/controllers/uploaded_files_controller.rb | 4 +- script/recreate_steptypes.rb | 4 +- .../controllers/activities_controller_spec.rb | 8 +-- .../activity_types_controller_spec.rb | 8 +-- .../asset_groups_controller_spec.rb | 32 ++++++------ spec/controllers/changes_controller_spec.rb | 4 +- .../instruments_controller_spec.rb | 8 +-- spec/controllers/kit_types_controller_spec.rb | 8 +-- spec/controllers/kits_controller_spec.rb | 8 +-- spec/controllers/printers_controller_spec.rb | 12 ++--- .../controllers/step_types_controller_spec.rb | 24 ++++----- spec/controllers/steps_controller_spec.rb | 16 +++--- spec/helpers/application_helper_spec.rb | 4 +- spec/lib/actions/racking_spec.rb | 8 +-- .../lib/changes_support/disjoint_list_spec.rb | 30 +++++------ spec/lib/fact_changes_spec.rb | 50 +++++++++---------- .../lib/parsers/csv_layout/csv_parser_spec.rb | 4 +- .../parsers/csv_layout/line_parser_spec.rb | 4 +- .../csv_layout/location_parser_spec.rb | 4 +- .../validators/any_barcode_validator_spec.rb | 8 +-- .../fluidx_barcode_validator_spec.rb | 8 +-- .../validators/location_validator_spec.rb | 8 +-- .../parsers/csv_metadata/csv_parser_spec.rb | 4 +- .../validators/headers_validator_spec.rb | 8 +-- spec/models/action_spec.rb | 20 ++++---- .../activities/steps_management_spec.rb | 8 +-- spec/models/asset_group_spec.rb | 8 +-- spec/models/step_spec.rb | 44 ++++++++-------- spec/models/step_type_spec.rb | 40 +++++++-------- .../steps/background_tasks/inference_spec.rb | 8 +-- spec/models/steps/stoppable_spec.rb | 24 ++++----- spec/models/steps/task_spec.rb | 28 +++++------ spec/script/runners/load_metadata_spec.rb | 12 ++--- .../runners/transfer_plate_to_plate_spec.rb | 4 +- spec/script/runners/transfer_samples_spec.rb | 16 +++--- ...fer_tubes_to_tube_rack_by_position_spec.rb | 24 ++++----- 37 files changed, 256 insertions(+), 302 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index ede0d40e..d0510ada 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -474,52 +474,6 @@ Rails/WhereNot: - 'app/models/step_type.rb' - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' -# Offense count: 120 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, IgnoredMethods, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. -# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces -# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object -# FunctionalMethods: let, let!, subject, watch -# IgnoredMethods: lambda, proc, it -Style/BlockDelimiters: - Exclude: - - 'app/controllers/uploaded_files_controller.rb' - - 'script/recreate_steptypes.rb' - - 'spec/controllers/activities_controller_spec.rb' - - 'spec/controllers/activity_types_controller_spec.rb' - - 'spec/controllers/asset_groups_controller_spec.rb' - - 'spec/controllers/changes_controller_spec.rb' - - 'spec/controllers/instruments_controller_spec.rb' - - 'spec/controllers/kit_types_controller_spec.rb' - - 'spec/controllers/kits_controller_spec.rb' - - 'spec/controllers/printers_controller_spec.rb' - - 'spec/controllers/step_types_controller_spec.rb' - - 'spec/controllers/steps_controller_spec.rb' - - 'spec/helpers/application_helper_spec.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/lib/changes_support/disjoint_list_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/validators/any_barcode_validator_spec.rb' - - 'spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb' - - 'spec/lib/parsers/csv_layout/validators/location_validator_spec.rb' - - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb' - - 'spec/models/action_spec.rb' - - 'spec/models/activities/steps_management_spec.rb' - - 'spec/models/asset_group_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/models/steps/background_tasks/inference_spec.rb' - - 'spec/models/steps/stoppable_spec.rb' - - 'spec/models/steps/task_spec.rb' - - 'spec/script/runners/load_metadata_spec.rb' - - 'spec/script/runners/transfer_plate_to_plate_spec.rb' - - 'spec/script/runners/transfer_samples_spec.rb' - - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' - # Offense count: 3 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowOnConstant. diff --git a/app/controllers/uploaded_files_controller.rb b/app/controllers/uploaded_files_controller.rb index 5e8927b4..f057962a 100644 --- a/app/controllers/uploaded_files_controller.rb +++ b/app/controllers/uploaded_files_controller.rb @@ -3,9 +3,9 @@ class UploadedFilesController < ApplicationController def show respond_to do |format| - format.bin { + format.bin do send_data(@uploaded_file.data, filename: @uploaded_file.filename) - } + end format.html { render :show } format.n3 { render :show } end diff --git a/script/recreate_steptypes.rb b/script/recreate_steptypes.rb index 279445b4..6fa51d95 100755 --- a/script/recreate_steptypes.rb +++ b/script/recreate_steptypes.rb @@ -52,8 +52,8 @@ ['Update Sequencescape', 'update_sequencescape.rb', %{ { ?p :a :TubeRack .}=>{}. }] -].map { |l| +].map do |l| s = StepType.find_by(name: l[0]) s2 = StepType.create(name: l[0], step_action: l[1], for_reasoning: true, n3_definition: l[2]) s.deprecate_with(s) -} +end diff --git a/spec/controllers/activities_controller_spec.rb b/spec/controllers/activities_controller_spec.rb index b54c1118..0ba60beb 100644 --- a/spec/controllers/activities_controller_spec.rb +++ b/spec/controllers/activities_controller_spec.rb @@ -27,9 +27,9 @@ end context "when scanning a new kit" do context 'when the kit does not exist' do - let(:subject) { + let(:subject) do post :create, params: { activity: { :kit_barcode => '11850', :instrument_barcode => @instrument.barcode } } - } + end it 'fails creating the activity' do count = @kit.kit_type.activity_type.activities.count subject @@ -43,9 +43,9 @@ end context 'when the kit exists' do context 'when the instrument does not support the activity type' do - let(:subject) { + let(:subject) do post :create, params: { activity: { :kit_barcode => @kit.barcode, :instrument_barcode => @instrument.barcode } } - } + end it 'fails creating the activity' do count = @kit.kit_type.activity_type.activities.count subject diff --git a/spec/controllers/activity_types_controller_spec.rb b/spec/controllers/activity_types_controller_spec.rb index ae98fbc4..fdebab69 100644 --- a/spec/controllers/activity_types_controller_spec.rb +++ b/spec/controllers/activity_types_controller_spec.rb @@ -16,9 +16,9 @@ end it "should create activity_type" do - expect { + expect do post :create, params: { activity_type: @activity_type.attributes } - }.to change { ActivityType.count }.by(1) + end.to change { ActivityType.count }.by(1) assert_redirected_to activity_type_path(assigns(:activity_type)) end @@ -39,9 +39,9 @@ end it "should destroy activity_type" do - expect { + expect do delete :destroy, params: { id: @activity_type } - }.to change { ActivityType.count }.by(-1) + end.to change { ActivityType.count }.by(-1) assert_redirected_to activity_types_path end diff --git a/spec/controllers/asset_groups_controller_spec.rb b/spec/controllers/asset_groups_controller_spec.rb index 7dcf93de..4a2363b5 100644 --- a/spec/controllers/asset_groups_controller_spec.rb +++ b/spec/controllers/asset_groups_controller_spec.rb @@ -12,19 +12,19 @@ let(:file) { fixture_file_upload('test/data/layout.csv', 'text/csv') } it 'creates a new uploaded file' do - expect { + expect do post :upload, params: { id: asset_group.id, qqfilename: 'myfile.csv', qqfile: file } - }.to change { UploadedFile.all.count }.by(1) + end.to change { UploadedFile.all.count }.by(1) end it 'adds the file to the asset group' do - expect { + expect do post :upload, params: { id: asset_group.id, qqfilename: 'myfile.csv', qqfile: file } - }.to change { asset_group.assets.count }.by(1) + end.to change { asset_group.assets.count }.by(1) end it 'creates a new step to track the change in the asset group' do - expect { + expect do post :upload, params: { id: asset_group.id, qqfilename: 'myfile.csv', qqfile: file } - }.to change { Step.all.count }.by(1) + end.to change { Step.all.count }.by(1) end end @@ -35,18 +35,18 @@ context "when the asset is in the database" do context 'finding by uuid' do it "add the new asset to the group" do - expect { + expect do post :update, params: { :asset_group => { :assets => [asset.uuid] }, :id => asset_group.id, :activity_id => activity.id } - }.to change { asset_group.assets.count }.by(1) + end.to change { asset_group.assets.count }.by(1) end end context 'finding by barcode' do it "add the new asset to the group" do - expect { + expect do post :update, params: { :asset_group => { :assets => [asset.barcode] }, :id => asset_group.id, :activity_id => activity.id } - }.to change { asset_group.assets.count }.by(1) + end.to change { asset_group.assets.count }.by(1) end end end @@ -65,19 +65,19 @@ # NOTE: We previously had an innaccurate mock making this test pass. # We're just pulling assets from SS based on barcode. xit "retrieves the asset from Sequencescape" do - expect { + expect do post :update, params: { :asset_group => { :assets => [uuid] }, :id => asset_group.id, :activity_id => activity.id } - }.to change { asset_group.assets.count }.by(1) + end.to change { asset_group.assets.count }.by(1) end end context 'finding by barcode' do it "retrieves the asset from Sequencescape" do - expect { + expect do post :update, params: { :asset_group => { :assets => [barcode] }, :id => asset_group.id, :activity_id => activity.id } - }.to change { asset_group.assets.count }.by(1) + end.to change { asset_group.assets.count }.by(1) end end end @@ -94,12 +94,12 @@ let(:creatable_barcode) { generate :barcode_creatable } it "creates a new asset" do - expect { + expect do post :update, params: { :asset_group => { :assets => [creatable_barcode] }, :id => asset_group.id, :activity_id => activity.id } - }.to change { asset_group.assets.count }.by(1) + end.to change { asset_group.assets.count }.by(1) end end end diff --git a/spec/controllers/changes_controller_spec.rb b/spec/controllers/changes_controller_spec.rb index fcb0e1a9..b06d6741 100644 --- a/spec/controllers/changes_controller_spec.rb +++ b/spec/controllers/changes_controller_spec.rb @@ -3,14 +3,14 @@ RSpec.describe ChangesController, type: :controller do context '#create' do it 'creates and performs the changes when providing fact_changes' do - expect { + expect do post :create, params: { changes: { create_assets: ['?p'], add_facts: [["?p", "a", "Tube"]] } }, as: :json - }.to change { Step.all.count }.and change { Asset.all.count }.by(1) + end.to change { Step.all.count }.and change { Asset.all.count }.by(1) change = JSON.parse(response.body) expect(change['assets'].count).to eq(1) expect(change['assets'][0]['uuid']).not_to eq(nil) diff --git a/spec/controllers/instruments_controller_spec.rb b/spec/controllers/instruments_controller_spec.rb index 935edff8..e6232617 100644 --- a/spec/controllers/instruments_controller_spec.rb +++ b/spec/controllers/instruments_controller_spec.rb @@ -21,9 +21,9 @@ end it "should create instrument" do - expect { + expect do post :create, params: { instrument: @instrument.attributes } - }.to change { Instrument.count }.by(1) + end.to change { Instrument.count }.by(1) assert_redirected_to instrument_path(assigns(:instrument)) end @@ -44,9 +44,9 @@ end it "should destroy instrument" do - expect { + expect do delete :destroy, params: { id: @instrument } - }.to change { Instrument.count }.by(-1) + end.to change { Instrument.count }.by(-1) assert_redirected_to instruments_path end diff --git a/spec/controllers/kit_types_controller_spec.rb b/spec/controllers/kit_types_controller_spec.rb index d500b48f..f3a7d940 100644 --- a/spec/controllers/kit_types_controller_spec.rb +++ b/spec/controllers/kit_types_controller_spec.rb @@ -17,9 +17,9 @@ end it "should create kit_type" do - expect { + expect do post :create, params: { kit_type: @kit_type.attributes } - }.to change { KitType.count }.by(1) + end.to change { KitType.count }.by(1) assert_redirected_to kit_type_path(assigns(:kit_type)) end @@ -40,9 +40,9 @@ end it "should destroy kit_type" do - expect { + expect do delete :destroy, params: { id: @kit_type } - }.to change { KitType.count }.by(-1) + end.to change { KitType.count }.by(-1) assert_redirected_to kit_types_path end diff --git a/spec/controllers/kits_controller_spec.rb b/spec/controllers/kits_controller_spec.rb index f338a124..22b7e14d 100644 --- a/spec/controllers/kits_controller_spec.rb +++ b/spec/controllers/kits_controller_spec.rb @@ -17,9 +17,9 @@ end it "should create kit" do - expect { + expect do post :create, params: { kit: @kit.attributes } - }.to change { Kit.count }.by(1) + end.to change { Kit.count }.by(1) assert_redirected_to kit_path(assigns(:kit)) end @@ -40,9 +40,9 @@ end it "should destroy kit" do - expect { + expect do delete :destroy, params: { id: @kit } - }.to change { Kit.count }.by(-1) + end.to change { Kit.count }.by(-1) assert_redirected_to kits_path end diff --git a/spec/controllers/printers_controller_spec.rb b/spec/controllers/printers_controller_spec.rb index 289907ae..01af5d33 100644 --- a/spec/controllers/printers_controller_spec.rb +++ b/spec/controllers/printers_controller_spec.rb @@ -16,11 +16,11 @@ end it "should create printer" do - expect { + expect do post :create, params: { printer: @printer.attributes } - }.to change { - Printer.count - }.by(1) + end.to change { + Printer.count + }.by(1) assert_redirected_to printer_path(assigns(:printer)) end @@ -41,9 +41,9 @@ end it "should destroy printer" do - expect { + expect do delete :destroy, params: { id: @printer } - }.to change { Printer.count }.by(-1) + end.to change { Printer.count }.by(-1) assert_redirected_to printers_path end diff --git a/spec/controllers/step_types_controller_spec.rb b/spec/controllers/step_types_controller_spec.rb index 2e8adb70..1f580f2f 100644 --- a/spec/controllers/step_types_controller_spec.rb +++ b/spec/controllers/step_types_controller_spec.rb @@ -16,11 +16,11 @@ end it "should create step_type" do - expect { + expect do post :create, params: { step_type: { :name => 'Test' } } - }.to change { - StepType.count - }.by(1) + end.to change { + StepType.count + }.by(1) assert_redirected_to step_type_url(StepType.last) end @@ -42,20 +42,20 @@ it "should update priority for step_type" do step_type = create :step_type - expect { + expect do post :update, params: { id: step_type.id, step_type: step_type.attributes.merge({ priority: 10 }.as_json) } - }.to change { + end.to change { step_type.reload step_type.priority }.to(10) end it "should destroy step_type" do - expect { + expect do delete :destroy, params: { id: @step_type } - }.to change { - StepType.count - }.by(-1) + end.to change { + StepType.count + }.by(-1) assert_redirected_to step_types_url end @@ -63,9 +63,9 @@ context '#create' do let(:params) { { step_type: { name: 'My task' } } } it 'creates a new step type' do - expect { + expect do post :create, params: params - }.to change { StepType.all.count }.by(1) + end.to change { StepType.all.count }.by(1) end it 'redirects to the step type url' do post :create, params: params diff --git a/spec/controllers/steps_controller_spec.rb b/spec/controllers/steps_controller_spec.rb index f7f97fc0..abb0d076 100644 --- a/spec/controllers/steps_controller_spec.rb +++ b/spec/controllers/steps_controller_spec.rb @@ -12,13 +12,13 @@ context '#create' do it 'creates a new step' do - expect { + expect do post :create, params: { activity_id: activity.id, step: { asset_group_id: asset_group.id, step_type_id: step_type.id } } - }.to change { Step.all.count } + end.to change { Step.all.count } end context 'when receiving a specific printer config' do @@ -40,9 +40,9 @@ end end context '#update' do - let(:step) { + let(:step) do create(:step, activity: activity, asset_group: asset_group, step_type: step_type) - } + end let(:event_name) { Step::EVENT_RUN } @@ -54,13 +54,13 @@ end context 'when a step is running' do - let(:step) { + let(:step) do create :step, activity: activity, asset_group: asset_group, step_type: step_type - } + end - let(:run_step) { + let(:run_step) do # We want to simulate that during a running process a 'stop' event is received so we # need 2 different calls ran asynchronously that is why one of them will be performed # in a different thread @@ -69,7 +69,7 @@ post :update, params: { id: step_id, step: { event_name: 'run' } } rescue ActionDispatch::IllegalStateError => e end - } + end it 'can be stopped' do step_id = step.id allow_any_instance_of(Step).to receive(:process) do diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 62103c74..59a0796c 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -11,11 +11,11 @@ def create_well(location, sample, aliquot) end context '#data_asset_display_for_plate' do - let(:well) { + let(:well) do w = create_well(location, sample, aliquot) w.update_attributes(barcode: barcode) w - } + end let(:sample) { nil } let(:aliquot) { nil } let(:location) { nil } diff --git a/spec/lib/actions/racking_spec.rb b/spec/lib/actions/racking_spec.rb index 9e5615ef..7a5a441b 100644 --- a/spec/lib/actions/racking_spec.rb +++ b/spec/lib/actions/racking_spec.rb @@ -9,12 +9,12 @@ let(:fact) { create(:fact, predicate: 'a', object: 'TubeRack') } let(:asset) { create :asset, uploaded_file: file, facts: [fact] } let(:step_type) { create(:step_type, condition_groups: [condition_group]) } - let(:step) { + let(:step) do create :step, activity: activity, state: Step::STATE_RUNNING, asset_group: asset_group, step_type: step_type - } + end let(:condition) { create(:condition, predicate: fact.predicate, object: fact.object) } let(:condition_group) { create(:condition_group, conditions: [condition]) } @@ -95,9 +95,9 @@ def initialize(asset_group) describe 'with empty slots in the layout .csv' do let(:num_empty) { 3 } let(:start_pos) { 0 } - let(:content) { + let(:content) do add_empty_slots(File.read('test/data/layout.csv'), num_empty, start_pos) - } + end def add_empty_slots(content, num_empty, start_pos = 0) csv = CSV.new(content).to_a num_empty.times do |i| diff --git a/spec/lib/changes_support/disjoint_list_spec.rb b/spec/lib/changes_support/disjoint_list_spec.rb index 5cb0b975..180249ad 100644 --- a/spec/lib/changes_support/disjoint_list_spec.rb +++ b/spec/lib/changes_support/disjoint_list_spec.rb @@ -119,25 +119,25 @@ expect(list.add(elem)).to eq(list) end it 'adds the element when is not present in any of the lists' do - expect { + expect do list.add(elem) - }.to change { list.to_a.length }.by(1) - .and change { list.length }.by(1) + end.to change { list.to_a.length }.by(1) + .and change { list.length }.by(1) expect(list.to_a).to eq([elem]) end it 'stores the position in the common hash' do - expect { + expect do list.add(elem) - }.to change { list.store_for(elem) }.from(nil).to(list) - .and change { list2.store_for(elem) }.from(nil).to(list) + end.to change { list.store_for(elem) }.from(nil).to(list) + .and change { list2.store_for(elem) }.from(nil).to(list) end it 'does not add the element again if it is already present' do list.add(elem) expect(list.to_a).to eq([elem]) - expect { + expect do list.add(elem) - }.to change { list.to_a.length }.by(0) - .and change { list.length }.by(0) + end.to change { list.to_a.length }.by(0) + .and change { list.length }.by(0) expect(list.to_a).to eq([elem]) end it 'disables the element from the list if is added to another disjoint list' do @@ -151,14 +151,14 @@ end context 'with a group of disjoint lists' do - let(:lists) { + let(:lists) do l = Array.new(5) { ChangesSupport::DisjointList.new([]) } l[0].add_disjoint_list(l[1]) l[0].add_disjoint_list(l[2]) l[0].add_disjoint_list(l[3]) l[0].add_disjoint_list(l[4]) l - } + end it 'disables element if present in another list' do lists[0] << [] lists[1] << [1] @@ -390,12 +390,12 @@ context 'when merging a chain of objects' do let(:winners) { Array.new(6) { ChangesSupport::DisjointList.new([]) } } let(:losers) { Array.new(6) { ChangesSupport::DisjointList.new([]) } } - let(:list) { - winners.zip(losers).map { |l| + let(:list) do + winners.zip(losers).map do |l| l[0].add_disjoint_list(l[1]) { winner: l[0], loser: l[1] } - } - } + end + end it 'keeps track of all restrictions until the final list' do list[0][:winner] << 'Manchester City' diff --git a/spec/lib/fact_changes_spec.rb b/spec/lib/fact_changes_spec.rb index 9c19ce2b..53412ce4 100644 --- a/spec/lib/fact_changes_spec.rb +++ b/spec/lib/fact_changes_spec.rb @@ -58,9 +58,9 @@ describe '#parse_json' do let(:updates) { FactChanges.new } it 'raises exception when the parsed object is not right' do - expect { + expect do updates.parse_json("something went wrong!") - }.to raise_error(StandardError) + end.to raise_error(StandardError) end it 'parses a json and loads the changes from it' do expect(updates.facts_to_add.length).to eq(0) @@ -217,17 +217,17 @@ context 'with add' do it 'applies a new added property' do updates1.add(asset1, property, value) - expect { + expect do updates1.apply(step) - }.to change { asset1.facts.count }.by(1) - .and change { Operation.count }.by(1) + end.to change { asset1.facts.count }.by(1) + .and change { Operation.count }.by(1) end it 'applies a new added relation' do updates1.add(asset1, relation, asset2) - expect { + expect do updates1.apply(step) - }.to change { asset1.facts.count }.by(1) - .and change { Operation.count }.by(1) + end.to change { asset1.facts.count }.by(1) + .and change { Operation.count }.by(1) end it 'is able to add facts to assets created before' do updates1.create_assets(['?p']) @@ -239,10 +239,10 @@ context 'with add_remote' do it 'adds a new remote fact' do updates1.add_remote(asset1, relation, asset2) - expect { + expect do updates1.apply(step) - }.to change { asset1.facts.count }.by(1) - .and change { Operation.count }.by(1) + end.to change { asset1.facts.count }.by(1) + .and change { Operation.count }.by(1) expect(asset1.facts.first.is_remote?).to eq(true) end @@ -250,10 +250,10 @@ context 'with replace_remote' do it 'adds a new remote fact if it does not exist' do updates1.replace_remote(asset1, relation, asset2) - expect { + expect do updates1.apply(step) - }.to change { asset1.facts.count }.by(1) - .and change { Operation.count }.by(1) + end.to change { asset1.facts.count }.by(1) + .and change { Operation.count }.by(1) expect(asset1.facts.count).to eq(1) expect(asset1.facts.first.is_remote?).to eq(true) end @@ -264,10 +264,10 @@ updates1.replace_remote(asset1, relation, asset2) asset1.facts.reload - expect { + expect do updates1.apply(step) - }.to change { asset1.facts.count }.by(0) - .and change { Operation.count }.by(2) + end.to change { asset1.facts.count }.by(0) + .and change { Operation.count }.by(2) asset1.facts.reload expect(asset1.facts.count).to eq(1) @@ -278,10 +278,10 @@ it 'removes an already existing fact' do asset1.facts << fact1 updates1.remove(fact1) - expect { + expect do updates1.apply(step) - }.to change { asset1.facts.count }.by(-1) - .and change { Operation.count }.by(1) + end.to change { asset1.facts.count }.by(-1) + .and change { Operation.count }.by(1) end end @@ -293,10 +293,10 @@ it 'removes facts with a condition' do asset1.facts << [fact1, fact2, fact3, fact4] updates1.remove_where(asset1, 'cond1', 'val') - expect { + expect do updates1.apply(step) - }.to change { asset1.facts.count }.by(-2) - .and change { Operation.count }.by(2) + end.to change { asset1.facts.count }.by(-2) + .and change { Operation.count }.by(2) end end @@ -746,9 +746,9 @@ obj2.merge(obj) end it 'merges wildcards used in other objects' do - expect { + expect do obj2.add("?p", "a", "Tube") - }.not_to raise_error + end.not_to raise_error end it 'merges mapping between wildcards and uuids from other objects' do obj2.add("?p", "a", "Tube") diff --git a/spec/lib/parsers/csv_layout/csv_parser_spec.rb b/spec/lib/parsers/csv_layout/csv_parser_spec.rb index 312c1125..3a6ff267 100644 --- a/spec/lib/parsers/csv_layout/csv_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/csv_parser_spec.rb @@ -11,12 +11,12 @@ let(:activity) { create(:activity) } let(:asset_group) { create(:asset_group) } let(:step_type) { create(:step_type) } - let(:step) { + let(:step) do create :step, activity: activity, state: Step::STATE_RUNNING, asset_group: asset_group, step_type: step_type - } + end setup do allow(SequencescapeClient).to receive(:labware).and_return([]) diff --git a/spec/lib/parsers/csv_layout/line_parser_spec.rb b/spec/lib/parsers/csv_layout/line_parser_spec.rb index ef4ae041..fe152257 100644 --- a/spec/lib/parsers/csv_layout/line_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/line_parser_spec.rb @@ -15,11 +15,11 @@ location_parser: Parsers::CsvLayout::LocationParser }) end - let(:input_reader) { + let(:input_reader) do reader = double('reader') allow(reader).to receive(:lines).and_return(@input) reader - } + end let(:parser) { Parsers::CsvLayout::LineParser.new(input_reader, main_parser) } before do diff --git a/spec/lib/parsers/csv_layout/location_parser_spec.rb b/spec/lib/parsers/csv_layout/location_parser_spec.rb index ea64615a..2f157e5b 100644 --- a/spec/lib/parsers/csv_layout/location_parser_spec.rb +++ b/spec/lib/parsers/csv_layout/location_parser_spec.rb @@ -3,14 +3,14 @@ require 'parsers/csv_layout/validators/location_validator' RSpec.describe Parsers::CsvLayout::LocationParser do - let(:main_parser) { + let(:main_parser) do main = double('parser') allow(main).to receive(:add_error) allow(main).to receive(:components).and_return({ location_validator: Parsers::CsvLayout::Validators::LocationValidator }) main - } + end let(:barcode) { '1234' } let(:location) { 'A10' } let(:input) { [location, barcode] } diff --git a/spec/lib/parsers/csv_layout/validators/any_barcode_validator_spec.rb b/spec/lib/parsers/csv_layout/validators/any_barcode_validator_spec.rb index 1d3b5e50..873c13fb 100644 --- a/spec/lib/parsers/csv_layout/validators/any_barcode_validator_spec.rb +++ b/spec/lib/parsers/csv_layout/validators/any_barcode_validator_spec.rb @@ -2,14 +2,14 @@ require 'parsers/csv_layout/validators/any_barcode_validator' RSpec.describe Parsers::CsvLayout::Validators::AnyBarcodeValidator do - let(:klass) { - Class.new { + let(:klass) do + Class.new do attr_accessor :barcode include ActiveModel::Validations validates_with Parsers::CsvLayout::Validators::AnyBarcodeValidator - } - } + end + end let(:instance) { klass.new } it 'validates a normal barcode' do instance.barcode = '1234' diff --git a/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb b/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb index 14991e00..0f681c70 100644 --- a/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb +++ b/spec/lib/parsers/csv_layout/validators/fluidx_barcode_validator_spec.rb @@ -3,14 +3,14 @@ require 'parsers/csv_layout/validators/fluidx_barcode_validator' RSpec.describe Parsers::CsvLayout::Validators::FluidxBarcodeValidator do - let(:klass) { - Class.new { + let(:klass) do + Class.new do attr_accessor :barcode include ActiveModel::Validations validates_with Parsers::CsvLayout::Validators::FluidxBarcodeValidator - } - } + end + end let(:instance) { klass.new } it 'validates a fluidx barcode' do instance.barcode = 'F1234' diff --git a/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb b/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb index 49c3c847..1b875c54 100644 --- a/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb +++ b/spec/lib/parsers/csv_layout/validators/location_validator_spec.rb @@ -2,14 +2,14 @@ require 'parsers/csv_layout/validators/location_validator' RSpec.describe Parsers::CsvLayout::Validators::LocationValidator do - let(:klass) { - Class.new { + let(:klass) do + Class.new do attr_accessor :location include ActiveModel::Validations validates_with Parsers::CsvLayout::Validators::LocationValidator - } - } + end + end let(:instance) { klass.new } it 'validates a valid location' do instance.location = 'A01' diff --git a/spec/lib/parsers/csv_metadata/csv_parser_spec.rb b/spec/lib/parsers/csv_metadata/csv_parser_spec.rb index 496f8f5b..2af6085f 100644 --- a/spec/lib/parsers/csv_metadata/csv_parser_spec.rb +++ b/spec/lib/parsers/csv_metadata/csv_parser_spec.rb @@ -11,12 +11,12 @@ let(:activity) { create(:activity) } let(:asset_group) { create(:asset_group) } let(:step_type) { create(:step_type) } - let(:step) { + let(:step) do create :step, activity: activity, state: Step::STATE_RUNNING, asset_group: asset_group, step_type: step_type - } + end setup do allow(Asset).to receive(:find_or_import_asset_with_barcode) do |barcode| diff --git a/spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb b/spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb index 6685be67..e306eb2b 100644 --- a/spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb +++ b/spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb @@ -2,14 +2,14 @@ require 'parsers/csv_metadata/validators/headers_validator' RSpec.describe Parsers::CsvMetadata::Validators::HeadersValidator do - let(:klass) { - Class.new { + let(:klass) do + Class.new do attr_accessor :headers include ActiveModel::Validations validates_with Parsers::CsvMetadata::Validators::HeadersValidator - } - } + end + end let(:instance) { klass.new } it 'validates normal headers' do instance.headers = ["h1", "h2"] diff --git a/spec/models/action_spec.rb b/spec/models/action_spec.rb index d333b29a..c97f61ca 100644 --- a/spec/models/action_spec.rb +++ b/spec/models/action_spec.rb @@ -1,16 +1,16 @@ require 'rails_helper' RSpec.describe Action, type: :model do context '#each_connected_asset' do - let(:action) { + let(:action) do create(:action, step_type: step_type, predicate: 'some verb', action_type: 'something') - } + end shared_examples 'a connector by position' do - let(:step_type) { + let(:step_type) do create(:step_type, connect_by: 'position') - } + end it 'yields sources and destination' do i = 0 action.each_connected_asset(sources, destinations) do |a, b| @@ -34,13 +34,13 @@ let(:sources) { [:a, :b, :c] } let(:destinations) { [:alpha, :beta, :gamma] } let(:pairs_by_position) { [[:a, :alpha], [:b, :beta], [:c, :gamma]] } - let(:pairs) { + let(:pairs) do [ [:a, :alpha], [:a, :beta], [:a, :gamma], [:b, :alpha], [:b, :beta], [:b, :gamma], [:c, :alpha], [:c, :beta], [:c, :gamma] ] - } + end it_behaves_like 'a connector by position' it_behaves_like 'a connector of all to all' @@ -49,12 +49,12 @@ let(:sources) { [:a, :b] } let(:destinations) { [:alpha, :beta, :gamma] } let(:pairs_by_position) { [[:a, :alpha], [:b, :beta]] } - let(:pairs) { + let(:pairs) do [ [:a, :alpha], [:a, :beta], [:a, :gamma], [:b, :alpha], [:b, :beta], [:b, :gamma] ] - } + end it_behaves_like 'a connector by position' it_behaves_like 'a connector of all to all' end @@ -62,13 +62,13 @@ let(:sources) { [:a, :b, :c] } let(:destinations) { [:alpha, :beta] } let(:pairs_by_position) { [[:a, :alpha], [:b, :beta]] } - let(:pairs) { + let(:pairs) do [ [:a, :alpha], [:a, :beta], [:b, :alpha], [:b, :beta], [:c, :alpha], [:c, :beta] ] - } + end it_behaves_like 'a connector by position' it_behaves_like 'a connector of all to all' end diff --git a/spec/models/activities/steps_management_spec.rb b/spec/models/activities/steps_management_spec.rb index 43bb2118..387f9cd0 100644 --- a/spec/models/activities/steps_management_spec.rb +++ b/spec/models/activities/steps_management_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' RSpec.describe 'Activities::StepsManagement' do context "with an activity configuration" do - let(:asset) { + let(:asset) do create :asset, { barcode: '1', facts: [ @@ -12,8 +12,8 @@ create :fact, { :predicate => a, :object => b } end } - } - let(:step_type) { + end + let(:step_type) do create :step_type, name: 'Step B', condition_groups: [ create(:condition_group, conditions: [ @@ -21,7 +21,7 @@ create(:condition, { predicate: 'aliquotType', object: 'DNA' }) ]) ] - } + end let(:step_type2) { create :step_type, name: 'Step A' } let(:activity_type) { create :activity_type, step_types: [step_type, step_type2] } let(:activity) { create :activity, activity_type: activity_type } diff --git a/spec/models/asset_group_spec.rb b/spec/models/asset_group_spec.rb index 33c483fa..2f9d9a9f 100644 --- a/spec/models/asset_group_spec.rb +++ b/spec/models/asset_group_spec.rb @@ -8,14 +8,14 @@ allow(group).to receive(:refresh!).and_return(true) end it 'adds new assets to the group' do - expect { + expect do group.update_with_assets(existing_assets.concat(new_assets)) - }.to change { Operation.count }.by(2).and change { group.assets.count }.by(2) + end.to change { Operation.count }.by(2).and change { group.assets.count }.by(2) end it 'removes assets not present anymore in the group' do - expect { + expect do group.update_with_assets(new_assets) - }.to change { Operation.count }.by(5).and change { group.assets.count }.by(-1) + end.to change { Operation.count }.by(5).and change { group.assets.count }.by(-1) end it 'refreshes the new added assets' do diff --git a/spec/models/step_spec.rb b/spec/models/step_spec.rb index b544c11f..112176e8 100644 --- a/spec/models/step_spec.rb +++ b/spec/models/step_spec.rb @@ -95,18 +95,18 @@ def create_assets(num, type) }) @step_type.condition_groups << @cg1 @step_type.condition_groups << @cg2 - @tubes = Array.new(7) { |_i| + @tubes = Array.new(7) do |_i| FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') ] }) - } - @racks = Array.new(5) { |_i| + end + @racks = Array.new(5) do |_i| FactoryBot.create(:asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') ] }) - } + end @assets = [@tubes, @racks].flatten @asset_group = FactoryBot.create(:asset_group, { :assets => @assets }) end @@ -114,9 +114,9 @@ def create_assets(num, type) describe 'when creating a new step' do it 'raises an exception if assets are not compatible with step_type' do @cg1.update_attributes(:cardinality => 1) - expect { + expect do @step = create_step - }.to raise_error(AASM::InvalidTransition) + end.to raise_error(AASM::InvalidTransition) end end @@ -159,9 +159,9 @@ def create_assets(num, type) it 'does not execute the rule when the wildcard condition is not met' do previous_num = @asset_group.assets.count - expect { + expect do @step = create_step - }.to raise_error(StandardError) + end.to raise_error(StandardError) @racks.each(&:reload) @@ -450,9 +450,9 @@ def create_assets(num, type) let(:asset_group) { create(:asset_group, assets: [origins, targets].flatten) } shared_examples 'a step type that can connect by position' do - let(:step_type) { + let(:step_type) do create(:step_type, condition_groups: condition_groups, actions: actions, connect_by: 'position') - } + end it 'connects origins with destinations 1 to 1 leaving outside assets without associated pair' do s = run_step_type(step_type, asset_group) origins.each(&:reload) @@ -465,9 +465,9 @@ def create_assets(num, type) end shared_examples 'a step type that can connect N to N' do - let(:step_type) { + let(:step_type) do create(:step_type, condition_groups: condition_groups, actions: actions, connect_by: nil) - } + end it 'connects all origins with all destinations' do s = run_step_type(step_type, asset_group) @@ -487,18 +487,18 @@ def create_assets(num, type) end context 'when the destinations exist upfront' do - let(:condition_groups) { + let(:condition_groups) do [ create_condition_group_to_select_asset_type('Tube'), create_condition_group_to_select_asset_type('Rack') ] - } - let(:actions) { + end + let(:actions) do [ create_action_for_connecting_condition_groups('transfer', condition_groups.first, condition_groups.last) ] - } + end let(:targets) { destinations } context 'when there are more destinations than origins' do let(:origins) { create_assets(5, 'Tube') } @@ -526,22 +526,22 @@ def create_assets(num, type) end context 'when the destinations are going to be created during the execution' do - let(:condition_groups) { + let(:condition_groups) do [ create_condition_group_to_select_asset_type('Tube') ] - } - let(:action_for_creating_rack) { + end + let(:action_for_creating_rack) do create_action_for_creating_asset('Rack') - } - let(:actions) { + end + let(:actions) do [ create_action_for_connecting_condition_groups('transfer', condition_groups.first, action_for_creating_rack.subject_condition_group), action_for_creating_rack ] - } + end let(:origins) { create_assets(5, 'Tube') } let(:targets) { [] } diff --git a/spec/models/step_type_spec.rb b/spec/models/step_type_spec.rb index 4dd69b3f..f2792528 100644 --- a/spec/models/step_type_spec.rb +++ b/spec/models/step_type_spec.rb @@ -116,12 +116,12 @@ def assert_equal(a, b) describe "with special configuration" do describe "related with cardinality" do setup do - @assets = Array.new(5) { |_i| + @assets = Array.new(5) do |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') ] } - } + end end it 'is compatible with any number of assets with no cardinality check' do @@ -150,12 +150,12 @@ def assert_equal(a, b) describe 'matching more than one asset' do describe 'for the same condition group' do setup do - @assets = Array.new(5) { |_i| + @assets = Array.new(5) do |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') ] } - } + end end it 'is compatible if all the assets match all the conditions of the rule' do @@ -190,18 +190,18 @@ def assert_equal(a, b) @step_type.condition_groups << @cg2 - @assets = Array.new(5) { |_i| + @assets = Array.new(5) do |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full') ] } - } + end - @racks = Array.new(5) { |_i| + @racks = Array.new(5) do |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack'), ] } - } + end end it 'is compatible with both condition groups when cardinality was set for one of them' do @@ -264,43 +264,43 @@ def assert_equal(a, b) :object_condition_group_id => @cg2.id }) - @racks = Array.new(5) { |_i| + @racks = Array.new(5) do |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack') ] } - } + end - @bad_racks = Array.new(5) { |_i| + @bad_racks = Array.new(5) do |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Rack') ] } - } + end - @assets = Array.new(5) { |i| + @assets = Array.new(5) do |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), FactoryBot.create(:fact, :predicate => 'inRack', :object_asset_id => @racks[i].id) ] } - } + end end it 'is compatible with condition groups that have relations with elements included in the asset group' do assert_equal true, @step_type.compatible_with?([@assets, @racks].flatten) end it 'is not compatible when the relation is not matching the conditions required' do - @bad_racks = Array.new(5) { |_i| + @bad_racks = Array.new(5) do |_i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'BadRack') ] } - } + end - @assets = Array.new(5) { |i| + @assets = Array.new(5) do |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), FactoryBot.create(:fact, :predicate => 'inRack', :object_asset_id => @bad_racks[i].id) ] } - } + end assert_equal false, @step_type.compatible_with?([@assets, @bad_racks].flatten) end it 'is compatible with condition groups that have relations with elements outside the asset group' do @@ -316,13 +316,13 @@ def assert_equal(a, b) }) end it 'is compatible with any literal when met the other conditions' do - @assets = Array.new(5) { |i| + @assets = Array.new(5) do |i| FactoryBot.create :asset, { :facts => [ FactoryBot.create(:fact, :predicate => 'is', :object => 'Tube'), FactoryBot.create(:fact, :predicate => 'is', :object => 'Full'), FactoryBot.create(:fact, :predicate => 'position', :object => i) ] } - } + end assert_equal true, @step_type.compatible_with?([@assets].flatten) end end diff --git a/spec/models/steps/background_tasks/inference_spec.rb b/spec/models/steps/background_tasks/inference_spec.rb index a7740889..a1639384 100644 --- a/spec/models/steps/background_tasks/inference_spec.rb +++ b/spec/models/steps/background_tasks/inference_spec.rb @@ -14,14 +14,14 @@ allow(execution).to receive(:run).and_raise(StandardError) end it 'changes the status to error' do - expect { + expect do inference.run! - }.to change { inference.failed? }.from(false).to(true) + end.to change { inference.failed? }.from(false).to(true) end it 'adds an output value explaining the error' do - expect { + expect do inference.run! - }.to change { inference.output.nil? }.to(false) + end.to change { inference.output.nil? }.to(false) end end context 'when there is no error' do diff --git a/spec/models/steps/stoppable_spec.rb b/spec/models/steps/stoppable_spec.rb index 5660c471..e3b79261 100644 --- a/spec/models/steps/stoppable_spec.rb +++ b/spec/models/steps/stoppable_spec.rb @@ -4,21 +4,21 @@ let(:asset_group) { create(:asset_group) } let(:step_type) { create(:step_type) } - let(:previous_steps) { + let(:previous_steps) do create_list(:step, 2, state: Step::STATE_RUNNING, activity: activity, asset_group: asset_group, step_type: step_type) - } - let(:next_steps) { + end + let(:next_steps) do create_list(:step, 2, state: Step::STATE_RUNNING, activity: activity, asset_group: asset_group, step_type: step_type) - } + end let(:step) { create(:step, state: previous_state, activity: activity, asset_group: asset_group, step_type: step_type) } context 'when a step is stopped' do - let(:do_action) { + let(:do_action) do steps = [previous_steps, step, next_steps].flatten step.stop! steps.each(&:reload) - } + end context 'but the step was already completed before' do let(:previous_state) { Step::STATE_COMPLETE } @@ -58,18 +58,18 @@ end end context 'when a step is continued' do - let(:do_action) { + let(:do_action) do steps = [previous_steps, step, next_steps].flatten step.continue! steps.each(&:reload) - } + end - let(:next_steps_stopped) { + let(:next_steps_stopped) do create_list(:step, 2, state: Step::STATE_STOPPED, activity: activity, asset_group: asset_group, step_type: step_type) - } - let(:next_steps_not_stopped) { + end + let(:next_steps_not_stopped) do create_list(:step, 2, state: Step::STATE_FAILED, activity: activity, asset_group: asset_group, step_type: step_type) - } + end let(:next_steps) { [next_steps_stopped, next_steps_not_stopped].flatten } context 'when the step was stopped before' do diff --git a/spec/models/steps/task_spec.rb b/spec/models/steps/task_spec.rb index a848c7db..24993dc2 100644 --- a/spec/models/steps/task_spec.rb +++ b/spec/models/steps/task_spec.rb @@ -2,13 +2,13 @@ describe Steps::Task do let(:user) { create :user, username: 'test' } - let(:printer_config) { + let(:printer_config) do { "Plate" => "plates", "Tube" => "tubes", "TubeRack" => "plates" } - } + end def build_instance asset_group = build :asset_group build :step, asset_group: asset_group, printer_config: printer_config @@ -21,7 +21,7 @@ def create_instance(step_type, activity, group) # it_behaves_like 'background task' context 'a background task with some changes defined' do - let(:step_type) { + let(:step_type) do create(:step_type, step_action: step_action, condition_groups: [cg], @@ -29,7 +29,7 @@ def create_instance(step_type, activity, group) create(:action, action_type: 'createAsset', predicate: 'a', object: 'Tube', subject_condition_group: cg2) ]) - } + end let(:cg) { create :condition_group, conditions: [create(:condition, predicate: 'a', object: 'Plate')] } let(:cg2) { create :condition_group } let(:group) { create :asset_group, assets: [asset] } @@ -42,20 +42,20 @@ def create_instance(step_type, activity, group) asset.reload step = create_instance(step_type, activity, group) - expect { + expect do step.run! - }.to change { Asset.all.count }.by(1).and change { Fact.count } + end.to change { Asset.all.count }.by(1).and change { Fact.count } end end context 'when the step type does have a step action' do let(:step_action) { 'some_action' } context 'when the step action runs correctly' do let(:valid_changes) { FactChanges.new.tap { |update| update.create_assets(["?p"]) } } - let(:correct_execution) { + let(:correct_execution) do execution = double('step_execution') allow(execution).to receive(:plan).and_return(valid_changes) execution - } + end before do allow(InferenceEngines::Runner::StepExecution).to receive(:new).and_return(correct_execution) end @@ -64,9 +64,9 @@ def create_instance(step_type, activity, group) asset.reload step = create_instance(step_type, activity, group) - expect { + expect do step.run! - }.to change { Asset.all.count }.by(2).and change { Fact.count } + end.to change { Asset.all.count }.by(2).and change { Fact.count } end it 'prints the selected list of assets' do @@ -95,10 +95,10 @@ def create_instance(step_type, activity, group) end end context 'when the step works fine but the step action fails' do - let(:failable_execution) { + let(:failable_execution) do execution = double('step_execution') execution - } + end before do allow(failable_execution).to receive(:plan).and_raise('not good!!') @@ -109,9 +109,9 @@ def create_instance(step_type, activity, group) asset.reload # We don't change asset count because assets are never destroyed, only facts step = create_instance(step_type, activity, group) - expect { + expect do step.run! - }.not_to change { Fact.count } + end.not_to change { Fact.count } end end end diff --git a/spec/script/runners/load_metadata_spec.rb b/spec/script/runners/load_metadata_spec.rb index 674fa4ae..baf82371 100644 --- a/spec/script/runners/load_metadata_spec.rb +++ b/spec/script/runners/load_metadata_spec.rb @@ -9,25 +9,25 @@ let(:file_asset) { create :asset, uploaded_file: file } let(:positions) { TokenUtil.generate_positions(('A'..'H').to_a, ('1'..'12').to_a) } - let(:wells) { + let(:wells) do Array.new(96) do |i| asset = FactoryBot.create(:asset) asset.facts << create(:fact, predicate: 'location', object: positions[i]) asset.facts << create(:fact, predicate: 'a', object: 'Well') asset end - } - let(:rack) { + end + let(:rack) do create(:asset, barcode: 'DN1001001', facts: [ create(:fact, predicate: 'a', object: 'TubeRack'), wells.map { |w| create(:fact, predicate: 'contains', object_asset_id: w.id) } ].flatten) - } - let(:instance) { + end + let(:instance) do LoadMetadata.new(asset_group: group) - } + end context 'when it receives a metadata file' do let(:group) { create(:asset_group, assets: [rack, file_asset].flatten) } let(:added_triples) { instance.process.to_h[:add_facts] } diff --git a/spec/script/runners/transfer_plate_to_plate_spec.rb b/spec/script/runners/transfer_plate_to_plate_spec.rb index 82fbd271..794637ae 100644 --- a/spec/script/runners/transfer_plate_to_plate_spec.rb +++ b/spec/script/runners/transfer_plate_to_plate_spec.rb @@ -19,9 +19,9 @@ def create_rack ].flatten) end - let(:instance) { + let(:instance) do TransferPlateToPlate.new(asset_group: group) - } + end context 'when we have 2 plates defined in the group' do let(:group) { create(:asset_group, assets: [source_rack, destination_rack]) } diff --git a/spec/script/runners/transfer_samples_spec.rb b/spec/script/runners/transfer_samples_spec.rb index dc99172f..78516062 100644 --- a/spec/script/runners/transfer_samples_spec.rb +++ b/spec/script/runners/transfer_samples_spec.rb @@ -3,21 +3,21 @@ RSpec.describe 'TransferSamples' do let(:sample) { create(:asset, facts: [create(:fact, predicate: 'sample_name', object: 'sample1')]) } - let(:sources) { - Array.new(5) { + let(:sources) do + Array.new(5) do create(:asset, facts: [ create(:fact, predicate: 'a', object: 'Tube'), create(:fact, predicate: 'study_name', object: 'Study 1'), create(:fact, predicate: 'sample_tube', object_asset_id: sample.id) ]) - } - } - let(:destinations) { + end + end + let(:destinations) do Array.new(5) { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } - } - let(:instance) { + end + let(:instance) do TransferSamples.new(asset_group: group) - } + end shared_examples_for 'transfers all facts from source to destination' do it 'transfers all facts from source to destination' do diff --git a/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb b/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb index 626b454e..0b28e718 100644 --- a/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb +++ b/spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb @@ -3,26 +3,26 @@ require Rails.root.to_s + '/script/runners/transfer_tubes_to_tube_rack_by_position' RSpec.describe 'TransferTubesToTubeRackByPosition' do - let(:wells) { + let(:wells) do 5.times.each_with_index.map do |i| create(:asset, facts: [ create(:fact, predicate: 'a', object: 'Well'), create(:fact, predicate: 'location', object: "A0#{i}") ]) end - } - let(:rack) { + end + let(:rack) do create(:asset, facts: [ create(:fact, predicate: 'a', object: 'TubeRack'), wells.map { |w| create(:fact, predicate: 'contains', object_asset_id: w.id) } ].flatten) - } - let(:tubes) { + end + let(:tubes) do Array.new(5) { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } - } - let(:instance) { + end + let(:instance) do TransferTubesToTubeRackByPosition.new(asset_group: group) - } + end context 'when it receives a rack and a set of tubes' do let(:group) { create(:asset_group, assets: [rack, tubes].flatten) } context 'when the tubes do not relate with the rack' do @@ -37,9 +37,9 @@ end end context 'when only some of the tubes are related with the rack' do - let(:unrelated_tubes) { + let(:unrelated_tubes) do Array.new(5) { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } - } + end before do group.assets << unrelated_tubes end @@ -170,9 +170,9 @@ end end context 'when there are no more space left in the rack' do - let(:tubes) { + let(:tubes) do Array.new(7) { create(:asset, facts: [create(:fact, predicate: 'a', object: 'Tube')]) } - } + end it 'produces an error' do set_errors = instance.process.to_h[:set_errors] expect(set_errors.count).not_to eq(0) From 0086a118736435f34881f693780ebd9695ce0a05 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 26 Apr 2022 15:06:36 +0100 Subject: [PATCH 185/303] Rubocop: Style/ColonMethodCall --- .rubocop_todo.yml | 13 ------------- app/models/assets/import.rb | 10 +++++----- app/models/step_type.rb | 2 +- db/seeds.rb | 4 ++-- lib/inference_engines/cwm/step_execution.rb | 4 ++-- lib/support_n3.rb | 10 +++++----- .../runners/put_tubes_into_rack_by_column_order.rb | 2 +- spec/inferences_helper.rb | 4 ++-- spec/integration/inference_spec.rb | 2 +- spec/models/assets/export_spec.rb | 10 +++++----- 10 files changed, 24 insertions(+), 37 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index d0510ada..0f8a7b8e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -559,19 +559,6 @@ Style/ClassVars: Exclude: - 'app/models/action.rb' -# Offense count: 24 -# This cop supports safe auto-correction (--auto-correct). -Style/ColonMethodCall: - Exclude: - - 'app/models/assets/import.rb' - - 'app/models/step_type.rb' - - 'db/seeds.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'lib/support_n3.rb' - - 'script/runners/put_tubes_into_rack_by_column_order.rb' - - 'spec/inferences_helper.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/models/assets/export_spec.rb' # Offense count: 6 # This cop supports safe auto-correction (--auto-correct). diff --git a/app/models/assets/import.rb b/app/models/assets/import.rb index 0cb9025d..df976031 100644 --- a/app/models/assets/import.rb +++ b/app/models/assets/import.rb @@ -66,11 +66,11 @@ def json_for_remote(remote_asset) end def update_digest_with_remote(remote_asset) - update_attributes(remote_digest: Digest::MD5::hexdigest(json_for_remote(remote_asset))) + update_attributes(remote_digest: Digest::MD5.hexdigest(json_for_remote(remote_asset))) end def changed_remote?(remote_asset) - Digest::MD5::hexdigest(json_for_remote(remote_asset)) != remote_digest + Digest::MD5.hexdigest(json_for_remote(remote_asset)) != remote_digest end def assets_to_refresh @@ -85,7 +85,7 @@ def is_refreshing_right_now? def refresh(fact_changes = nil) return self unless remote_asset? - remote_asset = SequencescapeClient::find_by_uuid(uuid) + remote_asset = SequencescapeClient.find_by_uuid(uuid) raise RefreshSourceNotFoundAnymore unless remote_asset refresh_from_remote(fact_changes: fact_changes, remote_asset: remote_asset) @@ -104,7 +104,7 @@ def refresh!(fact_changes = nil) return self unless remote_asset? @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Refresh!!'), state: 'running') - remote_asset = SequencescapeClient::find_by_uuid(uuid) + remote_asset = SequencescapeClient.find_by_uuid(uuid) raise RefreshSourceNotFoundAnymore unless remote_asset _process_refresh(remote_asset, fact_changes) @@ -149,7 +149,7 @@ def _process_refresh(remote_asset, fact_changes) module ClassMethods def import_barcode(barcode) @import_step = Step.create(step_type: StepType.find_or_create_by(name: 'Import'), state: 'running') - remote_asset = SequencescapeClient::find_by_barcode(barcode) + remote_asset = SequencescapeClient.find_by_barcode(barcode) import_remote_asset(remote_asset, barcode, @import_step) if remote_asset end diff --git a/app/models/step_type.rb b/app/models/step_type.rb index 0c619f74..defaf8f4 100644 --- a/app/models/step_type.rb +++ b/app/models/step_type.rb @@ -99,7 +99,7 @@ def class_for_task_type def create_next_conditions unless n3_definition.nil? - SupportN3::parse_string(n3_definition, {}, self) + SupportN3.parse_string(n3_definition, {}, self) end end diff --git a/db/seeds.rb b/db/seeds.rb index c543fa4d..d347f350 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -10,7 +10,7 @@ require 'support_n3' -SupportN3::parse_file('db/workflows/reracking.n3') +SupportN3.parse_file('db/workflows/reracking.n3') reracking_activity_type = ActivityType.last kit_type = KitType.create(name: 'Re-Racking', activity_type: reracking_activity_type) @@ -18,7 +18,7 @@ instrument = Instrument.create(barcode: '9999', name: 'Re-Racking') instrument.activity_types << reracking_activity_type -SupportN3::parse_file('db/workflows/qiacube.n3') +SupportN3.parse_file('db/workflows/qiacube.n3') activity_type = ActivityType.last diff --git a/lib/inference_engines/cwm/step_execution.rb b/lib/inference_engines/cwm/step_execution.rb index db849acf..32a38b34 100644 --- a/lib/inference_engines/cwm/step_execution.rb +++ b/lib/inference_engines/cwm/step_execution.rb @@ -76,7 +76,7 @@ def refresh end def export - step_actions = SupportN3::load_step_actions(step.output) + step_actions = SupportN3.load_step_actions(step.output) ['create_asset', 'remove_facts', 'add_facts', 'unselect_asset', 'select_asset'].each do |action_type| quads = step_actions[action_type.camelize(:lower).to_sym] @@ -87,7 +87,7 @@ def export end def fragment(k) - SupportN3::fragment(k) + SupportN3.fragment(k) end def add_facts(graphs) diff --git a/lib/support_n3.rb b/lib/support_n3.rb index 9046a767..1c8f2502 100644 --- a/lib/support_n3.rb +++ b/lib/support_n3.rb @@ -118,15 +118,15 @@ def self.subgraph(node, quads) end def self.create_fact(quad, quads, create_assets = true, created_assets = []) - asset = build_asset(SupportN3::fragment(quad[0]), create_assets, created_assets) + asset = build_asset(SupportN3.fragment(quad[0]), create_assets, created_assets) if is_literal?(quad[2], quads) asset.facts << Fact.create( - :predicate => SupportN3::fragment(quad[1]), - :object => SupportN3::fragment(quad[2]) + :predicate => SupportN3.fragment(quad[1]), + :object => SupportN3.fragment(quad[2]) ) else - related_asset = build_asset(SupportN3::fragment(quad[2]), create_assets, created_assets) - asset.facts << Fact.create(:predicate => SupportN3::fragment(quad[1]), + related_asset = build_asset(SupportN3.fragment(quad[2]), create_assets, created_assets) + asset.facts << Fact.create(:predicate => SupportN3.fragment(quad[1]), :object_asset => related_asset, :literal => false) end asset diff --git a/script/runners/put_tubes_into_rack_by_column_order.rb b/script/runners/put_tubes_into_rack_by_column_order.rb index b2ef96c7..443a9535 100644 --- a/script/runners/put_tubes_into_rack_by_column_order.rb +++ b/script/runners/put_tubes_into_rack_by_column_order.rb @@ -36,7 +36,7 @@ memo.push(asset: tube, location: available_locations[idx]) end updates.add(rack, 'layout', 'Complete') - updates.merge(Actions::Racking::reracking_tubes(rack, layout)) + updates.merge(Actions::Racking.reracking_tubes(rack, layout)) end puts updates.to_json diff --git a/spec/inferences_helper.rb b/spec/inferences_helper.rb index 6384b7f0..26973977 100644 --- a/spec/inferences_helper.rb +++ b/spec/inferences_helper.rb @@ -42,7 +42,7 @@ def assets_are_different(expected_assets, obtained_assets) def build_step(rule, input_facts, options = {}) step_type = FactoryBot.create(:step_type, :n3_definition => rule) - input_assets = SupportN3::parse_facts(input_facts, {}, false) + input_assets = SupportN3.parse_facts(input_facts, {}, false) reload_assets(input_assets) fail if input_assets.nil? @@ -85,7 +85,7 @@ def check_inference(rule, input_facts, output_facts) obtained_n3 = assets_to_n3(asset_group.assets) asset_group.assets.each { |a| a.facts.each(&:destroy) } - expected_output_assets = SupportN3::parse_facts(output_facts, {}, false) + expected_output_assets = SupportN3.parse_facts(output_facts, {}, false) fail if expected_output_assets.nil? reload_assets(expected_output_assets) diff --git a/spec/integration/inference_spec.rb b/spec/integration/inference_spec.rb index e47fa219..79198dfc 100644 --- a/spec/integration/inference_spec.rb +++ b/spec/integration/inference_spec.rb @@ -16,7 +16,7 @@ def cwm_engine? :tube2 :volume """17""" . } - obtained_assets = SupportN3::parse_facts(code) + obtained_assets = SupportN3.parse_facts(code) f1 = [ FactoryBot.create(:fact, { :predicate => 'name', :object => 'a name' }), diff --git a/spec/models/assets/export_spec.rb b/spec/models/assets/export_spec.rb index 101036df..0c76395d 100644 --- a/spec/models/assets/export_spec.rb +++ b/spec/models/assets/export_spec.rb @@ -56,7 +56,7 @@ :rack1 :a :TubeRack ; :contains :tube1, :tube2, :tube3, :tube4 . } - @assets = SupportN3::parse_facts(facts) + @assets = SupportN3.parse_facts(facts) @rack1 = Asset.includes(:facts).find_by(uuid: 'rack1') expect(@rack1.attributes_to_send).to eq([ @@ -152,7 +152,7 @@ :location "D1" ; :sample_tube :s4 . } - @assets = SupportN3::parse_facts(facts) + @assets = SupportN3.parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') expect(@rack2.attributes_to_send).to eq([ { sample_tube_uuid: "s1", location: "A1" }, @@ -184,7 +184,7 @@ :location "D1" ; :sample_tube :s4 . } - @assets = SupportN3::parse_facts(facts) + @assets = SupportN3.parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') expect(@rack2.attributes_to_send).to eq([ { sample_tube_uuid: "s1", location: "A1" }, @@ -215,7 +215,7 @@ :location "B1" ; :sample_tube :s4 . } - @assets = SupportN3::parse_facts(facts) + @assets = SupportN3.parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') expect { @rack2.attributes_to_send }.to raise_exception Assets::Export::DuplicateLocations end @@ -242,7 +242,7 @@ :location "D1" ; :sample_tube :s4 . } - @assets = SupportN3::parse_facts(facts) + @assets = SupportN3.parse_facts(facts) @rack2 = Asset.find_by(uuid: 'rack2') expect(@rack2.attributes_to_send).to eq([ { sample_tube_uuid: "s1", location: "A1" }, From a7669fc7e0fe11f2df1f41ae2d9f3a32e39158b9 Mon Sep 17 00:00:00 2001 From: James Glover Date: Tue, 26 Apr 2022 15:23:51 +0100 Subject: [PATCH 186/303] Add prettier --- .babelrc | 10 +- .github/workflows/lint.yml | 18 +- .github/workflows/test.yml | 63 +- .prettierignore | 53 ++ .prettierrc.json | 5 + .rubocop.yml | 12 +- .rubocop_todo.yml | 488 ++------------- Gemfile | 1 + README.md | 34 +- .../javascripts/add_fact_to_searchbox.js | 42 +- app/assets/javascripts/application.js | 2 +- app/assets/javascripts/asset_facts.js | 251 ++++---- app/assets/javascripts/barcode_reader.js | 66 +- app/assets/javascripts/button_switch.js | 68 +- app/assets/javascripts/component_builder.js | 104 ++-- app/assets/javascripts/condition_group.js | 288 +++++---- app/assets/javascripts/condition_groups.js | 436 +++++++------ app/assets/javascripts/delete_icon.js | 30 +- app/assets/javascripts/display_error.js | 31 +- app/assets/javascripts/editable_text.js | 157 ++--- .../javascripts/element_class_populator.js | 33 +- app/assets/javascripts/fact_reader.js | 104 ++-- app/assets/javascripts/fact_searcher.js | 467 +++++++------- .../javascripts/fact_searcher_lightweight.js | 187 +++--- app/assets/javascripts/finish_step_button.js | 23 +- app/assets/javascripts/loading_icon.js | 98 +-- app/assets/javascripts/rack_well_display.js | 98 +-- .../javascripts/source_to_destination.js | 235 +++---- app/assets/javascripts/step_button.js | 61 +- app/assets/javascripts/step_cancellable.js | 72 +-- app/assets/javascripts/transfer_manager.js | 19 +- app/assets/javascripts/tube_into_rack.js | 283 ++++----- app/assets/javascripts/user_status.js | 372 +++++------ app/assets/stylesheets/activities.scss | 69 ++- app/assets/stylesheets/application.scss | 552 +++++++++++------ app/assets/stylesheets/scaffolds.scss | 8 +- app/assets/stylesheets/step_types.scss | 24 +- app/assets/stylesheets/steps.scss | 5 +- app/channels/activity_channel.rb | 14 +- app/channels/application_cable/connection.rb | 2 +- app/controllers/activities_controller.rb | 2 +- app/controllers/activity_types_controller.rb | 7 +- app/controllers/application_controller.rb | 6 +- app/controllers/asset_groups_controller.rb | 19 +- app/controllers/assets_controller.rb | 40 +- app/controllers/changes_controller.rb | 16 +- app/controllers/history_controller.rb | 2 +- app/controllers/instruments_controller.rb | 10 +- app/controllers/kit_types_controller.rb | 10 +- app/controllers/kits_controller.rb | 10 +- app/controllers/printers_controller.rb | 8 +- app/controllers/reracking_controller.rb | 2 +- .../samples_not_started_controller.rb | 5 +- app/controllers/samples_started_controller.rb | 15 +- app/controllers/samples_status_controller.rb | 17 +- app/controllers/step_types_controller.rb | 13 +- app/controllers/steps_controller.rb | 11 +- app/controllers/uploaded_files_controller.rb | 4 +- app/controllers/user_sessions_controller.rb | 2 +- app/controllers/users_controller.rb | 10 +- app/helpers/activities_helper.rb | 115 ++-- app/helpers/application_helper.rb | 97 +-- app/helpers/assets_helper.rb | 25 +- app/helpers/step_types_helper.rb | 71 ++- app/helpers/steps_helper.rb | 2 +- app/javascript/components/activity.jsx | 232 +++---- .../activity_components/activity_control.jsx | 12 +- .../activity_description.jsx | 74 ++- .../activity_components/alert_display.jsx | 30 +- .../printers_selection.jsx | 27 +- .../printers_selection_hidden.jsx | 26 +- .../asset_components/asset_display.jsx | 7 +- .../components/asset_components/fact.jsx | 46 +- .../components/asset_components/facts.jsx | 58 +- .../asset_components/facts_editor.jsx | 65 +- .../asset_components/facts_image.jsx | 19 +- .../components/asset_components/facts_svg.jsx | 67 +- .../asset_group_components/asset_group.jsx | 70 ++- .../asset_group_editor.jsx | 94 +-- .../asset_groups_editor.jsx | 53 +- .../asset_group_components/barcode_reader.jsx | 31 +- .../components/lib/button_with_loading.jsx | 25 +- .../components/lib/search_control.jsx | 80 ++- app/javascript/components/lib/togglable.jsx | 12 +- .../components/lib/uploader_utils.jsx | 56 +- .../components/step_components/operations.jsx | 22 +- .../step_components/step_control.jsx | 55 +- .../step_components/step_states.jsx | 2 +- .../components/step_components/steps.jsx | 16 +- .../step_components/steps_failed.jsx | 54 +- .../step_components/steps_finished.jsx | 126 ++-- .../step_components/steps_running.jsx | 64 +- .../step_type_components/step_type_button.jsx | 47 +- .../step_type_buttons.jsx | 44 +- .../step_type_template_button.jsx | 31 +- .../step_type_template_control.jsx | 81 ++- .../step_type_templates/apply_file.jsx | 6 +- .../step_type_templates/pairing_sources.jsx | 40 +- .../step_type_templates/upload_file.jsx | 8 +- .../step_type_templates_buttons.jsx | 26 +- .../step_type_templates_controls.jsx | 53 +- .../step_type_components/step_types.jsx | 87 +-- .../step_types_active.jsx | 26 +- .../step_types_control.jsx | 31 +- app/javascript/packs/activity_pack.js | 15 +- app/javascript/packs/application.js | 4 +- app/javascript/packs/server_rendering.js | 4 +- app/messages/messages/activity.rb | 11 +- app/models/action.rb | 67 +- app/models/activities/background_tasks.rb | 10 +- app/models/activities/json_attributes.rb | 4 +- app/models/activities/state.rb | 8 +- app/models/activities/steps_management.rb | 10 +- app/models/activities/tasks.rb | 24 +- app/models/activities/websocket_events.rb | 25 +- app/models/activity.rb | 6 +- app/models/activity_type.rb | 14 +- app/models/asset.rb | 173 +++--- app/models/asset_group.rb | 55 +- app/models/assets/export.rb | 70 ++- app/models/assets/facts_management.rb | 22 +- app/models/assets/import.rb | 114 ++-- app/models/assets/traction_fields.rb | 21 +- app/models/concerns/deprecatable.rb | 10 +- app/models/concerns/uuidable.rb | 4 +- app/models/condition.rb | 43 +- app/models/condition_group.rb | 12 +- app/models/fact.rb | 18 +- app/models/instrument.rb | 7 +- app/models/kit.rb | 2 +- app/models/label_template.rb | 5 +- app/models/operation.rb | 14 +- app/models/printables/group.rb | 6 +- app/models/printables/instance.rb | 8 +- app/models/printables/print_asset.rb | 13 +- app/models/printer.rb | 11 +- app/models/step.rb | 27 +- app/models/step_type.rb | 84 ++- .../steps/background_tasks/inference.rb | 13 +- app/models/steps/background_tasks/runner.rb | 13 +- app/models/steps/cancellable.rb | 26 +- app/models/steps/deprecatable.rb | 8 +- app/models/steps/job.rb | 10 +- app/models/steps/queueable_job.rb | 6 +- app/models/steps/retryable.rb | 8 +- app/models/steps/state.rb | 63 +- app/models/steps/task.rb | 21 +- app/models/uploaded_file.rb | 15 +- app/models/user.rb | 31 +- app/resources/api/v1/asset_resource.rb | 14 +- .../move_barcodes_from_tube_rack_to_plate.rb | 6 +- app/views/printers/show.json.jbuilder | 2 +- app/views/users/show.json.jbuilder | 2 +- config/database.yml | 1 - config/environments/development.rb | 7 +- config/environments/production.rb | 4 +- config/environments/test.rb | 6 +- config/initializers/inflections.rb | 4 +- config/initializers/mime_types.rb | 2 +- config/initializers/wrap_parameters.rb | 4 +- config/locales/en.yml | 2 +- config/puma.rb | 2 +- config/routes.rb | 9 +- config/spring.rb | 7 +- config/storage.yml | 1 - db/migrate/20160623160518_create_users.rb | 4 +- db/migrate/20160626202605_create_steps.rb | 4 +- db/migrate/20160626224625_create_facts.rb | 14 +- .../20160626224627_create_condition_groups.rb | 4 +- .../20160626224628_create_conditions.rb | 8 +- db/migrate/20160629144842_create_actions.rb | 8 +- db/migrate/20160705084036_create_uploads.rb | 2 +- .../20160903164344_create_delayed_jobs.rb | 16 +- .../20160923094944_add_sessions_table.rb | 4 +- ...028122148_add_action_type_to_operations.rb | 4 +- ...61028134840_add_connect_by_to_step_type.rb | 4 +- .../20170122173205_add_state_to_step.rb | 4 +- ...8170039_add_namespace_to_fact_predicate.rb | 4 +- ...1416_migrate_operations_to_object_asset.rb | 10 +- ...170302135104_add_index_to_asset_barcode.rb | 2 +- ...710095951_change_extr_attr_to_long_text.rb | 2 +- .../20180428131814_create_uploaded_files.rb | 2 +- ...90526185059_change_handler_to_long_text.rb | 2 +- db/migrate/20190717130805_change_sti_type.rb | 2 +- ...0709123033_create_heron_activities_view.rb | 3 +- ...3815_move_script_based_actions_to_class.rb | 9 +- db/schema.rb | 584 +++++++++--------- db/seeds.rb | 83 ++- db/views_schema.rb | 5 +- lefthook.yml | 12 +- lib/actions/plate_transfer.rb | 74 ++- lib/actions/racking.rb | 133 ++-- lib/actions/tube_transfer.rb | 30 +- lib/changes_support/disjoint_list.rb | 59 +- lib/changes_support/transaction_scope.rb | 24 +- lib/deployed_version.rb | 22 +- lib/fact_changes.rb | 259 ++++---- lib/inference_engines/cwm/step_execution.rb | 28 +- .../default/step_execution.rb | 34 +- .../runner/step_execution.rb | 40 +- lib/label_template_setup.rb | 12 +- lib/label_templates/ss_plate.rb | 63 +- lib/label_templates/ss_tube.rb | 112 +++- lib/label_types/plate.rb | 25 +- lib/label_types/tube.rb | 25 +- .../csv_layout/barcode_creatable_parser.rb | 16 +- lib/parsers/csv_layout/barcode_parser.rb | 2 +- lib/parsers/csv_layout/csv_parser.rb | 27 +- lib/parsers/csv_layout/line_parser.rb | 19 +- lib/parsers/csv_metadata/csv_parser.rb | 4 +- lib/parsers/csv_metadata/data_parser.rb | 17 +- lib/parsers/csv_metadata/line_parser.rb | 40 +- lib/psd_formatter.rb | 6 +- lib/sequencescape_client.rb | 17 +- lib/sequencescape_client_v2.rb | 13 +- lib/support_n3.rb | 294 ++++----- lib/tasks/message_addition.rake | 33 +- lib/tasks/setup_templates.rake | 6 +- lib/tasks/views_schema.rake | 18 +- lib/token_util.rb | 2 +- lib/views_schema.rb | 36 +- package.json | 6 +- processing_a_step.md | 2 +- public/404.html | 116 ++-- public/422.html | 116 ++-- public/500.html | 114 ++-- script/aliquot_type_inference.rb | 20 +- script/claim_uuids.rb | 17 +- script/container_inferences.rb | 37 +- script/fix_duplicated_tubes.rb | 19 +- script/plate_to_code39.rb | 5 +- script/purpose_name_inference.rb | 35 +- script/recreate_steptypes.rb | 72 ++- script/runners/create_12_tubes.rb | 4 +- script/runners/create_file.rb | 19 +- script/runners/create_layout.rb | 23 +- script/runners/create_stamped_plate.rb | 14 +- script/runners/full_rack_generator.rb | 24 +- script/runners/load_metadata.rb | 9 +- script/runners/print_barcodes.rb | 3 +- .../put_tubes_into_rack_by_column_order.rb | 19 +- script/runners/rack_layout.rb | 8 +- script/runners/rack_layout_any_barcode.rb | 2 +- script/runners/transfer_plate_to_plate.rb | 25 +- ...plate_to_plate_and_update_sequencescape.rb | 2 +- script/runners/transfer_samples.rb | 34 +- ...transfer_tubes_to_tube_rack_by_position.rb | 56 +- script/runners/update_sequencescape.rb | 11 +- script/study_name_inference.rb | 33 +- .../tasks/runners/aliquot_type_inference.rb | 19 +- script/test2.rb | 13 +- spec/concerns/deprecatable_spec.rb | 4 +- .../controllers/activities_controller_spec.rb | 24 +- .../activity_types_controller_spec.rb | 28 +- .../asset_groups_controller_spec.rb | 92 +-- spec/controllers/assets_controller_spec.rb | 2 +- spec/controllers/changes_controller_spec.rb | 7 +- .../instruments_controller_spec.rb | 26 +- spec/controllers/kit_types_controller_spec.rb | 28 +- spec/controllers/kits_controller_spec.rb | 26 +- spec/controllers/printers_controller_spec.rb | 28 +- .../controllers/step_types_controller_spec.rb | 36 +- spec/controllers/steps_controller_spec.rb | 49 +- .../user_sessions_controller_spec.rb | 10 +- spec/helpers/application_helper_spec.rb | 16 +- spec/inferences_helper.rb | 39 +- spec/integration/inference_spec.rb | 37 +- spec/integration/inferences_data.rb | 202 +++--- spec/lib/actions/plate_transfer_spec.rb | 8 +- spec/lib/actions/racking_spec.rb | 88 +-- .../lib/changes_support/disjoint_list_spec.rb | 120 ++-- .../changes_support/transaction_scope_spec.rb | 24 +- spec/lib/fact_changes_spec.rb | 245 ++++---- .../barcode_creatable_parser_spec.rb | 52 +- .../parsers/csv_layout/barcode_parser_spec.rb | 35 +- .../lib/parsers/csv_layout/csv_parser_spec.rb | 17 +- .../parsers/csv_layout/line_parser_spec.rb | 63 +- .../parsers/csv_layout/line_reader_spec.rb | 2 +- .../csv_layout/location_parser_spec.rb | 18 +- .../parsers/csv_metadata/csv_parser_spec.rb | 29 +- .../validators/headers_validator_spec.rb | 4 +- spec/lib/support_n3_spec.rb | 518 ++++++++-------- spec/lib/token_util_spec.rb | 56 +- spec/messages/activity_spec.rb | 103 ++- spec/models/action_spec.rb | 55 +- .../activities/background_tasks_spec.rb | 7 +- .../activities/steps_management_spec.rb | 50 +- spec/models/activity_spec.rb | 4 +- spec/models/activity_type_spec.rb | 2 +- spec/models/asset_group_spec.rb | 16 +- spec/models/asset_spec.rb | 29 +- spec/models/assets/export_spec.rb | 94 +-- spec/models/assets/import_spec.rb | 192 ++++-- spec/models/condition_spec.rb | 85 +-- spec/models/fact_spec.rb | 4 +- spec/models/step_execution_spec.rb | 89 +-- spec/models/step_spec.rb | 582 ++++++++--------- spec/models/step_type_spec.rb | 251 ++++---- .../steps/background_tasks/inference_spec.rb | 39 +- spec/models/steps/cancellable_spec.rb | 17 +- spec/models/steps/deprecatable_spec.rb | 13 +- spec/models/steps/job_spec.rb | 20 +- spec/models/steps/queueable_job_spec.rb | 68 +- spec/models/steps/state_spec.rb | 28 +- spec/models/steps/stoppable_spec.rb | 52 +- spec/models/steps/task_spec.rb | 54 +- spec/rails_helper.rb | 2 +- spec/remote_assets_helper.rb | 106 ++-- spec/requests/api/v1/assets_spec.rb | 58 +- spec/script/runners/load_metadata_spec.rb | 20 +- .../runners/transfer_plate_to_plate_spec.rb | 79 +-- spec/script/runners/transfer_samples_spec.rb | 68 +- ...fer_tubes_to_tube_rack_by_position_spec.rb | 76 +-- spec/shared_examples/background_step.rb | 6 +- spec/support/api/v1/schemas/jsonapi.json | 52 +- spec/views/heron_activities_view_spec.rb | 91 ++- test/factories/actions.rb | 4 +- test/factories/activity_type_step_types.rb | 4 +- test/factories/activity_types.rb | 4 +- test/factories/asset_groups.rb | 4 +- test/factories/assets.rb | 8 +- test/factories/condition_groups.rb | 4 +- test/factories/conditions.rb | 4 +- test/factories/kit_types.rb | 4 +- test/factories/label_templates.rb | 4 +- test/factories/operations.rb | 4 +- test/factories/printers.rb | 4 +- test/factories/step_executions.rb | 4 +- test/factories/step_types.rb | 4 +- test/factories/steps.rb | 2 +- test/factories/uploaded_file.rb | 4 +- test/factories/user_sessions.rb | 4 +- test/factories/users.rb | 8 +- test/javascript/components/activity.test.js | 28 +- .../asset_group.test.js | 17 +- .../asset_group_editor.test.js | 27 +- test/javascript/test_helpers/factories.js | 51 +- test/javascript/test_helpers/test_init.js | 24 +- yarn.lock | 12 + 339 files changed, 8308 insertions(+), 7948 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc.json diff --git a/.babelrc b/.babelrc index 3dcb43e0..295d8128 100644 --- a/.babelrc +++ b/.babelrc @@ -1,10 +1,4 @@ { - "presets": [ - "@babel/preset-env", - "@babel/preset-react" - ], - "plugins": [ - "@babel/plugin-syntax-dynamic-import", - "@babel/plugin-proposal-object-rest-spread", - ] + "presets": ["@babel/preset-env", "@babel/preset-react"], + "plugins": ["@babel/plugin-syntax-dynamic-import", "@babel/plugin-proposal-object-rest-spread"] } diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 256efef0..caa439b4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,14 +9,14 @@ on: jobs: ruby: - runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true # Runs bundle install and caches gems. See the ruby_test.yml - # example if you need more control over bundler. - - name: Run Rubocop - run: bundle exec rubocop --extra-details --display-style-guide --parallel + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: + true # Runs bundle install and caches gems. See the ruby_test.yml + # example if you need more control over bundler. + - name: Run Rubocop + run: bundle exec rubocop --extra-details --display-style-guide --parallel diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 60541883..813e5e40 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,7 +9,6 @@ on: jobs: ruby: - runs-on: ubuntu-latest env: @@ -20,46 +19,46 @@ jobs: # Use the Mysql docker image https://hub.docker.com/_/mysql image: mysql:5.7 ports: - - 3306 # Default port mappings + - 3306 # Default port mappings options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 env: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - MYSQL_ROOT_PASSWORD: '' - MYSQL_DATABASE: samples_extraction_test + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_ROOT_PASSWORD: '' + MYSQL_DATABASE: samples_extraction_test steps: - - uses: actions/checkout@v2 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true # Runs bundle install and caches gems. See the ruby_test.yml - # example if you need more control over bundler. - - name: Set up environment - env: - DBPORT: ${{ job.services.mysql.ports[3306] }} - run: bin/setup + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: + true # Runs bundle install and caches gems. See the ruby_test.yml + # example if you need more control over bundler. + - name: Set up environment + env: + DBPORT: ${{ job.services.mysql.ports[3306] }} + run: bin/setup - - name: Run tests - env: - DBPORT: ${{ job.services.mysql.ports[3306] }} - run: bundle exec rake + - name: Run tests + env: + DBPORT: ${{ job.services.mysql.ports[3306] }} + run: bundle exec rake yarn: - runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Export node version - id: node_version - run: echo ::set-output name=NODE_VERSION::$(cat .nvmrc) - - name: Setup node - uses: actions/setup-node@v2 - with: - node-version: ${{ steps.node_version.outputs.NODE_VERSION }} + - uses: actions/checkout@v2 + - name: Export node version + id: node_version + run: echo ::set-output name=NODE_VERSION::$(cat .nvmrc) + - name: Setup node + uses: actions/setup-node@v2 + with: + node-version: ${{ steps.node_version.outputs.NODE_VERSION }} - - name: Install - run: yarn install + - name: Install + run: yarn install - - name: Run yarn test - run: yarn test + - name: Run yarn test + run: yarn test diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..7bacad99 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,53 @@ +*.rbc +.DS_Store +*~ +capybara-*.html +.rspec +/log +/tmp +/db/*.sqlite3 +/db/*.sqlite3-journal +/public/system +/public/assets +/coverage/ +/spec/tmp +**.orig +rerun.txt +pickle-email-*.html + +# TODO Comment out these rules if you are OK with secrets being uploaded to the repo +config/initializers/secret_token.rb +config/secrets.yml + +# dotenv +# TODO Comment out this rule if environment variables can be committed +.env + +## Environment normalization: +/.bundle +/vendor/bundle + +# these should all be checked in to normalize the environment: +# Gemfile.lock, .ruby-version, .ruby-gemset + +# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: +.rvmrc + +# if using bower-rails ignore default bower_components path bower.json files +/vendor/assets/bower_components +*.bowerrc +bower.json + +# Ignore pow environment settings +.powenv + +# Ignore Byebug command history file. +.byebug_history +/public/packs +/public/packs-test +/node_modules +yarn-debug.log* +.yarn-integrity + +# Ignore Rediscache +dump.rdb diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..cbe842ac --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "printWidth": 120, + "semi": false, + "singleQuote": true +} diff --git a/.rubocop.yml b/.rubocop.yml index b87fb717..d19314a8 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,4 +1,6 @@ -inherit_from: .rubocop_todo.yml +inherit_from: + - .rubocop_todo.yml + - node_modules/@prettier/plugin-ruby/rubocop.yml require: - rubocop-performance @@ -48,3 +50,11 @@ Metrics/BlockLength: - class_eval - has_metadata - resources + +# Rubocop is choking on this file, so we're excluding it for now. +Rails/NegateInclude: + inherit_mode: + merge: + - Exclude + Exclude: + - 'lib/changes_support/disjoint_list.rb' diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 0f8a7b8e..c5e1895f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --exclude-limit 1000` -# on 2022-03-31 12:36:56 UTC using RuboCop version 1.26.0. +# on 2022-04-26 14:16:25 UTC using RuboCop version 1.26.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -29,6 +29,12 @@ Lint/DuplicateMethods: - 'lib/parsers/csv_layout/barcode_parser.rb' - 'lib/support_n3.rb' +# Offense count: 1 +# Configuration parameters: MaximumRangeSize. +Lint/MissingCopEnableDirective: + Exclude: + - 'lib/deployed_version.rb' + # Offense count: 4 # This cop supports unsafe auto-correction (--auto-correct-all). Lint/NonDeterministicRequireOrder: @@ -36,7 +42,13 @@ Lint/NonDeterministicRequireOrder: - 'lib/tasks/setup_templates.rake' - 'spec/rails_helper.rb' -# Offense count: 9 +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +Lint/RedundantCopDisableDirective: + Exclude: + - 'lib/deployed_version.rb' + +# Offense count: 7 Lint/ShadowingOuterLocalVariable: Exclude: - 'app/models/printables/group.rb' @@ -92,16 +104,16 @@ Lint/Void: - 'lib/inference_engines/default/step_execution.rb' - 'spec/models/assets/export_spec.rb' -# Offense count: 80 +# Offense count: 78 # Configuration parameters: IgnoredMethods, CountRepeatedAttributes. Metrics/AbcSize: Max: 79 -# Offense count: 11 +# Offense count: 13 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. # IgnoredMethods: refine Metrics/BlockLength: - Max: 71 + Max: 68 # Offense count: 7 # Configuration parameters: CountBlocks. @@ -111,24 +123,24 @@ Metrics/BlockNesting: # Offense count: 11 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 470 + Max: 489 -# Offense count: 36 +# Offense count: 35 # Configuration parameters: IgnoredMethods. Metrics/CyclomaticComplexity: Max: 26 -# Offense count: 106 +# Offense count: 108 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. Metrics/MethodLength: - Max: 334 + Max: 363 -# Offense count: 6 +# Offense count: 8 # Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: - Max: 202 + Max: 206 -# Offense count: 30 +# Offense count: 31 # Configuration parameters: IgnoredMethods. Metrics/PerceivedComplexity: Max: 26 @@ -164,7 +176,7 @@ Naming/MethodParameterName: - 'spec/models/step_type_spec.rb' - 'spec/models/steps/queueable_job_spec.rb' -# Offense count: 22 +# Offense count: 21 # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros. # NamePrefix: is_, has_, have_ # ForbiddenPrefixes: is_, has_, have_ @@ -360,7 +372,6 @@ Rails/LexicallyScopedActionFilter: # This cop supports unsafe auto-correction (--auto-correct-all). Rails/NegateInclude: Exclude: - - 'lib/changes_support/disjoint_list.rb' - 'lib/support_n3.rb' # Offense count: 8 @@ -381,19 +392,13 @@ Rails/OutputSafety: - 'app/helpers/application_helper.rb' - 'app/helpers/steps_helper.rb' -# Offense count: 1 -# This cop supports safe auto-correction (--auto-correct). -Rails/Pluck: - Exclude: - - 'lib/actions/racking.rb' - # Offense count: 1 # This cop supports safe auto-correction (--auto-correct). Rails/Presence: Exclude: - 'app/models/asset.rb' -# Offense count: 6 +# Offense count: 5 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: NotNilAndNotEmpty, NotBlank, UnlessBlank. Rails/Present: @@ -559,7 +564,6 @@ Style/ClassVars: Exclude: - 'app/models/action.rb' - # Offense count: 6 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions. @@ -573,11 +577,10 @@ Style/ConditionalAssignment: - 'lib/inference_engines/runner/step_execution.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' -# Offense count: 191 +# Offense count: 190 # Configuration parameters: AllowedConstants. Style/Documentation: Exclude: - - 'spec/**/*' - 'app/channels/activity_channel.rb' - 'app/channels/application_cable/connection.rb' - 'app/controllers/activities_controller.rb' @@ -620,7 +623,6 @@ Style/Documentation: - 'app/models/assets/import.rb' - 'app/models/assets/traction_fields.rb' - 'app/models/concerns/deprecatable.rb' - - 'app/models/concerns/uuidable.rb' - 'app/models/condition.rb' - 'app/models/condition_group.rb' - 'app/models/instrument.rb' @@ -789,35 +791,6 @@ Style/EachWithObject: - 'script/fix_duplicated_tubes.rb' - 'spec/lib/changes_support/disjoint_list_spec.rb' -# Offense count: 28 -# This cop supports safe auto-correction (--auto-correct). -Style/EmptyLambdaParameter: - Exclude: - - 'app/models/activities/state.rb' - - 'app/models/asset.rb' - - 'app/models/fact.rb' - - 'app/models/operation.rb' - - 'app/models/printer.rb' - - 'app/models/step_type.rb' - - 'app/models/steps/deprecatable.rb' - - 'app/models/steps/state.rb' - -# Offense count: 14 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: compact, expanded -Style/EmptyMethod: - Exclude: - - 'app/controllers/activity_types_controller.rb' - - 'app/controllers/assets_controller.rb' - - 'app/controllers/instruments_controller.rb' - - 'app/controllers/kit_types_controller.rb' - - 'app/controllers/kits_controller.rb' - - 'app/controllers/printers_controller.rb' - - 'app/controllers/samples_status_controller.rb' - - 'app/controllers/step_types_controller.rb' - - 'app/controllers/users_controller.rb' - # Offense count: 4 # This cop supports safe auto-correction (--auto-correct). Style/EvenOdd: @@ -1207,29 +1180,20 @@ Style/GlobalStdStream: - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/inference_engines/runner/step_execution.rb' -# Offense count: 27 +# Offense count: 17 # Configuration parameters: MinBodyLength. Style/GuardClause: Exclude: - 'app/controllers/activities_controller.rb' - 'app/controllers/application_controller.rb' - - 'app/controllers/asset_groups_controller.rb' - 'app/models/activities/websocket_events.rb' - 'app/models/asset.rb' - - 'app/models/asset_group.rb' - - 'app/models/condition.rb' - - 'app/models/step_type.rb' - 'app/models/steps/deprecatable.rb' - - 'app/models/steps/retryable.rb' - - 'app/models/steps/task.rb' - 'lib/actions/racking.rb' - 'lib/changes_support/transaction_scope.rb' - 'lib/fact_changes.rb' - - 'lib/label_template_setup.rb' - 'lib/parsers/csv_layout/csv_parser.rb' - 'lib/parsers/csv_layout/line_parser.rb' - - 'lib/parsers/csv_metadata/csv_parser.rb' - - 'lib/parsers/csv_metadata/line_parser.rb' - 'lib/step_execution_process.rb' - 'lib/support_n3.rb' @@ -1244,94 +1208,6 @@ Style/HashEachMethods: - 'script/runners/load_metadata.rb' - 'spec/requests/api/v1/assets_spec.rb' -# Offense count: 939 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. -# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys -# SupportedShorthandSyntax: always, never, either -Style/HashSyntax: - Exclude: - - 'app/channels/activity_channel.rb' - - 'app/channels/application_cable/connection.rb' - - 'app/controllers/activity_types_controller.rb' - - 'app/controllers/application_controller.rb' - - 'app/controllers/asset_groups_controller.rb' - - 'app/controllers/assets_controller.rb' - - 'app/controllers/history_controller.rb' - - 'app/controllers/instruments_controller.rb' - - 'app/controllers/reracking_controller.rb' - - 'app/controllers/samples_status_controller.rb' - - 'app/controllers/step_types_controller.rb' - - 'app/controllers/user_sessions_controller.rb' - - 'app/controllers/users_controller.rb' - - 'app/helpers/application_helper.rb' - - 'app/helpers/assets_helper.rb' - - 'app/helpers/step_types_helper.rb' - - 'app/models/action.rb' - - 'app/models/activities/background_tasks.rb' - - 'app/models/activities/state.rb' - - 'app/models/activity.rb' - - 'app/models/activity_type.rb' - - 'app/models/asset.rb' - - 'app/models/asset_group.rb' - - 'app/models/assets/export.rb' - - 'app/models/assets/facts_management.rb' - - 'app/models/assets/import.rb' - - 'app/models/concerns/deprecatable.rb' - - 'app/models/condition.rb' - - 'app/models/condition_group.rb' - - 'app/models/fact.rb' - - 'app/models/kit.rb' - - 'app/models/printer.rb' - - 'app/models/step.rb' - - 'app/models/step_type.rb' - - 'app/models/steps/background_tasks/inference.rb' - - 'app/models/steps/background_tasks/runner.rb' - - 'app/models/steps/state.rb' - - 'app/models/steps/task.rb' - - 'app/models/user.rb' - - 'config/routes.rb' - - 'db/migrate/20160623160518_create_users.rb' - - 'db/migrate/20160626202605_create_steps.rb' - - 'db/migrate/20160626224625_create_facts.rb' - - 'db/migrate/20160626224627_create_condition_groups.rb' - - 'db/migrate/20160626224628_create_conditions.rb' - - 'db/migrate/20160629144842_create_actions.rb' - - 'db/migrate/20160705084036_create_uploads.rb' - - 'db/migrate/20160923094944_add_sessions_table.rb' - - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' - - 'db/migrate/20170302135104_add_index_to_asset_barcode.rb' - - 'db/migrate/20170710095951_change_extr_attr_to_long_text.rb' - - 'db/migrate/20180428131814_create_uploaded_files.rb' - - 'db/migrate/20190526185059_change_handler_to_long_text.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'lib/sequencescape_client.rb' - - 'lib/support_n3.rb' - - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - - 'script/runners/update_sequencescape.rb' - - 'spec/controllers/activities_controller_spec.rb' - - 'spec/controllers/asset_groups_controller_spec.rb' - - 'spec/controllers/kit_types_controller_spec.rb' - - 'spec/controllers/kits_controller_spec.rb' - - 'spec/controllers/printers_controller_spec.rb' - - 'spec/controllers/step_types_controller_spec.rb' - - 'spec/inferences_helper.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/integration/inferences_data.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - - 'spec/lib/support_n3_spec.rb' - - 'spec/models/activities/steps_management_spec.rb' - - 'spec/models/condition_spec.rb' - - 'spec/models/step_execution_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/models/steps/stoppable_spec.rb' - - 'test/factories/assets.rb' - - 'test/factories/steps.rb' - - 'test/factories/users.rb' - # Offense count: 5 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowIfModifier. @@ -1343,52 +1219,27 @@ Style/IfInsideElse: - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/support_n3.rb' -# Offense count: 59 +# Offense count: 24 # This cop supports safe auto-correction (--auto-correct). Style/IfUnlessModifier: Exclude: - - 'app/controllers/asset_groups_controller.rb' - - 'app/controllers/changes_controller.rb' + - 'app/models/action.rb' - 'app/models/asset.rb' - - 'app/models/asset_group.rb' - 'app/models/assets/export.rb' - 'app/models/assets/facts_management.rb' - 'app/models/assets/import.rb' - - 'app/models/assets/traction_fields.rb' - - 'app/models/condition.rb' - - 'app/models/printables/instance.rb' - - 'app/models/step_type.rb' - - 'app/models/steps/job.rb' - - 'app/models/steps/retryable.rb' - - 'app/models/steps/task.rb' - - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' + - 'app/models/steps/deprecatable.rb' - 'lib/actions/plate_transfer.rb' - 'lib/actions/racking.rb' - 'lib/actions/tube_transfer.rb' - - 'lib/changes_support/disjoint_list.rb' - 'lib/fact_changes.rb' - 'lib/inference_engines/cwm/step_execution.rb' - 'lib/inference_engines/default/step_execution.rb' - 'lib/inference_engines/runner/step_execution.rb' - - 'lib/label_template_setup.rb' - - 'lib/parsers/csv_layout/csv_parser.rb' - - 'lib/parsers/csv_metadata/csv_parser.rb' - - 'lib/parsers/csv_metadata/line_parser.rb' - 'lib/support_n3.rb' - - 'script/aliquot_type_inference.rb' - - 'script/claim_uuids.rb' - - 'script/runners/rack_layout.rb' - - 'script/tasks/runners/aliquot_type_inference.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/models/activities/background_tasks_spec.rb' + - 'script/study_name_inference.rb' - 'test/factories/assets.rb' -# Offense count: 2 -# This cop supports safe auto-correction (--auto-correct). -Style/IfUnlessModifierOfIfUnless: - Exclude: - - 'lib/actions/plate_transfer.rb' - # Offense count: 1 # This cop supports unsafe auto-correction (--auto-correct-all). # Configuration parameters: InverseMethods, InverseBlocks. @@ -1396,42 +1247,12 @@ Style/InverseMethods: Exclude: - 'app/helpers/activities_helper.rb' -# Offense count: 8 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: line_count_dependent, lambda, literal -Style/Lambda: - Exclude: - - 'app/models/activity.rb' - - 'app/models/asset.rb' - - 'app/models/assets/facts_management.rb' - - 'app/models/steps/state.rb' - # Offense count: 2 Style/MixinUsage: Exclude: - 'script/runners/put_tubes_into_rack_by_column_order.rb' - 'spec/inferences_helper.rb' -# Offense count: 14 -Style/MultilineBlockChain: - Exclude: - - 'app/models/asset_group.rb' - - 'lib/actions/racking.rb' - - 'lib/fact_changes.rb' - - 'lib/support_n3.rb' - - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/script/runners/transfer_samples_spec.rb' - -# Offense count: 5 -# This cop supports safe auto-correction (--auto-correct). -Style/MultilineIfModifier: - Exclude: - - 'app/helpers/application_helper.rb' - - 'app/helpers/step_types_helper.rb' - - 'app/models/user.rb' - # Offense count: 1 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowMethodComparison. @@ -1461,12 +1282,6 @@ Style/NegatedIf: Exclude: - 'app/models/printables/instance.rb' -# Offense count: 2 -# This cop supports safe auto-correction (--auto-correct). -Style/NestedModifier: - Exclude: - - 'lib/actions/plate_transfer.rb' - # Offense count: 11 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, MinBodyLength. @@ -1483,13 +1298,7 @@ Style/Next: - 'spec/lib/actions/racking_spec.rb' - 'spec/lib/support_n3_spec.rb' -# Offense count: 13 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: Strict, AllowedNumbers. -Style/NumericLiterals: - MinDigits: 14 - -# Offense count: 59 +# Offense count: 57 # This cop supports unsafe auto-correction (--auto-correct-all). # Configuration parameters: EnforcedStyle, IgnoredMethods. # SupportedStyles: predicate, comparison @@ -1532,6 +1341,11 @@ Style/NumericPredicate: - 'script/study_name_inference.rb' - 'script/tasks/runners/aliquot_type_inference.rb' +# Offense count: 1 +Style/OpenStructUse: + Exclude: + - 'lib/deployed_version.rb' + # Offense count: 15 # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? @@ -1557,7 +1371,7 @@ Style/ParallelAssignment: Exclude: - 'spec/models/step_spec.rb' -# Offense count: 79 +# Offense count: 73 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowSafeAssignment, AllowInMultilineConditions. Style/ParenthesesAroundCondition: @@ -1584,34 +1398,14 @@ Style/ParenthesesAroundCondition: - 'script/runners/create_layout.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - 'spec/models/activities/background_tasks_spec.rb' - - 'spec/models/step_spec.rb' - 'test/factories/assets.rb' -# Offense count: 81 +# Offense count: 1 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: PreferredDelimiters. Style/PercentLiteralDelimiters: Exclude: - - 'db/seeds.rb' - - 'script/aliquot_type_inference.rb' - - 'script/purpose_name_inference.rb' - - 'script/recreate_steptypes.rb' - - 'script/study_name_inference.rb' - - 'script/tasks/runners/aliquot_type_inference.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/integration/inferences_data.rb' - 'spec/lib/support_n3_spec.rb' - - 'spec/models/assets/export_spec.rb' - - 'spec/models/steps/cancellable_spec.rb' - -# Offense count: 20 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: lower_case_q, upper_case_q -Style/PercentQLiterals: - Exclude: - - 'spec/integration/inferences_data.rb' - - 'spec/models/steps/cancellable_spec.rb' # Offense count: 8 # This cop supports unsafe auto-correction (--auto-correct-all). @@ -1652,7 +1446,7 @@ Style/RedundantInterpolation: Exclude: - 'app/helpers/application_helper.rb' -# Offense count: 25 +# Offense count: 22 # This cop supports safe auto-correction (--auto-correct). Style/RedundantParentheses: Exclude: @@ -1669,22 +1463,7 @@ Style/RedundantParentheses: - 'lib/support_n3.rb' - 'script/runners/create_stamped_plate.rb' -# Offense count: 81 -# This cop supports safe auto-correction (--auto-correct). -Style/RedundantPercentQ: - Exclude: - - 'db/seeds.rb' - - 'script/aliquot_type_inference.rb' - - 'script/container_inferences.rb' - - 'script/purpose_name_inference.rb' - - 'script/recreate_steptypes.rb' - - 'script/study_name_inference.rb' - - 'script/tasks/runners/aliquot_type_inference.rb' - - 'spec/integration/inferences_data.rb' - - 'spec/models/assets/export_spec.rb' - - 'spec/models/steps/cancellable_spec.rb' - -# Offense count: 37 +# Offense count: 36 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowMultipleReturnValues. Style/RedundantReturn: @@ -1758,13 +1537,6 @@ Style/SelfAssignment: - 'script/runners/create_layout.rb' - 'spec/models/action_spec.rb' -# Offense count: 1 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: AllowAsExpressionSeparator. -Style/Semicolon: - Exclude: - - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - # Offense count: 3 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle. @@ -1815,120 +1587,13 @@ Style/StringConcatenation: - 'spec/script/runners/transfer_samples_spec.rb' - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' -# Offense count: 720 +# Offense count: 2 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes Style/StringLiterals: Exclude: - - 'app/channels/activity_channel.rb' - - 'app/controllers/assets_controller.rb' - - 'app/controllers/steps_controller.rb' - - 'app/helpers/activities_helper.rb' - - 'app/helpers/application_helper.rb' - - 'app/helpers/steps_helper.rb' - - 'app/models/asset.rb' - - 'app/models/asset_group.rb' - - 'app/models/fact.rb' - - 'app/models/step_type.rb' - - 'app/views/printers/show.json.jbuilder' - - 'app/views/users/show.json.jbuilder' - - 'config/initializers/mime_types.rb' - - 'db/migrate/20160903164344_create_delayed_jobs.rb' - - 'db/migrate/20170225191416_migrate_operations_to_object_asset.rb' - - 'db/migrate/20190717130805_change_sti_type.rb' - - 'lib/actions/racking.rb' - - 'lib/changes_support/disjoint_list.rb' - - 'lib/changes_support/transaction_scope.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'lib/inference_engines/runner/step_execution.rb' - - 'lib/label_template_setup.rb' - - 'lib/label_templates/ss_plate.rb' - - 'lib/label_templates/ss_tube.rb' - - 'lib/label_types/plate.rb' - - 'lib/label_types/tube.rb' - - 'lib/parsers/csv_layout/barcode_parser.rb' - - 'lib/parsers/csv_layout/csv_parser.rb' - - 'lib/parsers/csv_metadata/csv_parser.rb' - - 'lib/sequencescape_client_v2.rb' - - 'lib/support_n3.rb' - - 'lib/tasks/setup_templates.rake' - - 'script/aliquot_type_inference.rb' - - 'script/claim_uuids.rb' - - 'script/container_inferences.rb' - - 'script/plate_to_code39.rb' - - 'script/purpose_name_inference.rb' - - 'script/runners/create_12_tubes.rb' - - 'script/runners/create_file.rb' - - 'script/runners/create_layout.rb' - - 'script/runners/create_stamped_plate.rb' - - 'script/runners/full_rack_generator.rb' - - 'script/runners/load_metadata.rb' - - 'script/runners/print_barcodes.rb' - - 'script/runners/put_tubes_into_rack_by_column_order.rb' - - 'script/runners/rack_layout.rb' - - 'script/runners/rack_layout_any_barcode.rb' - - 'script/runners/transfer_plate_to_plate.rb' - - 'script/runners/transfer_plate_to_plate_and_update_sequencescape.rb' - - 'script/runners/transfer_samples.rb' - - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' - - 'script/runners/update_sequencescape.rb' - - 'script/study_name_inference.rb' - - 'script/test2.rb' - - 'spec/concerns/deprecatable_spec.rb' - - 'spec/controllers/activities_controller_spec.rb' - - 'spec/controllers/activity_types_controller_spec.rb' - - 'spec/controllers/asset_groups_controller_spec.rb' - - 'spec/controllers/assets_controller_spec.rb' - - 'spec/controllers/changes_controller_spec.rb' - - 'spec/controllers/instruments_controller_spec.rb' - - 'spec/controllers/kit_types_controller_spec.rb' - - 'spec/controllers/kits_controller_spec.rb' - - 'spec/controllers/printers_controller_spec.rb' - - 'spec/controllers/step_types_controller_spec.rb' - - 'spec/controllers/steps_controller_spec.rb' - - 'spec/controllers/user_sessions_controller_spec.rb' - - 'spec/helpers/application_helper_spec.rb' - - 'spec/integration/inference_spec.rb' - - 'spec/lib/actions/plate_transfer_spec.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/lib/changes_support/disjoint_list_spec.rb' - - 'spec/lib/changes_support/transaction_scope_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/line_reader_spec.rb' - - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' - - 'spec/lib/parsers/csv_metadata/csv_parser_spec.rb' - - 'spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb' - - 'spec/lib/support_n3_spec.rb' - 'spec/lib/token_util_spec.rb' - - 'spec/models/activities/steps_management_spec.rb' - - 'spec/models/activity_type_spec.rb' - - 'spec/models/asset_spec.rb' - - 'spec/models/assets/export_spec.rb' - - 'spec/models/assets/import_spec.rb' - - 'spec/models/condition_spec.rb' - - 'spec/models/fact_spec.rb' - - 'spec/models/step_execution_spec.rb' - - 'spec/models/step_spec.rb' - - 'spec/models/step_type_spec.rb' - - 'spec/models/steps/queueable_job_spec.rb' - - 'spec/models/steps/task_spec.rb' - - 'spec/rails_helper.rb' - - 'spec/remote_assets_helper.rb' - - 'spec/requests/api/v1/assets_spec.rb' - - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' - - 'spec/shared_examples/background_step.rb' - -# Offense count: 74 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: MinSize. -# SupportedStyles: percent, brackets -Style/SymbolArray: - EnforcedStyle: brackets # Offense count: 15 # This cop supports unsafe auto-correction (--auto-correct-all). @@ -1943,7 +1608,7 @@ Style/SymbolProc: - 'spec/controllers/steps_controller_spec.rb' - 'spec/models/steps/cancellable_spec.rb' -# Offense count: 7 +# Offense count: 9 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: EnforcedStyle, AllowSafeAssignment. # SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex @@ -1951,34 +1616,11 @@ Style/TernaryParentheses: Exclude: - 'app/helpers/activities_helper.rb' - 'app/helpers/application_helper.rb' + - 'lib/changes_support/disjoint_list.rb' - 'lib/fact_changes.rb' - 'spec/models/condition_spec.rb' - 'spec/models/step_execution_spec.rb' - -# Offense count: 2 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyleForMultiline. -# SupportedStylesForMultiline: comma, consistent_comma, no_comma -Style/TrailingCommaInArguments: - Exclude: - - 'app/models/user.rb' - -# Offense count: 1 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyleForMultiline. -# SupportedStylesForMultiline: comma, consistent_comma, no_comma -Style/TrailingCommaInArrayLiteral: - Exclude: - - 'spec/models/step_type_spec.rb' - -# Offense count: 5 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyleForMultiline. -# SupportedStylesForMultiline: comma, consistent_comma, no_comma -Style/TrailingCommaInHashLiteral: - Exclude: - - 'lib/label_templates/ss_plate.rb' - - 'lib/support_n3.rb' + - 'spec/models/step_spec.rb' # Offense count: 1 # This cop supports safe auto-correction (--auto-correct). @@ -1988,46 +1630,12 @@ Style/TrivialAccessors: Exclude: - 'lib/support_n3.rb' -# Offense count: 2 +# Offense count: 1 # This cop supports safe auto-correction (--auto-correct). Style/UnlessElse: Exclude: - - 'lib/fact_changes.rb' - 'spec/inferences_helper.rb' -# Offense count: 2 -# This cop supports safe auto-correction (--auto-correct). -Style/WhileUntilDo: - Exclude: - - 'script/runners/create_file.rb' - - 'script/runners/create_layout.rb' - -# Offense count: 72 -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: EnforcedStyle, MinSize, WordRegex. -# SupportedStyles: percent, brackets -Style/WordArray: - Exclude: - - 'app/channels/activity_channel.rb' - - 'lib/actions/plate_transfer.rb' - - 'lib/actions/tube_transfer.rb' - - 'lib/fact_changes.rb' - - 'lib/inference_engines/cwm/step_execution.rb' - - 'spec/lib/actions/plate_transfer_spec.rb' - - 'spec/lib/actions/racking_spec.rb' - - 'spec/lib/changes_support/disjoint_list_spec.rb' - - 'spec/lib/fact_changes_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_creatable_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/barcode_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/line_parser_spec.rb' - - 'spec/lib/parsers/csv_layout/line_reader_spec.rb' - - 'spec/lib/parsers/csv_layout/location_parser_spec.rb' - - 'spec/lib/parsers/csv_metadata/validators/headers_validator_spec.rb' - - 'spec/lib/token_util_spec.rb' - - 'spec/models/activities/steps_management_spec.rb' - - 'spec/models/assets/import_spec.rb' - - 'spec/script/runners/load_metadata_spec.rb' - # Offense count: 19 # This cop supports unsafe auto-correction (--auto-correct-all). Style/ZeroLengthPredicate: @@ -2043,7 +1651,7 @@ Style/ZeroLengthPredicate: - 'lib/parsers/csv_metadata/line_parser.rb' - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' -# Offense count: 130 +# Offense count: 24 # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https diff --git a/Gemfile b/Gemfile index 2e751162..72758f01 100644 --- a/Gemfile +++ b/Gemfile @@ -90,6 +90,7 @@ group :development do gem 'rubocop', require: false gem 'rubocop-performance' gem 'rubocop-rails' + # Mocks APi connections, and also prevents inadvertent network connections being made. gem 'webmock' end diff --git a/README.md b/README.md index daf5b159..68951fd4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ A workflow processor and management tool supported in metadata annotations that allows a user to specifiy the decisions to make during the process of a group of labware. Actions can be specified as metadata changes definition or as external scripts, allowing it to interact with external persistance applications. - ## Main Features: - UI for workflows creation and process @@ -12,7 +11,6 @@ A workflow processor and management tool supported in metadata annotations that - Searching facilities for labware based on metadata - Kits, kit types, users, printers - ## Requirements - Sequencescape @@ -40,7 +38,6 @@ This installation procedure is prepared for a MacOS environment: # redis-server ``` - ### Print_my_barcode config 1. Add the barcode printers that you would like to use in the server. In a MacOS environment open Settings/Printers & Scanners and add the barcode printers making sure they are defined with protocol LPD. @@ -134,7 +131,7 @@ the following environment variables: - SE_PMB_URI: PrintMyBarcode URI (Defaults: http://localhost:10000/v1) - SE_REDIS_URI: Redis DB (Defaults: redis://127.0.0.1:6379) -Additionally you may require to configure the database connection and credentials for mysql from database.yml. +Additionally you may require to configure the database connection and credentials for mysql from database.yml. Second, start the background jobs processor: @@ -149,9 +146,11 @@ bundle exec puma ``` ## Running Javascript tests + ``` yarn test ``` + ## Running tests in watch mode ``` @@ -178,7 +177,6 @@ bundle exec puma Workflows are selected by using one of the instruments from the instruments view at /instruments and scanning for them a kit barcode. The kit barcode is linked with one of the available workflows so it will create a new Activity to start processing labware with that workflow. - ### Brief description of the workflow process When inside an activity, labware from Sequencescape can be imported by scanning the barcode of @@ -208,8 +206,7 @@ selected group. The actions of the rule to ran are queued in a table in the database. A background processor (delayed_jobs) will load this changes to apply and run the associated action for the rule. Actions can be a combination of external scripts and metadata changes definitions. All metadata - changes are gathered to be applied in a single commit in the database. - +changes are gathered to be applied in a single commit in the database. ### User interface sections @@ -232,9 +229,10 @@ needed. Stopping the job will revert all metadata changes. All applied changes from past rules are stored in the Operations table and displayed in this view. A set of controls is provided so the user can perform the following actions: - - Cancel applied rules by reverting all metadata changes, which it would allow to revert history - - Re-apply cancelled rules - - Continue with already stopped jobs (this is really a re-run, as the changes + +- Cancel applied rules by reverting all metadata changes, which it would allow to revert history +- Re-apply cancelled rules +- Continue with already stopped jobs (this is really a re-run, as the changes from a stopped job are always reverted) #### User feedback @@ -256,3 +254,19 @@ ConditionGroups <--/ AssetGroups Operations Conditions Assets --> Facts ``` +## Linting and formatting + +Linting and formatting are provided by rubocop, prettier and Eslint. I strongly +recommend checking out editor integrations. Also, using lefthook will help +ensure that only valid files are committed. + +```shell +# Run rubocop +bundle exec rubocop +# Run rubocop with safe autofixes +bundle exec rubocop -a +# Check prettier formatting +yarn prettier --check . +# Fix prettier formatting +yarn prettier --write . +``` diff --git a/app/assets/javascripts/add_fact_to_searchbox.js b/app/assets/javascripts/add_fact_to_searchbox.js index 24237c2e..af35170d 100644 --- a/app/assets/javascripts/add_fact_to_searchbox.js +++ b/app/assets/javascripts/add_fact_to_searchbox.js @@ -1,28 +1,32 @@ -(function($, undefined) { +;(function ($, undefined) { function AddFactToSearchbox(node, params) { - this.node = $(node); + this.node = $(node) - this.attachHandlers(); + this.attachHandlers() } - var proto = AddFactToSearchbox.prototype; + var proto = AddFactToSearchbox.prototype - proto.addFactToSearchbox = function(event) { - var node = event.currentTarget; - var predicate = $(node).data('psd-fact-predicate'); - var object = $(node).data('psd-fact-object'); - predicate = (predicate || $('.predicate', node).text().trim()); - object = (object || $('.object', node).text().trim()); + proto.addFactToSearchbox = function (event) { + var node = event.currentTarget + var predicate = $(node).data('psd-fact-predicate') + var object = $(node).data('psd-fact-object') + predicate = predicate || $('.predicate', node).text().trim() + object = object || $('.object', node).text().trim() - this.node.trigger('fact_searcher.add_fact_to_searchbox', {predicate: predicate, object: object}); - }; - - proto.attachHandlers = function() { - $('.fact', this.node).on('click', $.proxy(this.addFactToSearchbox, this)); + this.node.trigger('fact_searcher.add_fact_to_searchbox', { + predicate: predicate, + object: object, + }) } - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'AddFactToSearchbox': AddFactToSearchbox}); - }); + proto.attachHandlers = function () { + $('.fact', this.node).on('click', $.proxy(this.addFactToSearchbox, this)) + } -}(jQuery)) \ No newline at end of file + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + AddFactToSearchbox: AddFactToSearchbox, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 1c889b05..f2f6311f 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -45,4 +45,4 @@ // require_asset "peek/views/performance_bar" window.App = {} -window.App.cable=ActionCable.createConsumer() +window.App.cable = ActionCable.createConsumer() diff --git a/app/assets/javascripts/asset_facts.js b/app/assets/javascripts/asset_facts.js index 21697031..f703e635 100644 --- a/app/assets/javascripts/asset_facts.js +++ b/app/assets/javascripts/asset_facts.js @@ -1,145 +1,158 @@ -(function($, undefined) { - function AssetFacts(node, params){ - this.factTemplate = JST['templates/fact']; - this.node = node; - this.title=$('[data-psd-condition-group-title]', node); - this.facts = $('.facts', this.node); - this.name = this.title.text(); - - this.factsStore = []; - - this.attachHandlers(); - - $(this.node).trigger('registered.condition-group', { conditionGroup: this}); - setTimeout($.proxy(function() { - this.initialize(params); - }, this), 0); - - }; - - var proto = AssetFacts.prototype; - - proto.initialize = function(facts) { - if (typeof facts!=='undefined') { - for (var i=0; i=0) { - $(this.node).trigger('msg.display_error', {msg: 'The fact provided is already present in the condition group'}); - return; + return checkFacts + } + + proto.getCardinality = function () { + return $('[data-psd-condition-group-cardinality]', this.node).text() + } + + proto.getActionFacts = function () { + return this.factsStore.filter(function (fact) { + return fact.actionType != 'checkFacts' + }) + } + + proto.addFact = function (fact) { + if (this.findFact(fact) >= 0) { + $(this.node).trigger('msg.display_error', { + msg: 'The fact provided is already present in the condition group', + }) + return } - fact.actionType='createAsset'; - this.factsStore.push(fact); - var renderedFact = this.factTemplate(fact); - this.addRenderedFact(this.facts, renderedFact); - $(document).trigger('execute.builder'); - }; - - proto.listenFactsHandler = function(event, fact) { - this.addFact(fact); - }; - - proto.listenEditableHandler = function(event, data) { - event.stopPropagation(); + fact.actionType = 'createAsset' + this.factsStore.push(fact) + var renderedFact = this.factTemplate(fact) + this.addRenderedFact(this.facts, renderedFact) + $(document).trigger('execute.builder') + } + + proto.listenFactsHandler = function (event, fact) { + this.addFact(fact) + } + + proto.listenEditableHandler = function (event, data) { + event.stopPropagation() if ($(data.node).data('psd-condition-group-title')) { - $(this.node).trigger('changed-name.condition-group', { nameOld: this.name, nameNew: data.text}); + $(this.node).trigger('changed-name.condition-group', { + nameOld: this.name, + nameNew: data.text, + }) } - }; - - proto.findFact = function(fact) { - return this.factsStore.findIndex(function(storedFact) { - return ((fact.predicate=== storedFact.predicate) && - (fact.object=== storedFact.object) && - (fact.object_reference=== storedFact.object_reference) && - (fact.actionType === storedFact.actionType)); - }); - }; - - proto.updateName = function(nameOld, nameNew) { - if (this.name===nameOld) { - this.name=nameNew; + } + + proto.findFact = function (fact) { + return this.factsStore.findIndex(function (storedFact) { + return ( + fact.predicate === storedFact.predicate && + fact.object === storedFact.object && + fact.object_reference === storedFact.object_reference && + fact.actionType === storedFact.actionType + ) + }) + } + + proto.updateName = function (nameOld, nameNew) { + if (this.name === nameOld) { + this.name = nameNew } - $(this.factsStore).each(function(pos, fact) { - if (fact.object===nameOld) { - fact.object=nameNew; + $(this.factsStore).each(function (pos, fact) { + if (fact.object === nameOld) { + fact.object = nameNew } - }); - $('.fact', this.node).each(function(pos, fact) { - if ($(fact).data('psd-fact-object').toString()===nameOld) { - $(fact).data('psd-fact-object', nameNew); - $('.object', fact).html(nameNew); + }) + $('.fact', this.node).each(function (pos, fact) { + if ($(fact).data('psd-fact-object').toString() === nameOld) { + $(fact).data('psd-fact-object', nameNew) + $('.object', fact).html(nameNew) } - }); - }; + }) + } - proto.onDeletedFactIcon = function(e, data) { + proto.onDeletedFactIcon = function (e, data) { var pos = this.findFact({ predicate: $(data.node).data('psd-fact-predicate').toString(), object: $(data.node).data('psd-fact-object').toString(), - actionType: $(data.node).data('psd-fact-actionType').toString() - }); - if (pos>=0) { - this.factsStore.splice(pos, 1); + actionType: $(data.node).data('psd-fact-actionType').toString(), + }) + if (pos >= 0) { + this.factsStore.splice(pos, 1) } - }; + } - proto.onChangeSelectionCheck = function(e, data) { - this.selectAsset = (data==="open"); - }; + proto.onChangeSelectionCheck = function (e, data) { + this.selectAsset = data === 'open' + } - proto.isSelected = function() { - return this.selectAsset; - }; + proto.isSelected = function () { + return this.selectAsset + } - proto.attachHandlers = function() { - $(this.node).on('fact.fact_reader', $.proxy(this.listenFactsHandler, this)); - $(this.node).on('updated-text.editable-text', $.proxy(this.listenEditableHandler, this)); - $(this.node).on('deleted_node.delete_icon', $.proxy(this.onDeletedFactIcon, this)); + proto.attachHandlers = function () { + $(this.node).on('fact.fact_reader', $.proxy(this.listenFactsHandler, this)) + $(this.node).on('updated-text.editable-text', $.proxy(this.listenEditableHandler, this)) + $(this.node).on('deleted_node.delete_icon', $.proxy(this.onDeletedFactIcon, this)) $(this.node).on('value.button_switch', $.proxy(this.onChangeSelectionCheck, this)) - }; - - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'AssetFacts': AssetFacts}); - }); - -}(jQuery)); + } + + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + AssetFacts: AssetFacts, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/barcode_reader.js b/app/assets/javascripts/barcode_reader.js index 18c70171..83c229fe 100644 --- a/app/assets/javascripts/barcode_reader.js +++ b/app/assets/javascripts/barcode_reader.js @@ -1,40 +1,44 @@ -(function($, undefined) { +;(function ($, undefined) { function BarcodeReader(node, params) { - this.node = $(node); - this.input = $('input', node); - this.button = $('button', node); + this.node = $(node) + this.input = $('input', node) + this.button = $('button', node) - this.attachHandlers(); - }; + this.attachHandlers() + } - var proto = BarcodeReader.prototype; + var proto = BarcodeReader.prototype - proto.readInput = function(e) { - if ((e.keyCode === 9) || (e.keyCode == 13)) { - this.send(e); + proto.readInput = function (e) { + if (e.keyCode === 9 || e.keyCode == 13) { + this.send(e) } - }; + } - proto.attachHandlers = function() { - this.input.on('keydown', $.proxy(this.readInput, this)); - this.button.on('click', $.proxy(this.send, this)); - }; + proto.attachHandlers = function () { + this.input.on('keydown', $.proxy(this.readInput, this)) + this.button.on('click', $.proxy(this.send, this)) + } - proto.readBarcodes = function(str) { - return str.split(' ').map(function(val) { - return val.replace(/\"\'/, ''); - }); - }; + proto.readBarcodes = function (str) { + return str.split(' ').map(function (val) { + return val.replace(/\"\'/, '') + }) + } - proto.send = function(e) { - e.preventDefault(); - this.readBarcodes(this.input.val()).forEach($.proxy(function(barcode) { - $(this.node).trigger('barcode.barcode_reader', {barcode: barcode}); - }, this)); - this.input.val(''); - }; + proto.send = function (e) { + e.preventDefault() + this.readBarcodes(this.input.val()).forEach( + $.proxy(function (barcode) { + $(this.node).trigger('barcode.barcode_reader', { barcode: barcode }) + }, this) + ) + this.input.val('') + } - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'BarcodeReader': BarcodeReader}); - }); -}(jQuery)); + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + BarcodeReader: BarcodeReader, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/button_switch.js b/app/assets/javascripts/button_switch.js index 64ce51ba..e283d05b 100644 --- a/app/assets/javascripts/button_switch.js +++ b/app/assets/javascripts/button_switch.js @@ -1,42 +1,44 @@ -(function($, undefined) { +;(function ($, undefined) { function ButtonSwitch(node) { - this.node = $(node); - this.contents = $('[data-psd-button-switch-content]', this.node); - this.default = $('[data-psd-button-switch-selected=true]', this.node)[0]; + this.node = $(node) + this.contents = $('[data-psd-button-switch-content]', this.node) + this.default = $('[data-psd-button-switch-selected=true]', this.node)[0] - this.selectedIndex = this.contents.index(this.default); + this.selectedIndex = this.contents.index(this.default) - this.render(); - this.attachHandlers(); - }; + this.render() + this.attachHandlers() + } - var proto = ButtonSwitch.prototype; + var proto = ButtonSwitch.prototype - proto.render = function() { - this.node.html(this.selectedContent()); - $(this.node).trigger("value.button_switch", $(this.selectedContent()).data("psd-button-switch-content")); - }; + proto.render = function () { + this.node.html(this.selectedContent()) + $(this.node).trigger('value.button_switch', $(this.selectedContent()).data('psd-button-switch-content')) + } - proto.switchContent = function() { - if ($(this.node).parents('.readonly').length!=0) { - return; + proto.switchContent = function () { + if ($(this.node).parents('.readonly').length != 0) { + return } - this.selectedIndex += 1; + this.selectedIndex += 1 if (this.selectedIndex >= this.contents.length) { - this.selectedIndex=0; + this.selectedIndex = 0 } - this.render(); - }; - - proto.selectedContent = function() { - return this.contents[this.selectedIndex]; - }; - - proto.attachHandlers = function() { - $(this.node).on('click', $.proxy(this.switchContent, this)); - }; - - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'ButtonSwitch': ButtonSwitch }); - }); -}(jQuery)); + this.render() + } + + proto.selectedContent = function () { + return this.contents[this.selectedIndex] + } + + proto.attachHandlers = function () { + $(this.node).on('click', $.proxy(this.switchContent, this)) + } + + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + ButtonSwitch: ButtonSwitch, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/component_builder.js b/app/assets/javascripts/component_builder.js index 0946a9d2..cc47a64a 100644 --- a/app/assets/javascripts/component_builder.js +++ b/app/assets/javascripts/component_builder.js @@ -1,73 +1,79 @@ -(function($, undefined) { +;(function ($, undefined) { function ComponentBuilder() { - this.instances = []; - this.components = {}; - }; + this.instances = [] + this.components = {} + } - var proto = ComponentBuilder.prototype; + var proto = ComponentBuilder.prototype - proto.addInstance = function(obj) { - this.instances.push(obj); - }; + proto.addInstance = function (obj) { + this.instances.push(obj) + } - proto.registerComponent = function(obj) { - $.extend(this.components, obj); - }; + proto.registerComponent = function (obj) { + $.extend(this.components, obj) + } - proto.instantiateNode = function(node) { - var className = $(node).data('psd-component-class'); + proto.instantiateNode = function (node) { + var className = $(node).data('psd-component-class') if (typeof this.components[className] === 'undefined') { - console.log('Builder cannot find the class '+className); + console.log('Builder cannot find the class ' + className) } - $(node).removeAttr('data-psd-component-class'); - var params = $(node).data('psd-component-parameters'); - this.addInstance(new this.components[className](node, params)); - }; + $(node).removeAttr('data-psd-component-class') + var params = $(node).data('psd-component-parameters') + this.addInstance(new this.components[className](node, params)) + } - proto.builderProcess = function() { + proto.builderProcess = function () { // When triggering the event to re-execute the builder, sometimes the DOM is not totally up to date // with the latest changes, which could result in instantiating temporary nodes instead of the final // ones. Events are lost in the path - setTimeout($.proxy(function() { - $('[data-psd-component-class]').each($.proxy(function(pos, node) { - this.instantiateNode(node); - }, this)); - $(document).trigger('done.builder'); - },this), 100); - }; + setTimeout( + $.proxy(function () { + $('[data-psd-component-class]').each( + $.proxy(function (pos, node) { + this.instantiateNode(node) + }, this) + ) + $(document).trigger('done.builder') + }, this), + 100 + ) + } - proto.listenComponentRegistration = function() { - $(document).on('registerComponent.builder', $.proxy(function(event, data) { - this.registerComponent(data); - }, this)); - }; + proto.listenComponentRegistration = function () { + $(document).on( + 'registerComponent.builder', + $.proxy(function (event, data) { + this.registerComponent(data) + }, this) + ) + } - proto.listenPageLoad = function() { - var builderProcess = $.proxy(componentBuilder.builderProcess, componentBuilder); + proto.listenPageLoad = function () { + var builderProcess = $.proxy(componentBuilder.builderProcess, componentBuilder) // This should be enough but... - $(document).ready(function() { - $(window).load(function() { - builderProcess(); - }); - }); + $(document).ready(function () { + $(window).load(function () { + builderProcess() + }) + }) // ... TurboLinks support - $(document).on('turbolinks:load', builderProcess); + $(document).on('turbolinks:load', builderProcess) // ... Jquery mobile support - $(document).on('pageinit', builderProcess); + $(document).on('pageinit', builderProcess) // ... and just in case - $(document).on('execute.builder', builderProcess); + $(document).on('execute.builder', builderProcess) //$(document).on('ajax:complete', builderProcess); - window.onunload = function(){}; + window.onunload = function () {} + } - }; - - var componentBuilder = new ComponentBuilder(); - componentBuilder.listenPageLoad(); - componentBuilder.listenComponentRegistration(); - -}(jQuery)); + var componentBuilder = new ComponentBuilder() + componentBuilder.listenPageLoad() + componentBuilder.listenComponentRegistration() +})(jQuery) diff --git a/app/assets/javascripts/condition_group.js b/app/assets/javascripts/condition_group.js index 1887c5b7..5b8336ac 100644 --- a/app/assets/javascripts/condition_group.js +++ b/app/assets/javascripts/condition_group.js @@ -1,167 +1,183 @@ -(function($, undefined) { - function ConditionGroup(node, params){ - this.factTemplate = JST['templates/fact']; - this.node = node; - this.title=$('[data-psd-condition-group-title]', node); - this.checksDiv = $('.check-facts', this.node); - this.facts = $('.facts', this.node); - this.name = this.title.text(); - - this.factsStore = []; - - this.attachHandlers(); - - $(this.node).trigger('registered.condition-group', { conditionGroup: this}); - setTimeout($.proxy(function() { - this.initialize(params); - }, this), 0); - - }; - - var proto = ConditionGroup.prototype; - - proto.initialize = function(facts) { - if (typeof facts!=='undefined') { - for (var i=0; i=0) { - $(this.node).trigger('msg.display_error', {msg: 'The fact provided is already present in the condition group'}); - return; + return checkFacts + } + + proto.getActionFacts = function () { + return this.factsStore.filter(function (fact) { + return fact.actionType != 'checkFacts' + }) + } + + proto.addFact = function (fact) { + if (this.findFact(fact) >= 0) { + $(this.node).trigger('msg.display_error', { + msg: 'The fact provided is already present in the condition group', + }) + return } - this.factsStore.push(fact); - var renderedFact = this.factTemplate(fact); - if (fact.actionType=='checkFacts') { - this.addRenderedFact(this.checksDiv, renderedFact); + this.factsStore.push(fact) + var renderedFact = this.factTemplate(fact) + if (fact.actionType == 'checkFacts') { + this.addRenderedFact(this.checksDiv, renderedFact) } else { - this.addRenderedFact(this.facts, renderedFact); + this.addRenderedFact(this.facts, renderedFact) } - $(document).trigger('execute.builder'); - }; + $(document).trigger('execute.builder') + } - proto.listenFactsHandler = function(event, fact) { - this.addFact(fact); - }; + proto.listenFactsHandler = function (event, fact) { + this.addFact(fact) + } - proto.listenEditableHandler = function(event, data) { - event.stopPropagation(); + proto.listenEditableHandler = function (event, data) { + event.stopPropagation() if ($(data.node).data('psd-condition-group-title')) { - $(this.node).trigger('changed-name.condition-group', { nameOld: this.name, nameNew: data.text}); + $(this.node).trigger('changed-name.condition-group', { + nameOld: this.name, + nameNew: data.text, + }) } if ($(data.node).hasClass('editable-fact')) { - this.updateFact(data.text, data.oldText); + this.updateFact(data.text, data.oldText) } - }; - - proto.updateFact = function(text, oldText) { - var list = oldText.split(":"); - var list2 = text.split(":"); - var pos = this.findSimilarFact({predicate : list[0], object: list[1]}); - this.factsStore[pos].predicate = list2[0]; - this.factsStore[pos].object = list2[1]; - }; - - proto.findSimilarFact = function(fact) { - return this.factsStore.findIndex(function(storedFact) { - return ((fact.predicate=== storedFact.predicate) && - (fact.object=== storedFact.object)); - }); - }; - - proto.findFact = function(fact) { - return this.factsStore.findIndex(function(storedFact) { - return ((fact.predicate=== storedFact.predicate) && - (fact.object=== storedFact.object) && - (fact.actionType === storedFact.actionType)); - }); - }; - - proto.updateName = function(nameOld, nameNew) { - if (this.name===nameOld) { - this.name=nameNew; + } + + proto.updateFact = function (text, oldText) { + var list = oldText.split(':') + var list2 = text.split(':') + var pos = this.findSimilarFact({ predicate: list[0], object: list[1] }) + this.factsStore[pos].predicate = list2[0] + this.factsStore[pos].object = list2[1] + } + + proto.findSimilarFact = function (fact) { + return this.factsStore.findIndex(function (storedFact) { + return fact.predicate === storedFact.predicate && fact.object === storedFact.object + }) + } + + proto.findFact = function (fact) { + return this.factsStore.findIndex(function (storedFact) { + return ( + fact.predicate === storedFact.predicate && + fact.object === storedFact.object && + fact.actionType === storedFact.actionType + ) + }) + } + + proto.updateName = function (nameOld, nameNew) { + if (this.name === nameOld) { + this.name = nameNew } - $(this.factsStore).each(function(pos, fact) { - if (fact.object===nameOld) { - fact.object=nameNew; + $(this.factsStore).each(function (pos, fact) { + if (fact.object === nameOld) { + fact.object = nameNew } - }); - $('.fact', this.node).each(function(pos, fact) { - if ($(fact).data('psd-fact-object').toString()===nameOld) { - $(fact).data('psd-fact-object', nameNew); - $('.object', fact).html(nameNew); + }) + $('.fact', this.node).each(function (pos, fact) { + if ($(fact).data('psd-fact-object').toString() === nameOld) { + $(fact).data('psd-fact-object', nameNew) + $('.object', fact).html(nameNew) } - }); - }; + }) + } - proto.onDeletedFactIcon = function(e, data) { + proto.onDeletedFactIcon = function (e, data) { var pos = this.findFact({ predicate: $(data.node).data('psd-fact-predicate').toString(), object: $(data.node).data('psd-fact-object').toString(), - actionType: $(data.node).data('psd-fact-actionType').toString() - }); - if (pos>=0) { - this.factsStore.splice(pos, 1); + actionType: $(data.node).data('psd-fact-actionType').toString(), + }) + if (pos >= 0) { + this.factsStore.splice(pos, 1) } - }; + } - proto.onChangeSelectionCheck = function(e, data) { - this.selectAsset = (data==="open"); - }; + proto.onChangeSelectionCheck = function (e, data) { + this.selectAsset = data === 'open' + } - proto.isSelected = function() { - return this.selectAsset; - }; + proto.isSelected = function () { + return this.selectAsset + } - proto.destroy = function() { - $(this.node).trigger('destroyed.condition-group', { conditionGroup: this}); - }; + proto.destroy = function () { + $(this.node).trigger('destroyed.condition-group', { conditionGroup: this }) + } - proto.attachHandlers = function() { - $('[data-condition-group-remove="1"]', this.node).on('click', $.proxy(this.destroy, this)); - $(this.node).on('fact.fact_reader', $.proxy(this.listenFactsHandler, this)); - $(this.node).on('updated-text.editable-text', $.proxy(this.listenEditableHandler, this)); - $(this.node).on('deleted_node.delete_icon', $.proxy(this.onDeletedFactIcon, this)); + proto.attachHandlers = function () { + $('[data-condition-group-remove="1"]', this.node).on('click', $.proxy(this.destroy, this)) + $(this.node).on('fact.fact_reader', $.proxy(this.listenFactsHandler, this)) + $(this.node).on('updated-text.editable-text', $.proxy(this.listenEditableHandler, this)) + $(this.node).on('deleted_node.delete_icon', $.proxy(this.onDeletedFactIcon, this)) $(this.node).on('value.button_switch', $.proxy(this.onChangeSelectionCheck, this)) - }; + } - $(document).trigger('registerComponent.builder', {'ConditionGroup': ConditionGroup}); -}(jQuery)); + $(document).trigger('registerComponent.builder', { + ConditionGroup: ConditionGroup, + }) +})(jQuery) diff --git a/app/assets/javascripts/condition_groups.js b/app/assets/javascripts/condition_groups.js index 98b42eca..7e77b789 100644 --- a/app/assets/javascripts/condition_groups.js +++ b/app/assets/javascripts/condition_groups.js @@ -1,213 +1,243 @@ - (function() { - var POS = 0; - - function ConditionGroups(node, params) { - this.template = JST['templates/condition_group']; - this.node = $(node); - this.button = $('[data-psd-condition-group-action-types]', this.node); - this.buttonNewAsset = $('[data-psd-asset-facts-action-types]', this.node); - this.conditionGroups = []; - this.attachHandlers(); - - if (params) { - setTimeout($.proxy(function() { - this.initializeConditionGroups(params); - }, this), 0); +;(function () { + var POS = 0 + + function ConditionGroups(node, params) { + this.template = JST['templates/condition_group'] + this.node = $(node) + this.button = $('[data-psd-condition-group-action-types]', this.node) + this.buttonNewAsset = $('[data-psd-asset-facts-action-types]', this.node) + this.conditionGroups = [] + this.attachHandlers() + + if (params) { + setTimeout( + $.proxy(function () { + this.initializeConditionGroups(params) + }, this), + 0 + ) + } + } + + var proto = ConditionGroups.prototype + + proto.assetFactsTemplate = function () { + return JST['templates/asset_facts'] + } + + proto.initializeConditionGroups = function (params) { + for (var key in params) { + var template = this.template + if (params[key].template) { + template = JST[params[key].template] } - }; - - var proto = ConditionGroups.prototype; - - proto.assetFactsTemplate = function() { - return JST['templates/asset_facts']; - }; - - proto.initializeConditionGroups = function(params) { - for (var key in params) { - var template = this.template; - if (params[key].template) { - template = JST[params[key].template] - } - if (params[key].facts.find(function(f) { return (f.actionType ==="createAsset"); })) { - template = this.assetFactsTemplate(); - } - this.addGroup(key, params[key], template); + if ( + params[key].facts.find(function (f) { + return f.actionType === 'createAsset' + }) + ) { + template = this.assetFactsTemplate() } - }; - - proto.addGroup = function(name, params, template) { - var template = template || this.template; - var conditionGroup = template({ - name: name, - cardinality: params.cardinality || 0, - keepSelected: !!params.keepSelected, - actionTypes: this.button.data('psd-condition-group-action-types')||[], - facts: JSON.stringify(params.facts) - }); - $('#conditionGroups').append(conditionGroup); - $(document).trigger('execute.builder'); - }; - - proto.generateGroupName = function() { - POS = POS + 1; - return "Condition" + POS; - }; - - proto.generateAssetName = function() { - POS = POS + 1; - return "Asset" + POS; - }; - - proto.checkFactToN3 = function(group, fact) { - return ["?"+group.getName(), ":"+fact.predicate, fact.object?'"""'+fact.object+ '"""': fact.literal].join("\t ")+" ."; - }; - - proto.actionFactToN3 = function(group, fact) { - return ":step\t :"+fact.actionType+"\t {"+this.checkFactToN3(group, fact)+"} .\n"; - }; - - proto.getStepTypeName = function() { - return $("div.step_type_name input", this.node).val(); - }; - - proto.getStepTemplate = function() { - return $("#step_type_step_template").val() - }; - - - proto.stepTypeToN3 = function() { - return ":step\t :stepTypeName \"\"\""+this.getStepTypeName()+"\"\"\" .\n"; - }; - - proto.stepTemplateToN3 = function() { - if (this.getStepTemplate().length >0) { - return "\t:step\t :stepTemplate \"\"\""+this.getStepTemplate()+"\"\"\" .\n"; - } else { - return ""; - } - }; - - proto.stepTypeConfigToN3 = function() { - return this.stepTypeToN3() + this.stepTemplateToN3(); - }; - - proto.renderRuleN3 = function(n3Checks, n3Actions, n3Selects) { - return "{\n\t"+n3Checks+"\n} => {\n\t"+this.stepTypeConfigToN3() + n3Selects + "\t"+ n3Actions+"} .\n"; - }; - - proto.toN3 = function(e) { - if (this.conditionGroups.length == 0) { - return ""; - } - var checksN3 = $.map(this.conditionGroups, $.proxy(function(group) { - return $.map(group.getCheckFacts(), $.proxy(this.checkFactToN3, this, group)); - }, this)).join('\n\t'); - - var actionsN3 = $.map(this.conditionGroups, $.proxy(function(group) { - return $.map(group.getActionFacts(), $.proxy(this.actionFactToN3, this, group)); - }, this)).join('\t'); - - var selectsN3 = $.map(this.conditionGroups, $.proxy(function(group) { + this.addGroup(key, params[key], template) + } + } + + proto.addGroup = function (name, params, template) { + var template = template || this.template + var conditionGroup = template({ + name: name, + cardinality: params.cardinality || 0, + keepSelected: !!params.keepSelected, + actionTypes: this.button.data('psd-condition-group-action-types') || [], + facts: JSON.stringify(params.facts), + }) + $('#conditionGroups').append(conditionGroup) + $(document).trigger('execute.builder') + } + + proto.generateGroupName = function () { + POS = POS + 1 + return 'Condition' + POS + } + + proto.generateAssetName = function () { + POS = POS + 1 + return 'Asset' + POS + } + + proto.checkFactToN3 = function (group, fact) { + return ( + ['?' + group.getName(), ':' + fact.predicate, fact.object ? '"""' + fact.object + '"""' : fact.literal].join( + '\t ' + ) + ' .' + ) + } + + proto.actionFactToN3 = function (group, fact) { + return ':step\t :' + fact.actionType + '\t {' + this.checkFactToN3(group, fact) + '} .\n' + } + + proto.getStepTypeName = function () { + return $('div.step_type_name input', this.node).val() + } + + proto.getStepTemplate = function () { + return $('#step_type_step_template').val() + } + + proto.stepTypeToN3 = function () { + return ':step\t :stepTypeName """' + this.getStepTypeName() + '""" .\n' + } + + proto.stepTemplateToN3 = function () { + if (this.getStepTemplate().length > 0) { + return '\t:step\t :stepTemplate """' + this.getStepTemplate() + '""" .\n' + } else { + return '' + } + } + + proto.stepTypeConfigToN3 = function () { + return this.stepTypeToN3() + this.stepTemplateToN3() + } + + proto.renderRuleN3 = function (n3Checks, n3Actions, n3Selects) { + return '{\n\t' + n3Checks + '\n} => {\n\t' + this.stepTypeConfigToN3() + n3Selects + '\t' + n3Actions + '} .\n' + } + + proto.toN3 = function (e) { + if (this.conditionGroups.length == 0) { + return '' + } + var checksN3 = $.map( + this.conditionGroups, + $.proxy(function (group) { + return $.map(group.getCheckFacts(), $.proxy(this.checkFactToN3, this, group)) + }, this) + ).join('\n\t') + + var actionsN3 = $.map( + this.conditionGroups, + $.proxy(function (group) { + return $.map(group.getActionFacts(), $.proxy(this.actionFactToN3, this, group)) + }, this) + ).join('\t') + + var selectsN3 = $.map( + this.conditionGroups, + $.proxy(function (group) { if (!group.isSelected()) { - return "\t:step\t :unselectAsset\t ?" + group.name+".\n"; + return '\t:step\t :unselectAsset\t ?' + group.name + '.\n' } else { - return ""; + return '' } - })).join(""); - - var n3 = this.renderRuleN3(checksN3, actionsN3, selectsN3); - - //$(this.node).trigger('msg.display_error', {msg: n3}); - - return n3; - }; - - proto.storeN3 = function(e) { - var n3 = this.toN3(); - if (n3.length > 0) { - $('input#step_type_n3_definition').val(n3); - } - //alert(this.toN3()); - }; - - proto.storeConditionGroup = function(e, data) { - this.conditionGroups.push(data.conditionGroup); - }; - - proto.destroyConditionGroup = function(e, data) { - var pos = this.conditionGroups.indexOf(data.conditionGroup); - if (pos > -1) { - this.conditionGroups.splice(pos, 1); - } - }; - - proto.updateConditionGroupName = function(e, data) { - $(this.conditionGroups).each(function(pos, conditionGroup) { - conditionGroup.updateName(data.nameOld, data.nameNew); - }); - }; - - proto.showEditor = function() { - var editor = ace.edit("editor"); - editor.setTheme("ace/theme/monokai"); - editor.getSession().setMode("ace/mode/text"); - - if ($('input#step_type_n3_definition').val().length == 0) { - editor.setValue(this.toN3()); - } else { - editor.setValue($('input#step_type_n3_definition').val()); - } - }; - - proto.getEditorContent = function() { - var editor = ace.edit("editor"); - //editor.setTheme("ace/theme/monokai"); - //editor.getSession().setMode("ace/mode/text"); - return editor.getValue(); - }; - - - proto.hideEditor = function() { - //$('#editorContainer').hide(); - }; - - proto.onChangeForReasoning = function() { - var node = $('#step_type_for_reasoning')[0]; - if (node) { - //$('.edit_step_type').toggleClass('for-reasoning', node.checked); - } - }; - - proto.attachHandlers = function() { - this.onChangeForReasoning(); - - $(this.button).on('click', $.proxy(function() { - this.addGroup(this.generateGroupName(), {}); - }, this)); - $(this.buttonNewAsset).on('click', $.proxy(function() { + }) + ).join('') + + var n3 = this.renderRuleN3(checksN3, actionsN3, selectsN3) + + //$(this.node).trigger('msg.display_error', {msg: n3}); + + return n3 + } + + proto.storeN3 = function (e) { + var n3 = this.toN3() + if (n3.length > 0) { + $('input#step_type_n3_definition').val(n3) + } + //alert(this.toN3()); + } + + proto.storeConditionGroup = function (e, data) { + this.conditionGroups.push(data.conditionGroup) + } + + proto.destroyConditionGroup = function (e, data) { + var pos = this.conditionGroups.indexOf(data.conditionGroup) + if (pos > -1) { + this.conditionGroups.splice(pos, 1) + } + } + + proto.updateConditionGroupName = function (e, data) { + $(this.conditionGroups).each(function (pos, conditionGroup) { + conditionGroup.updateName(data.nameOld, data.nameNew) + }) + } + + proto.showEditor = function () { + var editor = ace.edit('editor') + editor.setTheme('ace/theme/monokai') + editor.getSession().setMode('ace/mode/text') + + if ($('input#step_type_n3_definition').val().length == 0) { + editor.setValue(this.toN3()) + } else { + editor.setValue($('input#step_type_n3_definition').val()) + } + } + + proto.getEditorContent = function () { + var editor = ace.edit('editor') + //editor.setTheme("ace/theme/monokai"); + //editor.getSession().setMode("ace/mode/text"); + return editor.getValue() + } + + proto.hideEditor = function () { + //$('#editorContainer').hide(); + } + + proto.onChangeForReasoning = function () { + var node = $('#step_type_for_reasoning')[0] + if (node) { + //$('.edit_step_type').toggleClass('for-reasoning', node.checked); + } + } + + proto.attachHandlers = function () { + this.onChangeForReasoning() + + $(this.button).on( + 'click', + $.proxy(function () { + this.addGroup(this.generateGroupName(), {}) + }, this) + ) + $(this.buttonNewAsset).on( + 'click', + $.proxy(function () { this.addGroup(this.generateAssetName(), {}, this.assetFactsTemplate()) - }, this)); - $(this.node).on('registered.condition-group', $.proxy(this.storeConditionGroup, this)); - $(this.node).on('destroyed.condition-group', $.proxy(this.destroyConditionGroup, this)); - $(this.node).on('changed-name.condition-group', $.proxy(this.updateConditionGroupName, this)); - - $('[data-psd-condition-groups-save]').on('click', $.proxy(this.storeN3, this)); - - $('#step_type_for_reasoning').on('click', $.proxy(this.onChangeForReasoning, this)); - $('.show-n3').on('click', $.proxy(function(e) { + }, this) + ) + $(this.node).on('registered.condition-group', $.proxy(this.storeConditionGroup, this)) + $(this.node).on('destroyed.condition-group', $.proxy(this.destroyConditionGroup, this)) + $(this.node).on('changed-name.condition-group', $.proxy(this.updateConditionGroupName, this)) + + $('[data-psd-condition-groups-save]').on('click', $.proxy(this.storeN3, this)) + + $('#step_type_for_reasoning').on('click', $.proxy(this.onChangeForReasoning, this)) + $('.show-n3').on( + 'click', + $.proxy(function (e) { //e.stopPropagation(); - e.preventDefault(); - this.showEditor(); + e.preventDefault() + this.showEditor() //return false; - }, this)); - $('.update-n3').on('click', $.proxy(function(e) { + }, this) + ) + $('.update-n3').on( + 'click', + $.proxy(function (e) { if (this.getEditorContent().length > 0) { - $('input#step_type_n3_definition').val(this.getEditorContent()); + $('input#step_type_n3_definition').val(this.getEditorContent()) } - }, this)); - }; - - $(document).trigger('registerComponent.builder', {'ConditionGroups': ConditionGroups}); - - }()); - + }, this) + ) + } + + $(document).trigger('registerComponent.builder', { + ConditionGroups: ConditionGroups, + }) +})() diff --git a/app/assets/javascripts/delete_icon.js b/app/assets/javascripts/delete_icon.js index 62d0f9a7..32d90b30 100644 --- a/app/assets/javascripts/delete_icon.js +++ b/app/assets/javascripts/delete_icon.js @@ -1,21 +1,21 @@ -(function($,undefined) { +;(function ($, undefined) { function DeleteIcon(node) { - this.node=$(node); + this.node = $(node) - this.icon = $("[data-psd-delete-icon]", node); - this.attachHandlers(); - }; + this.icon = $('[data-psd-delete-icon]', node) + this.attachHandlers() + } - var proto = DeleteIcon.prototype; + var proto = DeleteIcon.prototype - proto.deleteElement = function() { - $(this.node).trigger('deleted_node.delete_icon', { node : this.node }); - this.node.remove(); - }; + proto.deleteElement = function () { + $(this.node).trigger('deleted_node.delete_icon', { node: this.node }) + this.node.remove() + } - proto.attachHandlers = function() { - this.icon.on('click', $.proxy(this.deleteElement, this)); - }; + proto.attachHandlers = function () { + this.icon.on('click', $.proxy(this.deleteElement, this)) + } - $(document).trigger('registerComponent.builder', {'DeleteIcon': DeleteIcon}); -}(jQuery)); + $(document).trigger('registerComponent.builder', { DeleteIcon: DeleteIcon }) +})(jQuery) diff --git a/app/assets/javascripts/display_error.js b/app/assets/javascripts/display_error.js index 06295ae9..2ac0b841 100644 --- a/app/assets/javascripts/display_error.js +++ b/app/assets/javascripts/display_error.js @@ -1,21 +1,22 @@ -(function($, undefined) { +;(function ($, undefined) { function DisplayError(node) { - this.node = $(node); - this.template = JST['templates/display_error']; - this.attachHandlers(); + this.node = $(node) + this.template = JST['templates/display_error'] + this.attachHandlers() } - var proto = DisplayError.prototype; - proto.showMsg = function(e, msg) { + var proto = DisplayError.prototype + proto.showMsg = function (e, msg) { if (typeof msg.type === 'undefined') { - msg.type='warning'; + msg.type = 'warning' } - this.node.html(this.template(msg)); - }; - - proto.attachHandlers = function() { - $(document).on('msg.display_error', $.proxy(this.showMsg, this)); - }; + this.node.html(this.template(msg)) + } - $(document).trigger('registerComponent.builder', {'DisplayError': DisplayError}); + proto.attachHandlers = function () { + $(document).on('msg.display_error', $.proxy(this.showMsg, this)) + } -}(jQuery)); + $(document).trigger('registerComponent.builder', { + DisplayError: DisplayError, + }) +})(jQuery) diff --git a/app/assets/javascripts/editable_text.js b/app/assets/javascripts/editable_text.js index f7b7f0f2..58a622f4 100644 --- a/app/assets/javascripts/editable_text.js +++ b/app/assets/javascripts/editable_text.js @@ -1,105 +1,110 @@ -(function($, undefined) { +;(function ($, undefined) { function EditableText(node) { - this.node = $(node); - this.template = JST['templates/editable_text']; - this.node.addClass('editable-text'); - this.textWhenEmpty = "None"; + this.node = $(node) + this.template = JST['templates/editable_text'] + this.node.addClass('editable-text') + this.textWhenEmpty = 'None' - if ($(this.node).text().length===0) { + if ($(this.node).text().length === 0) { $(this.node).html(this.textWhenEmpty) } - this.attachHandlers(); - }; + this.attachHandlers() + } - var proto = EditableText.prototype; + var proto = EditableText.prototype - proto.restoreContent = function() { + proto.restoreContent = function () { //this.contents.html(this.getTextFromEditor()); - if (this.contents===null) { - return; + if (this.contents === null) { + return } if (this.validatesContent()) { - var text = this.getTextFromEditor(); - if (text.length===0) { - text=this.textWhenEmpty; + var text = this.getTextFromEditor() + if (text.length === 0) { + text = this.textWhenEmpty } - $(this.node).html(text); - $(this.node).trigger('updated-text.editable-text', {text: this.getTextFromEditor(), node: this.node, oldText: this.contents.text()}); + $(this.node).html(text) + $(this.node).trigger('updated-text.editable-text', { + text: this.getTextFromEditor(), + node: this.node, + oldText: this.contents.text(), + }) } else { - $(this.node).html(this.contents); - $(document).trigger('msg.display_error', {msg: 'The supplied text should follow the pattern:'+$(this.node).data('psd-editable-text-regexp')}); + $(this.node).html(this.contents) + $(document).trigger('msg.display_error', { + msg: 'The supplied text should follow the pattern:' + $(this.node).data('psd-editable-text-regexp'), + }) } - this.contents=null; - this.attachEditor(); + this.contents = null + this.attachEditor() + } - }; - - proto.validatesContent = function() { - var regexp = $(this.node).data('psd-editable-text-regexp'); + proto.validatesContent = function () { + var regexp = $(this.node).data('psd-editable-text-regexp') if (regexp) { - return !!(this.getTextFromEditor().match(new RegExp(regexp))); + return !!this.getTextFromEditor().match(new RegExp(regexp)) } - return true; - }; + return true + } - proto.attachEditor = function() { - $(this.node).one('click', $.proxy(this.addEditor, this)); - }; + proto.attachEditor = function () { + $(this.node).one('click', $.proxy(this.addEditor, this)) + } - proto.getTextFromEditor = function() { - return this.editor.val(); - }; + proto.getTextFromEditor = function () { + return this.editor.val() + } - proto.specialKeysHandler = function(e) { - this.resizeEditor(); + proto.specialKeysHandler = function (e) { + this.resizeEditor() if (e.keyCode === 9) { - this.restoreContent(); - e.preventDefault(); + this.restoreContent() + e.preventDefault() } if (e.keyCode == 13) { - this.restoreContent(); - e.preventDefault(); + this.restoreContent() + e.preventDefault() } - }; + } - proto.setInputFocus = function() { - $(this.editor).focus(); - this.editor[0].selectionStart = this.editor[0].selectionEnd = this.editor[0].value.length; - }; + proto.setInputFocus = function () { + $(this.editor).focus() + this.editor[0].selectionStart = this.editor[0].selectionEnd = this.editor[0].value.length + } - proto.addEditor = function(event) { - if ($(this.node).parents('.readonly').length!=0) { - this.attachEditor(); - return; + proto.addEditor = function (event) { + if ($(this.node).parents('.readonly').length != 0) { + this.attachEditor() + return } var text = $(this.node).text() - if (text===this.textWhenEmpty) { - text = ""; + if (text === this.textWhenEmpty) { + text = '' } - var editorRendered = this.template({text: text}); - this.contents = $(this.node).contents(); - $(this.node).html(editorRendered); - - this.editor = $('input', this.node); - this.editor.on('blur', $.proxy(this.restoreContent, this)); - this.editor.on('keydown', $.proxy(this.specialKeysHandler, this)); - this.resizeEditor(); - this.setInputFocus(); - }; - - proto.resizeEditor = function() { - $(this.editor).attr('size', $(this.editor).val().length+1); - }; - - proto.attachHandlers = function() { - this.attachEditor(); - }; - - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'EditableText': EditableText}); - }); - - -}(jQuery)); + var editorRendered = this.template({ text: text }) + this.contents = $(this.node).contents() + $(this.node).html(editorRendered) + + this.editor = $('input', this.node) + this.editor.on('blur', $.proxy(this.restoreContent, this)) + this.editor.on('keydown', $.proxy(this.specialKeysHandler, this)) + this.resizeEditor() + this.setInputFocus() + } + + proto.resizeEditor = function () { + $(this.editor).attr('size', $(this.editor).val().length + 1) + } + + proto.attachHandlers = function () { + this.attachEditor() + } + + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + EditableText: EditableText, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/element_class_populator.js b/app/assets/javascripts/element_class_populator.js index 409c7dc2..69d9c437 100644 --- a/app/assets/javascripts/element_class_populator.js +++ b/app/assets/javascripts/element_class_populator.js @@ -1,25 +1,26 @@ -(function($, undefined) { +;(function ($, undefined) { function ElementClassPopulator(node, params) { - this.node = node; - this.params = params; + this.node = node + this.params = params - this.addClasses(this.params); - }; + this.addClasses(this.params) + } - var proto = ElementClassPopulator.prototype; + var proto = ElementClassPopulator.prototype - proto.addClasses = function(params) { + proto.addClasses = function (params) { if (typeof params !== 'undefined') { - for (var i=0; i= 0) { - var list = textInput.split(':'); - this.predicate = list[0]; - this.object = list[1]; + var list = textInput.split(':') + this.predicate = list[0] + this.object = list[1] } else { - this.predicate="is"; - this.object = textInput; + this.predicate = 'is' + this.object = textInput } var fact = { actionType: this.actionType, predicate: this.predicate, object: this.object, - cssClasses: this.cssClasses - }; - $(this.node).trigger('fact.fact_reader', fact); - this.input.val(''); - }; + cssClasses: this.cssClasses, + } + $(this.node).trigger('fact.fact_reader', fact) + this.input.val('') + } - proto.readTabulatorHandler = function(e) { + proto.readTabulatorHandler = function (e) { if (e.keyCode === 9) { - this.addFactHandler(); - e.preventDefault(); + this.addFactHandler() + e.preventDefault() } if (e.keyCode == 13) { - this.addFactHandler(); - e.preventDefault(); + this.addFactHandler() + e.preventDefault() } - }; + } - proto.attachHandlers = function(node) { - this.select.on('click', 'a', $.proxy(this.selectOperationHandler, this)); - this.input.on('keydown', $.proxy(this.readTabulatorHandler, this)); - this.addButton.on('click', $.proxy(this.addFactHandler, this)); - }; + proto.attachHandlers = function (node) { + this.select.on('click', 'a', $.proxy(this.selectOperationHandler, this)) + this.input.on('keydown', $.proxy(this.readTabulatorHandler, this)) + this.addButton.on('click', $.proxy(this.addFactHandler, this)) + } //window.FactReader = FactReader; - $(document).trigger('registerComponent.builder', {'FactReader': FactReader}); - -})(jQuery); + $(document).trigger('registerComponent.builder', { FactReader: FactReader }) +})(jQuery) diff --git a/app/assets/javascripts/fact_searcher.js b/app/assets/javascripts/fact_searcher.js index 982ac616..f1c8effc 100644 --- a/app/assets/javascripts/fact_searcher.js +++ b/app/assets/javascripts/fact_searcher.js @@ -1,288 +1,301 @@ -(function($, undefined) { +;(function ($, undefined) { function FactSearcher(node, params) { - this.factSearcherTemplate = JST['templates/fact_searcher']; - this.factTemplate = JST['templates/fact']; - this.node = $(node); + this.factSearcherTemplate = JST['templates/fact_searcher'] + this.factTemplate = JST['templates/fact'] + this.node = $(node) - this.node.html(this.factSearcherTemplate()); - this.input = $('input', this.node); - this.label = $('label', this.node); - this.content = $('.content', this.label); - this.cursor = $('span.cursor', this.node); - this.container = $('div.searcher'); + this.node.html(this.factSearcherTemplate()) + this.input = $('input', this.node) + this.label = $('label', this.node) + this.content = $('.content', this.label) + this.cursor = $('span.cursor', this.node) + this.container = $('div.searcher') - this.attachHandlers(); - }; + this.attachHandlers() + } - var proto = FactSearcher.prototype; + var proto = FactSearcher.prototype - proto.onKeyDown = function(e) { - if ((e.keyCode === 9) || (e.keyCode == 13)) { - this.input.val(this.input.val()+' '); + proto.onKeyDown = function (e) { + if (e.keyCode === 9 || e.keyCode == 13) { + this.input.val(this.input.val() + ' ') } - if ((e.keyCode === 9) || (e.keyCode == 13) || (e.keyCode == 32)) { - this.prepareInput(); + if (e.keyCode === 9 || e.keyCode == 13 || e.keyCode == 32) { + this.prepareInput() } - if ((e.keyCode === 9) || (e.keyCode == 13)) { + if (e.keyCode === 9 || e.keyCode == 13) { /* Tab will not change focus to next input */ /* We'll change carriage return later */ - e.preventDefault(); + e.preventDefault() } - this.resizeInput(); - return true; - }; + this.resizeInput() + return true + } - proto.getSelectedText = function() { - var selection; + proto.getSelectedText = function () { + var selection if (window.getSelection) { selection = window.getSelection().toString() - } else if (document.selection && document.selection.type != "Control") { - selection = document.selection.createRange().text; + } else if (document.selection && document.selection.type != 'Control') { + selection = document.selection.createRange().text } - return selection; - }; + return selection + } - proto.resizeInput = function() { - if (this.input.val().length>21) { - $(this.container)[0].style.setProperty('width', 'auto', 'important'); + proto.resizeInput = function () { + if (this.input.val().length > 21) { + $(this.container)[0].style.setProperty('width', 'auto', 'important') } else { - $(this.container)[0].style.setProperty('width', 'auto', ''); + $(this.container)[0].style.setProperty('width', 'auto', '') } - }; - - proto.prepareInput = function() { - var value = this.input.val(); - var list = this.joinSemicolon(value.split(/\b/)); - this.input.val($.map(list, function(keyword) { - if ((keyword.match(/^\d\d*$/)) && (!keyword.match(/:/))) { - return 'barcode:'+keyword; - } - if ((keyword.match(/\w/)) && (!keyword.match(/:/))) { - return 'is:'+keyword; - } - return keyword; - }).join('')); - }; - - proto.concatNodes = function(nodesList) { + } + + proto.prepareInput = function () { + var value = this.input.val() + var list = this.joinSemicolon(value.split(/\b/)) + this.input.val( + $.map(list, function (keyword) { + if (keyword.match(/^\d\d*$/) && !keyword.match(/:/)) { + return 'barcode:' + keyword + } + if (keyword.match(/\w/) && !keyword.match(/:/)) { + return 'is:' + keyword + } + return keyword + }).join('') + ) + } + ;(proto.concatNodes = function (nodesList) { if (nodesList === null) { - return ""; + return '' } if (nodesList.length > 1) { - var n = $('
'); + var n = $('
') n.append(nodesList) - return n; - } - return nodesList; - }, - - proto.resetHiddenInputs = function() { - if (typeof this.containerHiddenInputs === 'undefined') { - this.containerHiddenInputs = $('') - this.node.append(this.containerHiddenInputs); + return n } - this.containerHiddenInputs.html(''); - }; + return nodesList + }), + (proto.resetHiddenInputs = function () { + if (typeof this.containerHiddenInputs === 'undefined') { + this.containerHiddenInputs = $('') + this.node.append(this.containerHiddenInputs) + } + this.containerHiddenInputs.html('') + }) - proto.addHiddenInput = function(name, value) { - var input = $(''); - this.containerHiddenInputs.append(input); - }; + proto.addHiddenInput = function (name, value) { + var input = $('') + this.containerHiddenInputs.append(input) + } - proto.renderKeyword = function(keyword) { - var list = keyword.split(':'); - if ((list.length >1) && (list[1].length>0)) { - var predicateLabel= $.parseHTML(list[0]); - var objectLabel = $.parseHTML(list[1]); - var predicate = $(predicateLabel).text(); - var object = $(objectLabel).text(); + proto.renderKeyword = function (keyword) { + var list = keyword.split(':') + if (list.length > 1 && list[1].length > 0) { + var predicateLabel = $.parseHTML(list[0]) + var objectLabel = $.parseHTML(list[1]) + var predicate = $(predicateLabel).text() + var object = $(objectLabel).text() - predicateLabel = this.concatNodes(predicateLabel); - objectLabel = this.concatNodes(objectLabel); + predicateLabel = this.concatNodes(predicateLabel) + objectLabel = this.concatNodes(objectLabel) return this.factTemplate({ actionType: '', predicate: predicate, predicateLabel: $(predicateLabel).html(), - object:object, + object: object, objectLabel: $(objectLabel).html(), - cssClasses: '' - }); + cssClasses: '', + }) } else { - keyword= this.replaceEmptySpacesWithHTMLEntity(keyword); - keyword = this.selectSelectedText(keyword); - return keyword; + keyword = this.replaceEmptySpacesWithHTMLEntity(keyword) + keyword = this.selectSelectedText(keyword) + return keyword } - }; - - proto.replaceEmptySpacesWithHTMLEntity = function(keyword) { - return keyword.split(/(<[^>]*>)/g).map(function(str) { - if (str.match(/^\s*$/)) { - str = str.replace(/\s/g,' '); - } - return str; - }).join(''); - }; - - proto.joinSemicolon = function(list) { - var copy = [list[0]]; - for (var i=1; i]*>)/g) + .map(function (str) { + if (str.match(/^\s*$/)) { + str = str.replace(/\s/g, ' ') + } + return str + }) + .join('') + } + + proto.joinSemicolon = function (list) { + var copy = [list[0]] + for (var i = 1; i < list.length; i++) { + if (list[i] === ':' || list[i - 1] === ':') { + copy[copy.length - 1] = copy[copy.length - 1].concat(list[i]) } else { - copy.push(list[i]); + copy.push(list[i]) } } - return copy; - }; - - proto.createHiddenInputs = function() { - this.resetHiddenInputs(); - $('.fact', this.node).each($.proxy(function(pos, node) { - this.addHiddenInput('p'+(pos+1), $(node).data('psd-fact-predicate').replace(/\|/,'')); - this.addHiddenInput('o'+(pos+1), $(node).data('psd-fact-object').toString().replace(/\|/,'')); - }, this)); - }; - - proto.selectSelectedText = function(text) { - var selectedText = this.getSelectedText(); - if (selectedText.length>0) { + return copy + } + + proto.createHiddenInputs = function () { + this.resetHiddenInputs() + $('.fact', this.node).each( + $.proxy(function (pos, node) { + this.addHiddenInput('p' + (pos + 1), $(node).data('psd-fact-predicate').replace(/\|/, '')) + this.addHiddenInput('o' + (pos + 1), $(node).data('psd-fact-object').toString().replace(/\|/, '')) + }, this) + ) + } + + proto.selectSelectedText = function (text) { + var selectedText = this.getSelectedText() + if (selectedText.length > 0) { text = text.replace( - new RegExp(""+selectedText), - ""+selectedText+"" - ); + new RegExp('' + selectedText), + "" + selectedText + '' + ) } - return text; - }; + return text + } - proto.renderLabel = function(e) { - var keywords = this.joinSemicolon(this.input.val().split(/\b/)); - keywords = this.moveCursor(keywords); + proto.renderLabel = function (e) { + var keywords = this.joinSemicolon(this.input.val().split(/\b/)) + keywords = this.moveCursor(keywords) - var html = $.map(keywords, $.proxy(this.renderKeyword, this)).join(' '); + var html = $.map(keywords, $.proxy(this.renderKeyword, this)).join(' ') this.content.html(html) - this.createHiddenInputs(); - $(document).trigger('execute.builder'); - this.reloadCursor(); + this.createHiddenInputs() + $(document).trigger('execute.builder') + this.reloadCursor() if (e && e.keyCode == 13) { - $(this.input[0].form).trigger('submit'); + $(this.input[0].form).trigger('submit') } - return true; - }; - - proto.showCursor = function() { - this.cursor.css('visibility', 'visible'); - }; - - proto.hideCursor = function() { - this.cursor.css('visibility', 'hidden'); - }; - - - proto.onFocus = function() { - this.setInputFocus(); - this.renderLabel(); - this.showCursor(); - if (typeof this.cursorInterval!== 'undefined') { - clearInterval(this.cursorInterval); + return true + } + + proto.showCursor = function () { + this.cursor.css('visibility', 'visible') + } + + proto.hideCursor = function () { + this.cursor.css('visibility', 'hidden') + } + + proto.onFocus = function () { + this.setInputFocus() + this.renderLabel() + this.showCursor() + if (typeof this.cursorInterval !== 'undefined') { + clearInterval(this.cursorInterval) } - this.cursorInterval = setInterval($.proxy(function() { - this.hideCursor(); - this.timeout = setTimeout($.proxy(function() { - this.showCursor(); - }, this), 325); - },this), 650); - }; - - proto.getCursorPosition = function() { - var element = this.input; - var el = $(element).get(0); - var pos = 0; + this.cursorInterval = setInterval( + $.proxy(function () { + this.hideCursor() + this.timeout = setTimeout( + $.proxy(function () { + this.showCursor() + }, this), + 325 + ) + }, this), + 650 + ) + } + + proto.getCursorPosition = function () { + var element = this.input + var el = $(element).get(0) + var pos = 0 if ('selectionStart' in el) { - pos = el.selectionStart; + pos = el.selectionStart } else if ('selection' in document) { - el.focus(); - var Sel = document.selection.createRange(); - var SelLength = document.selection.createRange().text.length; - Sel.moveStart('character', -el.value.length); - pos = Sel.text.length - SelLength; + el.focus() + var Sel = document.selection.createRange() + var SelLength = document.selection.createRange().text.length + Sel.moveStart('character', -el.value.length) + pos = Sel.text.length - SelLength } - return pos; - }; - - proto.setInputFocus = function() { - this.input[0].selectionStart = this.input[0].selectionEnd = this.input[0].value.length; - }; - - proto.onBlur = function() { - clearTimeout(this.timeout); - clearInterval(this.cursorInterval); - this.timeout=null; - this.cursorInterval = null; - this.hideCursor(); - }; - - proto.splice = function(str, start, delCount, newSubStr) { - return str.slice(0, start) + newSubStr + str.slice(start + Math.abs(delCount)); - }; - - proto.moveCursor = function(keywords) { - var absolutePos = this.getCursorPosition(); - var currentPos = 0; - var found = false; - return $.map(keywords, $.proxy(function(keyword) { - var relativePos = (currentPos+keyword.length) - absolutePos; - if (!found && (relativePos >= 0)) { - var p = $('
|
'); - //p.append(this.cursor); - keyword = this.splice(keyword, keyword.length - relativePos, 0, p.html()); - this.cursor.remove(); - this.reloadCursor(); - found = true; - } - currentPos += keyword.length; - return keyword; - }, this)); - }; - - proto.reloadCursor = function() { - this.cursor = $('span.cursor', this.node); - }; - - proto.onKeyPressed = function(e) { - var keywords = this.input.val().split(' '); - keywords = this.moveCursor(keywords); + return pos + } + + proto.setInputFocus = function () { + this.input[0].selectionStart = this.input[0].selectionEnd = this.input[0].value.length + } + + proto.onBlur = function () { + clearTimeout(this.timeout) + clearInterval(this.cursorInterval) + this.timeout = null + this.cursorInterval = null + this.hideCursor() + } + + proto.splice = function (str, start, delCount, newSubStr) { + return str.slice(0, start) + newSubStr + str.slice(start + Math.abs(delCount)) + } + + proto.moveCursor = function (keywords) { + var absolutePos = this.getCursorPosition() + var currentPos = 0 + var found = false + return $.map( + keywords, + $.proxy(function (keyword) { + var relativePos = currentPos + keyword.length - absolutePos + if (!found && relativePos >= 0) { + var p = $('
|
') + //p.append(this.cursor); + keyword = this.splice(keyword, keyword.length - relativePos, 0, p.html()) + this.cursor.remove() + this.reloadCursor() + found = true + } + currentPos += keyword.length + return keyword + }, this) + ) + } + + proto.reloadCursor = function () { + this.cursor = $('span.cursor', this.node) + } + + proto.onKeyPressed = function (e) { + var keywords = this.input.val().split(' ') + keywords = this.moveCursor(keywords) /*this.repeatKeys = setInterval($.proxy(function() { this.input.val(this.input.val()+String.fromCharCode(e.keyCode)); var keywords = this.input.val().split(' '); keywords = this.moveCursor(keywords); }, this), 500);*/ - return true; - }; - + return true + } /*proto.onKeyUp = function() { clearInterval(this.repeatKeys); this.repeatKeys = null; };*/ - proto.attachHandlers = function() { - this.input.on('keydown', $.proxy(this.onKeyDown, this)); - this.input.on('keyup', $.proxy(this.renderLabel, this)); - this.input.on('keydown', $.proxy(this.onKeyPressed, this)); + proto.attachHandlers = function () { + this.input.on('keydown', $.proxy(this.onKeyDown, this)) + this.input.on('keyup', $.proxy(this.renderLabel, this)) + this.input.on('keydown', $.proxy(this.onKeyPressed, this)) //this.input.on('keyup', $.proxy(this.onKeyUp, this)); - this.input.on('focus', $.proxy(this.onFocus, this)); - this.input.on('blur', $.proxy(this.onBlur, this)); - }; - - proto.search = function() { - $(this.node).trigger('text.fact_searcher', this.input.val()); - }; - - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'FactSearcher': FactSearcher}); - }); - -}(jQuery)) + this.input.on('focus', $.proxy(this.onFocus, this)) + this.input.on('blur', $.proxy(this.onBlur, this)) + } + + proto.search = function () { + $(this.node).trigger('text.fact_searcher', this.input.val()) + } + + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + FactSearcher: FactSearcher, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/fact_searcher_lightweight.js b/app/assets/javascripts/fact_searcher_lightweight.js index b8c8d324..464fd765 100644 --- a/app/assets/javascripts/fact_searcher_lightweight.js +++ b/app/assets/javascripts/fact_searcher_lightweight.js @@ -1,112 +1,113 @@ -(function($, undefined) { +;(function ($, undefined) { function FactSearcherLightweight(node, params) { - this.node = $(node); - this.params = params; + this.node = $(node) + this.params = params - this.sidebarTemplate = JST['templates/sidebar_searchbox']; + this.sidebarTemplate = JST['templates/sidebar_searchbox'] - this.input = $('#fact_searcher', this.node); - this.attachHandlers(); - }; + this.input = $('#fact_searcher', this.node) + this.attachHandlers() + } - var proto = FactSearcherLightweight.prototype; + var proto = FactSearcherLightweight.prototype - proto.attachHandlers = function() { - $(this.node).on('submit', $.proxy(this.onSubmit, this)); + proto.attachHandlers = function () { + $(this.node).on('submit', $.proxy(this.onSubmit, this)) - $(document.body).on('fact_searcher.add_fact_to_searchbox', $.proxy(this.addFactToSearchbox, this)); + $(document.body).on('fact_searcher.add_fact_to_searchbox', $.proxy(this.addFactToSearchbox, this)) - $(document).ready(function() { - $(window).on('resize', function() { - $('.main-view').height($(window).height()-200); - }); - $('.main-view').height($(window).height()-200); - }); + $(document).ready(function () { + $(window).on('resize', function () { + $('.main-view').height($(window).height() - 200) + }) + $('.main-view').height($(window).height() - 200) + }) + } - }; - - proto.addFactToSearchbox = function(e, data) { - var predicate = data.predicate; - var object = data.object; - if (this.input.val().length>0) { - this.input.val(this.input.val()+' '); + proto.addFactToSearchbox = function (e, data) { + var predicate = data.predicate + var object = data.object + if (this.input.val().length > 0) { + this.input.val(this.input.val() + ' ') } - this.input.val(this.input.val()+predicate+':'+object); - }; - - proto.prepareOutput = function() { - var pos = 0; - var text = this.input.val(); - text.split(' ').forEach($.proxy(function(param, pos) { - var list = param.split(':'); - if (list.length == 1) { - list = ['barcode', param]; - /* if (param.match(/^\d\d*$/)) { + this.input.val(this.input.val() + predicate + ':' + object) + } + + proto.prepareOutput = function () { + var pos = 0 + var text = this.input.val() + text.split(' ').forEach( + $.proxy(function (param, pos) { + var list = param.split(':') + if (list.length == 1) { + list = ['barcode', param] + /* if (param.match(/^\d\d*$/)) { list = ['barcode', param]; } else { list = ['is', param]; }*/ - } - - this.addHiddenInput('p'+pos, list[0]); - this.addHiddenInput('o'+pos, list[1]); - }, this)); - }; - - proto.resetHiddenInputs = function() { - $('input.for-search', this.node).remove(); - }; - - proto.displayInSideBar = function(html) { - this.input.val(''); - - var containerSearchBox = $(this.sidebarTemplate()); - var nodeSearch = $("
"); - nodeSearch.html(html); - containerSearchBox.append(nodeSearch); - - containerSearchBox.show(); - containerSearchBox.css('display', 'table-cell'); - - $('.main-view').height($(window).height()-200); - $('.main-view').css('overflow', 'scroll'); - containerSearchBox.css('overflow', 'scroll'); - containerSearchBox.height($(window).height()-200); - containerSearchBox.on('resize', function() { - containerSearchBox.height($(window).height()-200); - }); - containerSearchBox.insertAfter('.main-view'); - - this.node.trigger('execute.builder'); - }; - - proto.search = function() { - var form = this.node; - return true; + } + + this.addHiddenInput('p' + pos, list[0]) + this.addHiddenInput('o' + pos, list[1]) + }, this) + ) + } + + proto.resetHiddenInputs = function () { + $('input.for-search', this.node).remove() + } + + proto.displayInSideBar = function (html) { + this.input.val('') + + var containerSearchBox = $(this.sidebarTemplate()) + var nodeSearch = $('
') + nodeSearch.html(html) + containerSearchBox.append(nodeSearch) + + containerSearchBox.show() + containerSearchBox.css('display', 'table-cell') + + $('.main-view').height($(window).height() - 200) + $('.main-view').css('overflow', 'scroll') + containerSearchBox.css('overflow', 'scroll') + containerSearchBox.height($(window).height() - 200) + containerSearchBox.on('resize', function () { + containerSearchBox.height($(window).height() - 200) + }) + containerSearchBox.insertAfter('.main-view') + + this.node.trigger('execute.builder') + } + + proto.search = function () { + var form = this.node + return true $.get({ url: form.attr('action'), data: form.serialize(), - dataType: 'html' + dataType: 'html', //success: $.proxy(this.displayInSideBar, this) - }); - }; + }) + } - proto.onSubmit = function(e) { + proto.onSubmit = function (e) { //e.preventDefault(); - this.resetHiddenInputs(); - this.prepareOutput(); - this.search(); - return true; - }; - - proto.addHiddenInput = function(name, value) { - var input = $(''); - this.node.append(input); - }; - - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'FactSearcherLightweight': FactSearcherLightweight}); - }); - - -}(jQuery)); + this.resetHiddenInputs() + this.prepareOutput() + this.search() + return true + } + + proto.addHiddenInput = function (name, value) { + var input = $('') + this.node.append(input) + } + + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + FactSearcherLightweight: FactSearcherLightweight, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/finish_step_button.js b/app/assets/javascripts/finish_step_button.js index de0624fb..f0daa048 100644 --- a/app/assets/javascripts/finish_step_button.js +++ b/app/assets/javascripts/finish_step_button.js @@ -1,12 +1,17 @@ -(function() { +;(function () { function FinishStepButton(node, params) { - this.node = $(node); - this.node.parent().on('click', $.proxy(function() { - $('form', this.node).submit(); - }, this)); + this.node = $(node) + this.node.parent().on( + 'click', + $.proxy(function () { + $('form', this.node).submit() + }, this) + ) } - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'FinishStepButton': FinishStepButton}); - }); -}()); + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + FinishStepButton: FinishStepButton, + }) + }) +})() diff --git a/app/assets/javascripts/loading_icon.js b/app/assets/javascripts/loading_icon.js index e37db2ad..91450834 100644 --- a/app/assets/javascripts/loading_icon.js +++ b/app/assets/javascripts/loading_icon.js @@ -1,50 +1,50 @@ -(function($, undefined) { +;(function ($, undefined) { function LoadingIcon(node, params) { - this.node=$(node); - - this.containerIconClass = params.containerIconClass || "spinner"; - this.iconClass = params.iconClass || "glyphicon"; - this.icon = $('.'+this.iconClass, this.node); - this.loadingClass = params.loadingClass || "fast-right-spinner" - this.container = $('.'+this.containerIconClass, this.node); - this.hideNode = $(params.hideNodeSelector); - - $(this.container).hide(); - - this.attachHandlers(); - }; - var proto = LoadingIcon.prototype; - - proto.onStartLoad = function(e, data) { - if (data && data.node) { - $(data.node).hide(); - } - if (this.hideNode) { - this.hideNode.hide(); - } - $(this.icon).addClass(this.loadingClass); - $(this.container).show(); - }; - - proto.onStopLoad = function(e, data) { - $(this.container).hide(); - $(this.icon).removeClass(this.loadingClass); - if (data && data.node) { - $(data.node).show(); - } - if (this.hideNode) { - this.hideNode.show(); - } - - }; - - proto.attachHandlers = function() { - $(this.node).on('load_start.loading_spinner', $.proxy(this.onStartLoad, this)); - $(this.node).on('load_stop.loading_spinner', $.proxy(this.onStopLoad, this)); - }; - - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'LoadingIcon': LoadingIcon}); - }); - -}(jQuery)); + this.node = $(node) + + this.containerIconClass = params.containerIconClass || 'spinner' + this.iconClass = params.iconClass || 'glyphicon' + this.icon = $('.' + this.iconClass, this.node) + this.loadingClass = params.loadingClass || 'fast-right-spinner' + this.container = $('.' + this.containerIconClass, this.node) + this.hideNode = $(params.hideNodeSelector) + + $(this.container).hide() + + this.attachHandlers() + } + var proto = LoadingIcon.prototype + + proto.onStartLoad = function (e, data) { + if (data && data.node) { + $(data.node).hide() + } + if (this.hideNode) { + this.hideNode.hide() + } + $(this.icon).addClass(this.loadingClass) + $(this.container).show() + } + + proto.onStopLoad = function (e, data) { + $(this.container).hide() + $(this.icon).removeClass(this.loadingClass) + if (data && data.node) { + $(data.node).show() + } + if (this.hideNode) { + this.hideNode.show() + } + } + + proto.attachHandlers = function () { + $(this.node).on('load_start.loading_spinner', $.proxy(this.onStartLoad, this)) + $(this.node).on('load_stop.loading_spinner', $.proxy(this.onStopLoad, this)) + } + + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + LoadingIcon: LoadingIcon, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/rack_well_display.js b/app/assets/javascripts/rack_well_display.js index aa97f37e..76818fb2 100644 --- a/app/assets/javascripts/rack_well_display.js +++ b/app/assets/javascripts/rack_well_display.js @@ -1,69 +1,69 @@ -(function ($, undefined) { +;(function ($, undefined) { function RackWellDisplay(node, params) { - this.node = $(node); - this.params = params; + this.node = $(node) + this.params = params - this.attachHandlers(); - }; + this.attachHandlers() + } - var proto = RackWellDisplay.prototype; + var proto = RackWellDisplay.prototype - proto.attachHandlers = function() { + proto.attachHandlers = function () { $('svg', this.node).on('click', $.proxy(this.toggleSize, this)) for (var key in this.params) { - var node = $('svg .'+key, this.node); - node.addClass(this.params[key].cssClass); - $(node).on('mouseover', $.proxy(this.showTubeDescription, this, this.params[key].title)); - $(node).on('mouseout', $.proxy(this.hideTubeDescription, this)); - $(node).on('mouseover', $.proxy(this.markRelatedLink, this, this.params[key].url)); - $(node).on('mouseout', $.proxy(this.unmarkRelatedLink, this, this.params[key].url)); - - var relatedLinks = $('a[href=\"'+this.params[key].url+'\"]', this.node); + var node = $('svg .' + key, this.node) + node.addClass(this.params[key].cssClass) + $(node).on('mouseover', $.proxy(this.showTubeDescription, this, this.params[key].title)) + $(node).on('mouseout', $.proxy(this.hideTubeDescription, this)) + $(node).on('mouseover', $.proxy(this.markRelatedLink, this, this.params[key].url)) + $(node).on('mouseout', $.proxy(this.unmarkRelatedLink, this, this.params[key].url)) + + var relatedLinks = $('a[href="' + this.params[key].url + '"]', this.node) relatedLinks.on('mouseover', $.proxy(this.markRelatedWell, this, node)) relatedLinks.on('mouseout', $.proxy(this.unmarkRelatedWell, this, node)) - node.on('click', $.proxy(this.linkTo, this, this.params[key].url)); + node.on('click', $.proxy(this.linkTo, this, this.params[key].url)) } - }; + } - proto.hideTubeDescription = function() { - $('svg .barcode', this.node).hide(); - }; + proto.hideTubeDescription = function () { + $('svg .barcode', this.node).hide() + } - proto.markRelatedLink = function(url) { - $('a[href=\"'+url+'\"]', this.node).addClass('active'); - }; + proto.markRelatedLink = function (url) { + $('a[href="' + url + '"]', this.node).addClass('active') + } - proto.unmarkRelatedLink = function(url) { - $('a[href=\"'+url+'\"]', this.node).removeClass('active'); - }; + proto.unmarkRelatedLink = function (url) { + $('a[href="' + url + '"]', this.node).removeClass('active') + } - proto.markRelatedWell = function(well) { - $(well).addClass('active'); - }; + proto.markRelatedWell = function (well) { + $(well).addClass('active') + } - proto.unmarkRelatedWell = function(well) { - $(well).removeClass('active'); - }; + proto.unmarkRelatedWell = function (well) { + $(well).removeClass('active') + } - proto.showTubeDescription = function(title) { - $('svg .barcode', this.node).html(title); - $('svg .barcode', this.node).show(); - }; + proto.showTubeDescription = function (title) { + $('svg .barcode', this.node).html(title) + $('svg .barcode', this.node).show() + } - proto.linkTo = function(url) { + proto.linkTo = function (url) { if ($('svg', this.node).hasClass('enlarge')) { //window.location.href = url; } - }; - - proto.toggleSize = function() { - $('svg', this.node).toggleClass('enlarge'); - }; - - - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'RackWellDisplay': RackWellDisplay}); - }); - - }(jQuery)); + } + + proto.toggleSize = function () { + $('svg', this.node).toggleClass('enlarge') + } + + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + RackWellDisplay: RackWellDisplay, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/source_to_destination.js b/app/assets/javascripts/source_to_destination.js index 577964c2..453daf20 100644 --- a/app/assets/javascripts/source_to_destination.js +++ b/app/assets/javascripts/source_to_destination.js @@ -1,144 +1,153 @@ -(function() { - +;(function () { function SourceToDestination(node, params) { - this.node = $(node); - this.params = params; - - this.template = params.template; - this.names = params.names; - this.identifiers = params.identifiers; - this.pairings = []; - this.dataParamsNode = $(params.paramsNodeQuery) || '#data_params'; + this.node = $(node) + this.params = params - this.firstRender(); + this.template = params.template + this.names = params.names + this.identifiers = params.identifiers + this.pairings = [] + this.dataParamsNode = $(params.paramsNodeQuery) || '#data_params' - this.addButton = $('.add-button', this.node); - this.sendbutton = $('.send-button', this.node); - this.resetButton = $('.reset-button', this.node); - this.table = $('table', this.node); + this.firstRender() + this.addButton = $('.add-button', this.node) + this.sendbutton = $('.send-button', this.node) + this.resetButton = $('.reset-button', this.node) + this.table = $('table', this.node) - this.attachHandlers(); - }; + this.attachHandlers() + } - var proto = SourceToDestination.prototype; + var proto = SourceToDestination.prototype - proto.nameToId = function(name) { - return name.replace(/ /,''); - }; + proto.nameToId = function (name) { + return name.replace(/ /, '') + } - proto.firstRender = function() { - this.template = JST[this.template]; - this.node.hide(); - this.node.html(this.template({ - names: this.names, - pairings: [], - identifiers: this.identifiers - })); - this.inputs = $($(this.names).map($.proxy(function(pos, name) { - return $('input[name=\"'+this.identifiers[pos]+'\"]', this.node)[0]; - }, this))); - this.table = $('table', this.node); - this.table.hide(); - this.node.show(); + proto.firstRender = function () { + this.template = JST[this.template] + this.node.hide() + this.node.html( + this.template({ + names: this.names, + pairings: [], + identifiers: this.identifiers, + }) + ) + this.inputs = $( + $(this.names).map( + $.proxy(function (pos, name) { + return $('input[name="' + this.identifiers[pos] + '"]', this.node)[0] + }, this) + ) + ) + this.table = $('table', this.node) + this.table.hide() + this.node.show() } - proto.addPairing = function(e) { + proto.addPairing = function (e) { if (e) { - e.preventDefault(); + e.preventDefault() } - this.table.show(); - this.pairings.push(this.inputsToPairing()); - this.resetInputs(); - this.renderTable(this); - }; - - proto.inputsToPairing = function() { - return $(this.inputs).toArray().reduce($.proxy(function(memo, input, pos) { - memo[input.name] = $(this.inputs[pos]).val(); - return memo; - }, this), {}); - }; - - proto.resetInputs = function() { - $(this.inputs).each(function(pos, node) { - $(node).val(''); - }); - }; - - proto.renderTable = function() { + this.table.show() + this.pairings.push(this.inputsToPairing()) + this.resetInputs() + this.renderTable(this) + } + + proto.inputsToPairing = function () { + return $(this.inputs) + .toArray() + .reduce( + $.proxy(function (memo, input, pos) { + memo[input.name] = $(this.inputs[pos]).val() + return memo + }, this), + {} + ) + } + + proto.resetInputs = function () { + $(this.inputs).each(function (pos, node) { + $(node).val('') + }) + } + + proto.renderTable = function () { var allRender = this.template({ pairings: this.pairings, names: this.names, - identifiers: this.identifiers - }); - var containerTable = this.table.parent(); - containerTable.html($('table', allRender)); - this.table = $('table', containerTable); - }; - - proto.send = function() { - this.dataParamsNode.val(JSON.stringify({pairings: this.pairings})); - this.node.trigger('rails.submit'); - }; - - proto.readTabulatorHandler = function(e) { - if ((e.keyCode === 9) || (e.keyCode === 13)){ - e.preventDefault(); + identifiers: this.identifiers, + }) + var containerTable = this.table.parent() + containerTable.html($('table', allRender)) + this.table = $('table', containerTable) + } + + proto.send = function () { + this.dataParamsNode.val(JSON.stringify({ pairings: this.pairings })) + this.node.trigger('rails.submit') + } + + proto.readTabulatorHandler = function (e) { + if (e.keyCode === 9 || e.keyCode === 13) { + e.preventDefault() } } - proto.nextInputHandler = function(e) { - var nextInput = ((e.keyCode === 9) || (e.keyCode == 13)); - var sendInput = (e.keyCode == 13); + proto.nextInputHandler = function (e) { + var nextInput = e.keyCode === 9 || e.keyCode == 13 + var sendInput = e.keyCode == 13 if (nextInput) { + e.preventDefault() - e.preventDefault(); - - var pos = this.inputs.index(e.target); - if (pos >=0) { - if (pos === (this.inputs.length-1)) { - this.addPairing(); - this.inputs[0].focus(); + var pos = this.inputs.index(e.target) + if (pos >= 0) { + if (pos === this.inputs.length - 1) { + this.addPairing() + this.inputs[0].focus() } else { - this.inputs[pos+1].focus(); + this.inputs[pos + 1].focus() } } } - return !nextInput; - }; - - proto.buildHidden = function(tag,pos,role,value) { - var hidden = document.createElement('input'); - $(hidden).attr('type', 'hidden'); - $(hidden).attr('name', [tag, '[', pos,'][',role,']'].join('')); - $(hidden).val(value); - this.node.append(hidden); - }; - - proto.reset = function(e) { + return !nextInput + } + + proto.buildHidden = function (tag, pos, role, value) { + var hidden = document.createElement('input') + $(hidden).attr('type', 'hidden') + $(hidden).attr('name', [tag, '[', pos, '][', role, ']'].join('')) + $(hidden).val(value) + this.node.append(hidden) + } + + proto.reset = function (e) { if (e) { - e.preventDefault(); + e.preventDefault() } - this.pairings = []; - this.renderTable(); - this.resetInputs(); - }; - - proto.attachHandlers = function() { - $(this.addButton).on('click', $.proxy(this.addPairing, this)); - $(this.sendbutton).on('click', $.proxy(this.send, this)); - $(this.resetButton).on('click', $.proxy(this.reset, this)); - $(this.node).on('keydown', this.inputs, $.proxy(this.readTabulatorHandler, this)); - $(this.node).on('keyup', this.inputs, $.proxy(this.nextInputHandler, this)); + this.pairings = [] + this.renderTable() + this.resetInputs() + } + + proto.attachHandlers = function () { + $(this.addButton).on('click', $.proxy(this.addPairing, this)) + $(this.sendbutton).on('click', $.proxy(this.send, this)) + $(this.resetButton).on('click', $.proxy(this.reset, this)) + $(this.node).on('keydown', this.inputs, $.proxy(this.readTabulatorHandler, this)) + $(this.node).on('keyup', this.inputs, $.proxy(this.nextInputHandler, this)) //$(this.sourceInput).on('keydown', $.proxy(this.readTabulatorHandler, this)); //$(this.destinationInput).on('keydown', $.proxy(this.readTabulatorHandler, this)); //$(this.sourceInput).on('keyup', $.proxy(this.nextInputHandler, this)); //$(this.destinationInput).on('keyup', $.proxy(this.nextInputHandler, this)); + } - }; - - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'SourceToDestination': SourceToDestination}); - }); -}()); + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + SourceToDestination: SourceToDestination, + }) + }) +})() diff --git a/app/assets/javascripts/step_button.js b/app/assets/javascripts/step_button.js index 4c598045..7b9ef2ae 100644 --- a/app/assets/javascripts/step_button.js +++ b/app/assets/javascripts/step_button.js @@ -1,42 +1,45 @@ -(function($,undefined) { +;(function ($, undefined) { /** - * Hijacks a form to send a post request to its url without changing the url and reloads afterwards - */ + * Hijacks a form to send a post request to its url without changing the url and reloads afterwards + */ function StepButton(node, params) { - this.node = $(node); - this.form = this.node; - this.params = params; - this.attachHandlers(); - }; + this.node = $(node) + this.form = this.node + this.params = params + this.attachHandlers() + } - var proto = StepButton.prototype; + var proto = StepButton.prototype - proto.attachHandlers = function(e) { - $(this.node).on('submit', $.proxy(this.onSubmit, this)); - $('input', this.node).on('click', $.proxy(this.onClick, this)); - }; + proto.attachHandlers = function (e) { + $(this.node).on('submit', $.proxy(this.onSubmit, this)) + $('input', this.node).on('click', $.proxy(this.onClick, this)) + } - proto.onSubmit = function(e) { - e.preventDefault(); + proto.onSubmit = function (e) { + e.preventDefault() $.ajax({ url: this.form.attr('action'), method: 'POST', data: this.form.serialize(), dataType: 'json', - success: function() { window.location.reload(); } - }); - return false; - }; - - proto.onClick = function(e) { - e.preventDefault(); - $('.step-selection input.btn').attr('disabled', true); - this.onSubmit(e); - return false; + success: function () { + window.location.reload() + }, + }) + return false } - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'StepButton': StepButton}); - }); + proto.onClick = function (e) { + e.preventDefault() + $('.step-selection input.btn').attr('disabled', true) + this.onSubmit(e) + return false + } -}(jQuery)); \ No newline at end of file + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + StepButton: StepButton, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/step_cancellable.js b/app/assets/javascripts/step_cancellable.js index 9141b1a3..c0f2ed7b 100644 --- a/app/assets/javascripts/step_cancellable.js +++ b/app/assets/javascripts/step_cancellable.js @@ -1,51 +1,53 @@ -(function($, undefined) { +;(function ($, undefined) { function StepCancellable(node, params) { - this.node = $(node); - this.params = params; + this.node = $(node) + this.params = params this.url = this.params.url - this.input = $('input[type=checkbox]', this.node); - this.attachHandlers(); + this.input = $('input[type=checkbox]', this.node) + this.attachHandlers() } - var proto = StepCancellable.prototype; + var proto = StepCancellable.prototype - proto.onClick = function() { - (this.input[0].checked) ? this.remake() : this.cancel(); - }; + proto.onClick = function () { + this.input[0].checked ? this.remake() : this.cancel() + } - proto.remake = function() { - var answer = { step: {state: 'complete'}}; - this.send(answer); - }; + proto.remake = function () { + var answer = { step: { state: 'complete' } } + this.send(answer) + } - proto.cancel = function() { - var answer = { step: {state: 'cancel'}}; - this.send(answer); - }; + proto.cancel = function () { + var answer = { step: { state: 'cancel' } } + this.send(answer) + } - proto.send = function(answer) { - return $.ajax({url: this.url, + proto.send = function (answer) { + return $.ajax({ + url: this.url, type: 'PUT', data: answer, dataType: 'json', - success: $.proxy(this.onReceive, this)}); - }; - - proto.onReceive = function(msg) { - var isCancelled = (msg.state==='cancel'); - this.node.toggleClass('cancelled', isCancelled); - this.node.attr('checked', !isCancelled); - }; + success: $.proxy(this.onReceive, this), + }) + } - proto.attachHandlers = function() { - this.input.on('change', $.proxy(this.onClick, this)); - }; + proto.onReceive = function (msg) { + var isCancelled = msg.state === 'cancel' + this.node.toggleClass('cancelled', isCancelled) + this.node.attr('checked', !isCancelled) + } - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'StepCancellable': StepCancellable}); - }); + proto.attachHandlers = function () { + this.input.on('change', $.proxy(this.onClick, this)) + } - -}(jQuery)) \ No newline at end of file + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + StepCancellable: StepCancellable, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/transfer_manager.js b/app/assets/javascripts/transfer_manager.js index d5875976..46eabb78 100644 --- a/app/assets/javascripts/transfer_manager.js +++ b/app/assets/javascripts/transfer_manager.js @@ -1,15 +1,12 @@ -(function($, undefined) { +;(function ($, undefined) { function TransferManager(node, params) { - this.node = node; - this.params = params; + this.node = node + this.params = params - this.attachHandlers(); - }; + this.attachHandlers() + } - var proto = TransferManager.prototype; + var proto = TransferManager.prototype - proto.attachHandlers = function() { - - }; - -}(jQuery)); + proto.attachHandlers = function () {} +})(jQuery) diff --git a/app/assets/javascripts/tube_into_rack.js b/app/assets/javascripts/tube_into_rack.js index a712d69d..2fb0e7a9 100644 --- a/app/assets/javascripts/tube_into_rack.js +++ b/app/assets/javascripts/tube_into_rack.js @@ -1,168 +1,173 @@ -(function() { - +;(function () { var STATUS_CLASSES = { editing: 'editing', edited: 'edited', info: 'info', - error: 'error' - }; + error: 'error', + } function TubeIntoRack(node, params) { - this.node = $(node); + this.node = $(node) this.params = params - this.maxRow = params.maxRow || 8; - this.maxColumn = params.maxColumn || 12; - this.locationPos = 0; - this.racking = {}; - - this.resetButton = $('button.reset-button', this.node); - this.barcodeInput = $('input[name=tube_barcode]', this.node); - this.locationDescription = $('.location-description', this.node); - this.attachHandlers(); - - this.resetRack(); - this.initializeParams(params); - this.renderTable(); - }; - var proto = TubeIntoRack.prototype; - - proto.getLocationFromCell = function(cell) { - return $(cell).attr('class').split(' ').filter(function(classname) { - return classname.match(/[A-Z]\d*/); - })[0]; - }; - - proto.resetRack = function() { - $('svg ellipse', this.node).each($.proxy(function(pos, cell) { - var locationPos = this.locationToPos(this.getLocationFromCell(cell)) - $(cell).on('click', $.proxy(this.modifyCell, this, locationPos+1)); - this.cleanCellCss(cell); - }, this)); - this.racking={}; - this.renderTable(); - }; - - proto.cleanCellCss = function(cell) { + this.maxRow = params.maxRow || 8 + this.maxColumn = params.maxColumn || 12 + this.locationPos = 0 + this.racking = {} + + this.resetButton = $('button.reset-button', this.node) + this.barcodeInput = $('input[name=tube_barcode]', this.node) + this.locationDescription = $('.location-description', this.node) + this.attachHandlers() + + this.resetRack() + this.initializeParams(params) + this.renderTable() + } + var proto = TubeIntoRack.prototype + + proto.getLocationFromCell = function (cell) { + return $(cell) + .attr('class') + .split(' ') + .filter(function (classname) { + return classname.match(/[A-Z]\d*/) + })[0] + } + + proto.resetRack = function () { + $('svg ellipse', this.node).each( + $.proxy(function (pos, cell) { + var locationPos = this.locationToPos(this.getLocationFromCell(cell)) + $(cell).on('click', $.proxy(this.modifyCell, this, locationPos + 1)) + this.cleanCellCss(cell) + }, this) + ) + this.racking = {} + this.renderTable() + } + + proto.cleanCellCss = function (cell) { for (var key in STATUS_CLASSES) { - $(cell).removeClass(STATUS_CLASSES[key]); + $(cell).removeClass(STATUS_CLASSES[key]) } - }; + } - proto.setEditingAtLocation = function(location) { - $('ellipse', this.node).removeClass(STATUS_CLASSES.editing); - $('ellipse.'+location).addClass(STATUS_CLASSES.editing); - this.locationDescription.text(location); - }; + proto.setEditingAtLocation = function (location) { + $('ellipse', this.node).removeClass(STATUS_CLASSES.editing) + $('ellipse.' + location).addClass(STATUS_CLASSES.editing) + this.locationDescription.text(location) + } - proto.initializeParams = function(params) { + proto.initializeParams = function (params) { if (typeof params.racking !== 'undefined') { for (var key in params.racking) { - this.setCell(key, params.racking[key]); + this.setCell(key, params.racking[key]) } if (typeof params.error_params !== 'undefined') { - $.each(params.error_params, $.proxy(function(pos, v) { - $('.'+v, this.node).addClass(STATUS_CLASSES.error); - }, this)); + $.each( + params.error_params, + $.proxy(function (pos, v) { + $('.' + v, this.node).addClass(STATUS_CLASSES.error) + }, this) + ) } } - this.modifyCell(1); - this.renderTable(); - }; - - proto.nextLocation = function() { - this.locationPos += 1; - return this.locationName(this.locationPos); - }; - - proto.locationName = function(locationPos) { - var firstCharcode = "A".charCodeAt(0); - var length = this.maxRow; - var desc_letter = String.fromCharCode(((locationPos-1)%length) + firstCharcode); - var desc_number = Math.floor((locationPos-1)/length) +1 - return (desc_letter+(desc_number)); - }; - - proto.renderTable = function() { - var list = []; + this.modifyCell(1) + this.renderTable() + } + + proto.nextLocation = function () { + this.locationPos += 1 + return this.locationName(this.locationPos) + } + + proto.locationName = function (locationPos) { + var firstCharcode = 'A'.charCodeAt(0) + var length = this.maxRow + var desc_letter = String.fromCharCode(((locationPos - 1) % length) + firstCharcode) + var desc_number = Math.floor((locationPos - 1) / length) + 1 + return desc_letter + desc_number + } + + proto.renderTable = function () { + var list = [] for (var key in this.racking) { - list = list.concat(['',key, '',this.racking[key], '']); + list = list.concat(['', key, '', this.racking[key], '']) } - $('table tbody', this.node).html(list.join('')); - }; - - proto.readBarcode = function(e, data) { - var cell = this.editNextCell(data.barcode); - - this.renderTable(); + $('table tbody', this.node).html(list.join('')) + } - }; + proto.readBarcode = function (e, data) { + var cell = this.editNextCell(data.barcode) + this.renderTable() + } - proto.setCell = function(location, barcode) { - var oldLocation = this.locationPos; - this.locationPos = this.locationToPos(location); - this.editNextCell(barcode); - this.locationPos = oldLocation; - }; + proto.setCell = function (location, barcode) { + var oldLocation = this.locationPos + this.locationPos = this.locationToPos(location) + this.editNextCell(barcode) + this.locationPos = oldLocation + } - proto.locationToPos = function(location) { - return ((parseInt(location.substring(1), 10)-1)* this.maxRow)+ (location[0].charCodeAt() - 'A'.charCodeAt()); - }; + proto.locationToPos = function (location) { + return (parseInt(location.substring(1), 10) - 1) * this.maxRow + (location[0].charCodeAt() - 'A'.charCodeAt()) + } - proto.editNextCell = function(barcode) { - if (this.locationPos >= (this.maxColumn * this.maxRow)) { - return; + proto.editNextCell = function (barcode) { + if (this.locationPos >= this.maxColumn * this.maxRow) { + return } - var location = this.nextLocation(); - this.racking[location] = barcode; - var cell = $("."+location, this.node); + var location = this.nextLocation() + this.racking[location] = barcode + var cell = $('.' + location, this.node) - this.cleanCellCss(cell); + this.cleanCellCss(cell) if (barcode.length !== 0) { - cell.addClass(STATUS_CLASSES.edited); + cell.addClass(STATUS_CLASSES.edited) } - cell.removeClass(STATUS_CLASSES.editing); - var nextCellLocation = this.locationName(this.locationPos+1); - var nextCell = $('.'+nextCellLocation, this.node); - nextCell.addClass(STATUS_CLASSES.editing); - - this.locationDescription.text(nextCellLocation); - - - cell.off('click'); - cell.on('click', $.proxy(this.modifyCell, this, this.locationPos)); - - nextCell.off('click'); - nextCell.on('click', $.proxy(this.modifyCell, this, this.locationPos+1)); - return cell; - }; - - proto.modifyCell = function(locationPos) { - $('ellipse', this.node).removeClass(STATUS_CLASSES.editing); - $('table tbody tr', this.node).removeClass(STATUS_CLASSES.info); - this.locationPos = locationPos - 1; - var locationName = this.locationName(locationPos); - this.barcodeInput.val(this.racking[locationName]); - this.locationDescription.text(locationName); - - $('table tbody tr.'+locationName, this.node).addClass(STATUS_CLASSES.info); - $('.'+this.locationName(locationPos), this.node).addClass(STATUS_CLASSES.editing); - }; - - proto.attachHandlers = function() { - this.node.on('barcode.barcode_reader', $.proxy(this.readBarcode, this)); - this.resetButton.on('click', $.proxy(this.resetRack, this)); - this.node.on('submit', $.proxy(this.prepareRackContent, this)); - }; - - proto.prepareRackContent = function() { - $('#step_data_action', this.node).val("racking"); - $('#step_data_params', this.node).val(JSON.stringify({racking: this.racking})); - }; - - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'TubeIntoRack': TubeIntoRack}); - }); - -}(jQuery)); + cell.removeClass(STATUS_CLASSES.editing) + var nextCellLocation = this.locationName(this.locationPos + 1) + var nextCell = $('.' + nextCellLocation, this.node) + nextCell.addClass(STATUS_CLASSES.editing) + + this.locationDescription.text(nextCellLocation) + + cell.off('click') + cell.on('click', $.proxy(this.modifyCell, this, this.locationPos)) + + nextCell.off('click') + nextCell.on('click', $.proxy(this.modifyCell, this, this.locationPos + 1)) + return cell + } + + proto.modifyCell = function (locationPos) { + $('ellipse', this.node).removeClass(STATUS_CLASSES.editing) + $('table tbody tr', this.node).removeClass(STATUS_CLASSES.info) + this.locationPos = locationPos - 1 + var locationName = this.locationName(locationPos) + this.barcodeInput.val(this.racking[locationName]) + this.locationDescription.text(locationName) + + $('table tbody tr.' + locationName, this.node).addClass(STATUS_CLASSES.info) + $('.' + this.locationName(locationPos), this.node).addClass(STATUS_CLASSES.editing) + } + + proto.attachHandlers = function () { + this.node.on('barcode.barcode_reader', $.proxy(this.readBarcode, this)) + this.resetButton.on('click', $.proxy(this.resetRack, this)) + this.node.on('submit', $.proxy(this.prepareRackContent, this)) + } + + proto.prepareRackContent = function () { + $('#step_data_action', this.node).val('racking') + $('#step_data_params', this.node).val(JSON.stringify({ racking: this.racking })) + } + + $(document).ready(function () { + $(document).trigger('registerComponent.builder', { + TubeIntoRack: TubeIntoRack, + }) + }) +})(jQuery) diff --git a/app/assets/javascripts/user_status.js b/app/assets/javascripts/user_status.js index e32f3800..bc4cf964 100644 --- a/app/assets/javascripts/user_status.js +++ b/app/assets/javascripts/user_status.js @@ -1,192 +1,208 @@ -(function($, undefined) { - var COOKIE_NAME = 'psd-samples-extraction-login'; - - function UserStatus(node, params) { - this.node = $(node); - this.userServiceUrl = params.userServiceUrl; - this.usernameNode = $(params.usernameSelector, this.node); - this.fullNameNode = $(params.fullNameSelector, this.node); - this.controlLoggedOut = $(params.logoutSelector, this.node); - this.controlLoggedIn = $(params.loginSelector, this.node); - this.changeLoginNode = $(params.changeLoginSelector, this.node); - this.roleNode = $(params.roleSelector, this.node); - this.tubePrinterNode = $(params.tubePrinterSelector, this.node); - this.platePrinterNode = $(params.platePrinterSelector, this.node); - - this.logoutButton = $('.logout', this.controlLoggedIn); - - this.attachHandlers(); - this.initialize(params); - }; - - var proto = UserStatus.prototype; - - proto.initialize = function(params) { - if (params.sessionInfo) { - this.updateLogin(params.sessionInfo); - } else { - this.setCookie({}); - } - }; - - proto.login = function(data) { - /*if (this.isLogged()) { +;(function ($, undefined) { + var COOKIE_NAME = 'psd-samples-extraction-login' + + function UserStatus(node, params) { + this.node = $(node) + this.userServiceUrl = params.userServiceUrl + this.usernameNode = $(params.usernameSelector, this.node) + this.fullNameNode = $(params.fullNameSelector, this.node) + this.controlLoggedOut = $(params.logoutSelector, this.node) + this.controlLoggedIn = $(params.loginSelector, this.node) + this.changeLoginNode = $(params.changeLoginSelector, this.node) + this.roleNode = $(params.roleSelector, this.node) + this.tubePrinterNode = $(params.tubePrinterSelector, this.node) + this.platePrinterNode = $(params.platePrinterSelector, this.node) + + this.logoutButton = $('.logout', this.controlLoggedIn) + + this.attachHandlers() + this.initialize(params) + } + + var proto = UserStatus.prototype + + proto.initialize = function (params) { + if (params.sessionInfo) { + this.updateLogin(params.sessionInfo) + } else { + this.setCookie({}) + } + } + + proto.login = function (data) { + /*if (this.isLogged()) { this.logout(); }*/ - this.updateLogin(data); - this.setCookie(data); - $(this.node).trigger('login.user_status', data); - }; + this.updateLogin(data) + this.setCookie(data) + $(this.node).trigger('login.user_status', data) + } - proto.setUsername = function(name) { - $(this.usernameNode).html(name); - }; + proto.setUsername = function (name) { + $(this.usernameNode).html(name) + } - proto.setFullName = function(fullName) { - $(this.fullNameNode).html(fullName); - }; + proto.setFullName = function (fullName) { + $(this.fullNameNode).html(fullName) + } - proto.setBarcode = function(barcode) { - this.barcode = barcode; - //$('input[name=user_barcode]').val(barcode); - }; + proto.setBarcode = function (barcode) { + this.barcode = barcode + //$('input[name=user_barcode]').val(barcode); + } - proto.setRole = function(role) { + proto.setRole = function (role) { if (typeof this.role !== 'undefined') { - $(document.body).removeClass(this.role+'-role'); - $(this.roleNode).html(''); + $(document.body).removeClass(this.role + '-role') + $(this.roleNode).html('') } - if (typeof role ==='undefined') { - return; + if (typeof role === 'undefined') { + return } - this.role=role; - $(this.roleNode).html(this.role); - $(document.body).addClass(this.role+'-role'); - } - - proto.setTubePrinter = function(tubePrinter) { - var idx = $('#tube_printer_select option').filter(function () { - return $(this).html() == tubePrinter; - }).val(); - $('#tube_printer_select').val(idx); - $(this.tubePrinterNode).html(tubePrinter); - }; - - proto.setPlatePrinter = function(platePrinter) { - var idx = $('#plate_printer_select option').filter(function () { - return $(this).html() == platePrinter; - }).val(); - $('#plate_printer_select').val(idx); - $(this.platePrinterNode).html(platePrinter); - }; - - - proto.getBarcode = function() { - return this.barcode; - }; - - proto.updateLogin = function(data) { - if (typeof data!=='undefined') { - this.setUsername(data.username); - this.setFullName(data.fullname); - this.setBarcode(data.barcode); - this.setRole(data.role); - this.setTubePrinter(data.tube_printer_name); - this.setPlatePrinter(data.plate_printer_name); - } - - var showStatus = ((typeof data!=='undefined') && (!!data.username)); - this.controlLoggedOut.toggle(!showStatus); - this.controlLoggedIn.toggle(showStatus); - $(document.body).toggleClass('logged-off', !showStatus); - $(document.body).toggleClass('logged-in', showStatus); - }; - - proto.logoutUrl = function() { + this.role = role + $(this.roleNode).html(this.role) + $(document.body).addClass(this.role + '-role') + } + + proto.setTubePrinter = function (tubePrinter) { + var idx = $('#tube_printer_select option') + .filter(function () { + return $(this).html() == tubePrinter + }) + .val() + $('#tube_printer_select').val(idx) + $(this.tubePrinterNode).html(tubePrinter) + } + + proto.setPlatePrinter = function (platePrinter) { + var idx = $('#plate_printer_select option') + .filter(function () { + return $(this).html() == platePrinter + }) + .val() + $('#plate_printer_select').val(idx) + $(this.platePrinterNode).html(platePrinter) + } + + proto.getBarcode = function () { + return this.barcode + } + + proto.updateLogin = function (data) { + if (typeof data !== 'undefined') { + this.setUsername(data.username) + this.setFullName(data.fullname) + this.setBarcode(data.barcode) + this.setRole(data.role) + this.setTubePrinter(data.tube_printer_name) + this.setPlatePrinter(data.plate_printer_name) + } + + var showStatus = typeof data !== 'undefined' && !!data.username + this.controlLoggedOut.toggle(!showStatus) + this.controlLoggedIn.toggle(showStatus) + $(document.body).toggleClass('logged-off', !showStatus) + $(document.body).toggleClass('logged-in', showStatus) + } + + proto.logoutUrl = function () { return this.userServiceUrl.replace('create', 'delete') - }; + } - proto.logout = function(e) { - if (typeof e !== 'undefined'){ - e.preventDefault(); + proto.logout = function (e) { + if (typeof e !== 'undefined') { + e.preventDefault() } - $.ajax({method: 'delete', cache: false, url: this.logoutUrl(), - dataType: 'json', success: $.proxy(function() { - this.resetBarcodeInput(); - this.val = this.getCookie(); - $(document.body).toggleClass('logged-in', false); - var data = {}; - this.updateLogin(data); - this.setCookie(data); - $(this.node).trigger('logout.user_status', data); - }, this)}). - fail($.proxy(this.onUserServiceFail, this)); - } - - proto.getCookie = function() { - var cookie = Cookies.get(COOKIE_NAME); - if (cookie) { - return JSON.parse(cookie); - } - - }; - - proto.setCookie = function(value) { - return Cookies.set(COOKIE_NAME, JSON.stringify(value)); - }; - - proto.isLogged = function() { - return ((typeof this.getCookie()!== 'undefined') && (typeof this.getCookie().username !== 'undefined')) - }; - - proto.readUserBarcode = function(e, data) { - e.stopPropagation(); - $(this.node).trigger('load_start.loading_spinner', {}); - $.ajax({method: 'post', cache: false, - dataType: "json", - url: this.userServiceUrl, - data:{user_session: data}, dataType: 'json', - success: $.proxy(this.onUserServiceSuccess, this)}). - fail($.proxy(this.onUserServiceFail, this)); - }; - - proto.resetBarcodeInput = function() { - $('input[name=userBarcode]').val(''); - }; - proto.onUserServiceSuccess = function(response) { - this.resetBarcodeInput(); - $(this.node).trigger('load_stop.loading_spinner', {}); - //$('.dropdown-toggle', this.node).dropdown('toggle'); - if (response && (!!response.username)) { - this.login(response); - } else { - this.node.trigger('msg.display_error', {msg: 'User barcode not valid'}); - } - }; - - proto.onUserServiceFail = function() { - this.resetBarcodeInput(); - this.node.trigger('msg.display_error', {msg: 'Cannot connect with user service'}); - $(this.node).trigger('load_stop.loading_spinner', {}); - }; - - - - proto.attachHandlers = function() { - $('#login-button').on('click', function(e) {e.preventDefault();}); - $(this.node).on('barcode.barcode_reader', $.proxy(this.readUserBarcode, this)); - $(document).on('login.user_status', $.proxy(function(e, data) { - - this.updateLogin(data); - }, this)); - $(document).on('logout.user_status', $.proxy(function() { - this.updateLogin({}); - }, this)); - - $(this.logoutButton).on('click', $.proxy(this.logout, this)); - }; - - $(document).trigger('registerComponent.builder', {'UserStatus': UserStatus}); - }(jQuery)); + $.ajax({ + method: 'delete', + cache: false, + url: this.logoutUrl(), + dataType: 'json', + success: $.proxy(function () { + this.resetBarcodeInput() + this.val = this.getCookie() + $(document.body).toggleClass('logged-in', false) + var data = {} + this.updateLogin(data) + this.setCookie(data) + $(this.node).trigger('logout.user_status', data) + }, this), + }).fail($.proxy(this.onUserServiceFail, this)) + } + + proto.getCookie = function () { + var cookie = Cookies.get(COOKIE_NAME) + if (cookie) { + return JSON.parse(cookie) + } + } + + proto.setCookie = function (value) { + return Cookies.set(COOKIE_NAME, JSON.stringify(value)) + } + + proto.isLogged = function () { + return typeof this.getCookie() !== 'undefined' && typeof this.getCookie().username !== 'undefined' + } + + proto.readUserBarcode = function (e, data) { + e.stopPropagation() + $(this.node).trigger('load_start.loading_spinner', {}) + $.ajax({ + method: 'post', + cache: false, + dataType: 'json', + url: this.userServiceUrl, + data: { user_session: data }, + dataType: 'json', + success: $.proxy(this.onUserServiceSuccess, this), + }).fail($.proxy(this.onUserServiceFail, this)) + } + + proto.resetBarcodeInput = function () { + $('input[name=userBarcode]').val('') + } + proto.onUserServiceSuccess = function (response) { + this.resetBarcodeInput() + $(this.node).trigger('load_stop.loading_spinner', {}) + //$('.dropdown-toggle', this.node).dropdown('toggle'); + if (response && !!response.username) { + this.login(response) + } else { + this.node.trigger('msg.display_error', { msg: 'User barcode not valid' }) + } + } + + proto.onUserServiceFail = function () { + this.resetBarcodeInput() + this.node.trigger('msg.display_error', { + msg: 'Cannot connect with user service', + }) + $(this.node).trigger('load_stop.loading_spinner', {}) + } + + proto.attachHandlers = function () { + $('#login-button').on('click', function (e) { + e.preventDefault() + }) + $(this.node).on('barcode.barcode_reader', $.proxy(this.readUserBarcode, this)) + $(document).on( + 'login.user_status', + $.proxy(function (e, data) { + this.updateLogin(data) + }, this) + ) + $(document).on( + 'logout.user_status', + $.proxy(function () { + this.updateLogin({}) + }, this) + ) + + $(this.logoutButton).on('click', $.proxy(this.logout, this)) + } + + $(document).trigger('registerComponent.builder', { UserStatus: UserStatus }) +})(jQuery) diff --git a/app/assets/stylesheets/activities.scss b/app/assets/stylesheets/activities.scss index 5a336b9c..63c34917 100644 --- a/app/assets/stylesheets/activities.scss +++ b/app/assets/stylesheets/activities.scss @@ -7,7 +7,7 @@ tr.output { background-color: lightgray; span { - font-family: "Courier New", Courier, monospace; + font-family: 'Courier New', Courier, monospace; } a:hover { background-color: lightgray; @@ -27,7 +27,7 @@ form.edit_asset_group .panel-header { } body.logged-off ul.step-selection input { - pointer-events:none; + pointer-events: none; opacity: 0.65; } @@ -35,7 +35,6 @@ body.logged-off ul.step-selection input { margin-bottom: 1em; } - .condition-group-label { @extend .alert-success; @@ -51,29 +50,41 @@ body.logged-off ul.step-selection input { overflow: hidden; } -.condition-group-label .type-name {padding-left: 2em;} +.condition-group-label .type-name { + padding-left: 2em; +} /* .condition-group-label:hover {*/ .condition-group-label { height: auto; - z-index:10; + z-index: 10; /*position:absolute;*/ - cursor:context-menu; + cursor: context-menu; } - -.condition-group-label .row { margin-left: 0px; } +.condition-group-label .row { + margin-left: 0px; +} .condition-group-container { padding-left: 1em !important; padding-top: 1em !important; /* padding-right: 1em; */ } -.not-matched .condition-group-label { @extend .alert-danger; } -.not-matched .condition-group-label.matched-group { @extend .alert-warning; } -.not-matched .condition-group-label.matched-group.empty-group { @extend .alert-info; } +.not-matched .condition-group-label { + @extend .alert-danger; +} +.not-matched .condition-group-label.matched-group { + @extend .alert-warning; +} +.not-matched .condition-group-label.matched-group.empty-group { + @extend .alert-info; +} -.not-matched .nav.nav-pills {margin-bottom: 0.5em; margin-left: 0.5em;} +.not-matched .nav.nav-pills { + margin-bottom: 0.5em; + margin-left: 0.5em; +} .condition-group { border-style: dashed; @@ -91,17 +102,17 @@ body.logged-off ul.step-selection input { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; - display: flex; + display: flex; } - .asset-groups .tab-pane.active form .panel { border-top-width: 0px; border-top-left-radius: 0px; border-top-right-radius: 0px; - } -.asset-groups .nav li.active a {background-color: #f5f5f5 !important;} +.asset-groups .nav li.active a { + background-color: #f5f5f5 !important; +} table.steps-table tr.operations div.react-toggle { border-style: none; @@ -134,7 +145,7 @@ table.steps-table tr.operations div.react-toggle-track-check { -ms-user-select: none; user-select: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -webkit-tap-highlight-color: transparent; } @@ -161,7 +172,7 @@ table.steps-table tr.operations div.react-toggle-track-check { height: 24px; padding: 0; border-radius: 30px; - background-color: #4D4D4D; + background-color: #4d4d4d; -webkit-transition: all 0.2s ease; -moz-transition: all 0.2s ease; transition: all 0.2s ease; @@ -172,11 +183,11 @@ table.steps-table tr.operations div.react-toggle-track-check { } .react-toggle--checked .react-toggle-track { - background-color: #19AB27; + background-color: #19ab27; } .react-toggle--checked:hover:not(.react-toggle--disabled) .react-toggle-track { - background-color: #128D15; + background-color: #128d15; } .react-toggle-track-check { @@ -229,9 +240,9 @@ table.steps-table tr.operations div.react-toggle-track-check { left: 1px; width: 22px; height: 22px; - border: 1px solid #4D4D4D; + border: 1px solid #4d4d4d; border-radius: 50%; - background-color: #FAFAFA; + background-color: #fafafa; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; @@ -244,17 +255,17 @@ table.steps-table tr.operations div.react-toggle-track-check { .react-toggle--checked .react-toggle-thumb { left: 27px; - border-color: #19AB27; + border-color: #19ab27; } .react-toggle--focus .react-toggle-thumb { - -webkit-box-shadow: 0px 0px 3px 2px #0099E0; - -moz-box-shadow: 0px 0px 3px 2px #0099E0; - box-shadow: 0px 0px 2px 3px #0099E0; + -webkit-box-shadow: 0px 0px 3px 2px #0099e0; + -moz-box-shadow: 0px 0px 3px 2px #0099e0; + box-shadow: 0px 0px 2px 3px #0099e0; } .react-toggle:active:not(.react-toggle--disabled) .react-toggle-thumb { - -webkit-box-shadow: 0px 0px 5px 5px #0099E0; - -moz-box-shadow: 0px 0px 5px 5px #0099E0; - box-shadow: 0px 0px 5px 5px #0099E0; + -webkit-box-shadow: 0px 0px 5px 5px #0099e0; + -moz-box-shadow: 0px 0px 5px 5px #0099e0; + box-shadow: 0px 0px 5px 5px #0099e0; } diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index b2c22c3c..ae35175e 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -17,9 +17,8 @@ * require peek * require peek/views/performance_bar */ -@import "bootstrap-sprockets"; -@import "bootstrap"; - +@import 'bootstrap-sprockets'; +@import 'bootstrap'; /*.navbar .nav .underlined { border-color: #e7e7e7; @@ -43,25 +42,47 @@ margin-bottom: 0px; } -.empty-description { margin-bottom: 1em;} +.empty-description { + margin-bottom: 1em; +} -.main-view table tbody tr td { padding-top: 1em;} +.main-view table tbody tr td { + padding-top: 1em; +} div#error_explanation { - h2 { @extend .alert-danger; @extend .alert;} + h2 { + @extend .alert-danger; + @extend .alert; + } @extend .alert-danger; @extend .alert; } -p#notice { display:none;} -p#danger { display:none;} +p#notice { + display: none; +} +p#danger { + display: none; +} -.activity-desc {margin-top: 1em; margin-bottom: 1em;} -.activity-desc label { margin-right: 1em; } -.activity-desc .form-group {margin-right: 0.5em; } +.activity-desc { + margin-top: 1em; + margin-bottom: 1em; +} +.activity-desc label { + margin-right: 1em; +} +.activity-desc .form-group { + margin-right: 0.5em; +} -.file-row div.upload-buttons { margin-bottom: 0.5em; } -.previews { margin-top: 0.5em;} +.file-row div.upload-buttons { + margin-bottom: 0.5em; +} +.previews { + margin-top: 0.5em; +} .main-view .custom-dropzone { margin-bottom: 0.5em; @@ -73,21 +94,24 @@ p#danger { display:none;} } table.steps-table { - tr { cursor: pointer;} - tr.operations td {padding-top: 0px; padding-bottom: 0px;} + tr { + cursor: pointer; + } + tr.operations td { + padding-top: 0px; + padding-bottom: 0px; + } tr.operations { margin-left: 1em; margin-right: 1em; table { - border-left: 1px; border-right: 1px; border-style: solid; border-top: 0px; border-bottom: 0px; border-color: rgba(0, 0, 0, 0.3); - } div { border-bottom: 1px; @@ -99,10 +123,10 @@ table.steps-table { } } tr.clickable > td { - border-top:0px; - border-bottom:0px; - border-left:1px; - border-right:1px; + border-top: 0px; + border-bottom: 0px; + border-left: 1px; + border-right: 1px; border-style: solid; border-color: lightgray; } @@ -112,259 +136,431 @@ table.steps-table { div.fact { margin-top: 4px; margin-left: 4px; - float:left; + float: left; span.label { font-size: 90%; font-weight: normal; /*box-shadow: 3px 3px 5px grey;*/ - } + } } -header, .blurheader { - background: rgba(255, 255, 255, .6); - height: 88px; - position: fixed; - width: 100%; - top: 0; - border-bottom:1px solid rgba(0, 0, 0, .2); - z-index: 10000000000; +header, +.blurheader { + background: rgba(255, 255, 255, 0.6); + height: 88px; + position: fixed; + width: 100%; + top: 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.2); + z-index: 10000000000; } - /** * Glyphicon spinner **/ .glyphicon.fast-right-spinner { - -webkit-animation: glyphicon-spin-r 1s infinite linear; - animation: glyphicon-spin-r 1s infinite linear; + -webkit-animation: glyphicon-spin-r 1s infinite linear; + animation: glyphicon-spin-r 1s infinite linear; } .glyphicon.normal-right-spinner { - -webkit-animation: glyphicon-spin-r 2s infinite linear; - animation: glyphicon-spin-r 2s infinite linear; + -webkit-animation: glyphicon-spin-r 2s infinite linear; + animation: glyphicon-spin-r 2s infinite linear; } .glyphicon.slow-right-spinner { - -webkit-animation: glyphicon-spin-r 3s infinite linear; - animation: glyphicon-spin-r 3s infinite linear; + -webkit-animation: glyphicon-spin-r 3s infinite linear; + animation: glyphicon-spin-r 3s infinite linear; } .glyphicon.fast-left-spinner { - -webkit-animation: glyphicon-spin-l 1s infinite linear; - animation: glyphicon-spin-l 1s infinite linear; + -webkit-animation: glyphicon-spin-l 1s infinite linear; + animation: glyphicon-spin-l 1s infinite linear; } .glyphicon.normal-left-spinner { - -webkit-animation: glyphicon-spin-l 2s infinite linear; - animation: glyphicon-spin-l 2s infinite linear; + -webkit-animation: glyphicon-spin-l 2s infinite linear; + animation: glyphicon-spin-l 2s infinite linear; } .glyphicon.slow-left-spinner { - -webkit-animation: glyphicon-spin-l 3s infinite linear; - animation: glyphicon-spin-l 3s infinite linear; + -webkit-animation: glyphicon-spin-l 3s infinite linear; + animation: glyphicon-spin-l 3s infinite linear; } @-webkit-keyframes glyphicon-spin-r { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } } @keyframes glyphicon-spin-r { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } } @-webkit-keyframes glyphicon-spin-l { - 0% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } + 0% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } - 100% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } + 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } } @keyframes glyphicon-spin-l { - 0% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } + 0% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } - 100% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } + 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } } -.icon-size -{ - font-size: 6em; +.icon-size { + font-size: 6em; } -.navbar-login -{ - /*width: 25em;*/ - padding: 1em; - padding-bottom: 0px; +.navbar-login { + /*width: 25em;*/ + padding: 1em; + padding-bottom: 0px; } -.navbar-logout -{ - padding: 10px; - padding-bottom: 0px; - padding-top: 0px; +.navbar-logout { + padding: 10px; + padding-bottom: 0px; + padding-top: 0px; } .user-status .dropdown-menu { - padding-left: 1em; - padding-right: 1em; + padding-left: 1em; + padding-right: 1em; } +.well div.fact { + display: inline; + float: none; +} -.well div.fact { display:inline; float:none;} - -.activity-step-types { padding-left: 2em;} - +.activity-step-types { + padding-left: 2em; +} /* images */ -.facts-list .svg svg { width: 50px; height: 50px; float:left; cursor: -webkit-zoom-in;} -.facts-list .svg.enlarge svg { width: 300px; height: 300px; cursor: -webkit-zoom-out;} +.facts-list .svg svg { + width: 50px; + height: 50px; + float: left; + cursor: -webkit-zoom-in; +} +.facts-list .svg.enlarge svg { + width: 300px; + height: 300px; + cursor: -webkit-zoom-out; +} -.aliquot { fill: gray;} +.aliquot { + fill: gray; +} svg { - .is-used,.is-Used { fill-opacity: 0.7 !important; background-color: #f5f5f5 !important; } - .is-empty,.is-Empty { fill-opacity: 0.3 !important; background-color: #f5f5f5 !important; } - .is-full,.is-Full { fill: #5bb75b; background-color: #5bb75b; } - .resource-not-data { fill: #49afcd; background-color: #49afcd; } - .data-not-resource { fill: #da4f49; background-color: #da4f49; } - .resource-and-data { fill: #5bb75b; background-color: #5bb75b; } - - .has-error,.has-Error { fill: #ff0000; background-color: #ff0000; } - .is-very-poor,.is-VeryPoor { fill: hsl(120, 100%, 75%); background-color: hsl(120, 100%, 75%); } - .is-poor,.is-Poor { fill: hsl(120, 100%, 50%); background-color: hsl(120, 100%, 50%); } - .is-good,.is-Good { fill: hsl(120, 100%, 30%); background-color: hsl(120, 100%, 30%); } - .is-very-good,.is-VeryGood { fill: hsl(120, 100%, 20%); background-color: hsl(120, 100%, 20%); } - .is-excellent,.is-Excellent { fill: hsl(120, 100%, 10%); background-color: hsl(120, 100%, 10%); } - - .has-dna,.has-DNA,.dna,.DNA { fill: hsl(120, 45%, 58%); background-color: hsl(120, 45%, 58%); } - .has-dnap,.has-DNAP,.dnap,.DNAP { fill: hsl(120, 34%, 25%); background-color: hsl(120, 34%, 25%); } - .has-rna,.has-RNA,.rna,.RNA { fill: hsl(3, 60%, 46%); background-color: hsl(3, 60%, 46%); } - .has-rna_p,.has-RNAP,.rnap,.RNAP { fill: hsl(3, 60%, 25%); background-color: hsl(3, 60%, 25%); } - .has-na_p,has-NAP,.nap,.NAP { fill: hsl(194, 59%, 45%); background-color: hsl(194, 59%, 45%); } - .has-blood,.has-Blood,.blood,.BLOOD { - fill: red; + .is-used, + .is-Used { + fill-opacity: 0.7 !important; + background-color: #f5f5f5 !important; + } + .is-empty, + .is-Empty { + fill-opacity: 0.3 !important; + background-color: #f5f5f5 !important; + } + .is-full, + .is-Full { + fill: #5bb75b; + background-color: #5bb75b; + } + .resource-not-data { + fill: #49afcd; + background-color: #49afcd; + } + .data-not-resource { + fill: #da4f49; + background-color: #da4f49; + } + .resource-and-data { + fill: #5bb75b; + background-color: #5bb75b; + } + .has-error, + .has-Error { + fill: #ff0000; + background-color: #ff0000; + } + .is-very-poor, + .is-VeryPoor { + fill: hsl(120, 100%, 75%); + background-color: hsl(120, 100%, 75%); + } + .is-poor, + .is-Poor { + fill: hsl(120, 100%, 50%); + background-color: hsl(120, 100%, 50%); + } + .is-good, + .is-Good { + fill: hsl(120, 100%, 30%); + background-color: hsl(120, 100%, 30%); + } + .is-very-good, + .is-VeryGood { + fill: hsl(120, 100%, 20%); + background-color: hsl(120, 100%, 20%); + } + .is-excellent, + .is-Excellent { + fill: hsl(120, 100%, 10%); + background-color: hsl(120, 100%, 10%); } - .unknown-aliquot { fill: gray;} - .empty-well-aliquot { fill: white;} + .has-dna, + .has-DNA, + .dna, + .DNA { + fill: hsl(120, 45%, 58%); + background-color: hsl(120, 45%, 58%); + } + .has-dnap, + .has-DNAP, + .dnap, + .DNAP { + fill: hsl(120, 34%, 25%); + background-color: hsl(120, 34%, 25%); + } + .has-rna, + .has-RNA, + .rna, + .RNA { + fill: hsl(3, 60%, 46%); + background-color: hsl(3, 60%, 46%); + } + .has-rna_p, + .has-RNAP, + .rnap, + .RNAP { + fill: hsl(3, 60%, 25%); + background-color: hsl(3, 60%, 25%); + } + .has-na_p, + has-NAP, + .nap, + .NAP { + fill: hsl(194, 59%, 45%); + background-color: hsl(194, 59%, 45%); + } + .has-blood, + .has-Blood, + .blood, + .BLOOD { + fill: red; + } + .unknown-aliquot { + fill: gray; + } + .empty-well-aliquot { + fill: white; + } - ellipse.error { stroke: red !important;} - .editing { fill: lightblue; } - .editing.edited { fill: lightblue;} - .edited {fill: gray;} - .empty-edited {fill: black;} + ellipse.error { + stroke: red !important; + } + .editing { + fill: lightblue; + } + .editing.edited { + fill: lightblue; + } + .edited { + fill: gray; + } + .empty-edited { + fill: black; + } - ellipse:hover { fill: white !important;} - ellipse.active { fill: white !important;} - .a1_dna .A1 { @extend .has-dna; } + ellipse:hover { + fill: white !important; + } + ellipse.active { + fill: white !important; + } + .a1_dna .A1 { + @extend .has-dna; + } } - /** * Navbar */ -@media (max-width: 767px){ - body nav .navbar-right .user-status { display:none;} +@media (max-width: 767px) { + body nav .navbar-right .user-status { + display: none; + } body nav .navbar-header .user-status { - display:block; position:relative; float:right; - margin-top: 8px; margin-right: 0.5em; - .user-status-description-text { display:none;} - .dropdown-menu {left: auto; right: 0;} - div.form-group {margin-bottom: 0px;} + display: block; + position: relative; + float: right; + margin-top: 8px; + margin-right: 0.5em; + .user-status-description-text { + display: none; + } + .dropdown-menu { + left: auto; + right: 0; + } + div.form-group { + margin-bottom: 0px; + } } - } -@media (min-width: 768px){ - body nav .navbar-right .user-status { display:inline-block;} - body nav .navbar-header .user-status { display:none;} +@media (min-width: 768px) { + body nav .navbar-right .user-status { + display: inline-block; + } + body nav .navbar-header .user-status { + display: none; + } } - -@media (min-width: 768px) -{ +@media (min-width: 768px) { body nav { .container-fluid { border-bottom: 1px solid; border-color: #e7e7e7; - }; + } .navbar-collapse { background-color: #fff; border-radius: 4px; - }; - }; + } + } } -div.fact span.to_add { }; -div.fact .object-reference { color: #eee; background-color: #777777; text-decoration: underline;} -div.fact span.to_remove { color:silver; text-decoration: line-through;}; - -.navbar-login i.role { text-transform: capitalize;} - -nav.navbar ul.nav > li {display: none;} -body .anonymous-allowed { display: inline-block !important;} -body .operator-allowed { display: none;} -body .administrator-allowed { display: none;} -body.operator-role .operator-allowed {display:inline-block !important;} -body.administrator-role .administrator-allowed {display:inline-block !important;} -body.administrator-role .operator-allowed {display:inline-block !important;} - - -form.edit_asset_group .barcode-adding-control { width: 100%;} -form.edit_asset_group .barcode-adding-control { @extend .operator-allowed; } -body .btn { @extend .operator-allowed; } -body nav .btn { @extend .anonymous-allowed; } +div.fact span.to_add { +} +div.fact .object-reference { + color: #eee; + background-color: #777777; + text-decoration: underline; +} +div.fact span.to_remove { + color: silver; + text-decoration: line-through; +} -.asset .panel-heading {display: none;} -.asset small {display: none;} +.navbar-login i.role { + text-transform: capitalize; +} -div.fact a.active.object-reference {color:orange;} +nav.navbar ul.nav > li { + display: none; +} +body .anonymous-allowed { + display: inline-block !important; +} +body .operator-allowed { + display: none; +} +body .administrator-allowed { + display: none; +} +body.operator-role .operator-allowed { + display: inline-block !important; +} +body.administrator-role .administrator-allowed { + display: inline-block !important; +} +body.administrator-role .operator-allowed { + display: inline-block !important; +} -.no-compatible-steps-desc {font-size:11pt;} +form.edit_asset_group .barcode-adding-control { + width: 100%; +} +form.edit_asset_group .barcode-adding-control { + @extend .operator-allowed; +} +body .btn { + @extend .operator-allowed; +} +body nav .btn { + @extend .anonymous-allowed; +} -#asset-group-container ul.nav-pills li.active a {background-color: #777777; color: #fff;} -#asset-group-container ul.nav-pills a { color: #666;} +.asset .panel-heading { + display: none; +} +.asset small { + display: none; +} +div.fact a.active.object-reference { + color: orange; +} +.no-compatible-steps-desc { + font-size: 11pt; +} -.step_types_active svg ellipse { cursor: pointer;} -.step_types_active svg { cursor: default;} +#asset-group-container ul.nav-pills li.active a { + background-color: #777777; + color: #fff; +} +#asset-group-container ul.nav-pills a { + color: #666; +} -.facts-list svg.enlarge { height: 150px;} +.step_types_active svg ellipse { + cursor: pointer; +} +.step_types_active svg { + cursor: default; +} +.facts-list svg.enlarge { + height: 150px; +} -.fact {cursor: pointer;} +.fact { + cursor: pointer; +} -.max-svg-size { max-width: 500px;} +.max-svg-size { + max-width: 500px; +} -.svg-small-size { height: 150px; } +.svg-small-size { + height: 150px; +} diff --git a/app/assets/stylesheets/scaffolds.scss b/app/assets/stylesheets/scaffolds.scss index ed7a765d..ed0b1ed8 100644 --- a/app/assets/stylesheets/scaffolds.scss +++ b/app/assets/stylesheets/scaffolds.scss @@ -6,7 +6,10 @@ body { line-height: 18px; } -p, ol, ul, td { +p, +ol, +ul, +td { font-family: verdana, arial, helvetica, sans-serif; font-size: 13px; line-height: 18px; @@ -32,7 +35,8 @@ a { } div { - &.field, &.actions { + &.field, + &.actions { margin-bottom: 10px; } } diff --git a/app/assets/stylesheets/step_types.scss b/app/assets/stylesheets/step_types.scss index b68fd17d..749fcec7 100644 --- a/app/assets/stylesheets/step_types.scss +++ b/app/assets/stylesheets/step_types.scss @@ -2,11 +2,12 @@ // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ - -#conditionGroups a[data-psd-condition-group-action-types]{ +#conditionGroups a[data-psd-condition-group-action-types] { margin-bottom: 1em; } -#conditionGroups div.alert { padding: 0px; } +#conditionGroups div.alert { + padding: 0px; +} .main-view #conditionGroups .panel-body { padding-bottom: 15px; @@ -38,8 +39,15 @@ span.editable-text { .not-for-reasoning { display: none;} }*/ -.readonly .btn-group { display: none; } -.readonly .input-group { display: none; } -.readonly span[data-psd-delete-icon] { display: none; } -.readonly button { display: none; } - +.readonly .btn-group { + display: none; +} +.readonly .input-group { + display: none; +} +.readonly span[data-psd-delete-icon] { + display: none; +} +.readonly button { + display: none; +} diff --git a/app/assets/stylesheets/steps.scss b/app/assets/stylesheets/steps.scss index f33653ff..48ec5bd4 100644 --- a/app/assets/stylesheets/steps.scss +++ b/app/assets/stylesheets/steps.scss @@ -1,4 +1,7 @@ // Place all the styles related to the steps controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -tr.cancelled .fact span { color:silver; text-decoration: line-through;}; \ No newline at end of file +tr.cancelled .fact span { + color: silver; + text-decoration: line-through; +} diff --git a/app/channels/activity_channel.rb b/app/channels/activity_channel.rb index ef20d1a3..1f9d191d 100644 --- a/app/channels/activity_channel.rb +++ b/app/channels/activity_channel.rb @@ -23,8 +23,8 @@ def self.subscribed_ids end def receive(data) - process_asset_group(strong_params_for_asset_group(data)) if data["asset_group"] - process_activity(strong_params_for_activity(data)) if data["activity"] + process_asset_group(strong_params_for_asset_group(data)) if data['asset_group'] + process_activity(strong_params_for_activity(data)) if data['activity'] end def process_asset_group(strong_params) @@ -49,7 +49,11 @@ def process_asset_group(strong_params) missing_barcodes = fluidx_barcodes - barcode_assets.map(&:barcode) asset_group.update_with_assets(uuid_assets + barcode_assets) - asset_group.activity.send_wss_event({ error: { type: 'danger', msg: "Could not find barcodes: #{missing_barcodes.join(', ')}" } }) if missing_barcodes.present? + if missing_barcodes.present? + asset_group.activity.send_wss_event( + { error: { type: 'danger', msg: "Could not find barcodes: #{missing_barcodes.join(', ')}" } } + ) + end rescue Errno::ECONNREFUSED => e asset_group.activity.send_wss_event({ error: { type: 'danger', msg: 'Cannot connect with sequencescape' } }) rescue StandardError => e @@ -62,7 +66,7 @@ def process_activity(strong_params) obj = ActivityChannel.activity_attributes(params[:activity_id]) - ['stepTypes', 'stepsPending', 'stepsRunning', 'stepsFailed', 'stepsFinished'].reduce(obj) do |memo, key| + %w[stepTypes stepsPending stepsRunning stepsFailed stepsFinished].reduce(obj) do |memo, key| memo[key] = !!strong_params[key] unless strong_params[key].nil? memo end @@ -86,7 +90,7 @@ def self.activity_attributes(id) def strong_params_for_asset_group(params) params = ActionController::Parameters.new(params) - params.require(:asset_group).permit(:id, :assets => []) + params.require(:asset_group).permit(:id, assets: []) end def strong_params_for_activity(params) diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index 5b3255c3..7128b21c 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -6,7 +6,7 @@ def connect # self.current_user = nil token = cookies.encrypted['_samples_extraction_session']['token'] if token - self.current_user = User.find_by(:token => token) + self.current_user = User.find_by(token: token) return if self.current_user end reject_unauthorized_connection diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb index 87b7ebb5..96388c31 100644 --- a/app/controllers/activities_controller.rb +++ b/app/controllers/activities_controller.rb @@ -1,7 +1,7 @@ class ActivitiesController < ApplicationController include ActionController::Live - before_action :set_activity, only: [:show, :update] + before_action :set_activity, only: %i[show update] before_action :set_instrument, only: [:create] before_action :set_kit, only: [:create] before_action :set_activity_type, only: [:create] diff --git a/app/controllers/activity_types_controller.rb b/app/controllers/activity_types_controller.rb index d71124a5..a08dd7af 100644 --- a/app/controllers/activity_types_controller.rb +++ b/app/controllers/activity_types_controller.rb @@ -1,5 +1,5 @@ class ActivityTypesController < ApplicationController - before_action :set_activity_type, only: [:show, :edit, :update, :destroy] + before_action :set_activity_type, only: %i[show edit update destroy] # GET /activity_types # GET /activity_types.json @@ -23,8 +23,7 @@ def new end # GET /activity_types/1/edit - def edit - end + def edit; end # POST /activity_types # POST /activity_types.json @@ -75,6 +74,6 @@ def set_activity_type # Never trust parameters from the scary internet, only allow the white list through. def activity_type_params - params.require(:activity_type).permit(:name, :n3_definition, { :step_type_ids => [] }) + params.require(:activity_type).permit(:name, :n3_definition, { step_type_ids: [] }) end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3ac19b8d..f41fc7dc 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,7 +3,7 @@ class ApplicationController < ActionController::Base # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception - rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found + rescue_from ActiveRecord::RecordNotFound, with: :record_not_found before_action :set_current_user @@ -11,13 +11,13 @@ class ApplicationController < ActionController::Base def record_not_found(_exception) flash.now[:error] = 'No record found' - redirect_to :action => 'index' + redirect_to action: 'index' end def set_current_user @current_user = nil if session[:token] - @current_user = User.find_by(:token => session[:token]) + @current_user = User.find_by(token: session[:token]) unless @current_user # If I am logged in a different host, I lose the session in this one session[:token] = nil diff --git a/app/controllers/asset_groups_controller.rb b/app/controllers/asset_groups_controller.rb index 76f2076e..11df32e3 100644 --- a/app/controllers/asset_groups_controller.rb +++ b/app/controllers/asset_groups_controller.rb @@ -1,6 +1,6 @@ class AssetGroupsController < ApplicationController - before_action :set_asset_group, only: [:show, :update, :print, :upload] - before_action :set_activity, only: [:show, :update] + before_action :set_asset_group, only: %i[show update print upload] + before_action :set_activity, only: %i[show update] before_action :update_barcodes, only: [:update] include ActionController::Live @@ -43,9 +43,7 @@ def print def update_barcodes perform_assets_update - if @alerts - render json: { errors: @alerts } - end + render json: { errors: @alerts } if @alerts end def set_activity @@ -59,9 +57,12 @@ def set_asset_group end def perform_assets_update - @asset_group.update_attributes(assets: params_update_asset_group[:assets].filter_map do |uuid_or_barcode| - Asset.find_or_import_asset_with_barcode(uuid_or_barcode) - end.uniq) + @asset_group.update_attributes( + assets: + params_update_asset_group[:assets].filter_map do |uuid_or_barcode| + Asset.find_or_import_asset_with_barcode(uuid_or_barcode) + end.uniq + ) end def show_alert(data) @@ -70,6 +71,6 @@ def show_alert(data) end def params_update_asset_group - params.require(:asset_group).permit(:assets => []) + params.require(:asset_group).permit(assets: []) end end diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index e232d769..9c529d4a 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -1,50 +1,44 @@ class AssetsController < ApplicationController - before_action :set_asset, only: [:show, :edit, :update, :destroy, :print] - before_action :set_queries, only: [:search, :print_search] + before_action :set_asset, only: %i[show edit update destroy print] + before_action :set_queries, only: %i[search print_search] # GET /assets # GET /assets.json def index - @assets = Asset.all.includes(:facts).paginate(:page => params[:page], :per_page => 5) + @assets = Asset.all.includes(:facts).paginate(page: params[:page], per_page: 5) end def print @asset.print(@current_user.printer_config, @current_user.username) - respond_to do |format| - format.html { redirect_to @asset, notice: 'Asset was printed.' } - end + respond_to { |format| format.html { redirect_to @asset, notice: 'Asset was printed.' } } end def print_search @start_time = Time.now - @assets = get_search_results(@queries).paginate(:page => params[:page], :per_page => 10) + @assets = get_search_results(@queries).paginate(page: params[:page], per_page: 10) temp_group = AssetGroup.new temp_group.assets << @assets temp_group.print(@current_user.printer_config, @current_user.username) - respond_to do |format| - format.html { render :search, notice: 'Search was printed.' } - end + respond_to { |format| format.html { render :search, notice: 'Search was printed.' } } end def search @start_time = Time.now - @assets = get_search_results(@queries).paginate(:page => params[:page], :per_page => 10) + @assets = get_search_results(@queries).paginate(page: params[:page], per_page: 10) @valid_indexes = valid_indexes - respond_to do |format| - format.html { render :search } - end + respond_to { |format| format.html { render :search } } end # GET /assets/1 # GET /assets/1.json def show_by_internal_id @asset = Asset.find!(params[:id]) - redirect_to asset_path(@asset.uuid, :format => nil) + redirect_to asset_path(@asset.uuid, format: nil) end # GET /assets/1 @@ -62,8 +56,7 @@ def new end # GET /assets/1/edit - def edit - end + def edit; end # POST /assets # POST /assets.json @@ -111,11 +104,7 @@ def destroy # Use callbacks to share common setup or constraints between actions. def set_asset - @asset = if TokenUtil::UUID_REGEXP.match(params[:id]) - Asset.find_by(uuid: params[:id]) - else - Asset.find(params[:id]) - end + @asset = TokenUtil::UUID_REGEXP.match(params[:id]) ? Asset.find_by(uuid: params[:id]) : Asset.find(params[:id]) end def get_search_results(queries) @@ -127,9 +116,10 @@ def valid_indexes end def set_queries - @queries = valid_indexes.map do |val| - OpenStruct.new({ :predicate => params["p" + val], :object => params["o" + val] }) # rubocop:todo Style/OpenStructUse - end + @queries = + valid_indexes.map do |val| + OpenStruct.new({ predicate: params['p' + val], object: params['o' + val] }) # rubocop:todo Style/OpenStructUse + end end # Never trust parameters from the scary internet, only allow the white list through. diff --git a/app/controllers/changes_controller.rb b/app/controllers/changes_controller.rb index 7a205d75..55ada07d 100644 --- a/app/controllers/changes_controller.rb +++ b/app/controllers/changes_controller.rb @@ -3,18 +3,14 @@ def create @step = Step.create(state: 'running') json = params_changes.to_json @updates = FactChanges.new(json) - if @updates.apply(@step) - @step.update_attributes(state: 'complete') - end + @step.update_attributes(state: 'complete') if @updates.apply(@step) facts_updated = @updates.assets_updated.map(&:facts) render json: { - step: @step, - assets: @updates.assets_updated, - facts: facts_updated, - dataAssetDisplay: facts_updated.map do |facts| - helpers.data_asset_display(facts) - end - } + step: @step, + assets: @updates.assets_updated, + facts: facts_updated, + dataAssetDisplay: facts_updated.map { |facts| helpers.data_asset_display(facts) } + } end private diff --git a/app/controllers/history_controller.rb b/app/controllers/history_controller.rb index 69ada7b2..d834430c 100644 --- a/app/controllers/history_controller.rb +++ b/app/controllers/history_controller.rb @@ -1,5 +1,5 @@ class HistoryController < ApplicationController def index - @steps = Step.order(id: :desc).paginate(:page => params[:page], :per_page => 10) + @steps = Step.order(id: :desc).paginate(page: params[:page], per_page: 10) end end diff --git a/app/controllers/instruments_controller.rb b/app/controllers/instruments_controller.rb index 497f9c3d..3ee7acf0 100644 --- a/app/controllers/instruments_controller.rb +++ b/app/controllers/instruments_controller.rb @@ -1,5 +1,5 @@ class InstrumentsController < ApplicationController - before_action :set_instrument, only: [:show, :edit, :update, :destroy, :use] + before_action :set_instrument, only: %i[show edit update destroy use] # GET /instruments # GET /instruments.json @@ -9,8 +9,7 @@ def index # GET /instruments/1 # GET /instruments/1.json - def show - end + def show; end def use @activity = Activity.new @@ -22,8 +21,7 @@ def new end # GET /instruments/1/edit - def edit - end + def edit; end # POST /instruments # POST /instruments.json @@ -74,6 +72,6 @@ def set_instrument # Never trust parameters from the scary internet, only allow the white list through. def instrument_params - params.require(:instrument).permit(:barcode, :name, { :activity_type_ids => [] }) + params.require(:instrument).permit(:barcode, :name, { activity_type_ids: [] }) end end diff --git a/app/controllers/kit_types_controller.rb b/app/controllers/kit_types_controller.rb index d564ae94..7d5359f8 100644 --- a/app/controllers/kit_types_controller.rb +++ b/app/controllers/kit_types_controller.rb @@ -1,6 +1,6 @@ class KitTypesController < ApplicationController - before_action :set_kit_type, only: [:show, :edit, :update, :destroy] - before_action :set_activity_types, only: [:new, :show, :edit, :update] + before_action :set_kit_type, only: %i[show edit update destroy] + before_action :set_activity_types, only: %i[new show edit update] # GET /kit_types # GET /kit_types.json @@ -10,8 +10,7 @@ def index # GET /kit_types/1 # GET /kit_types/1.json - def show - end + def show; end # GET /kit_types/new def new @@ -19,8 +18,7 @@ def new end # GET /kit_types/1/edit - def edit - end + def edit; end # POST /kit_types # POST /kit_types.json diff --git a/app/controllers/kits_controller.rb b/app/controllers/kits_controller.rb index 6dd5def6..a6183e42 100644 --- a/app/controllers/kits_controller.rb +++ b/app/controllers/kits_controller.rb @@ -1,6 +1,6 @@ class KitsController < ApplicationController - before_action :set_kit, only: [:show, :edit, :update, :destroy] - before_action :set_kit_types, only: [:new, :show, :edit, :update] + before_action :set_kit, only: %i[show edit update destroy] + before_action :set_kit_types, only: %i[new show edit update] # GET /kits # GET /kits.json @@ -10,8 +10,7 @@ def index # GET /kits/1 # GET /kits/1.json - def show - end + def show; end # GET /kits/new def new @@ -19,8 +18,7 @@ def new end # GET /kits/1/edit - def edit - end + def edit; end # POST /kits # POST /kits.json diff --git a/app/controllers/printers_controller.rb b/app/controllers/printers_controller.rb index b4055f96..13ee7b8b 100644 --- a/app/controllers/printers_controller.rb +++ b/app/controllers/printers_controller.rb @@ -1,5 +1,5 @@ class PrintersController < ApplicationController - before_action :set_printer, only: [:show, :edit, :update, :destroy] + before_action :set_printer, only: %i[show edit update destroy] # GET /printers # GET /printers.json @@ -9,8 +9,7 @@ def index # GET /printers/1 # GET /printers/1.json - def show - end + def show; end # GET /printers/new def new @@ -18,8 +17,7 @@ def new end # GET /printers/1/edit - def edit - end + def edit; end # POST /printers # POST /printers.json diff --git a/app/controllers/reracking_controller.rb b/app/controllers/reracking_controller.rb index e38a5f24..f5703291 100644 --- a/app/controllers/reracking_controller.rb +++ b/app/controllers/reracking_controller.rb @@ -1,6 +1,6 @@ class RerackingController < ApplicationController before_action :set_activity_type - before_action :set_activity, :only => [:update, :show] + before_action :set_activity, only: %i[update show] def set_activity_type @activity_type = ActivityType.not_deprecated.where(name: 'Re-Racking').last diff --git a/app/controllers/samples_not_started_controller.rb b/app/controllers/samples_not_started_controller.rb index 9dae765b..8674a21e 100644 --- a/app/controllers/samples_not_started_controller.rb +++ b/app/controllers/samples_not_started_controller.rb @@ -2,9 +2,6 @@ class SamplesNotStartedController < SamplesStatusController private def get_assets_for_activity_type(activity_type) - activity_type.assets - .not_started - .preload(:facts) - .paginate(pagination_params_for_activity_type(activity_type)) + activity_type.assets.not_started.preload(:facts).paginate(pagination_params_for_activity_type(activity_type)) end end diff --git a/app/controllers/samples_started_controller.rb b/app/controllers/samples_started_controller.rb index edbd242f..3c12a48e 100644 --- a/app/controllers/samples_started_controller.rb +++ b/app/controllers/samples_started_controller.rb @@ -2,12 +2,13 @@ class SamplesStartedController < SamplesStatusController private def get_assets_for_activity_type(activity_type) - activity_type.assets - .started - .joins(:activities) - .preload(:facts, activities: [:instrument]) - .distinct(activities: :id, assets: :id) - .order(id: :desc) - .paginate(pagination_params_for_activity_type(activity_type)) + activity_type + .assets + .started + .joins(:activities) + .preload(:facts, activities: [:instrument]) + .distinct(activities: :id, assets: :id) + .order(id: :desc) + .paginate(pagination_params_for_activity_type(activity_type)) end end diff --git a/app/controllers/samples_status_controller.rb b/app/controllers/samples_status_controller.rb index 79ea531b..b31cbcf4 100644 --- a/app/controllers/samples_status_controller.rb +++ b/app/controllers/samples_status_controller.rb @@ -5,16 +5,15 @@ class SamplesStatusController < ApplicationController before_action :set_activity_types, only: [:index] before_action :set_assets_for_activity_types, only: [:index] - def index - end + def index; end private def pagination_params_for_activity_type(activity_type) if samples_started_params[:activity_type_id].to_i == activity_type.id - { :page => samples_started_params[:page], :per_page => 5 } + { page: samples_started_params[:page], per_page: 5 } else - { :page => 1, :per_page => 5 } + { page: 1, per_page: 5 } end end @@ -31,11 +30,9 @@ def set_activity_types end def set_assets_for_activity_types - @assets_for_activity_types = @activity_types.map do |activity_type| - { - :activity_type => activity_type, - :assets => get_assets_for_activity_type(activity_type) - } - end + @assets_for_activity_types = + @activity_types.map do |activity_type| + { activity_type: activity_type, assets: get_assets_for_activity_type(activity_type) } + end end end diff --git a/app/controllers/step_types_controller.rb b/app/controllers/step_types_controller.rb index cc2407b9..80dc90f5 100644 --- a/app/controllers/step_types_controller.rb +++ b/app/controllers/step_types_controller.rb @@ -1,12 +1,12 @@ class StepTypesController < ApplicationController - before_action :set_step_type, only: [:show, :edit, :update, :destroy] + before_action :set_step_type, only: %i[show edit update destroy] # GET /step_types # GET /step_types.json def index @step_types = StepType.not_deprecated unless @activity respond_to do |format| - format.html { render 'active', :layout => false } if @activity + format.html { render 'active', layout: false } if @activity format.html { render 'index' } end end @@ -26,8 +26,7 @@ def new end # GET /step_types/1/edit - def edit - end + def edit; end # POST /step_types # POST /step_types.json @@ -79,7 +78,7 @@ def set_step_type def empty_options_set_to_nil(params) params_copy = params.dup if params - [:step_template, :connect_by, :step_action].each do |key| + %i[step_template connect_by step_action].each do |key| params_copy[key] = nil if params[key] && params[key].empty? end end @@ -88,6 +87,8 @@ def empty_options_set_to_nil(params) # Never trust parameters from the scary internet, only allow the white list through. def step_type_params - params.require(:step_type).permit(:n3_definition, :name, :step_template, :connect_by, :for_reasoning, :step_action, :priority) + params + .require(:step_type) + .permit(:n3_definition, :name, :step_template, :connect_by, :for_reasoning, :step_action, :priority) end end diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb index 38e3e657..cc9633e4 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -57,17 +57,16 @@ def set_step_type def set_printer_config tube_printer = Printer.find_by(id: params_step[:tube_printer_id]) || nil - plate_printer = Printer.find_by(id: params_step[:plate_printer_id]) || nil + plate_printer = Printer.find_by(id: params_step[:plate_printer_id]) || nil tube_rack_printer = Printer.find_by(id: params_step[:plate_printer_id]) || nil @printer_config = { - 'Tube' => tube_printer.nil? ? "" : tube_printer.name, - 'Plate' => plate_printer.nil? ? "" : plate_printer.name, - 'TubeRack' => tube_rack_printer.nil? ? "" : tube_rack_printer.name + 'Tube' => tube_printer.nil? ? '' : tube_printer.name, + 'Plate' => plate_printer.nil? ? '' : plate_printer.name, + 'TubeRack' => tube_rack_printer.nil? ? '' : tube_rack_printer.name } end def params_step - params.require(:step).permit(:step_type_id, :asset_group_id, :tube_printer_id, :plate_printer_id, - :event_name) + params.require(:step).permit(:step_type_id, :asset_group_id, :tube_printer_id, :plate_printer_id, :event_name) end end diff --git a/app/controllers/uploaded_files_controller.rb b/app/controllers/uploaded_files_controller.rb index f057962a..863fac0f 100644 --- a/app/controllers/uploaded_files_controller.rb +++ b/app/controllers/uploaded_files_controller.rb @@ -3,9 +3,7 @@ class UploadedFilesController < ApplicationController def show respond_to do |format| - format.bin do - send_data(@uploaded_file.data, filename: @uploaded_file.filename) - end + format.bin { send_data(@uploaded_file.data, filename: @uploaded_file.filename) } format.html { render :show } format.n3 { render :show } end diff --git a/app/controllers/user_sessions_controller.rb b/app/controllers/user_sessions_controller.rb index c03d7011..1cde1679 100644 --- a/app/controllers/user_sessions_controller.rb +++ b/app/controllers/user_sessions_controller.rb @@ -19,6 +19,6 @@ def user_session_params end def set_user - @user = User.find_by!(:barcode => user_session_params[:barcode]) + @user = User.find_by!(barcode: user_session_params[:barcode]) end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 8df0d715..8d866bf6 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,5 @@ class UsersController < ApplicationController - before_action :set_user, only: [:show, :edit, :update, :destroy] + before_action :set_user, only: %i[show edit update destroy] # GET /users # GET /users.json @@ -9,8 +9,7 @@ def index # GET /users/1 # GET /users/1.json - def show - end + def show; end # GET /users/new def new @@ -18,13 +17,12 @@ def new end def find_by_barcode - @user = User.find_by(:barcode => user_params[:barcode]) + @user = User.find_by(barcode: user_params[:barcode]) render @user end # GET /users/1/edit - def edit - end + def edit; end # POST /users # POST /users.json diff --git a/app/helpers/activities_helper.rb b/app/helpers/activities_helper.rb index 81c3c34a..62901ca9 100644 --- a/app/helpers/activities_helper.rb +++ b/app/helpers/activities_helper.rb @@ -9,13 +9,15 @@ def ontology_json end def step_types_data_for_step_types(activity, step_types) - step_types.select { |st| st.step_template.blank? }.map do |st| - { - createStepUrl: Rails.application.routes.url_helpers.activity_steps_path(activity), - stepType: st, - name: st.name - } - end + step_types + .select { |st| st.step_template.blank? } + .map do |st| + { + createStepUrl: Rails.application.routes.url_helpers.activity_steps_path(activity), + stepType: st, + name: st.name + } + end end def step_types_for_asset_groups_data(activity, asset_group) @@ -30,11 +32,13 @@ def step_types_for_asset_groups_data(activity, asset_group) def step_types_control_data(activity) return {} if activity.running? - activity.owned_asset_groups.reduce({}) do |memo, asset_group| - data_for_step_types = step_types_for_asset_groups_data(activity, asset_group) - memo[asset_group.id] = data_for_step_types - memo - end + activity + .owned_asset_groups + .reduce({}) do |memo, asset_group| + data_for_step_types = step_types_for_asset_groups_data(activity, asset_group) + memo[asset_group.id] = data_for_step_types + memo + end end def steps_data_for_steps(steps) @@ -53,28 +57,26 @@ def steps_data_for_steps(steps) def steps_without_operations_data_for_steps(steps) steps.map do |step| - { - state: step.state, - asset_group_id: step.asset_group.id, - step_type_id: step.step_type.id, - step_id: step.id - } + { state: step.state, asset_group_id: step.asset_group.id, step_type_id: step.step_type.id, step_id: step.id } end end def operations_data(operations) operations.map do |fact| elem = fact.object_asset - obj = if elem - { "object_asset" => { - uuid: elem.uuid, - barcode: elem.barcode, - id: elem.id, - info_line: elem.info_line - } }.merge(fact.attributes) - else - fact.attributes - end + obj = + if elem + { + 'object_asset' => { + uuid: elem.uuid, + barcode: elem.barcode, + id: elem.id, + info_line: elem.info_line + } + }.merge(fact.attributes) + else + fact.attributes + end obj[:asset] = fact.asset.attributes obj end @@ -84,12 +86,9 @@ def facts_data(facts) facts.map do |fact| elem = fact.object_asset if elem - { "object_asset" => { - uuid: elem.uuid, - barcode: elem.barcode, - id: elem.id, - info_line: elem.info_line - } }.merge(fact.attributes) + { 'object_asset' => { uuid: elem.uuid, barcode: elem.barcode, id: elem.id, info_line: elem.info_line } }.merge( + fact.attributes + ) else fact.attributes end @@ -115,41 +114,41 @@ def asset_group_data(activity, asset_group) end def asset_groups_data(activity) - activity.owned_asset_groups.reduce({}) do |memo, asset_group| - asset_group.assets.reload - data_for_step_types = asset_group_data(activity, asset_group) - memo[asset_group.id] = data_for_step_types - memo - end + activity + .owned_asset_groups + .reduce({}) do |memo, asset_group| + asset_group.assets.reload + data_for_step_types = asset_group_data(activity, asset_group) + memo[asset_group.id] = data_for_step_types + memo + end end def step_type_templates_data_for_step_types(activity, step_types, asset_group) - step_types.select { |s| !s.step_template.blank? }.map do |st| - { - assetGroup: asset_group, - createStepUrl: Rails.application.routes.url_helpers.activity_steps_path(activity), - stepType: st, - name: st.name, - id: "step-type-id-#{rand(9999)}-#{st.id}" - } - end + step_types + .select { |s| !s.step_template.blank? } + .map do |st| + { + assetGroup: asset_group, + createStepUrl: Rails.application.routes.url_helpers.activity_steps_path(activity), + stepType: st, + name: st.name, + id: "step-type-id-#{rand(9999)}-#{st.id}" + } + end end def data_asset_display_for_asset_group(asset_group) - asset_group.assets.each_with_object({}) do |asset, memo| - memo[asset.uuid] = data_asset_display(asset.facts) - end + asset_group.assets.each_with_object({}) { |asset, memo| memo[asset.uuid] = data_asset_display(asset.facts) } end def data_asset_display_for_activity(activity) - activity.owned_asset_groups.reduce({}) do |memo, asset_group| - memo.merge(data_asset_display_for_asset_group(asset_group)) - end + activity + .owned_asset_groups + .reduce({}) { |memo, asset_group| memo.merge(data_asset_display_for_asset_group(asset_group)) } end def messages_for_activity(activity) - activity.steps.failed.map(&:step_messages).flatten.map do |m| - { type: 'danger', msg: m.content.to_s.html_safe } - end + activity.steps.failed.map(&:step_messages).flatten.map { |m| { type: 'danger', msg: m.content.to_s.html_safe } } end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 8b649b55..120ca847 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -8,7 +8,7 @@ def empty_well_aliquot_type end def bootstrap_link_to(name = nil, options = nil, html_options = nil) - modified_options = { :class => 'btn btn-default' } + modified_options = { class: 'btn btn-default' } modified_options.merge!(html_options) if html_options link_to(name, options, modified_options) end @@ -16,26 +16,18 @@ def bootstrap_link_to(name = nil, options = nil, html_options = nil) def default_ontologies [ "@prefix se: <#{n3_url_for_ontology('root-ontology.ttl')}#> .", - "@prefix log: ." + '@prefix log: .' ].join("\n").html_safe end def n3_url_for_ontology(name) url_definition = Rails.configuration.default_n3_resources_url - if url_definition - "#{url_definition}#{path_to_asset(name)}" - else - "#{url_to_asset(name)}" - end + url_definition ? "#{url_definition}#{path_to_asset(name)}" : "#{url_to_asset(name)}" end def n3_url_resource_for(asset_uuid) url_definition = Rails.configuration.default_n3_resources_url - if url_definition - "#{url_definition}/labware/#{asset_uuid}" - else - asset_url(asset_uuid) - end + url_definition ? "#{url_definition}/labware/#{asset_uuid}" : asset_url(asset_uuid) end def traversable_predicate(predicate) @@ -44,11 +36,7 @@ def traversable_predicate(predicate) def object_for(fact) if fact.object_asset.nil? - if fact.literal? - "\"\"\"#{fact.object}\"\"\"".html_safe - else - "se:#{fact.object}".html_safe - end + fact.literal? ? "\"\"\"#{fact.object}\"\"\"".html_safe : "se:#{fact.object}".html_safe else "<#{n3_url_resource_for(fact.object_asset.uuid)}>".html_safe end @@ -56,7 +44,10 @@ def object_for(fact) def render_react_display_for_asset(asset) data_asset_display = {}.tap { |o| o[asset.uuid] = data_asset_display(asset.facts) } - react_component('FactsSvg', { asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display }) + react_component( + 'FactsSvg', + { asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display } + ) end def render_react_tooltip @@ -64,7 +55,10 @@ def render_react_tooltip end def facts_with_object_asset(facts) - facts.left_outer_joins(:object_asset).to_a.map { |f| f.attributes.merge({ object_asset: object_with_facts(f.object_asset) }) } + facts + .left_outer_joins(:object_asset) + .to_a + .map { |f| f.attributes.merge({ object_asset: object_with_facts(f.object_asset) }) } end def object_with_facts(object) @@ -75,35 +69,46 @@ def object_with_facts(object) def render_react_display_and_facts_for_asset(asset) data_asset_display = {}.tap { |o| o[asset.uuid] = data_asset_display(asset.facts) } - react_component('Facts', { asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display }) + react_component( + 'Facts', + { asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display } + ) end def render_react_edit_asset(asset, readonly = false) data_asset_display = {}.tap { |o| o[asset.uuid] = data_asset_display(asset.facts) } - react_component('FactsEditor', { - changesUrl: readonly ? nil : changes_url, - asset: asset, facts: facts_with_object_asset(asset.facts), dataAssetDisplay: data_asset_display - }) + react_component( + 'FactsEditor', + { + changesUrl: readonly ? nil : changes_url, + asset: asset, + facts: facts_with_object_asset(asset.facts), + dataAssetDisplay: data_asset_display + } + ) end def data_asset_display_for_plate(facts) - facts.with_predicate('contains').map(&:object_asset).reduce({}) do |memo, asset| - location = TokenUtil.unpad_location(asset.first_value_for('location')) - if (location && (asset.has_sample? || !asset.barcode.nil?)) - if asset.has_sample? - aliquotType = asset.first_value_for('aliquotType') || unknown_aliquot_type - else - aliquotType = empty_well_aliquot_type + facts + .with_predicate('contains') + .map(&:object_asset) + .reduce({}) do |memo, asset| + location = TokenUtil.unpad_location(asset.first_value_for('location')) + if (location && (asset.has_sample? || !asset.barcode.nil?)) + if asset.has_sample? + aliquotType = asset.first_value_for('aliquotType') || unknown_aliquot_type + else + aliquotType = empty_well_aliquot_type + end + + memo[location] = { + title: "#{asset.short_description}", + cssClass: aliquotType, + url: Rails.application.routes.url_helpers.asset_path(asset) + } unless location.nil? end - - memo[location] = { - title: "#{asset.short_description}", - cssClass: aliquotType, - url: Rails.application.routes.url_helpers.asset_path(asset) - } unless location.nil? + memo end - memo - end end def data_asset_display_for_tube(facts) @@ -118,11 +123,7 @@ def data_asset_display_for_tube(facts) url = '' title = '' end - { - aliquot: { - cssClass: css_classes, title: title, url: url - } - } + { aliquot: { cssClass: css_classes, title: title, url: url } } end def data_asset_display(facts) @@ -148,8 +149,10 @@ def show_alert(data) end def trigger_alerts - triggers = @alerts.map do |a| - "" - end.join('\n').html_safe if @alerts + triggers = + @alerts + .map { |a| "" } + .join('\n') + .html_safe if @alerts end end diff --git a/app/helpers/assets_helper.rb b/app/helpers/assets_helper.rb index c9caf848..d0f8ccf4 100644 --- a/app/helpers/assets_helper.rb +++ b/app/helpers/assets_helper.rb @@ -1,18 +1,19 @@ module AssetsHelper def condition_groups_init_for_asset(asset) obj = {} - obj[asset.barcode] = { :template => 'templates/asset_facts' } - obj[asset.barcode][:facts] = asset.facts.map do |fact| - { - :cssClasses => '', - :name => asset.uuid, - :actionType => 'createAsset', - :predicate => fact.predicate, - :object_reference => fact.object_asset_id, - :object_label => fact.object_label, - :object => asset.object_value(fact) - } - end + obj[asset.barcode] = { template: 'templates/asset_facts' } + obj[asset.barcode][:facts] = + asset.facts.map do |fact| + { + cssClasses: '', + name: asset.uuid, + actionType: 'createAsset', + predicate: fact.predicate, + object_reference: fact.object_asset_id, + object_label: fact.object_label, + object: asset.object_value(fact) + } + end obj end diff --git a/app/helpers/step_types_helper.rb b/app/helpers/step_types_helper.rb index 79856601..400c2c87 100644 --- a/app/helpers/step_types_helper.rb +++ b/app/helpers/step_types_helper.rb @@ -11,39 +11,48 @@ def fact_css_classes end def condition_groups_init_for_step_type(step_type) - cgroups = step_type.condition_groups.reduce({}) do |memo, condition_group| - name = condition_group.name || "a#{condition_group.id}" - memo[name] = { - :cardinality => condition_group.cardinality, - :keepSelected => condition_group.keep_selected, - :facts => condition_group.conditions.map do |condition| - { - :cssClasses => fact_css_classes['checkFacts'], - :name => name, - :actionType => 'checkFacts', - :predicate => condition.predicate, - :object => condition.object + cgroups = + step_type + .condition_groups + .reduce({}) do |memo, condition_group| + name = condition_group.name || "a#{condition_group.id}" + memo[name] = { + cardinality: condition_group.cardinality, + keepSelected: condition_group.keep_selected, + facts: + condition_group.conditions.map do |condition| + { + cssClasses: fact_css_classes['checkFacts'], + name: name, + actionType: 'checkFacts', + predicate: condition.predicate, + object: condition.object + } + end } + memo + end + agroups = + step_type + .actions + .reduce(cgroups) do |memo, action| + name = action.subject_condition_group.name || "a#{action.subject_condition_group.id}" + memo[name] = { + facts: [], + cardinality: action.subject_condition_group.cardinality, + keepSelected: action.subject_condition_group.keep_selected + } unless memo[name] + memo[name][:facts].push( + { + cssClasses: fact_css_classes[action.action_type], + name: name, + actionType: action.action_type, + predicate: action.predicate, + object: action.object + } + ) + memo end - } - memo - end - agroups = step_type.actions.reduce(cgroups) do |memo, action| - name = action.subject_condition_group.name || "a#{action.subject_condition_group.id}" - memo[name] = { - :facts => [], - :cardinality => action.subject_condition_group.cardinality, - :keepSelected => action.subject_condition_group.keep_selected - } unless memo[name] - memo[name][:facts].push({ - :cssClasses => fact_css_classes[action.action_type], - :name => name, - :actionType => action.action_type, - :predicate => action.predicate, - :object => action.object - }) - memo - end agroups.to_json end end diff --git a/app/helpers/steps_helper.rb b/app/helpers/steps_helper.rb index d7311421..17c60246 100644 --- a/app/helpers/steps_helper.rb +++ b/app/helpers/steps_helper.rb @@ -4,7 +4,7 @@ def text_color_for_state(state) end def color_for_state(state) - css = "primary" + css = 'primary' css = 'success' if state == 'complete' css = 'danger' if state == 'error' css = 'warning' if state == 'running' diff --git a/app/javascript/components/activity.jsx b/app/javascript/components/activity.jsx index 114d6865..1a3d7e50 100644 --- a/app/javascript/components/activity.jsx +++ b/app/javascript/components/activity.jsx @@ -1,20 +1,20 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; +import React from 'react' +import ReactDOM from 'react-dom' import ReactTooltip from 'react-tooltip' import ActivityControl from './activity_components/activity_control' import AlertDisplay from './activity_components/alert_display' -import ActivityDescription from "./activity_components/activity_description" -import PrintersSelection from "./activity_components/printers_selection" -import AssetGroupsEditor from "./asset_group_components/asset_groups_editor" -import Steps from "./step_components/steps" -import StepsRunning from "./step_components/steps_running" -import StepsFailed from "./step_components/steps_failed" -import StepTypesControl from "./step_type_components/step_types_control" -import C from "./step_components/step_states" +import ActivityDescription from './activity_components/activity_description' +import PrintersSelection from './activity_components/printers_selection' +import AssetGroupsEditor from './asset_group_components/asset_groups_editor' +import Steps from './step_components/steps' +import StepsRunning from './step_components/steps_running' +import StepsFailed from './step_components/steps_failed' +import StepTypesControl from './step_type_components/step_types_control' +import C from './step_components/step_states' -import {FormFor, HashFields} from "react-rails-form-helpers" +import { FormFor, HashFields } from 'react-rails-form-helpers' const MAX_BARCODE_SIZE = 255 @@ -35,7 +35,7 @@ class Activity extends React.Component { stepsFailed: props.stepsFailed, activityRunning: props.activityRunning, dataAssetDisplay: props.dataAssetDisplay, - collapsedFacts: {} + collapsedFacts: {}, } this.onSelectAssetGroup = this.onSelectAssetGroup.bind(this) this.onChangeAssetGroup = this.onChangeAssetGroup.bind(this) @@ -62,26 +62,29 @@ class Activity extends React.Component { this.listenWebSockets() } onCollapseFacts(collapsedFacts, uuid, predicate) { - return(()=>{ + return () => { let obj = Object.create({}, collapsedFacts) if (!obj[uuid]) { - obj[uuid]={} + obj[uuid] = {} } if (obj[uuid][predicate] === true) { - obj[uuid][predicate]=false + obj[uuid][predicate] = false } else { - obj[uuid][predicate]=true + obj[uuid][predicate] = true } return obj - }) + } } listenWebSockets() { - this.activityChannel = App.cable.subscriptions.create({ - channel: 'ActivityChannel', - activity_id: this.props.activity.id - }, { - received: $.proxy(this.onWebSocketsMessage, this) - }) + this.activityChannel = App.cable.subscriptions.create( + { + channel: 'ActivityChannel', + activity_id: this.props.activity.id, + }, + { + received: $.proxy(this.onWebSocketsMessage, this), + } + ) } getAllAssets() { return Object.values(this.state.assetGroups).flat() @@ -90,7 +93,7 @@ class Activity extends React.Component { let newState if (msg.error) { - newState = {messages: [msg.error]} + newState = { messages: [msg.error] } } else { var selectedGroup = this.state.selectedAssetGroup if (!(msg.assetGroups && msg.assetGroups[selectedGroup])) { @@ -111,23 +114,22 @@ class Activity extends React.Component { stepsRunning: msg.stepsRunning || [], stepsFailed: msg.stepsFailed, stepsPending: msg.stepsPending || [], - stepsFinished: msg.stepsFinished + stepsFinished: msg.stepsFinished, } } this.setState(newState) - } onRemoveErrorMessage(msg, pos) { - this.state.messages.splice(pos,1) - this.setState({messages: this.state.messages}) + this.state.messages.splice(pos, 1) + this.setState({ messages: this.state.messages }) } onErrorMessage(msg) { this.state.messages.push(msg) - this.setState({messages: this.state.messages}) + this.setState({ messages: this.state.messages }) } onSelectAssetGroup(assetGroup) { - this.setState({selectedAssetGroup: assetGroup.id}) + this.setState({ selectedAssetGroup: assetGroup.id }) } onChangeAssetGroup(msg) { return msg @@ -142,42 +144,40 @@ class Activity extends React.Component { barcodesFromInput(barcodes) { return barcodes.split(' ').filter((b) => { - return ((b.length > 0) && (b.length < MAX_BARCODE_SIZE) && (b.match(/\w+/))) + return b.length > 0 && b.length < MAX_BARCODE_SIZE && b.match(/\w+/) }) } onAddBarcodesToAssetGroup(assetGroup, userInput) { - return this.changeAssetGroup(assetGroup, - {asset_group: { - id: assetGroup.id, - assets: this.getAssetUuidsForAssetGroup(assetGroup).concat(this.barcodesFromInput(userInput)) - } - } - ) + return this.changeAssetGroup(assetGroup, { + asset_group: { + id: assetGroup.id, + assets: this.getAssetUuidsForAssetGroup(assetGroup).concat(this.barcodesFromInput(userInput)), + }, + }) } - onRemoveAssetFromAssetGroup(assetGroup, asset, pos){ - + onRemoveAssetFromAssetGroup(assetGroup, asset, pos) { let uuids = this.getAssetUuidsForAssetGroup(assetGroup) let removedUuid = asset.uuid - let newUuids = uuids.filter((uuid) => (uuid != removedUuid)) + let newUuids = uuids.filter((uuid) => uuid != removedUuid) this.state.uuidsPendingRemoval.push(removedUuid) let uuidsPendingRemoval = this.state.uuidsPendingRemoval - this.setState({uuidsPendingRemoval}) + this.setState({ uuidsPendingRemoval }) return this.changeAssetGroup(assetGroup, { asset_group: { id: assetGroup.id, - assets: newUuids - } + assets: newUuids, + }, }) } - onRemoveAllAssetsFromAssetGroup(assetGroup){ + onRemoveAllAssetsFromAssetGroup(assetGroup) { return this.changeAssetGroup(assetGroup, { asset_group: { id: assetGroup.id, - assets: [] - } + assets: [], + }, }) } @@ -188,8 +188,12 @@ class Activity extends React.Component { return; }*/ const event_name = stateEventName || (e.target.checked ? C.STEP_EVENT_REMAKE : C.STEP_EVENT_CANCEL) - this.setState({activityRunning: true}) - this.changeStateStep(step, event_name).then($.proxy(() => { this.setState({activityRunning: false}) }, this)) + this.setState({ activityRunning: true }) + this.changeStateStep(step, event_name).then( + $.proxy(() => { + this.setState({ activityRunning: false }) + }, this) + ) } } @@ -199,31 +203,31 @@ class Activity extends React.Component { dataType: 'json', contentType: 'application/json; charset=utf-8', url: step.stepUpdateUrl, - data: JSON.stringify({step: {event_name}}) + data: JSON.stringify({ step: { event_name } }), }) } onChangeTubePrinter(e) { - this.setState({selectedTubePrinter: e.target.value}) + this.setState({ selectedTubePrinter: e.target.value }) } onChangePlatePrinter(e) { - this.setState({selectedPlatePrinter: e.target.value}) + this.setState({ selectedPlatePrinter: e.target.value }) } onExecuteStep(msg) { - this.setState({activityRunning: true}) + this.setState({ activityRunning: true }) } changeShownComponents() { this.activityChannel.send({ activity: { id: this.props.activity.id, - stepsFinished: !this.state.stepsFinished - } + stepsFinished: !this.state.stepsFinished, + }, }) } onToggleComponentBuilder(componentName) { return () => { let msg = { activity: {} } - msg.activity[componentName] = (typeof this.state[componentName] === 'undefined') + msg.activity[componentName] = typeof this.state[componentName] === 'undefined' console.log(this.state) this.activityChannel.send(msg) } @@ -233,86 +237,84 @@ class Activity extends React.Component { } renderStepTypesControl(instanceId) { const steps = [].concat(this.state.stepsRunning).concat(this.state.stepsPending) - if ((this.state.stepsFailed) && (this.state.stepsFailed.length > 0)) { - return() + if (this.state.stepsFailed && this.state.stepsFailed.length > 0) { + return } else { - if ((this.state.stepsRunning) && (this.state.stepsRunning.length > 0)) { - return() + if (this.state.stepsRunning && this.state.stepsRunning.length > 0) { + return } else { - return( - - ) + instanceId={instanceId} + onExecuteStep={this.onExecuteStep} + activityRunning={this.state.activityRunning} + selectedAssetGroup={this.state.selectedAssetGroup} + selectedTubePrinter={this.state.selectedTubePrinter} + selectedPlatePrinter={this.state.selectedPlatePrinter} + /> + ) } } } renderAssetGroupsEditorAndStepTypes() { - if (this.props.activityState=='finish') { + if (this.props.activityState == 'finish') { return null } else { - return( + return ( - {this.renderStepTypesControl("1")} - - {this.renderStepTypesControl("2")} + {this.renderStepTypesControl('1')} + + {this.renderStepTypesControl('2')} ) } } - render () { + render() { return (
-

Activity {this.props.activity.id }  - -

+

+ Activity {this.props.activity.id}  + +

- - - + + + - - {this.renderAssetGroupsEditorAndStepTypes()} - + + {this.renderAssetGroupsEditorAndStepTypes()} +
) } diff --git a/app/javascript/components/activity_components/activity_control.jsx b/app/javascript/components/activity_components/activity_control.jsx index 23144a8a..3e01b219 100644 --- a/app/javascript/components/activity_components/activity_control.jsx +++ b/app/javascript/components/activity_components/activity_control.jsx @@ -1,15 +1,15 @@ const ActivityControl = (props) => { if (props.activityRunning) { return ( - - - - - ) + + + + + + ) } else { return null } } - export default ActivityControl diff --git a/app/javascript/components/activity_components/activity_description.jsx b/app/javascript/components/activity_components/activity_description.jsx index 5c038d68..8cccc7f0 100644 --- a/app/javascript/components/activity_components/activity_description.jsx +++ b/app/javascript/components/activity_components/activity_description.jsx @@ -1,39 +1,53 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import {Label, TextField} from "react-rails-form-helpers" +import React from 'react' +import ReactDOM from 'react-dom' +import { Label, TextField } from 'react-rails-form-helpers' class ActivityDescription extends React.Component { - renderCompletedAt() { - if (this.props.activity.completed_at) { - return( -
- This activity was finished at {this.props.activity.completed_at} -
- ) - } - } - render() { - return( + renderCompletedAt() { + if (this.props.activity.completed_at) { + return
This activity was finished at {this.props.activity.completed_at}
+ } + } + render() { + return ( {this.renderCompletedAt()} -
-
- - -
-
- - -
+
+
+ + +
+
+ + +
-
- - -
-
+
+ + +
+
- ) - } + ) + } } export default ActivityDescription diff --git a/app/javascript/components/activity_components/alert_display.jsx b/app/javascript/components/activity_components/alert_display.jsx index 5cb846fd..79f17a8e 100644 --- a/app/javascript/components/activity_components/alert_display.jsx +++ b/app/javascript/components/activity_components/alert_display.jsx @@ -7,29 +7,35 @@ class AlertDisplay extends React.Component { this.renderMessage = this.renderMessage.bind(this) } onRemoveMsg(m, pos) { - this.props.onRemoveErrorMessage(m,pos) + this.props.onRemoveErrorMessage(m, pos) } renderMessage(m, pos) { const destroyMessage = $.proxy(this.onRemoveMsg, this, m, pos) - if (m.type=='info') { + if (m.type == 'info') { setTimeout(destroyMessage, 3000) } - return (
- {m.msg} - -
) - } + return ( +
+ {m.msg} + +
+ ) + } render() { if (this.props.messages.length == 0) { return null } - let messages = this.props.messages.slice(0,5) - return( + let messages = this.props.messages.slice(0, 5) + return ( - { this.props.messages.length } errors, showing { messages.length } -
- { messages.map(this.renderMessage) } + + {this.props.messages.length} errors, showing {messages.length} + +
+ {messages.map(this.renderMessage)}
) } diff --git a/app/javascript/components/activity_components/printers_selection.jsx b/app/javascript/components/activity_components/printers_selection.jsx index fe397b1f..615895b3 100644 --- a/app/javascript/components/activity_components/printers_selection.jsx +++ b/app/javascript/components/activity_components/printers_selection.jsx @@ -1,38 +1,45 @@ -import React from "react" +import React from 'react' -import {LabelTag, SelectTag} from "react-rails-form-helpers" +import { LabelTag, SelectTag } from 'react-rails-form-helpers' class PrintersSelection extends React.Component { renderOptions(optsData, defaultValue) { return optsData.map((pos, val) => { - return () + return ( + + ) }) } render() { - return( + return (
Tube Printer - + > {this.renderOptions(this.props.tubePrinter.optionsData)}
Plate Printer - + > {this.renderOptions(this.props.platePrinter.optionsData)}
- ) } } -export default PrintersSelection; +export default PrintersSelection diff --git a/app/javascript/components/activity_components/printers_selection_hidden.jsx b/app/javascript/components/activity_components/printers_selection_hidden.jsx index 4744fb97..3bcf29fd 100644 --- a/app/javascript/components/activity_components/printers_selection_hidden.jsx +++ b/app/javascript/components/activity_components/printers_selection_hidden.jsx @@ -1,21 +1,29 @@ import React from 'react' -import {HashFields, HiddenFieldTag} from "react-rails-form-helpers" +import { HashFields, HiddenFieldTag } from 'react-rails-form-helpers' class PrintersSelectionHidden extends React.Component { constructor(props) { super(props) this.nameForField = this.nameForField.bind(this) } nameForField(field) { - return this.props.entityName + "[" + field + "]" + return this.props.entityName + '[' + field + ']' } render() { - return( - - - - - ) + return ( + + + + + ) } } -export default PrintersSelectionHidden; +export default PrintersSelectionHidden diff --git a/app/javascript/components/asset_components/asset_display.jsx b/app/javascript/components/asset_components/asset_display.jsx index df5dcbf4..405b552b 100644 --- a/app/javascript/components/asset_components/asset_display.jsx +++ b/app/javascript/components/asset_components/asset_display.jsx @@ -2,10 +2,11 @@ import React from 'react' class AssetDisplay extends React.Component { render() { - return( -
{this.props.asset.barcode} + return ( +
+ {this.props.asset.barcode} -
+
diff --git a/app/javascript/components/asset_components/fact.jsx b/app/javascript/components/asset_components/fact.jsx index d9c167e9..11de8e42 100644 --- a/app/javascript/components/asset_components/fact.jsx +++ b/app/javascript/components/asset_components/fact.jsx @@ -1,7 +1,6 @@ import React from 'react' class Fact extends React.Component { - constructor(props) { super(props) this.valueForPredicate = this.valueForPredicate.bind(this) @@ -13,9 +12,11 @@ class Fact extends React.Component { } valueForPredicate(asset, predicate) { - let val = (asset.facts && asset.facts.filter((a) => { - return (a.predicate == predicate) - })[0]) + let val = + asset.facts && + asset.facts.filter((a) => { + return a.predicate == predicate + })[0] if (val) { return val.object } else { @@ -28,11 +29,11 @@ class Fact extends React.Component { } renderShortDescription(asset) { - let label = (asset && asset.barcode) ? asset.barcode : '#'+asset.id + let label = asset && asset.barcode ? asset.barcode : '#' + asset.id if (asset && asset.info_line) { - return (`${asset.info_line} ${this.classType(asset)} ${label}`) + return `${asset.info_line} ${this.classType(asset)} ${label}` } - return(`${this.valueForPredicate(asset, 'aliquotType')} ${this.classType(asset)} ${label}`) + return `${this.valueForPredicate(asset, 'aliquotType')} ${this.classType(asset)} ${label}` } renderObject(fact) { @@ -41,23 +42,31 @@ class Fact extends React.Component { return ( - { fact.object_asset ? this.renderShortDescription(fact.object_asset) : '#'+fact.object_asset_id } + {fact.object_asset ? this.renderShortDescription(fact.object_asset) : '#' + fact.object_asset_id} ) } else { - return ( { fact.object } ) + return {fact.object} } } tipForPredicate(predicate) { if (window.ONTOLOGY && window.ONTOLOGY[predicate]) { - return (window.ONTOLOGY[predicate].description || null) + return window.ONTOLOGY[predicate].description || null } } renderRemoveButton(fact) { if (this.props.onRemoveFact) { - return( { this.props.onRemoveFact(fact) }}>×) + return ( + { + this.props.onRemoveFact(fact) + }} + > + × + + ) } return null } @@ -65,20 +74,17 @@ class Fact extends React.Component { render() { const fact = this.props.fact - return( + return (
- - - { fact.predicate } - - : - - + + + {fact.predicate} + + : {this.renderObject(fact)}   {this.renderRemoveButton(fact)} -
) } diff --git a/app/javascript/components/asset_components/facts.jsx b/app/javascript/components/asset_components/facts.jsx index 49ce874f..96460ed7 100644 --- a/app/javascript/components/asset_components/facts.jsx +++ b/app/javascript/components/asset_components/facts.jsx @@ -8,11 +8,11 @@ class Facts extends React.Component { this.state = { collapsed: {} } } collapsedPredicate(facts) { - return facts[0].predicate; + return facts[0].predicate } onClickCollapse(predicate) { this.state.collapsed[predicate] = !this.isCollapsed(predicate) - this.setState({collapsed: this.state.collapsed}) + this.setState({ collapsed: this.state.collapsed }) } isCollapsed(predicate) { if (typeof this.state.collapsed[predicate] === 'undefined') { @@ -23,37 +23,38 @@ class Facts extends React.Component { } renderCollapsedControl(classifiedFacts, posPredicate) { let predicate = this.collapsedPredicate(classifiedFacts) - return( + return (
{ this.onClickCollapse(predicate) }} - className="fact administrator-allowed"> - -   - - { this.collapsedPredicate(classifiedFacts) } - - : - - - - ({classifiedFacts.length}) - - + onClick={() => { + this.onClickCollapse(predicate) + }} + className="fact administrator-allowed" + > + + +   + {this.collapsedPredicate(classifiedFacts)}: + ({classifiedFacts.length}) +
) } renderCollapsedList(classifiedFacts, posPredicate) { if (classifiedFacts.length == 1) { - return this.renderFact(classifiedFacts[0], posPredicate+"-1") + return this.renderFact(classifiedFacts[0], posPredicate + '-1') } else { let render = [this.renderCollapsedControl(classifiedFacts, posPredicate)] let predicate = this.collapsedPredicate(classifiedFacts) if (!this.isCollapsed(predicate)) { - render = render.concat(classifiedFacts.map((fact, pos) => { return this.renderFact(fact, posPredicate+"-"+pos)})) + render = render.concat( + classifiedFacts.map((fact, pos) => { + return this.renderFact(fact, posPredicate + '-' + pos) + }) + ) } - return(render) + return render } } renderCollapsedFacts(facts) { @@ -62,7 +63,7 @@ class Facts extends React.Component { let posPredicate = 0 for (var predicate in factsByPredicate) { rendered.push(this.renderCollapsedList(factsByPredicate[predicate], posPredicate)) - posPredicate+=1 + posPredicate += 1 } return rendered } @@ -74,25 +75,22 @@ class Facts extends React.Component { } else { memo[fact.predicate].push(fact) } - return memo; + return memo }, {}) } renderFact(fact, index) { - return() + return } render() { - if ((!this.props.facts) || (this.props.facts.length == 0)) { + if (!this.props.facts || this.props.facts.length == 0) { return null } - return( + return ( - -
- {this.renderCollapsedFacts(this.props.facts)} -
+ +
{this.renderCollapsedFacts(this.props.facts)}
) diff --git a/app/javascript/components/asset_components/facts_editor.jsx b/app/javascript/components/asset_components/facts_editor.jsx index fc1982bf..9baf4f8b 100644 --- a/app/javascript/components/asset_components/facts_editor.jsx +++ b/app/javascript/components/asset_components/facts_editor.jsx @@ -10,10 +10,10 @@ class FactsEditor extends Facts { this.updateFromJson = this.updateFromJson.bind(this) this.state = { - text: "", + text: '', asset: this.props.asset, facts: this.props.facts, - dataAssetDisplay: this.props.dataAssetDisplay + dataAssetDisplay: this.props.dataAssetDisplay, } } @@ -28,11 +28,9 @@ class FactsEditor extends Facts { contentType: 'application/json; charset=utf-8', data: JSON.stringify({ changes: { - add_facts:[ - [this.props.asset.uuid, predicate, object] - ] - } - }) + add_facts: [[this.props.asset.uuid, predicate, object]], + }, + }), }).then(this.updateFromJson) } @@ -44,30 +42,28 @@ class FactsEditor extends Facts { contentType: 'application/json; charset=utf-8', data: JSON.stringify({ changes: { - remove_facts:[ - [this.props.asset.uuid, fact.predicate, fact.object || fact.object_asset.uuid] - ] - } - }) + remove_facts: [[this.props.asset.uuid, fact.predicate, fact.object || fact.object_asset.uuid]], + }, + }), }).then(this.updateFromJson) } updateFromJson(json) { - const asset=json.assets[0] - const facts=json.facts[0] - let dataAssetDisplay={} - dataAssetDisplay[asset.uuid]=json.dataAssetDisplay[0] + const asset = json.assets[0] + const facts = json.facts[0] + let dataAssetDisplay = {} + dataAssetDisplay[asset.uuid] = json.dataAssetDisplay[0] this.setState({ text: '', asset, dataAssetDisplay, - facts: facts + facts: facts, }) } onChangeText(e) { - this.setState({text: e.target.value }) + this.setState({ text: e.target.value }) } onKeyPress(e) { @@ -77,13 +73,15 @@ class FactsEditor extends Facts { } render() { - return( + return (
- +
@@ -96,12 +94,23 @@ class FactsEditor extends Facts { + type="text" + name="object" + value={this.state.text} + onChange={this.onChangeText} + className="form-control" + aria-label="..." + onKeyPress={this.onKeyPress} + />
- +
diff --git a/app/javascript/components/asset_components/facts_image.jsx b/app/javascript/components/asset_components/facts_image.jsx index f7dd0c17..dbe2bc16 100644 --- a/app/javascript/components/asset_components/facts_image.jsx +++ b/app/javascript/components/asset_components/facts_image.jsx @@ -1,6 +1,5 @@ import React from 'react' -import SVG from 'react-inlinesvg'; - +import SVG from 'react-inlinesvg' class FactsImage extends React.Component { imageForFacts(facts) { @@ -8,22 +7,22 @@ class FactsImage extends React.Component { } render() { - return( + return (
- }*/ onLoad={(src) => { /*debugger myOnLoadHandler(src);*/ }} - > - Here's some optional content for browsers that don't support XHR or inline - SVGs. You can use other React components here too. Here, I'll show you. - - + > + Here's some optional content for browsers that don't support XHR or inline SVGs. You can use other React + components here too. Here, I'll show you. + +
- ) + ) } } diff --git a/app/javascript/components/asset_components/facts_svg.jsx b/app/javascript/components/asset_components/facts_svg.jsx index c793eb06..10f66008 100644 --- a/app/javascript/components/asset_components/facts_svg.jsx +++ b/app/javascript/components/asset_components/facts_svg.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React from 'react' import ReactDOM from 'react-dom' import SVG from 'react-inlinesvg' import classNames from 'classnames' @@ -16,15 +16,17 @@ class FactsSvg extends React.Component { this.classesConfig = this.classesConfig.bind(this) this.state = { enlarge: false, - previousValue: {} + previousValue: {}, } } numWells(facts) { - return facts.filter((v) => { return v.predicate=='contains'}).length + return facts.filter((v) => { + return v.predicate == 'contains' + }).length } filename(facts) { const name = this.nameForFacts(facts) - if (name == 'plate'){ + if (name == 'plate') { if (this.numWells(facts) > 96) { return '384_plate' } else { @@ -62,7 +64,9 @@ class FactsSvg extends React.Component { if (facts.length == 0) { return null } - let typeFact = facts.find((v) => { return v.predicate=="a" }) + let typeFact = facts.find((v) => { + return v.predicate == 'a' + }) if (!typeFact) { return null } @@ -75,7 +79,6 @@ class FactsSvg extends React.Component { } else { return null } - } componentDidUpdate(prevProps) { this.onLoadSvg(prevProps) @@ -85,46 +88,52 @@ class FactsSvg extends React.Component { this.setState({ enlarge: !this.state.enlarge }) } onLoadSvg(prevProps) { - var data = this.props.dataAssetDisplay[this.props.asset.uuid]; - var ignoreKeys=[]; + var data = this.props.dataAssetDisplay[this.props.asset.uuid] + var ignoreKeys = [] for (var key in data) { - if (prevProps && prevProps.dataAssetDisplay && + if ( + prevProps && + prevProps.dataAssetDisplay && prevProps.dataAssetDisplay[this.props.asset.uuid] && - prevProps.dataAssetDisplay[this.props.asset.uuid][key]) { + prevProps.dataAssetDisplay[this.props.asset.uuid][key] + ) { ignoreKeys.push(key) } - var node = $('.svg-'+this.props.asset.uuid+' .'+key); + var node = $('.svg-' + this.props.asset.uuid + ' .' + key) // We want to reset all previous css but we also want to // to keep the location, that is represented as a css class (key) - node.attr('class', key+' '+data[key].cssClass); + node.attr('class', key + ' ' + data[key].cssClass) if (node[0]) { - node[0].setAttribute('data-tip', data[key].title); + node[0].setAttribute('data-tip', data[key].title) } } if (prevProps && prevProps.dataAssetDisplay) { - var oldData = prevProps.dataAssetDisplay[this.props.asset.uuid]; + var oldData = prevProps.dataAssetDisplay[this.props.asset.uuid] for (var key in oldData) { - if (!(ignoreKeys.find((e)=> {return e==key}))) { - var node = $('.svg-'+this.props.asset.uuid+' .'+key); + if ( + !ignoreKeys.find((e) => { + return e == key + }) + ) { + var node = $('.svg-' + this.props.asset.uuid + ' .' + key) // We want to reset all previous css but we also want to // to keep the location, that is represented as a css class (key) - node.attr('class', key); + node.attr('class', key) if (node[0]) { - node[0].setAttribute('data-tip', null); + node[0].setAttribute('data-tip', null) } } } - } ReactTooltip.rebuild() } classesConfig() { let classesConfig = { - 'svg': true, - 'enlarge': this.state.enlarge + svg: true, + enlarge: this.state.enlarge, } - classesConfig["svg-"+this.props.asset.uuid]=true + classesConfig['svg-' + this.props.asset.uuid] = true return classNames(classesConfig) } @@ -133,21 +142,21 @@ class FactsSvg extends React.Component { if (path) { return ( -
+
this.el = el} + ref={(el) => (this.el = el)} cacheGetRequests={true} - onLoad={this.onLoadSvg}> - + onLoad={this.onLoadSvg} + >
) } else { - return( -
+ return ( +
- ) + ) } } } diff --git a/app/javascript/components/asset_group_components/asset_group.jsx b/app/javascript/components/asset_group_components/asset_group.jsx index cfacbf7e..6c0c1566 100644 --- a/app/javascript/components/asset_group_components/asset_group.jsx +++ b/app/javascript/components/asset_group_components/asset_group.jsx @@ -1,7 +1,7 @@ import React from 'react' -import AssetDisplay from "../asset_components/asset_display" +import AssetDisplay from '../asset_components/asset_display' import Facts from '../asset_components/facts' -import ButtonWithLoading from "../lib/button_with_loading" +import ButtonWithLoading from '../lib/button_with_loading' import classNames from 'classnames' class AssetGroup extends React.Component { @@ -20,7 +20,9 @@ class AssetGroup extends React.Component { this.props.onRemoveAllAssetsFromAssetGroup(this.props.assetGroup) } runningAsset(asset) { - const found = this.props.assetGroup.assets_running.find((uuid) => { return (uuid == asset.uuid) }) + const found = this.props.assetGroup.assets_running.find((uuid) => { + return uuid == asset.uuid + }) if (found) { return (
@@ -30,33 +32,40 @@ class AssetGroup extends React.Component { } } renderAssetRow(asset, index) { - return( - + 'bg-warning': this.props.uuidsPendingRemoval.includes(asset.uuid), + })} + > {this.runningAsset(asset)} - + dataAssetDisplay={this.props.dataAssetDisplay} + /> - {index+1} + {index + 1} + onClick={$.proxy(this.removeAsset, this, asset, index)} + className="btn btn-primary " + text="Delete" + /> ) @@ -64,16 +73,29 @@ class AssetGroup extends React.Component { render() { if (this.props.assetGroup.assets.length == 0) { - return(
This activity has no assets selected yet.
) + return ( +
+ This activity has no assets selected yet. +
+ ) } else { - return( + return ( - - - {this.props.assetGroup.assets.map(this.renderAssetRow)} - + + + + + + + + + {this.props.assetGroup.assets.map(this.renderAssetRow)}
BarcodeFactsPosition - -
BarcodeFactsPosition + +
) } diff --git a/app/javascript/components/asset_group_components/asset_group_editor.jsx b/app/javascript/components/asset_group_components/asset_group_editor.jsx index 9fb4d88b..396283cd 100644 --- a/app/javascript/components/asset_group_components/asset_group_editor.jsx +++ b/app/javascript/components/asset_group_components/asset_group_editor.jsx @@ -1,12 +1,12 @@ import React from 'react' -import {FormFor} from "react-rails-form-helpers" -import BarcodeReader from "../asset_group_components/barcode_reader" -import AssetGroup from "../asset_group_components/asset_group" +import { FormFor } from 'react-rails-form-helpers' +import BarcodeReader from '../asset_group_components/barcode_reader' +import AssetGroup from '../asset_group_components/asset_group' import FineUploaderTraditional from 'fine-uploader-wrappers' import Dropzone from 'react-fine-uploader/dropzone' import 'react-fine-uploader/gallery/gallery.css' -import {uploaderOptions} from '../lib/uploader_utils' +import { uploaderOptions } from '../lib/uploader_utils' /** assetGroup { updateUrl: url to update the asset group (not in use for the moment) @@ -30,7 +30,7 @@ class AssetGroupEditor extends React.Component { this.state = { barcodesInputText: '', disabledBarcodesInput: false, - assets_status: {} + assets_status: {}, } this.onSubmit = this.onSubmit.bind(this) this.onAjaxSuccess = this.onAjaxSuccess.bind(this) @@ -39,7 +39,7 @@ class AssetGroupEditor extends React.Component { this.assetsChanging = this.assetsChanging.bind(this) } handleBarcodeReaderChange(e) { - this.setState({barcodesInputText: e.target.value}) + this.setState({ barcodesInputText: e.target.value }) } onAjaxSuccess(msg, text) { if (msg.errors) { @@ -47,58 +47,60 @@ class AssetGroupEditor extends React.Component { } else { this.props.onChangeAssetGroup(msg) } - } onAjaxComplete() { - this.setState({disabledBarcodesInput: false, barcodesInputText: ''}) + this.setState({ disabledBarcodesInput: false, barcodesInputText: '' }) } onSubmit(e) { e.preventDefault() - this.setState({disabledBarcodesInput: true}) + this.setState({ disabledBarcodesInput: true }) this.props.onAddBarcodesToAssetGroup(this.props.assetGroup, this.state.barcodesInputText) this.onAjaxComplete() } assetsChanging() { - return Object.keys(this.state.assets_status).filter($.proxy(function(uuid) { - return (this.state.assets_status[uuid] == 'running') - }, this)) + return Object.keys(this.state.assets_status).filter( + $.proxy(function (uuid) { + return this.state.assets_status[uuid] == 'running' + }, this) + ) } render() { - return( - + return ( +
- -
-
- -
-
- -
-
-
-
-
+ +
+
+ +
+
+ +
+
+
+
) diff --git a/app/javascript/components/asset_group_components/asset_groups_editor.jsx b/app/javascript/components/asset_group_components/asset_groups_editor.jsx index c0684a38..c7b2b782 100644 --- a/app/javascript/components/asset_group_components/asset_groups_editor.jsx +++ b/app/javascript/components/asset_group_components/asset_groups_editor.jsx @@ -1,5 +1,5 @@ import React from 'react' -import AssetGroupEditor from "../asset_group_components/asset_group_editor" +import AssetGroupEditor from '../asset_group_components/asset_group_editor' class AssetGroupsEditor extends React.Component { constructor(props) { @@ -11,18 +11,22 @@ class AssetGroupsEditor extends React.Component { } renderTab(assetGroupId, index) { const assetGroup = this.props.assetGroups[assetGroupId] - const selectedClass = (assetGroup.selected === true)? 'active' : '' - return( + const selectedClass = assetGroup.selected === true ? 'active' : '' + return (
  • + role="presentation" + className={this.classSelection(assetGroup)} + key={assetGroupId} + > - { assetGroup.name } + key={assetGroupId} + aria-controls={assetGroup.condition_group_name} + role="tab" + > + {assetGroup.name}
  • ) @@ -31,48 +35,49 @@ class AssetGroupsEditor extends React.Component { return this.isShown(assetGroup) ? 'active' : '' } isShown(assetGroup) { - return (this.props.selectedAssetGroup == assetGroup.id) + return this.props.selectedAssetGroup == assetGroup.id } renderPanel(assetGroupId, index) { const assetGroup = this.props.assetGroups[assetGroupId] - return( -
    - + + onChangeAssetGroup={this.props.onChangeAssetGroup} + />
    ) } render() { - return( + return (
    - {/* Tab panes */} + {/* Tab panes */}
    - + {/* Nav tabs */}
      {Object.keys(this.props.assetGroups).map(this.renderTab)}
    - { this.renderPanel(this.props.selectedAssetGroup) } + {this.renderPanel(this.props.selectedAssetGroup)}
    -
    - - ) } } diff --git a/app/javascript/components/asset_group_components/barcode_reader.jsx b/app/javascript/components/asset_group_components/barcode_reader.jsx index 3331ddc0..a1d3f142 100644 --- a/app/javascript/components/asset_group_components/barcode_reader.jsx +++ b/app/javascript/components/asset_group_components/barcode_reader.jsx @@ -2,31 +2,42 @@ import React from 'react' class BarcodeReader extends React.Component { renderIcon() { if (this.props.disabledBarcodesInput) { - return( + return (
    ) } else { - return( - - ) + return } } render() { - return( + return (
    - +
    { this.nameInput = input }} + ref={(input) => { + this.nameInput = input + }} value={this.props.barcodesInputText} onChange={this.props.handleChange} disabled={this.props.disabledBarcodesInput || this.props.activityRunning} - autoComplete="off" name="asset_group[assets]" - className="form-control" type='text' placeholder='Scan a barcode' /> + autoComplete="off" + name="asset_group[assets]" + className="form-control" + type="text" + placeholder="Scan a barcode" + /> - diff --git a/app/javascript/components/lib/button_with_loading.jsx b/app/javascript/components/lib/button_with_loading.jsx index f62eb353..09066b7a 100644 --- a/app/javascript/components/lib/button_with_loading.jsx +++ b/app/javascript/components/lib/button_with_loading.jsx @@ -8,7 +8,7 @@ class ButtonWithLoading extends React.Component { this.propsForButton = this.propsForButton.bind(this) this.state = { disabledButton: false, - lastText: null + lastText: null, } } componentDidUpdate(prevProps, prevState, snapshot) { @@ -17,7 +17,7 @@ class ButtonWithLoading extends React.Component { } } toggleDisableButton(flag) { - this.setState({disabledButton: flag, lastText: this.props.text}) + this.setState({ disabledButton: flag, lastText: this.props.text }) } onClick(e) { this.toggleDisableButton(true) @@ -29,18 +29,27 @@ class ButtonWithLoading extends React.Component { return Object.assign({}, this.props, { onClick: this.onClick, disabled: this.state.disabledButton, - text: null + text: null, }) } render() { const text = this.props.text - const loadingIcon = () - const hiddenLoadingIcon = () + const loadingIcon = ( + + ) + const hiddenLoadingIcon = ( + + ) const propsToUse = this.propsForButton() - return( - ) } diff --git a/app/javascript/components/lib/search_control.jsx b/app/javascript/components/lib/search_control.jsx index d3497f83..15d9aa45 100644 --- a/app/javascript/components/lib/search_control.jsx +++ b/app/javascript/components/lib/search_control.jsx @@ -9,50 +9,64 @@ class SearchControl extends React.Component { this.dataFromInput = this.dataFromInput.bind(this) this.state = { - text: '' + text: '', } } onChange(e) { - this.setState({text: e.target.value}) + this.setState({ text: e.target.value }) } onClick(e) { - return($(document.body).html($.get({url: this.props.searchUrl, data: this.dataFromInput(), dataType: 'html'}))) + return $(document.body).html( + $.get({ + url: this.props.searchUrl, + data: this.dataFromInput(), + dataType: 'html', + }) + ) } dataFromInput() { - return this.state.text.split(' ').reduce((memo,value) => { - let list = value.split(':') - if (list.length === 1) { - memo.push({ predicate: 'barcode', object: list[0]}) - } else { - memo.push({ predicate: list[0], object: list[1]}) - } - return memo - }, []).map((entry, pos) => { - let obj = {} - obj["p"+pos] = entry.predicate - obj["o"+pos] = entry.object - return obj - }).reduce((memo, value) => { - Object.keys(value).forEach((key) => { - memo[key] = value[key] + return this.state.text + .split(' ') + .reduce((memo, value) => { + let list = value.split(':') + if (list.length === 1) { + memo.push({ predicate: 'barcode', object: list[0] }) + } else { + memo.push({ predicate: list[0], object: list[1] }) + } + return memo + }, []) + .map((entry, pos) => { + let obj = {} + obj['p' + pos] = entry.predicate + obj['o' + pos] = entry.object + return obj }) - return memo - }, {}) + .reduce((memo, value) => { + Object.keys(value).forEach((key) => { + memo[key] = value[key] + }) + return memo + }, {}) } render() { - return(
    - - - - -
    ) + return ( +
    + + + + +
    + ) } } diff --git a/app/javascript/components/lib/togglable.jsx b/app/javascript/components/lib/togglable.jsx index 3b57f4d9..7d73e546 100644 --- a/app/javascript/components/lib/togglable.jsx +++ b/app/javascript/components/lib/togglable.jsx @@ -2,15 +2,19 @@ const Togglable = (description, valueToCheck, onToggle, render) => { if (typeof valueToCheck === 'undefined') { return (
    - +
    ) } - return( + return (
    - - { render() } + + {render()}
    ) } diff --git a/app/javascript/components/lib/uploader_utils.jsx b/app/javascript/components/lib/uploader_utils.jsx index 05bbd5b4..eeab616f 100644 --- a/app/javascript/components/lib/uploader_utils.jsx +++ b/app/javascript/components/lib/uploader_utils.jsx @@ -7,36 +7,32 @@ const getCsrfToken = () => { } const uploaderOptions = (props) => { - return( - { - options: { - validation: { - sizeLimit: 12000000, + return { + options: { + validation: { + sizeLimit: 12000000, + }, + chunking: { + enabled: false, + }, + deleteFile: { + enabled: true, + endpoint: '/asset_groups/' + props.assetGroup.id + '/upload', + }, + request: { + endpoint: '/asset_groups/' + props.assetGroup.id + '/upload', + customHeaders: { 'X-CSRF-Token': getCsrfToken() }, + }, + retry: { + enableAuto: true, + }, + callbacks: { + onError: function (id, name, errorReason, xhrOrXdr) { + props.onErrorMessage({ type: 'danger', msg: errorReason }) }, - chunking: { - enabled: false - }, - deleteFile: { - enabled: true, - endpoint: '/asset_groups/'+props.assetGroup.id+'/upload' - }, - request: { - endpoint: '/asset_groups/'+props.assetGroup.id+'/upload', - customHeaders: { 'X-CSRF-Token': getCsrfToken() } - }, - retry: { - enableAuto: true - }, - callbacks: { - onError: function(id, name, errorReason, xhrOrXdr) { - props.onErrorMessage({type: 'danger', msg: errorReason}) - } - } - } - } - ) + }, + }, + } } -export { - getCsrfToken, uploaderOptions -} +export { getCsrfToken, uploaderOptions } diff --git a/app/javascript/components/step_components/operations.jsx b/app/javascript/components/step_components/operations.jsx index ce8360e8..1f51b9ab 100644 --- a/app/javascript/components/step_components/operations.jsx +++ b/app/javascript/components/step_components/operations.jsx @@ -19,28 +19,28 @@ class Operations extends React.Component { if (operation.action_type == 'deleteAssetGroups') return 'glyphicon-minus' } renderOperationRow(operation, index) { - return( + return ( - - { operation.action_type } - - - {operation.asset ? operation.asset.barcode || operation.asset.uuid : ''} + + {operation.action_type} + {operation.asset ? operation.asset.barcode || operation.asset.uuid : ''} - + ) } render() { if (this.props.operations.length == 0) { - return( No operations performed in this step.) - } else { - return( - this.props.operations.map(this.renderOperationRow) + return ( + + No operations performed in this step. + ) + } else { + return this.props.operations.map(this.renderOperationRow) } } } diff --git a/app/javascript/components/step_components/step_control.jsx b/app/javascript/components/step_components/step_control.jsx index 3676361d..e359c616 100644 --- a/app/javascript/components/step_components/step_control.jsx +++ b/app/javascript/components/step_components/step_control.jsx @@ -1,7 +1,7 @@ import classNames from 'classnames' import React from 'react' import C from '../step_components/step_states' -import ButtonWithLoading from "../lib/button_with_loading" +import ButtonWithLoading from '../lib/button_with_loading' class StepControl extends React.Component { constructor(props) { @@ -19,20 +19,33 @@ class StepControl extends React.Component { } renderStepRunningControl() { - return( - + return ( + ) } renderStepErrorControl() { - return( + return ( -   - + +   + ) } eventNameForState(state) { - switch(state) { + switch (state) { case C.STEP_STATE_STOPPED: case C.STEP_STATE_PENDING: case C.STEP_STATE_FAILED: @@ -51,22 +64,26 @@ class StepControl extends React.Component { renderStepFinishedControl() { const state = this.props.step.state - return( + return ( + 'Stop?': state === null || state === C.STEP_STATE_FAILED || state === C.STEP_STATE_RUNNING, + 'Redo?': state === C.STEP_STATE_CANCELLED, + 'Continue?': state === C.STEP_STATE_PENDING || state == C.STEP_STATE_STOPPED || state == C.STEP_STATE_FAILED, + 'Revert?': state === C.STEP_STATE_COMPLETED, + })} + /> ) } render() { @@ -75,7 +92,7 @@ class StepControl extends React.Component { return null } - switch(state){ + switch (state) { case C.STEP_STATE_COMPLETED: case C.STEP_STATE_PENDING: case C.STEP_STATE_CANCELLED: diff --git a/app/javascript/components/step_components/step_states.jsx b/app/javascript/components/step_components/step_states.jsx index ebee7d8d..e349d1de 100644 --- a/app/javascript/components/step_components/step_states.jsx +++ b/app/javascript/components/step_components/step_states.jsx @@ -15,7 +15,7 @@ const C = { STEP_EVENT_CONTINUE: 'continue', STEP_EVENT_STOP: 'stop', STEP_EVENT_REMAKE: 'remake', - STEP_EVENT_CANCEL: 'cancel' + STEP_EVENT_CANCEL: 'cancel', } export default C diff --git a/app/javascript/components/step_components/steps.jsx b/app/javascript/components/step_components/steps.jsx index 9bdc7777..ad8a3289 100644 --- a/app/javascript/components/step_components/steps.jsx +++ b/app/javascript/components/step_components/steps.jsx @@ -10,24 +10,24 @@ class Steps extends React.Component { this.renderSteps = this.renderSteps.bind(this) } renderSteps() { - return( - + return ( + ) } renderTogglable() { return (
    -
    - {this.renderSteps()} -
    +
    {this.renderSteps()}
    ) } render() { - return Togglable("What happened before?", this.props.steps, this.props.onToggle, this.renderTogglable) + return Togglable('What happened before?', this.props.steps, this.props.onToggle, this.renderTogglable) } - } export default Steps diff --git a/app/javascript/components/step_components/steps_failed.jsx b/app/javascript/components/step_components/steps_failed.jsx index a5a2e7a3..966278cf 100644 --- a/app/javascript/components/step_components/steps_failed.jsx +++ b/app/javascript/components/step_components/steps_failed.jsx @@ -10,38 +10,44 @@ class StepsFailed extends StepsFinished { this.renderStepRow = this.renderStepRow.bind(this) } renderHeaders() { - return( - Step idStep type - Asset GroupUsernameDurationActions? - ) + return ( + + + Step id + Step type + Asset Group + Username + Duration + Actions? + + + ) } - renderStepRow(step,index) { + renderStepRow(step, index) { const stepTypeName = step.step_type ? step.step_type.name : '' const stepActivityId = step.activity ? step.activity.id : '' const stepAssetGroup = step.assetGroup ? step.assetGroup.id : '' const stepUsername = step.username - const classForState = (step.state == C.STEP_STATE_RUNNING) ? 'spinner' : '' + const classForState = step.state == C.STEP_STATE_RUNNING ? 'spinner' : '' - const dataTarget = "#step-"+ step.id + const dataTarget = '#step-' + step.id if (step.deprecated == true) { return } else { - return( + return ( - - { step.id } - { stepTypeName } - { stepAssetGroup } - { stepUsername } - { this.renderDuration(step) } - - + {step.id} + {stepTypeName} + {stepAssetGroup} + {stepUsername} + {this.renderDuration(step)} + + + isDisabled={this.props.activityRunning && !step.state === null} + /> @@ -49,13 +55,11 @@ class StepsFailed extends StepsFinished { } } render() { - return( + return (
    -
    - {this.renderSteps()} -
    +
    {this.renderSteps()}
    ) diff --git a/app/javascript/components/step_components/steps_finished.jsx b/app/javascript/components/step_components/steps_finished.jsx index 0ed69350..4730a743 100644 --- a/app/javascript/components/step_components/steps_finished.jsx +++ b/app/javascript/components/step_components/steps_finished.jsx @@ -1,5 +1,5 @@ import React from 'react' -import Moment from 'react-moment'; +import Moment from 'react-moment' import Operations from '../step_components/operations' import classNames from 'classnames' import Text from 'react-format-text' @@ -7,7 +7,6 @@ import Toggle from 'react-toggle' import StepControl from '../step_components/step_control' import C from './step_states' - class StepsFinished extends React.Component { constructor() { super() @@ -18,7 +17,7 @@ class StepsFinished extends React.Component { this.renderStepRow = this.renderStepRow.bind(this) } colorForState(state) { - switch(state) { + switch (state) { case C.STEP_STATE_COMPLETED: return 'success' case C.STEP_STATE_FAILED: @@ -38,7 +37,7 @@ class StepsFinished extends React.Component { } } classImageForState(state) { - switch(state) { + switch (state) { case C.STEP_STATE_COMPLETED: return 'glyphicon-ok' case C.STEP_STATE_FAILED: @@ -60,31 +59,28 @@ class StepsFinished extends React.Component { } } imageForState(state) { - const classToAssign = 'glyphicon ' + - this.classImageForState(state) + ' ' + this.textColorForState(state) + const classToAssign = 'glyphicon ' + this.classImageForState(state) + ' ' + this.textColorForState(state) - return( - - ) + return } textColorForState(state) { - return 'text-'+this.colorForState(state) + return 'text-' + this.colorForState(state) } renderStepOutput(step) { if (step.output) { - return( + return ( - + + + - - - + + +
    Output
    Output
    - - { step.output } - -
    + {step.output} +
    ) @@ -92,55 +88,67 @@ class StepsFinished extends React.Component { } renderDuration(step) { if (step.started_at && step.finished_at) { - return( - { step.finished_at }s + return ( + + + {step.finished_at} + + s + ) } else { - return("") + return '' } } - renderStepRow(step,index) { + renderStepRow(step, index) { const stepTypeName = step.step_type ? step.step_type.name : '' const stepActivityId = step.activity ? step.activity.id : '' const stepAssetGroup = step.assetGroup ? step.assetGroup.id : '' const stepUsername = step.username - const classForState = (step.state == C.STEP_STATE_RUNNING) ? 'spinner' : '' + const classForState = step.state == C.STEP_STATE_RUNNING ? 'spinner' : '' - const dataTarget = "#step-"+ step.id + const dataTarget = '#step-' + step.id if (step.deprecated == true) { return } else { - return( + return ( - - { step.id } - { stepTypeName } - { stepActivityId } - { stepAssetGroup } - { step.operations.length } - { this.renderDuration(step) } - { stepUsername } + data-psd-step-id={step.id} + key={'a1-' + index} + className={'clickable ' + this.colorForState(step.state)} + > + {step.id} + {stepTypeName} + {stepActivityId} + {stepAssetGroup} + {step.operations.length} + {this.renderDuration(step)} + {stepUsername} {step.state}   - { this.imageForState(step.state) } + {this.imageForState(step.state)} - + -
    -
    - +
    + + isDisabled={this.props.activityRunning && !step.state === null} + />
    - + + + + + @@ -155,27 +163,31 @@ class StepsFinished extends React.Component { } } renderHeaders() { - return( - - - - - ) + return ( + + + + + + + + + + + ) } renderSteps() { if (this.props.steps.length == 0) { - return( + return (
    This activity has no steps yet.
    ) } else { - return( + return (
    ActionBarcodeFact
    ActionBarcodeFact
    Step idStep typeActivityAsset GroupNum. operations Duration UsernameStatus
    Step idStep typeActivityAsset GroupNum. operations Duration UsernameStatus
    - { this.renderHeaders() } - - {this.props.steps.map(this.renderStepRow)} - + {this.renderHeaders()} + {this.props.steps.map(this.renderStepRow)}
    ) } diff --git a/app/javascript/components/step_components/steps_running.jsx b/app/javascript/components/step_components/steps_running.jsx index f5fe29c1..7aced0d7 100644 --- a/app/javascript/components/step_components/steps_running.jsx +++ b/app/javascript/components/step_components/steps_running.jsx @@ -1,5 +1,5 @@ import React from 'react' -import Moment from 'react-moment'; +import Moment from 'react-moment' import StepsFinished from '../step_components/steps_finished' import StepControl from '../step_components/step_control' import C from './step_states' @@ -7,49 +7,59 @@ import C from './step_states' class StepsRunning extends StepsFinished { renderDuration(step) { if (step.started_at) { - return( - + return ( + + + ) } else { return '' } } renderHeaders() { - return( - Step idStep type - Asset GroupUsernameEllapsed timeStatusActions - ) + return ( + + + Step id + Step type + Asset Group + Username + Ellapsed time + Status + Actions + + + ) } - renderStepRow(step,index) { + renderStepRow(step, index) { const stepTypeName = step.step_type ? step.step_type.name : '' const stepActivityId = step.activity ? step.activity.id : '' const stepAssetGroup = step.assetGroup ? step.assetGroup.id : '' const stepUsername = step.username - const classForState = (step.state == C.STEP_STATE_RUNNING) ? 'spinner' : '' + const classForState = step.state == C.STEP_STATE_RUNNING ? 'spinner' : '' - const dataTarget = "#step-"+ step.id + const dataTarget = '#step-' + step.id if (step.deprecated == true) { return } else { - return( + return ( - - { step.id } - { stepTypeName } - { stepAssetGroup } - { stepUsername } - { this.renderDuration(step) } + + {step.id} + {stepTypeName} + {stepAssetGroup} + {stepUsername} + {this.renderDuration(step)} - { step.state }   - { this.imageForState(step.state) } + {step.state}   + {this.imageForState(step.state)} - + isDisabled={this.props.activityRunning && !step.state === null} + /> @@ -58,13 +68,11 @@ class StepsRunning extends StepsFinished { } render() { - return( + return (
    -
    - {this.renderSteps()} -
    +
    {this.renderSteps()}
    ) diff --git a/app/javascript/components/step_type_components/step_type_button.jsx b/app/javascript/components/step_type_components/step_type_button.jsx index 239c6ab6..56631ecb 100644 --- a/app/javascript/components/step_type_components/step_type_button.jsx +++ b/app/javascript/components/step_type_components/step_type_button.jsx @@ -1,7 +1,7 @@ import React from 'react' -import {FormFor} from "react-rails-form-helpers" -import PrintersSelectionHidden from "../activity_components/printers_selection_hidden" -import ButtonWithLoading from "../lib/button_with_loading" +import { FormFor } from 'react-rails-form-helpers' +import PrintersSelectionHidden from '../activity_components/printers_selection_hidden' +import ButtonWithLoading from '../lib/button_with_loading' class StepTypeButton extends React.Component { constructor(props) { @@ -28,36 +28,37 @@ class StepTypeButton extends React.Component { step_type_id: this.props.stepTypeData.stepType.id, asset_group_id: this.props.assetGroupId, tube_printer_id: this.props.selectedTubePrinter, - plate_printer_id: this.props.selectedPlatePrinter - } - } + plate_printer_id: this.props.selectedPlatePrinter, + }, + }, }) } renderButton() { - return( + return ( + type="submit" + className="btn btn-primary" + text={this.props.stepTypeData.name} + /> ) } render() { - return( -
  • -
    - - -
  • - ) + return ( +
  • +
    + + +
  • + ) } - } - export default StepTypeButton diff --git a/app/javascript/components/step_type_components/step_type_buttons.jsx b/app/javascript/components/step_type_components/step_type_buttons.jsx index 980c0d70..089486f0 100644 --- a/app/javascript/components/step_type_components/step_type_buttons.jsx +++ b/app/javascript/components/step_type_components/step_type_buttons.jsx @@ -1,28 +1,28 @@ import React from 'react' -import StepTypeButton from "./step_type_button" +import StepTypeButton from './step_type_button' class StepTypeButtons extends React.Component { - constructor(props) { - super(props) + constructor(props) { + super(props) - this.renderStepTypeData = this.renderStepTypeData.bind(this) - } - renderStepTypeData(stepTypeData, pos) { - return( - - ) - } - render() { - return (this.props.stepTypesData.map(this.renderStepTypeData)) - } + this.renderStepTypeData = this.renderStepTypeData.bind(this) + } + renderStepTypeData(stepTypeData, pos) { + return ( + + ) + } + render() { + return this.props.stepTypesData.map(this.renderStepTypeData) + } } -export default StepTypeButtons; +export default StepTypeButtons diff --git a/app/javascript/components/step_type_components/step_type_template_button.jsx b/app/javascript/components/step_type_components/step_type_template_button.jsx index 87e1b153..6547d34b 100644 --- a/app/javascript/components/step_type_components/step_type_template_button.jsx +++ b/app/javascript/components/step_type_components/step_type_template_button.jsx @@ -1,19 +1,22 @@ import React from 'react' -import {FormFor} from "react-rails-form-helpers" -import PrintersSelectionHidden from "../activity_components/printers_selection_hidden" +import { FormFor } from 'react-rails-form-helpers' +import PrintersSelectionHidden from '../activity_components/printers_selection_hidden' class StepTypeTemplateButton extends React.Component { - render() { - const stepTypeTemplateData = this.props.stepTypeTemplateData - return( -
  • - - {stepTypeTemplateData.name} - -
  • - ) - } + render() { + const stepTypeTemplateData = this.props.stepTypeTemplateData + return ( +
  • + + {stepTypeTemplateData.name} + +
  • + ) + } } -export default StepTypeTemplateButton; +export default StepTypeTemplateButton diff --git a/app/javascript/components/step_type_components/step_type_template_control.jsx b/app/javascript/components/step_type_components/step_type_template_control.jsx index c0f5b0a1..01777dbf 100644 --- a/app/javascript/components/step_type_components/step_type_template_control.jsx +++ b/app/javascript/components/step_type_components/step_type_template_control.jsx @@ -1,48 +1,45 @@ import React from 'react' -import ReactDOM from 'react-dom'; +import ReactDOM from 'react-dom' -import {FormFor} from "react-rails-form-helpers" -import PrintersSelectionHidden from "../activity_components/printers_selection_hidden" -import UploadFile from "./step_type_templates/upload_file" -import ApplyFile from "./step_type_templates/apply_file" +import { FormFor } from 'react-rails-form-helpers' +import PrintersSelectionHidden from '../activity_components/printers_selection_hidden' +import UploadFile from './step_type_templates/upload_file' +import ApplyFile from './step_type_templates/apply_file' class StepTypeTemplateControl extends React.Component { - - renderTemplate(template, params) { - const Template = { - 'upload_file': UploadFile, - 'rack_layout_creating_tubes': ApplyFile, - 'rack_layout': ApplyFile, - 'rack_order_symphony': UploadFile, - 'racking_by_columns': UploadFile, - 'transfer_tube_to_tube': UploadFile - }[template] - - return(