diff --git a/.babelrc b/.babelrc index aa27d4ac..295d8128 100644 --- a/.babelrc +++ b/.babelrc @@ -1,16 +1,4 @@ { - "presets": [ - "@babel/preset-env", - "@babel/preset-react" - ], - "plugins": [ - "syntax-dynamic-import", - "@babel/plugin-proposal-object-rest-spread", - [ - "transform-class-properties", - { - "spec": true - } - ] - ] + "presets": ["@babel/preset-env", "@babel/preset-react"], + "plugins": ["@babel/plugin-syntax-dynamic-import", "@babel/plugin-proposal-object-rest-spread"] } 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 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 24ae0a98..da618d61 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -4,35 +4,50 @@ on: branches: - develop - master - - release-2.0.8-docker + tags: + - release-* + - uat-* + - dev-* env: - IMAGE_NAME: ${{ github.repository }}/latest + IMAGE_NAME: ${{ github.repository }}/${{ github.event.repository.name }} jobs: build_and_publish: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest 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- - - 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' + + - name: Remove old releases + uses: snok/container-retention-policy@v2 + with: + image-names: ${{ github.event.repository.name }}/* + cut-off: Four months ago UTC + timestamp-to-use: updated_at + account-type: org + org-name: sanger + keep-at-least: 5 + skip-tags: latest + token: ${{ secrets.REMOVE_OLD_IMAGES }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..671cfe9c --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,30 @@ +name: Linting + +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: Setup node + uses: actions/setup-node@v2 + with: + node-version: ${{ steps.node_version.outputs.NODE_VERSION }} + - name: Install + run: yarn install + - name: Run prettier + run: yarn prettier --check . + - 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 new file mode 100644 index 00000000..813e5e40 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,64 @@ +name: Tests + +env: + TZ: Europe/London + +on: + - push + - pull_request + +jobs: + ruby: + runs-on: ubuntu-latest + + 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 + 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 + + 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 }} + + - name: Install + run: yarn install + + - name: Run yarn test + run: yarn test 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/.nvmrc b/.nvmrc new file mode 100644 index 00000000..6276cf12 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v16.14.2 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/.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 5c85b271..d19314a8 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,2 +1,60 @@ -require: rubocop-performance -require: rubocop-rails +inherit_from: + - .rubocop_todo.yml + - node_modules/@prettier/plugin-ruby/rubocop.yml + +require: + - rubocop-performance + - rubocop-rails + +AllCops: + NewCops: enable + inherit_mode: + merge: + - Exclude + Exclude: + - 'db/views_schema.rb' + +# 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. +Metrics/BlockLength: + Exclude: + - Gemfile + IgnoredMethods: + - describe + - context + - background + - scenario + - namespace + - task + - included + - shared_context + - shared_examples + - shared_examples_for + - 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 + +# 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 new file mode 100644 index 00000000..cd31b2e2 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,1419 @@ +# This configuration was generated by +# `rubocop --auto-gen-config --exclude-limit 1000` +# 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 +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 16 +# Configuration parameters: IgnoredMethods. +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: 3 +# Configuration parameters: AllowedMethods. +# AllowedMethods: enums +Lint/ConstantDefinitionInBlock: + Exclude: + - 'spec/lib/parsers/csv_layout/barcode_creatable_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: 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: + Exclude: + - 'lib/tasks/setup_templates.rake' + - 'spec/rails_helper.rb' + +# 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' + - 'lib/actions/plate_transfer.rb' + - 'lib/support_n3.rb' + - 'spec/lib/support_n3_spec.rb' + +# Offense count: 2 +# Configuration parameters: AllowComments, AllowNil. +Lint/SuppressedException: + Exclude: + - 'spec/controllers/steps_controller_spec.rb' + +# Offense count: 56 +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/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/location_parser.rb' + - 'lib/sequencescape_client.rb' + - 'lib/support_n3.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: 78 +# Configuration parameters: IgnoredMethods, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 79 + +# Offense count: 13 +# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. +# IgnoredMethods: refine +Metrics/BlockLength: + Max: 68 + +# Offense count: 7 +# Configuration parameters: CountBlocks. +Metrics/BlockNesting: + Max: 5 + +# Offense count: 11 +# Configuration parameters: CountComments, CountAsOne. +Metrics/ClassLength: + Max: 489 + +# Offense count: 35 +# Configuration parameters: IgnoredMethods. +Metrics/CyclomaticComplexity: + Max: 26 + +# Offense count: 108 +# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. +Metrics/MethodLength: + Max: 363 + +# Offense count: 8 +# Configuration parameters: CountComments, CountAsOne. +Metrics/ModuleLength: + Max: 206 + +# Offense count: 31 +# Configuration parameters: IgnoredMethods. +Metrics/PerceivedComplexity: + Max: 26 + +# Offense count: 4 +Naming/AccessorMethodName: + Exclude: + - 'app/models/fact.rb' + - 'app/models/step.rb' + - 'lib/fact_changes.rb' + +# Offense count: 1 +# 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: 29 +# 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: 21 +# 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: + - '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/support_n3.rb' + - 'lib/token_util.rb' + +# Offense count: 36 +# Configuration parameters: EnforcedStyle, AllowedIdentifiers. +# 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' + - 'spec/script/runners/transfer_samples_spec.rb' + - 'spec/script/runners/transfer_tubes_to_tube_rack_by_position_spec.rb' + +# Offense count: 84 +# This cop supports safe auto-correction (--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' + - '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: 1 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/ActiveRecordCallbacksOrder: + Exclude: + - 'app/models/step_type.rb' + +# Offense count: 2 +# This cop supports safe auto-correction (--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 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: EnforceForPrefixed. +Rails/Delegate: + Exclude: + - 'lib/parsers/csv_metadata/csv_parser.rb' + +# Offense count: 29 +# This cop supports unsafe auto-correction (--auto-correct-all). +# 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: 2 +# 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' + - '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: IgnoreScopes, 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: 1 +# This cop supports unsafe auto-correction (--auto-correct-all). +Rails/NegateInclude: + Exclude: + - 'lib/support_n3.rb' + +# Offense count: 8 +# This cop supports safe auto-correction (--auto-correct). +# 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: 1 +# This cop supports safe auto-correction (--auto-correct). +Rails/Presence: + Exclude: + - 'app/models/asset.rb' + +# Offense count: 5 +# This cop supports safe auto-correction (--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 +# This cop supports safe auto-correction (--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: 1 +# Configuration parameters: Include. +# Include: db/**/*.rb +Rails/ReversibleMigration: + Exclude: + - 'db/migrate/20190516153622_remove_task_type.rb' + +# 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: + 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' + - 'spec/models/steps/job_spec.rb' + - 'spec/shared_examples/background_step.rb' + +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +Rails/SquishedSQLHeredocs: + Exclude: + - 'db/migrate/20200709123033_create_heron_activities_view.rb' + +# Offense count: 3 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: strict, flexible +Rails/TimeZone: + Exclude: + - 'app/controllers/assets_controller.rb' + - 'spec/remote_assets_helper.rb' + +# Offense count: 3 +# 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: 3 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: AllowOnConstant. +Style/CaseEquality: + Exclude: + - 'lib/sequencescape_client.rb' + - 'lib/support_n3.rb' + +# 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' + +# Offense count: 39 +# This cop supports safe auto-correction (--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: 38 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: is_a?, kind_of? +Style/ClassCheck: + Exclude: + - '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: 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' + +# Offense count: 1 +Style/ClassVars: + Exclude: + - 'app/models/action.rb' + +# 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/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: 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: 25 +# This cop supports safe auto-correction (--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/traction_fields.rb' + - 'app/models/printables/group.rb' + - 'app/models/step_type.rb' + - 'app/models/steps/cancellable.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/fact_changes.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: 4 +# This cop supports safe auto-correction (--auto-correct). +Style/EvenOdd: + Exclude: + - 'spec/models/condition_spec.rb' + - 'spec/models/step_execution_spec.rb' + +# Offense count: 4 +# This cop supports safe auto-correction (--auto-correct). +Style/ExpandPathArguments: + Exclude: + - 'Rakefile' + - 'config.ru' + - 'spec/rails_helper.rb' + - 'test/test_helper.rb' + +# Offense count: 2 +# Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, IgnoredMethods. +# SupportedStyles: annotated, template, unannotated +Style/FormatStringToken: + Exclude: + - 'config/routes.rb' + - 'lib/views_schema.rb' + +# Offense count: 351 +# This cop supports safe auto-correction (--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_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/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' + - '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/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_metadata/csv_parser.rb' + - 'lib/parsers/csv_metadata/data_parser.rb' + - 'lib/parsers/csv_metadata/headers_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.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/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/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 +# 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: 17 +# Configuration parameters: MinBodyLength. +Style/GuardClause: + Exclude: + - 'app/controllers/activities_controller.rb' + - 'app/controllers/application_controller.rb' + - 'app/models/activities/websocket_events.rb' + - 'app/models/asset.rb' + - 'app/models/steps/deprecatable.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/transaction_scope.rb' + - 'lib/fact_changes.rb' + - 'lib/parsers/csv_layout/csv_parser.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/step_execution_process.rb' + - 'lib/support_n3.rb' + +# Offense count: 7 +# This cop supports unsafe auto-correction (--auto-correct-all). +# Configuration parameters: AllowedReceivers. +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: 5 +# This cop supports safe auto-correction (--auto-correct). +# 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: 24 +# This cop supports safe auto-correction (--auto-correct). +Style/IfUnlessModifier: + Exclude: + - 'app/models/action.rb' + - 'app/models/asset.rb' + - 'app/models/assets/export.rb' + - 'app/models/assets/facts_management.rb' + - 'app/models/assets/import.rb' + - 'app/models/steps/deprecatable.rb' + - 'lib/actions/plate_transfer.rb' + - 'lib/actions/racking.rb' + - 'lib/actions/tube_transfer.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/study_name_inference.rb' + - 'test/factories/assets.rb' + +# Offense count: 1 +# This cop supports unsafe auto-correction (--auto-correct-all). +# Configuration parameters: InverseMethods, InverseBlocks. +Style/InverseMethods: + Exclude: + - 'app/helpers/activities_helper.rb' + +# Offense count: 2 +Style/MixinUsage: + Exclude: + - 'script/runners/put_tubes_into_rack_by_column_order.rb' + - 'spec/inferences_helper.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: 18 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: literals, strict +Style/MutableConstant: + Exclude: + - 'app/models/steps/state.rb' + - 'config/initializers/version_string.rb' + - 'lib/actions/racking.rb' + - 'lib/changes_support/disjoint_list.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 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: both, prefix, postfix +Style/NegatedIf: + Exclude: + - 'app/models/printables/instance.rb' + +# Offense count: 11 +# This cop supports safe auto-correction (--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: 57 +# This cop supports unsafe auto-correction (--auto-correct-all). +# 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/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' + - 'script/aliquot_type_inference.rb' + - 'script/container_inferences.rb' + - 'script/purpose_name_inference.rb' + - 'script/runners/load_metadata.rb' + - 'script/runners/print_barcodes.rb' + - 'script/runners/rack_layout.rb' + - 'script/runners/rack_layout_any_barcode.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: 1 +Style/OpenStructUse: + Exclude: + - 'lib/deployed_version.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: 4 +# This cop supports safe auto-correction (--auto-correct). +Style/OrAssignment: + Exclude: + - 'app/controllers/asset_groups_controller.rb' + - 'app/helpers/application_helper.rb' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +Style/ParallelAssignment: + Exclude: + - 'spec/models/step_spec.rb' + +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: PreferredDelimiters. +Style/PercentLiteralDelimiters: + Exclude: + - 'spec/lib/support_n3_spec.rb' + +# Offense count: 8 +# This cop supports unsafe auto-correction (--auto-correct-all). +# 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 +# This cop supports safe auto-correction (--auto-correct). +Style/RedundantCondition: + Exclude: + - 'spec/integration/inference_spec.rb' + +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +Style/RedundantFreeze: + Exclude: + - 'lib/psd_formatter.rb' + +# Offense count: 4 +# This cop supports safe auto-correction (--auto-correct). +Style/RedundantInterpolation: + Exclude: + - 'app/helpers/application_helper.rb' + +# Offense count: 22 +# This cop supports safe auto-correction (--auto-correct). +Style/RedundantParentheses: + 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/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_stamped_plate.rb' + +# Offense count: 36 +# This cop supports safe auto-correction (--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/step_type.rb' + - 'app/models/steps/compatible.rb' + - 'app/models/uploaded_file.rb' + - 'lib/actions/racking.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 +# This cop supports safe auto-correction (--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: 15 +# This cop supports safe auto-correction (--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/condition.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: 5 +# This cop supports safe auto-correction (--auto-correct). +Style/SelfAssignment: + Exclude: + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'script/runners/create_file.rb' + - 'script/runners/create_layout.rb' + - 'spec/models/action_spec.rb' + +# Offense count: 3 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: only_raise, only_fail, semantic +Style/SignalException: + Exclude: + - 'spec/inferences_helper.rb' + +# Offense count: 1 +# This cop supports unsafe auto-correction (--auto-correct-all). +Style/SlicingWithRange: + Exclude: + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' + +# 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/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: 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' + - 'lib/inference_engines/cwm/step_execution.rb' + - 'lib/inference_engines/runner/step_execution.rb' + - 'script/runners/load_metadata.rb' + - 'script/runners/rack_layout.rb' + - 'script/runners/rack_layout_any_barcode.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: 2 +# This cop supports safe auto-correction (--auto-correct). +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiterals: + Exclude: + - 'spec/lib/token_util_spec.rb' + +# 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' + - '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: 9 +# This cop supports safe auto-correction (--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/changes_support/disjoint_list.rb' + - 'lib/fact_changes.rb' + - 'spec/models/condition_spec.rb' + - 'spec/models/step_execution_spec.rb' + - 'spec/models/step_spec.rb' + +# Offense count: 1 +# 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: + Exclude: + - 'lib/support_n3.rb' + +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +Style/UnlessElse: + Exclude: + - 'spec/inferences_helper.rb' + +# Offense count: 19 +# This cop supports unsafe auto-correction (--auto-correct-all). +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/changes_support/transaction_scope.rb' + - 'lib/fact_changes.rb' + - 'lib/parsers/csv_layout/line_parser.rb' + - 'lib/parsers/csv_metadata/line_parser.rb' + - 'script/runners/transfer_tubes_to_tube_rack_by_position.rb' diff --git a/.ruby-version b/.ruby-version index 951d42f2..49cdd668 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-2.4.2 +2.7.6 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 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 31069c40..00000000 --- a/.travis.yml +++ /dev/null @@ -1,32 +0,0 @@ -language: ruby -cache: - bundler: true - yarn: true - directories: - - 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 -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/Dockerfile b/Dockerfile index 7ec31d38..3e2e9470 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,26 @@ -FROM starefossen/ruby-node +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_16.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 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 -RUN apt-get -y install git vim + ADD . /samples_extraction/ # Compiling assets -RUN RAILS_ENV=production bundle exec rake assets:precompile -RUN RAILS_ENV=production bundle exec rake webpacker:compile +RUN SE_REDIS_URI= 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 RUN git tag -l --points-at HEAD --sort -version:refname | head -1 > TAG RUN git rev-parse --abbrev-ref HEAD > BRANCH - diff --git a/Gemfile b/Gemfile index c9c205db..eb19ba76 100644 --- a/Gemfile +++ b/Gemfile @@ -1,99 +1,94 @@ -source 'http://rubygems.org' - +source 'https://rubygems.org' # Service libraries -gem 'puma' +gem 'bootsnap', require: false gem 'daemons' -gem 'redis' -gem 'delayed_job' gem 'delayed_job_active_record' +gem 'hiredis' gem 'mysql2' +gem 'puma' +gem 'redis', '< 5' +gem 'sanger_warren' # Wraps bunny and manages connection pools and configuration # Rails and framework libraries -gem 'rails', '~> 5.1' -gem 'tzinfo-data' +gem 'aasm' +gem 'activerecord-import' gem 'activerecord-session_store' gem 'micro_token' -gem 'activerecord-import' -gem 'aasm' - +gem 'rails', '~> 6.1' +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 'dropzonejs-rails' -gem 'rails-assets-tether'#, '>= 1.1.0' gem 'ace-rails-ap' +gem 'dropzonejs-rails' +gem 'ejs' +gem 'rails-assets-tether' # Serializers +gem 'jbuilder' +gem 'oj' gem 'rdf-n3' -gem 'jbuilder'#, '~> 2.0' -gem 'yajl-ruby'#, '>= 1.3' -gem 'google_hash' # 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 'sequencescape-client-api', git: 'https://github.com/sanger/sequencescape-client-api.git', branch: 'rails_4', require: 'sequencescape' -# -#gem 'sequencescape-client-api', require: 'sequencescape' +gem 'rest-client' +gem 'sequencescape-client-api', require: 'sequencescape' # Debugging gem 'rb-readline' # Docs -gem 'sdoc'#, '~> 0.4.0', group: :doc +gem 'yard' +# Feature flags +gem 'flipper' +gem 'flipper-redis' +gem 'flipper-ui' 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' + # Call 'pry' anywhere in the code to stop execution and get a debugger console + gem 'pry-byebug' + gem 'pry-rails' gem 'ruby-growl' end group :test do - gem 'factory_bot' - gem 'rspec-rails' - gem 'shoulda-matchers' - gem 'rails-controller-testing' gem 'database_cleaner' + gem 'factory_bot_rails' gem 'json-schema' -end - -group :test do gem 'launchy' gem 'rack_session_access' + gem 'rails-controller-testing' + gem 'rspec-rails' + gem 'shoulda-matchers' + gem 'simplecov', require: false 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' @@ -102,12 +97,10 @@ group :development do gem 'rubocop-performance' gem 'rubocop-rails' - - gem 'travis' - gem 'travis-lint' + # Mocks APi connections, and also prevents inadvertent network connections being made. + gem 'webmock' end - group :deployment do gem 'exception_notification' gem 'gmetric', '~>0.1.3' diff --git a/Gemfile.lock b/Gemfile.lock index e92f178c..0e5a8e53 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,404 +1,503 @@ GIT remote: https://github.com/sanger/pmb-client.git - revision: 016f151a3bde84448ed64e528259c3511282dcdb + revision: d87b1534796974448eec3ca9abff36cfbe777412 specs: pmb-client (0.1.0) json_api_client (~> 1.1) GIT remote: https://github.com/sanger/sanger_barcode_format.git - revision: f409a218a74a1d1571383ceaf693fe296eb6beb7 + revision: 27409a5af0fd98c0111eac8f545c6005508fbab1 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) + sanger_barcode_format (0.1.2) GEM - remote: http://rubygems.org/ + remote: https://rubygems.org/ specs: - aasm (5.0.5) + aasm (5.4.0) concurrent-ruby (~> 1.0) - ace-rails-ap (4.2) - actioncable (5.1.7) - actionpack (= 5.1.7) + ace-rails-ap (4.5) + actioncable (6.1.7.2) + actionpack (= 6.1.7.2) + activesupport (= 6.1.7.2) 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) + actionmailbox (6.1.7.2) + actionpack (= 6.1.7.2) + activejob (= 6.1.7.2) + activerecord (= 6.1.7.2) + activestorage (= 6.1.7.2) + activesupport (= 6.1.7.2) + mail (>= 2.7.1) + actionmailer (6.1.7.2) + actionpack (= 6.1.7.2) + actionview (= 6.1.7.2) + activejob (= 6.1.7.2) + activesupport (= 6.1.7.2) 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 (6.1.7.2) + actionview (= 6.1.7.2) + activesupport (= 6.1.7.2) + rack (~> 2.0, >= 2.0.9) 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) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (6.1.7.2) + actionpack (= 6.1.7.2) + activerecord (= 6.1.7.2) + activestorage (= 6.1.7.2) + activesupport (= 6.1.7.2) + nokogiri (>= 1.8.5) + actionview (6.1.7.2) + activesupport (= 6.1.7.2) 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) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (6.1.7.2) + activesupport (= 6.1.7.2) 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) - activerecord-import (1.0.2) - activerecord (>= 3.2) - activerecord-session_store (1.1.3) - actionpack (>= 4.0) - activerecord (>= 4.0) + activemodel (6.1.7.2) + activesupport (= 6.1.7.2) + activerecord (6.1.7.2) + activemodel (= 6.1.7.2) + activesupport (= 6.1.7.2) + activerecord-import (1.4.1) + activerecord (>= 4.2) + 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) - activesupport (5.1.7) + rack (>= 2.0.8, < 3) + railties (>= 5.2.4.1) + activestorage (6.1.7.2) + actionpack (= 6.1.7.2) + activejob (= 6.1.7.2) + activerecord (= 6.1.7.2) + activesupport (= 6.1.7.2) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (6.1.7.2) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - addressable (2.6.0) - public_suffix (>= 2.0.2, < 4.0) - arel (8.0.0) - ast (2.4.0) - autoprefixer-rails (9.6.0) - execjs + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) + amazing_print (1.4.0) + amq-protocol (2.3.2) + ast (2.4.2) + autoprefixer-rails (10.4.7.0) + execjs (~> 2) babel-source (5.8.35) babel-transpiler (0.7.0) babel-source (>= 4.0, < 6) execjs (~> 2.0) - backports (3.15.0) - bindex (0.7.0) + bindex (0.8.1) + bootsnap (1.16.0) + 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) - byebug (11.0.1) - coderay (1.1.2) - concurrent-ruby (1.1.5) - connection_pool (2.2.2) - crass (1.0.4) - 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) + bootstrap_form (5.1.0) + actionpack (>= 5.2) + activemodel (>= 5.2) + builder (3.2.4) + bunny (2.20.3) + amq-protocol (~> 2.3, >= 2.3.1) + sorted_set (~> 1, >= 1.0.2) + byebug (11.1.3) + coderay (1.1.3) + concurrent-ruby (1.2.0) + connection_pool (2.3.0) + crack (0.4.5) + rexml + crass (1.0.6) + daemons (1.4.1) + 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) + date (3.3.3) + delayed_job (4.1.11) + 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) + diff-lcs (1.5.0) + docile (1.4.0) + domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - dropzonejs-rails (0.8.4) + dropzonejs-rails (0.8.5) rails (> 3.1) - ebnf (1.1.3) - rdf (~> 3.0) - sxp (~> 1.0) + ebnf (2.3.1) + amazing_print (~> 1.4) + htmlentities (~> 4.3) + rdf (~> 3.2) + scanf (~> 1.0) + sxp (~> 1.2) + unicode-types (~> 1.7) 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) - 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) - faraday (0.15.4) - multipart-post (>= 1.2, < 3) - 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) + erubi (1.12.0) + exception_notification (4.5.0) + actionmailer (>= 5.2, < 8) + activesupport (>= 5.2, < 8) + execjs (2.8.1) + factory_bot (6.2.1) + activesupport (>= 5.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) + railties (>= 5.0.0) + faraday (1.10.3) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.0) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + faraday-retry (~> 1.0) + ruby2_keywords (>= 0.0.4) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-multipart (1.0.4) + multipart-post (~> 2) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday-retry (1.0.3) + faraday_middleware (1.2.0) + faraday (~> 1.0) + ffi (1.15.5) + flipper (0.26.0) + concurrent-ruby (< 2) + flipper-redis (0.26.0) + flipper (~> 0.26.0) + redis (>= 3.0, < 6) + flipper-ui (0.26.0) + erubi (>= 1.0.0, < 2.0.0) + flipper (~> 0.26.0) + rack (>= 1.4, < 3) + rack-protection (>= 1.5.3, <= 4.0.0) + sanitize (< 7) + globalid (1.1.0) + activesupport (>= 5.0) gmetric (0.1.3) - google_hash (0.9.0) - sane (~> 0) - hamster (3.0.0) - concurrent-ruby (~> 1.0) - highline (1.7.10) - http-cookie (1.0.3) + hashdiff (1.0.1) + hiredis (0.6.3) + htmlentities (4.3.4) + http-accept (1.7.0) + http-cookie (1.0.5) domain_name (~> 0.5) - i18n (1.6.0) + i18n (1.12.0) concurrent-ruby (~> 1.0) - jaro_winkler (1.5.3) - jbuilder (2.9.1) - activesupport (>= 4.2.0) - jquery-rails (4.3.5) + jbuilder (2.11.5) + actionview (>= 5.0.0) + activesupport (>= 5.0.0) + jquery-rails (4.5.1) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) 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) + json (2.6.3) + json-schema (3.0.0) + addressable (>= 2.8) + json_api_client (1.21.0) activemodel (>= 3.2.0) activesupport (>= 3.2.0) addressable (~> 2.2) - faraday (~> 0.15, >= 0.15.2) - faraday_middleware (~> 0.9) + faraday (>= 0.15.2, < 2.0) + faraday_middleware (>= 0.9.0, < 2.0) rack (>= 0.2) - jsonapi-resources (0.9.10) + jsonapi-resources (0.10.7) activerecord (>= 4.1) concurrent-ruby railties (>= 4.1) - launchy (2.4.3) - addressable (~> 2.3) + launchy (2.5.2) + addressable (~> 2.8) link_header (0.0.8) - loofah (2.2.3) + logger (1.5.3) + loofah (2.19.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) macaddr (1.7.2) systemu (~> 2.6.5) - mail (2.7.1) + mail (2.8.0.1) mini_mime (>= 0.1.1) - method_source (0.9.2) + net-imap + net-pop + net-smtp + marcel (1.0.2) + matrix (0.4.2) + method_source (1.0.0) 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) - mini_mime (1.0.2) - mini_portile2 (2.4.0) - minitest (5.11.3) - multi_json (1.13.1) - multipart-post (2.1.1) - mysql2 (0.5.2) - net-http-persistent (3.0.1) + mime-types-data (3.2022.0105) + mini_mime (1.1.2) + mini_portile2 (2.8.1) + minitest (5.17.0) + msgpack (1.6.0) + multi_json (1.15.0) + multipart-post (2.3.0) + mysql2 (0.5.5) + net-http-persistent (4.0.1) connection_pool (~> 2.2) - net-http-pipeline (1.0.1) + net-imap (0.3.4) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.1) + timeout + net-smtp (0.3.3) + net-protocol netrc (0.11.0) - nio4r (2.4.0) - 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) - pry (0.12.2) - coderay (~> 1.1.0) - method_source (~> 0.9.0) - public_suffix (3.1.0) - puma (3.12.1) - pusher-client (0.6.2) - json - websocket (~> 1.0) - rack (2.0.7) - rack-proxy (0.6.5) + nio4r (2.5.8) + nokogiri (1.14.1) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) + oj (3.14.0) + parallel (1.22.1) + parser (3.2.0.0) + ast (~> 2.4.1) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) + pry-byebug (3.10.1) + byebug (~> 11.0) + pry (>= 0.13, < 0.15) + pry-rails (0.3.9) + pry (>= 0.10.4) + public_suffix (5.0.1) + puma (6.0.2) + nio4r (~> 2.0) + racc (1.6.2) + rack (2.2.6.2) + rack-protection (3.0.5) + rack + rack-proxy (0.7.6) rack - rack-test (1.1.0) - rack (>= 1.0, < 3) + rack-test (2.0.2) + rack (>= 1.3) 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) - bundler (>= 1.3.0) - railties (= 5.1.7) + rails (6.1.7.2) + actioncable (= 6.1.7.2) + actionmailbox (= 6.1.7.2) + actionmailer (= 6.1.7.2) + actionpack (= 6.1.7.2) + actiontext (= 6.1.7.2) + actionview (= 6.1.7.2) + activejob (= 6.1.7.2) + activemodel (= 6.1.7.2) + activerecord (= 6.1.7.2) + activestorage (= 6.1.7.2) + activesupport (= 6.1.7.2) + bundler (>= 1.15.0) + railties (= 6.1.7.2) 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) - 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.5.0) + loofah (~> 2.19, >= 2.19.1) + railties (6.1.7.2) + actionpack (= 6.1.7.2) + activesupport (= 6.1.7.2) method_source - rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) - rainbow (3.0.0) - rake (12.3.3) - rb-fsevent (0.10.3) - rb-inotify (0.10.0) - ffi (~> 1.0) + rake (>= 12.2) + thor (~> 1.0) + rainbow (3.1.1) + rake (13.0.6) rb-readline (0.5.5) - rdf (3.0.12) - hamster (~> 3.0) + rbtree (0.4.6) + rdf (3.2.9) link_header (~> 0.0, >= 0.0.8) - rdf-aggregate-repo (2.2.1) - rdf (>= 2.2, < 4.0) - rdf-n3 (3.1.0) - rdf (~> 3.0) - sparql (~> 3.0) - sxp (~> 1.0) - rdf-xsd (3.0.1) - rdf (~> 3.0) - rdoc (6.1.1) - react-rails (2.5.0) + rdf-aggregate-repo (3.2.1) + rdf (~> 3.2) + rdf-n3 (3.2.1) + ebnf (~> 2.2) + rdf (~> 3.2) + sparql (~> 3.2) + sxp (~> 1.2) + rdf-xsd (3.2.1) + rdf (~> 3.2) + rexml (~> 3.2) + react-rails (2.6.2) babel-transpiler (>= 0.7.0) connection_pool execjs railties (>= 3.2) tilt - redis (4.1.2) - rest-client (2.0.2) + redis (4.8.0) + regexp_parser (2.6.2) + rest-client (2.1.0) + http-accept (>= 1.7.0, < 2.0) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - rspec-core (3.8.1) - rspec-support (~> 3.8.0) - rspec-expectations (3.8.4) + rexml (3.2.5) + rspec-core (3.12.0) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.8.0) - rspec-mocks (3.8.1) + rspec-support (~> 3.12.0) + rspec-mocks (3.12.3) 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) - rubocop (0.71.0) - jaro_winkler (~> 1.5.1) + rspec-support (~> 3.12.0) + rspec-rails (6.0.1) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.11) + rspec-expectations (~> 3.11) + rspec-mocks (~> 3.11) + rspec-support (~> 3.11) + rspec-support (3.12.0) + rubocop (1.44.1) + json (~> 2.3) parallel (~> 1.10) - parser (>= 2.6) + parser (>= 3.2.0.0) rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.24.1, < 2.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 (>= 2.4.0, < 3.0) + rubocop-ast (1.24.1) + parser (>= 3.1.1.0) + rubocop-performance (1.15.2) + rubocop (>= 1.7.0, < 2.0) + rubocop-ast (>= 0.4.0) + rubocop-rails (2.17.4) + activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.70.0) + rubocop (>= 1.33.0, < 2.0) ruby-growl (4.1) uuid (~> 2.3, >= 2.3.5) - ruby-progressbar (1.10.1) - sane (0.25.8) - os (~> 0) - sass (3.7.4) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.0.7) - railties (>= 4.0.0, < 6) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) - sassc (2.0.1) + ruby-progressbar (1.11.0) + ruby2_keywords (0.0.5) + sanger_warren (0.4.1) + bunny (~> 2.17) + connection_pool (~> 2.2) + multi_json (~> 1.0) + thor (~> 1.1) + sanitize (6.0.1) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + sass-rails (6.0.0) + sassc-rails (~> 2.1, >= 2.1.1) + sassc (2.4.0) ffi (~> 1.9) - rake - sdoc (1.0.0) - rdoc (>= 5.0) - shoulda-matchers (4.1.0) - activesupport (>= 4.2.0) - sparql (3.0.2) + sassc-rails (2.1.2) + railties (>= 4.0.0) + sassc (>= 2.0) + sprockets (> 3.0) + sprockets-rails + tilt + scanf (1.0.0) + semantic_range (3.0.0) + sequencescape-client-api (2.0.0) + activemodel (>= 5.0.0) + activesupport (>= 5.0.0) + i18n + multi_json + set (1.0.3) + shoulda-matchers (5.3.0) + activesupport (>= 5.2.0) + simplecov (0.22.0) + 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) + sparql (3.2.5) builder (~> 3.2) - ebnf (~> 1.1) - rdf (~> 3.0) - rdf-aggregate-repo (>= 2.2, < 4.0) - rdf-xsd (~> 3.0) - sparql-client (~> 3.0) - sxp (~> 1.0) - sparql-client (3.0.1) - net-http-persistent (>= 2.9, < 4) - rdf (~> 3.0) - spring (2.1.0) - sprockets (3.7.2) + ebnf (~> 2.2, >= 2.3.1) + logger (~> 1.5) + rdf (~> 3.2, >= 3.2.8) + rdf-aggregate-repo (~> 3.2) + rdf-xsd (~> 3.2) + sparql-client (~> 3.2, >= 3.2.1) + sxp (~> 1.2, >= 1.2.2) + sparql-client (3.2.1) + net-http-persistent (~> 4.0, >= 4.0.1) + rdf (~> 3.2, >= 3.2.6) + spring (4.1.1) + sprockets (4.2.0) concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.1) - actionpack (>= 4.0) - activesupport (>= 4.0) + rack (>= 2.2.4, < 4) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) sprockets (>= 3.0.0) - sxp (1.0.2) - rdf (~> 3.0) + sxp (1.2.3) + matrix (~> 0.4) + rdf (~> 3.2) systemu (2.6.5) - 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) + thor (1.2.1) + tilt (2.0.11) + timeout (0.3.1) + turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - typhoeus (0.8.0) - ethon (>= 0.8.0) - tzinfo (1.2.5) - thread_safe (~> 0.1) - tzinfo-data (1.2019.1) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + tzinfo-data (1.2022.7) tzinfo (>= 1.0.0) unf (0.1.4) unf_ext - unf_ext (0.0.7.6) - unicode-display_width (1.6.0) + unf_ext (0.0.8.2) + unicode-display_width (2.4.2) + unicode-types (1.8.0) uuid (2.3.9) macaddr (~> 1.0) - web-console (3.7.0) - actionview (>= 5.0) - activemodel (>= 5.0) + web-console (4.2.0) + actionview (>= 6.0.0) + activemodel (>= 6.0.0) bindex (>= 0.4.0) - railties (>= 5.0) - webpacker (4.0.7) - activesupport (>= 4.2) + railties (>= 6.0.0) + webmock (3.18.1) + addressable (>= 2.8.0) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) + webpacker (5.4.4) + 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 (1.2.8) - websocket-driver (0.6.5) + webrick (1.7.0) + websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.4) - will_paginate (3.1.7) + websocket-extensions (0.1.5) + will_paginate (3.3.1) will_paginate-bootstrap (1.0.2) will_paginate (>= 3.0.3) - yajl-ruby (1.4.1) + yard (0.9.28) + webrick (~> 1.7.0) + zeitwerk (2.6.6) PLATFORMS ruby @@ -408,21 +507,22 @@ DEPENDENCIES ace-rails-ap activerecord-import activerecord-session_store + bootsnap bootstrap-sass bootstrap_form - byebug daemons database_cleaner - delayed_job delayed_job_active_record dropzonejs-rails ejs exception_notification - factory_bot factory_bot_rails faraday + flipper + flipper-redis + flipper-ui gmetric (~> 0.1.3) - google_hash + hiredis jbuilder jquery-rails js_cookie_rails @@ -432,17 +532,19 @@ DEPENDENCIES launchy micro_token mysql2 + oj pmb-client! - pry + pry-byebug + pry-rails puma rack_session_access - rails (~> 5.1) + rails (~> 6.1) rails-assets-tether rails-controller-testing rb-readline rdf-n3 react-rails - redis + redis (< 5) rest-client rspec-rails rubocop @@ -450,22 +552,22 @@ DEPENDENCIES rubocop-rails ruby-growl sanger_barcode_format! + sanger_warren sass-rails - sdoc - sequencescape-client-api! + sequencescape-client-api shoulda-matchers + simplecov spring sprockets-rails - travis - travis-lint turbolinks tzinfo-data web-console + webmock webpacker webpacker-react will_paginate will_paginate-bootstrap - yajl-ruby + yard BUNDLED WITH - 1.16.2 + 2.2.26 diff --git a/README.md b/README.md index 47a2f01c..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 @@ -20,7 +18,110 @@ 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: @@ -30,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: @@ -45,9 +146,11 @@ bundle exec puma ``` ## Running Javascript tests + ``` yarn test ``` + ## Running tests in watch mode ``` @@ -74,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 @@ -104,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 @@ -128,16 +229,16 @@ 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 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. - #### Data model: ```text @@ -153,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/config/manifest.js b/app/assets/config/manifest.js new file mode 100644 index 00000000..b16e53d6 --- /dev/null +++ b/app/assets/config/manifest.js @@ -0,0 +1,3 @@ +//= link_tree ../images +//= link_directory ../javascripts .js +//= link_directory ../stylesheets .css 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 a5d11fa9..83c229fe 100644 --- a/app/assets/javascripts/barcode_reader.js +++ b/app/assets/javascripts/barcode_reader.js @@ -1,41 +1,44 @@ -(function($, undefined) { - function BarcodeReader(node, params) { - this.node = $(node); - this.input = $('input', node); - this.button = $('button', node); +;(function ($, undefined) { + 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)) { - 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.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(''); - }; - - $(document).ready(function() { - $(document).trigger('registerComponent.builder', {'BarcodeReader': BarcodeReader}); - }); -}(jQuery)); + } + + 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.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) 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 664747d2..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..d93c4474 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; @@ -19,15 +19,20 @@ tr.output { padding-left: 1em; } -form.edit_asset_group .panel-header { +form.edit_asset_group .panel-header, +.print-asset-group-header { padding: 10px 15px; background-color: #f5f5f5; - /*border-top: 1px solid #ddd;*/ border-bottom: 1px solid #ddd; } +.main-view form.edit_asset_group, +.main-view form.print_asset_group { + padding-bottom: 0; +} + body.logged-off ul.step-selection input { - pointer-events:none; + pointer-events: none; opacity: 0.65; } @@ -35,7 +40,6 @@ body.logged-off ul.step-selection input { margin-bottom: 1em; } - .condition-group-label { @extend .alert-success; @@ -51,29 +55,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 +107,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 { +.asset-groups .tab-pane.active .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 +150,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 +177,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 +188,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 +245,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 +260,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..b752dad0 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,430 @@ 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;} - +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; +} -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; } +.navbar-login i.role { + text-transform: capitalize; +} -.asset .panel-heading {display: none;} -.asset small {display: none;} +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; +} -div.fact a.active.object-reference {color:orange;} +form.edit_asset_group .barcode-adding-control { + width: 100%; + @extend .operator-allowed; +} -.no-compatible-steps-desc {font-size:11pt;} +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 09b1f1a4..49a3f84c 100644 --- a/app/channels/activity_channel.rb +++ b/app/channels/activity_channel.rb @@ -1,5 +1,4 @@ -class ActivityChannel < ApplicationCable::Channel - +class ActivityChannel < ApplicationCable::Channel # rubocop:todo Style/Documentation def self.connection_for_redis ActionCable.server.pubsub.redis_connection_for_subscriptions end @@ -19,34 +18,160 @@ def redis def self.subscribed_ids value = connection_for_redis.get('SUBSCRIBED_IDS') return [] unless value + JSON.parse(value) 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 + + # + # Struct type class to store the information related to a user provided input + # input: str, with the contents that we are going to process as input + # raw_input: str, with the original contents for the input before pre-process + # pos: integer, position of the user input in the original list of inputs + # result: Asset, resolved object for the user input + class BarcodeInput + attr_reader :input, :raw_input, :pos + attr_accessor :result + + def initialize(options) + @input = options[:input] + @raw_input = options[:raw_input] + @pos = options[:pos] + end + end + + # + # Struct type class to handle assets after it has been resolved + # together with the failing inputs + # assets: List, list of resolved assets + # missing_inputs: List, list of all inputs that didnt have a match + class BarcodeInputResolvedAssets + attr_reader :assets, :missing_inputs + def initialize(options) + @assets = options[:assets] + @missing_inputs = options[:missing_inputs] + end + end + + # Class that will handle resolving a user input into an Asset from the + # database. It supports 3 different types of user inputs: + # 1. UUID of an asset, which it will be resolved into the Asset it represents + # 2. Machine barcode of an asset, which it will be converted to human barcode + # and resolved into the Asset + # 3. Human barcode of an asset, which it will be resolved into the Asset it + # represents + class BarcodeInputResolver + def initialize + @input_objects_uuids = [] + @input_objects_human_barcodes = [] + @pos = 0 + end + + # Adds a new input to the resolver, classifying it into UUID or human barcode + def add_input(input) + return if input.blank? + if TokenUtil.is_uuid?(input) + @input_objects_uuids.push(BarcodeInput.new(input: input, raw_input: input, pos: _next_position)) + else + human_barcode = TokenUtil.human_barcode(input) + transformed_value = human_barcode.length.positive? ? human_barcode : input + @input_objects_human_barcodes.push( + BarcodeInput.new(input: transformed_value, raw_input: input, pos: _next_position) + ) + end + end + + # Returns a BarcodeInputResolvedAssets with the resolution of the Assets + # from the inputs added + def resolved_assets + BarcodeInputResolvedAssets.new( + assets: _resolved_objects.reject { |input| input.result.nil? }.map(&:result), + missing_inputs: _resolved_objects.select { |input| input.result.nil? }.map(&:raw_input) + ) + end + + private + + # Next number in position for the new input added. + def _next_position + @pos += 1 + end + + # Add the results for the resolution of the inputs provided + def _add_results_for_input_objects(inputs) + return unless inputs + results = yield + inputs.zip(results).each { |input, result| input.result = result } + end + + # Resolves all UUIDs read into Assets sorted by the order they were found, or + # with a nil value if they position was not found and maps them together + def _resolve_objects_uuids + _add_results_for_input_objects(@input_objects_uuids) do + uuids = @input_objects_uuids.map(&:input) + assets = Asset.where(uuid: uuids).to_a + uuids.map { |uuid| assets.detect { |a| a.uuid == uuid unless a.nil? } } + end + end + + # Resolves all human barcodes read into Assets or return nil if the position + # was not found + def _resolve_objects_human_barcodes + _add_results_for_input_objects(@input_objects_human_barcodes) do + inputs = inputs = @input_objects_human_barcodes.map(&:input) + Asset.find_or_import_assets_with_barcodes(inputs) + assets = Asset.where(barcode: inputs).to_a + inputs.map { |input| assets.detect { |a| a.barcode == input unless a.nil? } } + end + end + + # Sorts the list of inputs + def _sorted_input_objects + @input_objects_uuids.concat(@input_objects_human_barcodes).sort_by(&:pos) + end + + # Resolves all inputs into the Assets they represent. Caches the value and + # returns it in subsequents calls + def _resolved_objects + return @resolved_objects if @resolved_objects + _resolve_objects_uuids + _resolve_objects_human_barcodes + @resolved_objects = _sorted_input_objects + end + end + + # Process all inputs and resolves them into a BarcodeInputResolvedAssets object + def resolve_assets_from_inputs(inputs) + resolver = BarcodeInputResolver.new + inputs.each { |input| resolver.add_input(input) } + resolver.resolved_assets 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 = [] - - received_list = assets.map do |uuid_or_barcode| - Asset.find_or_import_asset_with_barcode(uuid_or_barcode) - end.compact - - 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} }) + inputs = strong_params[:assets] + + # @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 inputs + + begin + resolved_inputs = resolve_assets_from_inputs(inputs) + asset_group.update_with_assets(resolved_inputs.assets) + + if resolved_inputs.missing_inputs.present? + asset_group.activity.report_error("Could not find barcodes: #{resolved_inputs.missing_inputs.to_sentence}") end + rescue Errno::ECONNREFUSED => e + asset_group.activity.report_error('Cannot connect with sequencescape') + rescue StandardError => e + logger.error(e.backtrace.join("\n")) + asset_group.activity.report_error(e.message) end end @@ -55,7 +180,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 @@ -66,20 +191,18 @@ 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 } end def self.activity_attributes(id) - begin - JSON.parse(redis.hget('activities', id)) || default_activity_attributes - rescue StandardError => e - default_activity_attributes - end + JSON.parse(redis.hget('activities', id)) || default_activity_attributes + rescue StandardError => e + default_activity_attributes end 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) @@ -104,7 +227,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 eab38420..7a21e102 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -1,12 +1,12 @@ module ApplicationCable - class Connection < ActionCable::Connection::Base + class Connection < ActionCable::Connection::Base # rubocop:todo Style/Documentation identified_by :current_user def connect - #self.current_user = nil - token = cookies.encrypted['SOME SECRET']['token'] + # 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 48f49893..98ec8045 100644 --- a/app/controllers/activities_controller.rb +++ b/app/controllers/activities_controller.rb @@ -1,46 +1,35 @@ -class ActivitiesController < ApplicationController +class ActivitiesController < ApplicationController # rubocop:todo Style/Documentation 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] 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' - - respond_to do |format| - format.html { render :show } - format.json { render :show, status: :created, location: @activity } - end + def index + @my_activities = @current_user ? Activity.for_user(@current_user) : [] end - def show - respond_to do |format| format.html { render :show } format.json { render :show, status: :created, location: @activity } end end - def index - @my_activities = @current_user ? Activity.for_user(@current_user) : [] - 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 - format.html { redirect_to @activity, notice: 'Activity was successfully created.' } + format.html { redirect_to @activity, notice: 'Activity was successfully created.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :created, location: @activity } else format.html { render :new } @@ -49,60 +38,68 @@ def create end end - private + def update + @activity.finish if activity_params[:state] == 'finish' - def set_user - @user = @current_user - if @user.nil? - flash[:danger] = 'User not found' - redirect_to :back - end + respond_to do |format| + format.html { render :show } + format.json { render :show, status: :created, location: @activity } 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)) - end + private - 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) + def set_user + @user = @current_user + if @user.nil? + flash[:danger] = 'User not found' # rubocop:todo Rails/I18nLocaleTexts + redirect_to :back end + end - 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 + def set_kit + return true if activity_params[:activity_type_id] - # Use callbacks to share common setup or constraints between actions. - def set_activity - @activity = Activity.find(params[:id]) - end + @kit = Kit.find_by_barcode!(activity_params[:kit_barcode]) + rescue ActiveRecord::RecordNotFound => e + flash[:danger] = 'Kit not found' # rubocop:todo Rails/I18nLocaleTexts + redirect_back(fallback_location: use_instrument_path(@instrument)) + end + def set_instrument + return true if activity_params[:activity_type_id] - # 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) + @instrument = Instrument.find_by_barcode!(activity_params[:instrument_barcode]) + rescue ActiveRecord::RecordNotFound => e + flash[:danger] = 'Instrument not found' # rubocop:todo Rails/I18nLocaleTexts + redirect_back(fallback_location: instruments_path) + end + + 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' # rubocop:todo Rails/I18nLocaleTexts + 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..7bffec20 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] +class ActivityTypesController < ApplicationController # rubocop:todo Style/Documentation + 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 @@ -33,7 +32,7 @@ def create respond_to do |format| if @activity_type.save - format.html { redirect_to @activity_type, notice: 'Activity type was successfully created.' } + format.html { redirect_to @activity_type, notice: 'Activity type was successfully created.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :created, location: @activity_type } else format.html { render :new } @@ -47,7 +46,7 @@ def create def update respond_to do |format| if @activity_type.update(activity_type_params) - format.html { redirect_to @activity_type, notice: 'Activity type was successfully updated.' } + format.html { redirect_to @activity_type, notice: 'Activity type was successfully updated.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :ok, location: @activity_type } else format.html { render :edit } @@ -61,19 +60,20 @@ def update def destroy @activity_type.destroy respond_to do |format| - format.html { redirect_to activity_types_url, notice: 'Activity type was successfully destroyed.' } + format.html { redirect_to activity_types_url, notice: 'Activity type was successfully destroyed.' } # rubocop:todo Rails/I18nLocaleTexts format.json { head :no_content } end 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..a90b948f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,29 +1,27 @@ -class ApplicationController < ActionController::Base - +class ApplicationController < ActionController::Base # rubocop:todo Style/Documentation # Prevent CSRF attacks by raising an exception. # 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 attr_reader :current_user - def record_not_found(exception) + 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 + session[:token] = nil end end end - end diff --git a/app/controllers/asset_groups_controller.rb b/app/controllers/asset_groups_controller.rb index 8985b956..a40fd5ff 100644 --- a/app/controllers/asset_groups_controller.rb +++ b/app/controllers/asset_groups_controller.rb @@ -1,80 +1,90 @@ -class AssetGroupsController < ApplicationController - before_action :set_asset_group, only: [:show, :update, :print, :upload] - before_action :set_activity, only: [:show, :update] +class AssetGroupsController < ApplicationController # rubocop:todo Style/Documentation + 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 include ActivitiesHelper - - def show @assets = @asset_group.assets respond_to do |format| format.html { render @asset_group } format.n3 { render :show } - format.json { head :ok} + format.json { head :ok } end end - def update @assets = @asset_group.assets head :ok - #render json: { asset_group: {assets: @asset_group.assets.map(&:uuid) }} end def upload @file = UploadedFile.create(filename: params[:qqfilename], data: params[:qqfile].read) asset = @file.build_asset(content_type: params[:qqfile].content_type) - @asset_group.update_with_assets([].concat(@asset_group.assets).concat([asset])) + @asset_group.update_with_assets([].concat(@asset_group.assets).push(asset)) @asset_group.touch - render json: {success: true} + render json: { success: true } end def print - @asset_group.print(@current_user.printer_config, @current_user.username) + summary = @asset_group.print(printer_config) - redirect_to :back + respond_to do |format| + format.html { redirect_back fallback_location: root_path, notice: summary.to_s } + format.json { render json: { success: true, message: summary.to_s } } + end + rescue PrintMyBarcodeJob::PrintingError => e + respond_to do |format| + format.html { redirect_back fallback_location: root_path, alert: e.message, status: e.status_code } + format.json { render json: { success: false, message: e.message }, status: e.status_code } + end end private - def update_barcodes - perform_assets_update + def update_barcodes + perform_assets_update - if @alerts - render json: {errors: @alerts} - end - end + render json: { errors: @alerts } if @alerts + 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 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 - # Use callbacks to share common setup or constraints between actions. - def set_asset_group - @asset_group = AssetGroup.find(params[:id]) - end + # Use callbacks to share common setup or constraints between actions. + def set_asset_group + @asset_group = AssetGroup.find(params[:id]) + end - def perform_assets_update - @asset_group.update_attributes(assets: params_update_asset_group[:assets].map do |uuid_or_barcode| - Asset.find_or_import_asset_with_barcode(uuid_or_barcode) - end.compact.uniq) - end + def perform_assets_update + @asset_group.update( + 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) - @alerts = [] unless @alerts - @alerts.push(data) - end + def show_alert(data) + @alerts = [] unless @alerts + @alerts.push(data) + end - def params_update_asset_group - params.require(:asset_group).permit(:assets => []) - end + def printer_config + # We permit the entire hash, as we just use it for lookup. + request_config = params.fetch(:printer_config, {}).permit! + @current_user.printer_config.merge(request_config) + 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 94be11af..c0d2cbab 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -1,74 +1,64 @@ -require 'pry' -class AssetsController < ApplicationController - - before_action :set_asset, only: [:show, :edit, :update, :destroy, :print] - before_action :set_queries, only: [:search, :print_search] +class AssetsController < ApplicationController # rubocop:todo Style/Documentation + 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) + @asset.print(@current_user.printer_config) respond_to do |format| - format.html { redirect_to @asset, notice: 'Asset was printed.' } + format.html { redirect_to @asset, notice: 'Asset was printed.' } # rubocop:todo Rails/I18nLocaleTexts end - 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) + temp_group.print(@current_user.printer_config) - 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 # 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 } end end - # GET /assets/new def new @asset = Asset.new end # GET /assets/1/edit - def edit - end + def edit; end # POST /assets # POST /assets.json @@ -77,7 +67,7 @@ def create respond_to do |format| if @asset.save - format.html { redirect_to @asset, notice: 'Asset was successfully created.' } + format.html { redirect_to @asset, notice: 'Asset was successfully created.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :created, location: @asset } else format.html { render :new } @@ -90,11 +80,10 @@ def create # PATCH/PUT /assets/1.json def update respond_to do |format| - if @asset.update(asset_params) @asset.touch - format.html { redirect_to @asset, notice: 'Asset was successfully updated.' } + format.html { redirect_to @asset, notice: 'Asset was successfully updated.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :ok, location: @asset } else format.html { render :edit } @@ -108,22 +97,16 @@ def update def destroy @asset.destroy respond_to do |format| - format.html { redirect_to assets_url, notice: 'Asset was successfully destroyed.' } + format.html { redirect_to assets_url, notice: 'Asset was successfully destroyed.' } # rubocop:todo Rails/I18nLocaleTexts format.json { head :no_content } 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 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) @@ -131,20 +114,18 @@ 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*)$/) }.pluck(1) end - def set_queries - @queries = valid_indexes.map do |val| - OpenStruct.new({:predicate => params["p"+val], :object => params["o"+val]}) + 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 - - UUID_REGEXP = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/ + 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..e46c81fd 100644 --- a/app/controllers/changes_controller.rb +++ b/app/controllers/changes_controller.rb @@ -1,26 +1,21 @@ -class ChangesController < ApplicationController +class ChangesController < ApplicationController # rubocop:todo Style/Documentation 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(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 - def params_changes - params.require(:changes).permit! - end - + def params_changes + params.require(:changes).permit! + end end diff --git a/app/controllers/history_controller.rb b/app/controllers/history_controller.rb index 69ada7b2..bec44188 100644 --- a/app/controllers/history_controller.rb +++ b/app/controllers/history_controller.rb @@ -1,5 +1,5 @@ -class HistoryController < ApplicationController +class HistoryController < ApplicationController # rubocop:todo Style/Documentation 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 6f359ce4..3de2e9a7 100644 --- a/app/controllers/instruments_controller.rb +++ b/app/controllers/instruments_controller.rb @@ -1,6 +1,5 @@ -require 'pry' -class InstrumentsController < ApplicationController - before_action :set_instrument, only: [:show, :edit, :update, :destroy, :use] +class InstrumentsController < ApplicationController # rubocop:todo Style/Documentation + before_action :set_instrument, only: %i[show edit update destroy use] # GET /instruments # GET /instruments.json @@ -10,8 +9,7 @@ def index # GET /instruments/1 # GET /instruments/1.json - def show - end + def show; end def use @activity = Activity.new @@ -23,8 +21,7 @@ def new end # GET /instruments/1/edit - def edit - end + def edit; end # POST /instruments # POST /instruments.json @@ -33,7 +30,7 @@ def create respond_to do |format| if @instrument.save - format.html { redirect_to @instrument, notice: 'Instrument was successfully created.' } + format.html { redirect_to @instrument, notice: 'Instrument was successfully created.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :created, location: @instrument } else format.html { render :new } @@ -47,7 +44,7 @@ def create def update respond_to do |format| if @instrument.update(instrument_params) - format.html { redirect_to @instrument, notice: 'Instrument was successfully updated.' } + format.html { redirect_to @instrument, notice: 'Instrument was successfully updated.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :ok, location: @instrument } else format.html { render :edit } @@ -61,20 +58,20 @@ def update def destroy @instrument.destroy respond_to do |format| - format.html { redirect_to instruments_url, notice: 'Instrument was successfully destroyed.' } + format.html { redirect_to instruments_url, notice: 'Instrument was successfully destroyed.' } # rubocop:todo Rails/I18nLocaleTexts format.json { head :no_content } end 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..5d3228c0 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] +class KitTypesController < ApplicationController # rubocop:todo Style/Documentation + 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 @@ -29,7 +27,7 @@ def create respond_to do |format| if @kit_type.save - format.html { redirect_to @kit_type, notice: 'Kit type was successfully created.' } + format.html { redirect_to @kit_type, notice: 'Kit type was successfully created.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :created, location: @kit_type } else format.html { render :new } @@ -43,7 +41,7 @@ def create def update respond_to do |format| if @kit_type.update(kit_type_params) - format.html { redirect_to @kit_type, notice: 'Kit type was successfully updated.' } + format.html { redirect_to @kit_type, notice: 'Kit type was successfully updated.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :ok, location: @kit_type } else format.html { render :edit } @@ -57,23 +55,24 @@ def update def destroy @kit_type.destroy respond_to do |format| - format.html { redirect_to kit_types_url, notice: 'Kit type was successfully destroyed.' } + format.html { redirect_to kit_types_url, notice: 'Kit type was successfully destroyed.' } # rubocop:todo Rails/I18nLocaleTexts format.json { head :no_content } end 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..29a50d7b 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] +class KitsController < ApplicationController # rubocop:todo Style/Documentation + 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 @@ -28,7 +26,7 @@ def create @kit = Kit.new(kit_params) respond_to do |format| if @kit.save - format.html { redirect_to @kit, notice: 'Kit was successfully created.' } + format.html { redirect_to @kit, notice: 'Kit was successfully created.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :created, location: @kit } else format.html { render :new } @@ -42,7 +40,7 @@ def create def update respond_to do |format| if @kit.update(kit_params) - format.html { redirect_to @kit, notice: 'Kit was successfully updated.' } + format.html { redirect_to @kit, notice: 'Kit was successfully updated.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :ok, location: @kit } else format.html { render :edit } @@ -56,23 +54,24 @@ def update def destroy @kit.destroy respond_to do |format| - format.html { redirect_to kits_url, notice: 'Kit was successfully destroyed.' } + format.html { redirect_to kits_url, notice: 'Kit was successfully destroyed.' } # rubocop:todo Rails/I18nLocaleTexts format.json { head :no_content } end 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..ce9d792b 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] +class PrintersController < ApplicationController # rubocop:todo Style/Documentation + 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 @@ -28,7 +26,7 @@ def create respond_to do |format| if @printer.save - format.html { redirect_to @printer, notice: 'Printer was successfully created.' } + format.html { redirect_to @printer, notice: 'Printer was successfully created.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :created, location: @printer } else format.html { render :new } @@ -42,7 +40,7 @@ def create def update respond_to do |format| if @printer.update(printer_params) - format.html { redirect_to @printer, notice: 'Printer was successfully updated.' } + format.html { redirect_to @printer, notice: 'Printer was successfully updated.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :ok, location: @printer } else format.html { render :edit } @@ -56,19 +54,20 @@ def update def destroy @printer.destroy respond_to do |format| - format.html { redirect_to printers_url, notice: 'Printer was successfully destroyed.' } + format.html { redirect_to printers_url, notice: 'Printer was successfully destroyed.' } # rubocop:todo Rails/I18nLocaleTexts format.json { head :no_content } end 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..9770a6a4 100644 --- a/app/controllers/reracking_controller.rb +++ b/app/controllers/reracking_controller.rb @@ -1,15 +1,12 @@ -class RerackingController < ApplicationController - +class RerackingController < ApplicationController # rubocop:todo Style/Documentation 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 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 decd174b..b3207f35 100644 --- a/app/controllers/samples_not_started_controller.rb +++ b/app/controllers/samples_not_started_controller.rb @@ -1,9 +1,7 @@ -class SamplesNotStartedController < SamplesStatusController - +class SamplesNotStartedController < SamplesStatusController # rubocop:todo Style/Documentation 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..a35b6409 100644 --- a/app/controllers/samples_started_controller.rb +++ b/app/controllers/samples_started_controller.rb @@ -1,9 +1,14 @@ -class SamplesStartedController < SamplesStatusController - +class SamplesStartedController < SamplesStatusController # rubocop:todo Style/Documentation 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/controllers/samples_status_controller.rb b/app/controllers/samples_status_controller.rb index aeb0cbd0..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} + 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} + { page: 1, per_page: 5 } end end @@ -27,16 +26,13 @@ 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 - @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 5e80e96c..3606d398 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] +class StepTypesController < ApplicationController # rubocop:todo Style/Documentation + 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,9 +26,7 @@ def new end # GET /step_types/1/edit - def edit - end - + def edit; end # POST /step_types # POST /step_types.json @@ -37,7 +35,7 @@ def create respond_to do |format| if @step_type.save - format.html { redirect_to @step_type, notice: 'Step type was successfully created.' } + format.html { redirect_to @step_type, notice: 'Step type was successfully created.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :created, location: @step_type } else format.html { render :new } @@ -51,7 +49,7 @@ def create def update respond_to do |format| if @step_type.update(empty_options_set_to_nil(step_type_params)) - format.html { redirect_to @step_type, notice: 'Step type was successfully updated.' } + format.html { redirect_to @step_type, notice: 'Step type was successfully updated.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :ok, location: @step_type } else format.html { render :edit } @@ -65,30 +63,32 @@ def update def destroy @step_type.destroy respond_to do |format| - format.html { redirect_to step_types_url, notice: 'Step type was successfully destroyed.' } + format.html { redirect_to step_types_url, notice: 'Step type was successfully destroyed.' } # rubocop:todo Rails/I18nLocaleTexts format.json { head :no_content } end 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 + %i[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 5a98630a..93923a55 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -1,6 +1,4 @@ -require 'pry' - -class StepsController < ApplicationController +class StepsController < ApplicationController # rubocop:todo Style/Documentation before_action :set_step, only: [:update] before_action :set_activity, only: [:create] before_action :set_printer_config, only: [:create] @@ -14,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 @@ -35,42 +33,40 @@ 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..b966439c 100644 --- a/app/controllers/uploaded_files_controller.rb +++ b/app/controllers/uploaded_files_controller.rb @@ -1,17 +1,14 @@ -class UploadedFilesController < ApplicationController +class UploadedFilesController < ApplicationController # rubocop:todo Style/Documentation before_action :set_uploaded_file, only: [:show] def show respond_to do |format| - format.bin { - send_data(@uploaded_file.data,filename: @uploaded_file.filename) - } + format.bin { 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..909c88bf 100644 --- a/app/controllers/user_sessions_controller.rb +++ b/app/controllers/user_sessions_controller.rb @@ -1,4 +1,4 @@ -class UserSessionsController < ApplicationController +class UserSessionsController < ApplicationController # rubocop:todo Style/Documentation before_action :set_user, only: [:create] def create @@ -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 @@ -20,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 bf73e007..653bd799 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] +class UsersController < ApplicationController # rubocop:todo Style/Documentation + 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 @@ -33,7 +31,7 @@ def create respond_to do |format| if @user.save - format.html { redirect_to @user, notice: 'User was successfully created.' } + format.html { redirect_to @user, notice: 'User was successfully created.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :created, location: @user } else format.html { render :new } @@ -47,7 +45,7 @@ def create def update respond_to do |format| if @user.update(user_params) - format.html { redirect_to @user, notice: 'User was successfully updated.' } + format.html { redirect_to @user, notice: 'User was successfully updated.' } # rubocop:todo Rails/I18nLocaleTexts format.json { render :show, status: :ok, location: @user } else format.html { render :edit } @@ -61,19 +59,20 @@ def update def destroy @user.destroy respond_to do |format| - format.html { redirect_to users_url, notice: 'User was successfully destroyed.' } + format.html { redirect_to users_url, notice: 'User was successfully destroyed.' } # rubocop:todo Rails/I18nLocaleTexts format.json { head :no_content } end 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 48830ce1..682e85fe 100644 --- a/app/helpers/activities_helper.rb +++ b/app/helpers/activities_helper.rb @@ -1,24 +1,25 @@ require 'support_n3' -module ActivitiesHelper - +module ActivitiesHelper # rubocop:todo Style/Documentation 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 - } - 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) step_types = activity.step_types_for(asset_group.assets) { @@ -30,11 +31,14 @@ 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) @@ -45,7 +49,7 @@ def steps_data_for_steps(steps) activity: step.activity, assetGroup: step.asset_group, step_type: step.step_type, - operations: operations_data(step.operations.joins(:asset)), + operations: operations_data(step.operations), username: username }.merge(step.attributes) end @@ -53,69 +57,46 @@ 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) - 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 - 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 + operations + .with_asset + .includes(:object_asset, :asset) + .map do |fact| + fact.attributes.tap do |data| + elem = fact.object_asset + + data['object_asset'] = { + uuid: elem.uuid, + barcode: elem.barcode, + id: elem.id, + info_line: elem.info_line + } if elem + + data[:asset] = fact.asset.attributes + end end - 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 - next memo - end + facts.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) + { '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 - 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) @@ -124,56 +105,55 @@ def asset_group_data(activity, asset_group) activityId: asset_group.activity_owner.id, lastUpdate: asset_group.updated_at, updateUrl: Rails.application.routes.url_helpers.activity_asset_group_path(activity, asset_group), + printUrl: Rails.application.routes.url_helpers.print_asset_group_path(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 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).to_s }-#{ 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.reduce({}) do |memo, asset| - 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 + 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 + .include_messages + .flat_map(&:step_messages) + .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 2f92faff..6b6f546f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,4 +1,4 @@ -module ApplicationHelper +module ApplicationHelper # rubocop:todo Style/Documentation def unknown_aliquot_type 'unknown-aliquot' end @@ -7,8 +7,8 @@ def empty_well_aliquot_type 'empty-well-aliquot' end - def bootstrap_link_to(name = nil, options = nil, html_options = nil, &block) - modified_options = {:class => 'btn btn-default'} + 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) end @@ -16,26 +16,18 @@ def bootstrap_link_to(name = nil, options = nil, html_options = nil, &block) 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,63 +36,79 @@ 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 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 - 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) 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 }) - 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( + '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 + } + ) 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: asset_path(asset) - } unless location.nil? + memo end - memo - end end def data_asset_display_for_tube(facts) @@ -108,22 +116,19 @@ 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: { - cssClass: css_classes, title: title, url: url - } - } + { aliquot: { cssClass: css_classes, title: title, url: url } } end 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 @@ -135,7 +140,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' }.pick(:object)) end def show_alert(data) @@ -144,9 +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 8b9be361..27f99b93 100644 --- a/app/helpers/assets_helper.rb +++ b/app/helpers/assets_helper.rb @@ -1,19 +1,20 @@ -module AssetsHelper +module AssetsHelper # rubocop:todo Style/Documentation 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 + end end diff --git a/app/helpers/step_types_helper.rb b/app/helpers/step_types_helper.rb index a0f6a70f..f507b96f 100644 --- a/app/helpers/step_types_helper.rb +++ b/app/helpers/step_types_helper.rb @@ -1,4 +1,4 @@ -module StepTypesHelper +module StepTypesHelper # rubocop:todo Style/Documentation def fact_css_classes { 'addFacts' => 'glyphicon glyphicon-pencil', @@ -11,40 +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..6efa3e59 100644 --- a/app/helpers/steps_helper.rb +++ b/app/helpers/steps_helper.rb @@ -1,10 +1,10 @@ -module StepsHelper +module StepsHelper # rubocop:todo Style/Documentation def text_color_for_state(state) "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..5a4841e7 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,92 @@ 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.props.featureFlags?.dpl348_decouple_automatic_printing_from_steps && ( + + )} + {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..0a170827 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} messages, 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..36c65f9f 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,59 +47,57 @@ 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_group_printing.jsx b/app/javascript/components/asset_group_components/asset_group_printing.jsx new file mode 100644 index 00000000..3bb44c45 --- /dev/null +++ b/app/javascript/components/asset_group_components/asset_group_printing.jsx @@ -0,0 +1,98 @@ +import React from 'react' +import { FormFor } from 'react-rails-form-helpers' +import { getCsrfToken } from '../lib/uploader_utils' + +import PrintersSelection from '../activity_components/printers_selection' + +const findName = (options, value) => { + const [defaultName, _defaultId] = options.find(([_name, id]) => id === value) || options[0] + return defaultName +} +const findDefaultName = ({ optionsData, defaultValue }) => findName(optionsData, defaultValue) +/** + assetGroup: { + printUrl: The target url for the form + }, + platePrinter: { + defaultValue: default printer id, + optionsData: [ + [ + printer name , + printer id + ] + ] + }, + tubePrinter: { + defaultValue: default printer id, + optionsData: [ + [ + printer name , + printer id + ] + ] + }, + onMessage: Error message handler function +**/ +class AssetGroupPrinting extends React.Component { + constructor(props) { + super(props) + this.state = { + Tube: findDefaultName(this.props.tubePrinter), + Plate: findDefaultName(this.props.platePrinter), + } + + // Bind Events + // https://reactjs.org/docs/faq-functions.html#how-do-i-bind-a-function-to-a-component-instance + this.onChangeTubePrinter = this.onChangeTubePrinter.bind(this) + this.onChangePlatePrinter = this.onChangePlatePrinter.bind(this) + this.onSubmit = this.onSubmit.bind(this) + } + onChangeTubePrinter(e) { + this.setState({ Tube: findName(this.props.tubePrinter.optionsData, e.target.value) }) + } + onChangePlatePrinter(e) { + this.setState({ Plate: findName(this.props.platePrinter.optionsData, e.target.value) }) + } + onSubmit(e) { + e.preventDefault() + window + .fetch(this.props.assetGroup.printUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + 'X-CSRF-Token': getCsrfToken(), + }, + body: JSON.stringify({ printerConfig: this.state }), + }) + .then((response) => response.json()) + .then((result) => this.props.onMessage({ type: result.success ? 'success' : 'danger', msg: result.message })) + .catch((error) => this.props.onMessage({ type: 'danger', msg: error.toString() })) + } + render() { + if (this.props.assetGroup.assets.length > 0) { + return ( + +
+ +
+
+ + +
+
+ ) + } else { + return 'No assets to print' + } + } +} + +export default AssetGroupPrinting 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..e965d10d 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,6 @@ import React from 'react' -import AssetGroupEditor from "../asset_group_components/asset_group_editor" +import AssetGroupEditor from './asset_group_editor' +import AssetGroupPrinting from './asset_group_printing' class AssetGroupsEditor extends React.Component { constructor(props) { @@ -11,18 +12,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 +36,61 @@ 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( -
    - + return ( +
    +
    + {this.props.allowPrinting && ( +
    + +
    + )} + +
    ) } 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..8106639b 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,33 @@ 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. operationsDurationUsernameStatus
    - { 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(