From 3ceab08e09c07b1526ab89be47fcdbba02e309aa Mon Sep 17 00:00:00 2001 From: Ian London Date: Thu, 6 Dec 2018 16:59:58 -0500 Subject: [PATCH] Update PD beta staging from edge (#2789) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(components): remove old clickOutside HoC (#2664) Closes #2590 * refactor(shared-data): Modify z-height logic and docs for labware designer (#2670) * refactor(shared-data): Modify z-height logic and docs for labware designer * feat(protocol-designer): liquid placement modal performance boost (#2661) Move liquid placement modal to use new abstraction, SelectableLabware, and mirror the changes that went into the performance improvements of the WellSelectionModal. Also, rename the SelectablePlate component and container to HighlightableLabware as it is now only being used in the LabwareOnDeck compound and is neither hoverable, nor selectable. Closes #2557 * feat(protocol-designer): disconnect well selection modal from hovered step state (#2662) Well selection modal well contents are now only correlated with the currently selected step (the one being edited) Closes #2558 * refactor(protocol-designer): change StepType from number to string (#2666) * uses UUID for steps * update step reducer tests to use string IDs not numbers Closes #2588 * build(travis): Refactor build to use stages (#2668) * build(app-shell): Add publisherName to electron-builder windows config (#2677) * ci(travis): Move flow typechecking to separate job in test stage (#2683) * refactor(protocol-designer): unite delete labware and handleFormChange logic (#2680) There was some unecessary duplication of concerns between handling unsaved form changes and handling deletion of labware in all saved forms. This addition creates a function that can be used by both cases, to unite the logic into one source of truth. Closes #2657 * fix(api): re-position p1000 droptip/blowout positions (#2681) * fix(api): re-position p1000 droptip/blowout positions to better handle tip variance * restores p1000_single_v1 positions to previous API values * perf(api): Decrease plunger motor max speed by 20% (#2682) * feat(api): Add 1.5ml tuberack to old labware definition section (#2679) * refactor(api): more functions use hc (#2675) * refactor(api): Move smoothie update into smoothie driver This makes it easier to use hardware control instead of the robot in main and is where the functionality should have been in the first place. Note that this doesn’t currently apply to the update server. * refactor(api): Add a fixture to test with both new and old apis By using the new old_and_new_client fixture instead of either async_client or test_client and building a server instance directly, tests can now check both the old and new versions of the API. old_and_new_client is a parameterized fixture that pytest will automatically run once with each parameter, resetting the globals to the correct version. In addition, the globals in opentrons/__init__ are now defined such that they can be reset to a different API version by a function call. This has to be used quite carefully since it will only reset the global instances themselves, not copies interned elsewhere, but it’s quite useful for this testing purpose. * refactor(api): Change modules to work with control endpoints We needed the old and new modules to look a bit more alike, and now can get attached modules and module info from the run app while using hardware_control. * refactor(api): Pull light control fully into gpio driver Previously it lived an uncomfortable life half in robot and half in gpio. Since lights aren’t controlled by smoothie, robot is a bad place for them (but the calls remain there for back compatibility). * refactor(api): Make servers use injected hw and new api if ff set The RPC and HTTP servers (to a large but not complete extent) and the system as a whole now rely on an injected hardware instance for talking to hardware. This does not extend to deck calibration, protocol sessions (including labware calibration), or testing tools. In addition, there’s work done on the tests so that tests can more easily run on both versions of the api while relying on simple fixtures; async_client and main_router and the things that depend on them, for instance, now will run on both apis unless marked otherwise. Many small additions have been made to both the new and old APIs to get them to work a bit more like each other to make the logic necessary in dependent systems like the servers to be a little more similar between versions. * refactor(api): add ability to override critical point in moves and get position This is needed for the move endpoint because it makes it a lot easier to move pipettes to a change pipette position guaranteed to neither be too high nor too low. Closes #2245 * feat(protocol-designer): use tip max vol, not pipette max vol (#2656) * aspirate/consolidate/transfer/distribute use smallest of (tip max volume, pipette max volume) * added 200uL Tiprack to PD as an option Closes #2160 * chore(react): upgrade react to v16.6.3 (#2687) * feat(protocol-designer): allow user to set touch-tip offset (#2691) * refactor tip offset components to allow them to also work with touch tip * add new fields for forms and to step-generation command creator args to allow touch-tip offsets * rename fields used only by mix to have mix_ prefix * refactor field types Closes #2540 * docs(api): Add instructions to set up API locally (#2699) There have been several customer questions about how to use the API locally to test protocols. While there is still not a good workflow, these instructions should help. * feat(protocol-designer): make settings tab always active (#2700) Closes #2697 * refactor(protocol-designer): remove activeModals selector (#2701) Closes #2592 * feat(protocol-designer): disambiguate left/right pipette names when they match (#2698) Closes #2078 * refactor(app): Update app before robot (#2685) * feat(api): Adds pipette models v1.4 to robot config (#2689) * feat(api): Adds pipette models v1.4 to robot config * shift p10-multi blowout position up 1.5mm * fixed mistake in p1000 v1.4 blow-out position * adds v1.4 to pipette barcoding scanning tool * refactor(api): Use modules in protocol api (#2702) * refactor(api): Use modules in protocol api There are now ModuleContexts in protocol_api/contexts.py that expose the module API. The protocol API also has a new workflow for adding labware to modules: - create a module with ProtocolContext.load_module() - call module.load_labware[_by_name]() to load the labware This avoids the shared=True functionality that was only used for modules but was designed to be super generic. Modules also now have their own specs file that defines their geometry, including the offsets from the deck to their labware and their overall shape. In addition, fix some minor bugs: - axis maxima bumped by +0.05mm for all axes to avoid floating point precision problems when positions are run through deck transform - hardware_control SynchronousAdapter needs to actually return the results of coroutines it executes - Reset the protocol context location cache after homing feature(api): Add magnetic module compatiblity to labware schema Labware now has an extra couple of parameters. isMagneticModuleCompatible is a bool indicating whether the labware can be easily used by a magdeck; magneticModuleEngageHeight is the height to raise the magnets for that piece of labware. If a labware that is not compatible is loaded onto a magdeck, you get a warning and must explicitly specify the magnet height. * Fix failing tests * docs(api): Fix incorrect labels for rows and columns in labware docs (#2710) * docs: Correct the link for changing robot gantry speed (#2711) * chore(release): 3.6.0-beta.1 (#2724) * refactor(app): Remove padding from wifi connect form (#2730) * refactor(protocol-designer): rename selectors to start with "get" (#2720) Closes #2591 * feat(protocol-designer): make multichannel substeps collapsed by default (#2729) Closes #2678 * feat(protocol-designer): add tooltip to advanced settings icon (#2727) Closes #2706 * feat(protocol-designer): remove label from 200ul/300ul tiprack image (#2722) Closes #2704 * fix(api): Fix the flaky tempdeck test (#2725) * fix(api): Fix the flaky tempdeck test The tempdeck driver, when it fails, will sleep and try again. When we’re testing that, we need to wait a bit - since it’s in a thread - before checking the output. * refactor(app): Add update in progress and restart screens (#2728) * refactor(shared-data): rename slot width/height constants (#2723) use separate constants when dealing with robot coordinate system (eg in labwareTools) versus when rendering deck/labware in SVG coordinates Closes #2535 * refactor(app): Add app update message and release notes toggle (#2738) * fix(shared-data): fix total-liquid-volume of opentrons-tuberack-50ml (#2744) Closes #2743 * chore(release): 3.6.0 (#2746) * feat(protocol-designer): allow user to re-enable dismissed hints (#2726) Closes #2652 * feat(protocol-designer): highlight tips per substep (#2716) Closes #2537 * feat(protocol-designer): drag and drop step reordering (#2714) Add drag and drop functionality allowing users to arbitrarily reorder their steps in the steplist. Closes #2654 * fix(protocol-designer): fix missing disposal volume in new distribute forms (#2733) Closes #2705 * feat(protocol-designer): remove option of tiprack-1000ul-chem from pd (#2745) * feat(protocol-designer): new protocol modal defaults and visual updates (#2739) remove null selection for pipette models from new file modal. Also condense styles to clean up visual space. Closes #2721 * feat(protocol-designer): remove delay from advanced settings of all step types (#2731) Closes #2579 * feat(protocol-designer): place tipracks on protocol creation (#2750) By default, when a user creates a protocol, one tip rack for each given mount should be placed on the deck. Closes #1327 * new p10s function added to config file (#2774) * fix(api): new p10s function added to config file Due to inaccuracy of the old function, this new function was calculated based on testing several pipettes. The function has been tested on the scale and the robot. * feat(protocol-designer): show file created and modified date (#2754) * make metadata be a Formik form; remove unsaved metadata fields from redux Closes #1623 * chore(release): 3.6.1 (#2780) * feat(protocol-designer): implement duplicate step (#2715) * feat(protocol-designer): implement duplicate step Right click on a step in the step list and you now have the option to duplicate it or delete it. * feat(protocol-designer): standardize blowout and disposal volume destinations (#2732) Flesh out differences in options and implementation of blowout destination (disposal volume and otherwise) across Transfer, Consolidate, Distribute, and Mix type steps. Closes #1989 * refactor(step-generation): getNextRobotStateAndWarnings and use in aspirate (#2747) In an effort to consolidate the logic in step generation that calculates the next robotState given a command, this adds a function called getNextRobotStateAndWarnings. Eventually this will be used in all command creators to generate the next robotState given StepArgs. This takes the first step by migrating the aspirate commandCreator from aspirateUpdateLiquidState to the new getNextRobotStateAndWarnings Closes #2734 * feat(protocol-designer): enable sharing tip racks between pipettes (#2753) * feat(protocol-designer): scroll to top of page when step created/selected (#2785) * fix(protocol-designer): fix changeTip once bug in distribute step (#2784) Closes #2748 * fix(protocol-designer): finish implementing flow rate in PD (#2782) Closes #2773 * fix(protocol-designer): fix when add liquid hint is shown (#2787) Closes #2777 * feat(protocol-designer): use pipette min vol as default/recommended disposal volume (#2788) Closes #2777 --- .python-version | 1 - .travis.yml | 262 +- CHANGELOG.md | 75 + CONTRIBUTING.md | 3 +- Makefile | 16 +- api/Makefile | 7 +- api/Pipfile | 13 +- api/Pipfile.lock | 521 ++-- api/README.rst | 23 +- api/docs/source/labware.rst | 8 +- api/docs/source/robot.rst | 2 +- api/pytest.ini | 5 +- api/src/opentrons/CHANGELOG.md | 41 + api/src/opentrons/__init__.py | 83 +- api/src/opentrons/api/calibration.py | 3 +- api/src/opentrons/api/routers.py | 7 +- api/src/opentrons/api/session.py | 111 +- api/src/opentrons/broker/broker.py | 16 +- .../config/containers/default-containers.json | 214 +- api/src/opentrons/config/robot_configs.py | 4 +- api/src/opentrons/drivers/rpi_drivers/gpio.py | 45 + .../drivers/smoothie_drivers/driver_3_0.py | 97 +- .../opentrons/hardware_control/__init__.py | 243 +- .../opentrons/hardware_control/adapters.py | 96 +- .../opentrons/hardware_control/controller.py | 75 +- .../hardware_control/modules/magdeck.py | 15 +- .../hardware_control/modules/mod_abc.py | 6 + .../hardware_control/modules/tempdeck.py | 6 +- api/src/opentrons/hardware_control/pipette.py | 14 +- .../opentrons/hardware_control/simulator.py | 60 +- api/src/opentrons/hardware_control/types.py | 15 + .../opentrons/legacy_api/modules/magdeck.py | 21 +- .../opentrons/legacy_api/modules/tempdeck.py | 12 +- api/src/opentrons/legacy_api/robot/robot.py | 39 +- api/src/opentrons/main.py | 74 +- api/src/opentrons/package.json | 2 +- api/src/opentrons/protocol_api/__init__.py | 7 +- api/src/opentrons/protocol_api/back_compat.py | 73 +- api/src/opentrons/protocol_api/contexts.py | 204 +- api/src/opentrons/protocol_api/geometry.py | 26 +- api/src/opentrons/protocol_api/labware.py | 192 +- .../opentrons/resources/scripts/setup_gpio.py | 3 +- api/src/opentrons/server/__init__.py | 33 +- .../opentrons/server/endpoints/__init__.py | 4 +- api/src/opentrons/server/endpoints/control.py | 187 +- .../server/endpoints/serverlib_fallback.py | 9 +- api/src/opentrons/server/endpoints/update.py | 84 +- api/src/opentrons/server/rpc.py | 27 +- api/src/opentrons/system/smoothie_update.py | 16 + .../opentrons/tools/write_pipette_memory.py | 17 +- api/src/opentrons/types.py | 9 +- api/tests/opentrons/api/test_session.py | 63 +- api/tests/opentrons/conftest.py | 93 +- .../database/test_labware_definitions.py | 2 +- .../module_drivers/test_temp_deck_driver.py | 16 +- api/tests/opentrons/drivers/test_driver.py | 12 +- .../modules/test_hc_tempdeck.py | 4 +- .../hardware_control/test_instantiation.py | 39 +- .../hardware_control/test_instruments.py | 30 +- .../hardware_control/test_modules.py | 2 +- .../opentrons/hardware_control/test_moves.py | 18 +- .../hardware_control/test_pipette.py | 14 +- api/tests/opentrons/integration/test_api.py | 6 +- .../opentrons/integration/test_server.py | 8 +- .../protocol_api/test_accessor_fn.py | 34 +- .../opentrons/protocol_api/test_context.py | 104 +- .../opentrons/protocol_api/test_geometry.py | 26 +- .../opentrons/protocol_api/test_labware.py | 63 +- .../opentrons/protocol_api/test_offsets.py | 17 +- .../server/calibration_integration_test.py | 3 + .../server/test_calibration_endpoints.py | 9 + .../server/test_control_endpoints.py | 354 +-- .../opentrons/server/test_update_endpoints.py | 6 +- api/tests/opentrons/tools/test_qc_scripts.py | 9 +- app-shell/CHANGELOG.md | 27 + app-shell/Makefile | 10 +- app-shell/build/release-notes.md | 50 +- app-shell/electron-builder.json | 7 +- app-shell/package.json | 6 +- app/CHANGELOG.md | 27 + app/package.json | 10 +- .../AppSettings/UpdateApp/RestartAppModal.js | 28 + .../AppSettings/UpdateApp/UpdateAppMessage.js | 41 + .../AppSettings/UpdateApp/UpdateAppModal.js | 74 + .../components/AppSettings/UpdateApp/index.js | 28 + .../AppSettings/UpdateApp/styles.css | 7 + app/src/components/ReleaseNotes/styles.css | 1 - .../RobotSettings/ReachableRobotBanner.js | 2 +- .../RobotSettings/SelectNetwork/styles.css | 1 - .../UpdateRobot/RestartRobotModal.js | 58 + .../UpdateRobot/SkipAppUpdateMessage.js | 23 + .../UpdateRobot/SyncRobotMessage.js | 48 + .../UpdateRobot/UpdateAppMessage.js | 34 + .../UpdateRobot/UpdateRobotModal.js | 192 ++ .../RobotSettings/UpdateRobot/VersionList.js | 14 + .../RobotSettings/UpdateRobot/index.js | 54 + .../RobotSettings/UpdateRobot/styles.css | 17 + .../RobotSettings/UpdateRobot/types.js | 7 + app/src/components/modals/styles.css | 5 +- app/src/config/index.js | 5 + app/src/pages/More/AppSettings.js | 15 +- app/src/pages/Robots/RobotSettings.js | 15 +- app/src/robot/api-client/client.js | 7 +- app/src/robot/test/api-client.test.js | 5 +- app/src/shell/index.js | 6 +- appveyor.yml | 8 +- components/CHANGELOG.md | 27 + components/package.json | 4 +- .../__snapshots__/lists.test.js.snap | 6 + components/src/deck/ContainerNameOverlay.js | 4 +- components/src/deck/Deck.js | 13 +- components/src/deck/LabwareContainer.js | 6 +- components/src/deck/LabwareOutline.js | 6 +- components/src/deck/constants.js | 6 - .../src/interaction-enhancers/ClickOutside.js | 47 + .../src/interaction-enhancers/ClickOutside.md | 19 + .../ExampleClickOutside.js | 89 - .../ExampleClickOutside.md | 12 - .../src/interaction-enhancers/clickOutside.js | 108 - components/src/interaction-enhancers/index.js | 5 +- components/src/lists/TitledList.js | 6 +- discovery-client/CHANGELOG.md | 27 + discovery-client/package.json | 2 +- labware-designer/CHANGELOG.md | 27 + labware-designer/README.md | 578 ++++- labware-designer/package.json | 4 +- lerna.json | 2 +- package.json | 4 +- protocol-designer/CHANGELOG.md | 61 + protocol-designer/package.json | 11 +- protocol-designer/src/components/FilePage.js | 90 +- .../FileSidebar/ConnectedFileSidebar.js | 6 +- ...ablePlate.css => HighlightableLabware.css} | 0 .../src/components/HighlightableLabware.js | 72 + .../LabwareDetailsCard/index.js | 2 +- .../LabwareSelectionModal.js | 2 +- .../components/LabwareSelectionModal/index.js | 2 +- .../components/LiquidPlacementForm/index.js | 6 +- .../src/components/LiquidPlacementModal.js | 104 +- .../src/components/ProtocolEditor.js | 6 +- .../src/components/SelectablePlate.js | 150 -- .../{Privacy.js => SettingsApp.js} | 31 +- .../components/SettingsPage/SettingsPage.css | 6 +- .../SettingsPage/SettingsSidebar.js | 8 +- .../src/components/SettingsPage/index.js | 8 +- .../src/components/SingleLabware.js | 8 +- .../src/components/StepEditForm/ButtonRow.js | 4 +- .../StepEditForm/FlowRateField/index.js | 2 +- .../src/components/StepEditForm/FormAlerts.js | 2 +- .../components/StepEditForm/FormSection.js | 24 +- .../src/components/StepEditForm/MixForm.js | 20 +- .../components/StepEditForm/StepFormField.js | 3 +- .../TipPositionInput/TipPositionModal.js | 130 +- .../TipPositionInput/TipPositionZAxisViz.js | 8 +- .../StepEditForm/TipPositionInput/index.js | 74 +- .../StepEditForm/TipPositionInput/utils.js | 31 + .../StepEditForm/TransferLikeForm.js | 34 +- .../WellSelectionInput/WellSelectionInput.js | 3 +- .../WellSelectionInput/WellSelectionModal.js | 12 +- .../StepEditForm/WellSelectionInput/index.js | 7 +- .../src/components/StepEditForm/formFields.js | 79 +- .../src/components/StepEditForm/index.js | 13 +- .../src/components/alerts/TimelineAlerts.js | 5 +- .../components/labware/BrowseLabwareModal.js | 4 +- .../src/components/labware/LabwareOnDeck.js | 18 +- .../components/labware/SelectableLabware.js | 7 +- .../modals/EditPipettesModal/index.js | 5 +- .../modals/NewFileModal/NewFileModal.css | 44 +- .../components/modals/NewFileModal/index.js | 77 +- .../src/components/steplist/ContextMenu.js | 119 + .../components/steplist/DraggableStepItems.js | 138 ++ .../steplist/MultiChannelSubstep.js | 4 +- .../steplist/StartingDeckStateTerminalItem.js | 2 +- .../src/components/steplist/StepItem.css | 25 + .../src/components/steplist/StepItem.js | 8 +- .../src/components/steplist/StepList.js | 19 +- protocol-designer/src/constants.js | 3 +- protocol-designer/src/containers/Alerts.js | 2 +- .../src/containers/ConnectedDeckSetup.js | 7 +- .../src/containers/ConnectedFilePage.js | 62 +- .../src/containers/ConnectedMainPanel.js | 4 +- .../containers/ConnectedMoreOptionsModal.js | 2 +- .../src/containers/ConnectedNav.js | 15 +- .../src/containers/ConnectedNewFileModal.js | 4 +- .../src/containers/ConnectedSidebar.js | 6 +- .../src/containers/ConnectedStepItem.js | 4 +- .../src/containers/ConnectedStepList.js | 15 +- .../src/containers/ConnectedTitleBar.js | 10 +- .../src/containers/HighlightableLabware.js | 119 + .../src/containers/IngredientsList.js | 4 +- .../src/containers/LabwareContainer.js | 9 +- .../src/containers/SelectablePlate.js | 218 -- .../src/containers/StepCreationButton.js | 2 +- protocol-designer/src/dismiss/actions.js | 3 +- protocol-designer/src/dismiss/reducers.js | 5 +- protocol-designer/src/dismiss/selectors.js | 9 +- protocol-designer/src/file-data/actions.js | 9 +- .../src/file-data/reducers/index.js | 28 +- .../src/file-data/selectors/commands.js | 25 +- .../src/file-data/selectors/fileCreator.js | 19 +- .../src/file-data/selectors/fileFields.js | 10 +- protocol-designer/src/form-types.js | 84 +- .../src/images/labware/Tiprack-200ul.png | Bin 143011 -> 171582 bytes protocol-designer/src/images/labware/index.js | 1 - .../src/labware-ingred/actions.js | 2 +- .../src/labware-ingred/reducers/index.js | 123 +- protocol-designer/src/labware-ingred/types.js | 2 +- protocol-designer/src/load-file/selectors.js | 2 +- .../src/localization/en/alert.json | 1 + .../src/localization/en/button.json | 2 + .../src/localization/en/card.json | 9 +- .../src/localization/en/context_menu.json | 6 + .../src/localization/en/index.js | 2 + .../src/localization/en/modal.json | 11 +- .../src/localization/en/nav.json | 7 +- .../src/localization/en/tooltip.json | 3 +- protocol-designer/src/navigation/selectors.js | 4 +- protocol-designer/src/navigation/types.js | 2 +- protocol-designer/src/pipettes/selectors.js | 77 +- protocol-designer/src/pipettes/thunks.js | 2 +- .../aspirateUpdateLiquidState.js | 1 + .../{ => commandCreators/atomic}/aspirate.js | 39 +- .../{ => commandCreators/atomic}/blowout.js | 8 +- .../{ => commandCreators/atomic}/delay.js | 2 +- .../{ => commandCreators/atomic}/dispense.js | 12 +- .../atomic}/dropAllTips.js | 4 +- .../{ => commandCreators/atomic}/dropTip.js | 8 +- .../commandCreators/atomic/index.js | 20 + .../atomic}/replaceTip.js | 14 +- .../{ => commandCreators/atomic}/touchTip.js | 6 +- .../compound}/consolidate.js | 106 +- .../compound}/distribute.js | 45 +- .../commandCreators/compound/index.js | 12 + .../{ => commandCreators/compound}/mix.js | 71 +- .../compound}/transfer.js | 89 +- .../step-generation/commandCreators/index.js | 19 + .../src/step-generation/errorCreators.js | 12 + .../forAspirateDispense.js | 93 + .../getNextRobotStateAndWarnings/index.js | 35 + .../src/step-generation/index.js | 24 +- .../step-generation/robotStateSelectors.js | 59 +- .../test-with-flow/aspirate.test.js | 131 +- .../test-with-flow/blowout.test.js | 10 +- .../test-with-flow/blowoutUtil.test.js | 65 + .../test-with-flow/consolidate.test.js | 86 +- .../test-with-flow/delay.test.js | 2 +- .../test-with-flow/dispense.test.js | 69 +- .../test-with-flow/distribute.test.js | 10 +- .../test-with-flow/dropAllTips.test.js | 4 +- .../test-with-flow/dropTip.test.js | 6 +- .../test-with-flow/fixtureGeneration.test.js | 4 +- .../fixtures/commandFixtures.js | 16 +- .../test-with-flow/fixtures/fixtures.js | 42 +- .../getNextRobotStateAndWarnings.test.js | 35 + ...xtRobotStateAndWarningsForAspDisp.test.js} | 90 +- .../test-with-flow/mix.test.js | 53 +- .../test-with-flow/replaceTip.test.js | 80 +- .../robotStateSelectors.test.js | 98 +- .../test-with-flow/testMatchers.js | 10 + .../test-with-flow/touchTip.test.js | 10 +- .../test-with-flow/transfer.test.js | 60 +- .../src/step-generation/types.js | 53 +- .../src/step-generation/utils.js | 34 +- .../src/steplist/actions/actions.js | 33 +- .../src/steplist/actions/handleFormChange.js | 111 +- .../src/steplist/actions/thunks.js | 82 +- .../src/steplist/actions/types.js | 7 +- .../src/steplist/fieldLevel/index.js | 12 +- .../src/steplist/fieldLevel/types.js | 50 - .../src/steplist/formLevel/errors.js | 2 +- .../src/steplist/formLevel/generateNewForm.js | 9 +- .../formLevel/getDefaultsForStepType.js | 16 +- .../getNextDefaultPipetteId/index.js | 11 +- .../test/getNextDefaultPipetteId.test.js | 19 +- .../formLevel/stepFormToArgs/mixFormToArgs.js | 23 +- .../stepFormToArgs/transferLikeFormToArgs.js | 42 +- .../src/steplist/formLevel/warnings.js | 14 +- .../src/steplist/generateSubsteps.js | 17 +- protocol-designer/src/steplist/reducers.js | 93 +- protocol-designer/src/steplist/selectors.js | 94 +- .../src/steplist/substepTimeline.js | 116 +- .../src/steplist/test/reducers.test.js | 32 +- protocol-designer/src/steplist/types.js | 13 +- .../src/top-selectors/substep-highlight.js | 6 +- .../src/top-selectors/substeps.js | 10 +- .../src/top-selectors/tip-contents/index.js | 53 +- ...t.js => getWellContentsAllLabware.test.js} | 8 +- ...abware.js => getWellContentsAllLabware.js} | 28 +- .../src/top-selectors/well-contents/index.js | 22 +- protocol-designer/src/tutorial/actions.js | 4 + protocol-designer/src/tutorial/reducers.js | 1 + protocol-designer/src/tutorial/selectors.js | 10 +- protocol-designer/src/utils/index.js | 2 +- .../src/well-selection/actions.js | 12 +- .../src/well-selection/selectors.js | 12 +- protocol-library-kludge/CHANGELOG.md | 27 + protocol-library-kludge/package.json | 8 +- scripts/travis-env.sh | 17 - scripts/travis-install.sh | 29 - shared-data/CHANGELOG.md | 39 + .../opentrons-tuberack-1.5ml-eppendorf.json | 311 +++ .../definitions/opentrons-tuberack-50ml.json | 14 +- ...pentrons_24_tuberack_1.5_mL_Eppendorf.json | 284 +++ .../Opentrons_6x15_mL_4x50_mL_tuberack.json | 3 +- .../Opentrons_96_tiprack_300_uL.json | 3 +- .../biorad_96_wellPlate_pcr_200_uL.json | 1039 ++++++++ .../generic_96_wellPlate_380_uL.json | 3 +- .../fixtures/irregularLabwareExample1.json | 3 +- .../js/__tests__/fixtures/labwareExample.json | 3 +- .../__tests__/fixtures/labwareExample2.json | 3 +- shared-data/js/constants.js | 10 +- shared-data/js/getLabware.js | 4 +- .../__tests__/createIrregularLabware.test.js | 5 +- .../__tests__/createLabware.test.js | 8 +- shared-data/js/labwareTools/index.js | 16 +- .../labware-json-schema/labware-schema.json | 12 +- shared-data/package.json | 2 +- shared-data/robot-data/moduleSpecs.json | 38 + shared-data/robot-data/pipetteModelSpecs.json | 210 +- update-server/otupdate/CHANGELOG.md | 27 + update-server/otupdate/package.json | 2 +- webpack-config/CHANGELOG.md | 27 + webpack-config/package.json | 2 +- yarn.lock | 2114 +---------------- 324 files changed, 9340 insertions(+), 5854 deletions(-) delete mode 100644 .python-version mode change 100755 => 100644 .travis.yml create mode 100644 api/src/opentrons/system/smoothie_update.py create mode 100644 app/src/components/AppSettings/UpdateApp/RestartAppModal.js create mode 100644 app/src/components/AppSettings/UpdateApp/UpdateAppMessage.js create mode 100644 app/src/components/AppSettings/UpdateApp/UpdateAppModal.js create mode 100644 app/src/components/AppSettings/UpdateApp/index.js create mode 100644 app/src/components/AppSettings/UpdateApp/styles.css create mode 100644 app/src/components/RobotSettings/UpdateRobot/RestartRobotModal.js create mode 100644 app/src/components/RobotSettings/UpdateRobot/SkipAppUpdateMessage.js create mode 100644 app/src/components/RobotSettings/UpdateRobot/SyncRobotMessage.js create mode 100644 app/src/components/RobotSettings/UpdateRobot/UpdateAppMessage.js create mode 100644 app/src/components/RobotSettings/UpdateRobot/UpdateRobotModal.js create mode 100644 app/src/components/RobotSettings/UpdateRobot/VersionList.js create mode 100644 app/src/components/RobotSettings/UpdateRobot/index.js create mode 100644 app/src/components/RobotSettings/UpdateRobot/styles.css create mode 100644 app/src/components/RobotSettings/UpdateRobot/types.js create mode 100644 components/src/interaction-enhancers/ClickOutside.js create mode 100644 components/src/interaction-enhancers/ClickOutside.md delete mode 100644 components/src/interaction-enhancers/ExampleClickOutside.js delete mode 100644 components/src/interaction-enhancers/ExampleClickOutside.md delete mode 100644 components/src/interaction-enhancers/clickOutside.js rename protocol-designer/src/components/{SelectablePlate.css => HighlightableLabware.css} (100%) create mode 100644 protocol-designer/src/components/HighlightableLabware.js delete mode 100644 protocol-designer/src/components/SelectablePlate.js rename protocol-designer/src/components/SettingsPage/{Privacy.js => SettingsApp.js} (60%) create mode 100644 protocol-designer/src/components/StepEditForm/TipPositionInput/utils.js create mode 100644 protocol-designer/src/components/steplist/ContextMenu.js create mode 100644 protocol-designer/src/components/steplist/DraggableStepItems.js create mode 100644 protocol-designer/src/containers/HighlightableLabware.js delete mode 100644 protocol-designer/src/containers/SelectablePlate.js create mode 100644 protocol-designer/src/localization/en/context_menu.json rename protocol-designer/src/step-generation/{ => commandCreators/atomic}/aspirate.js (60%) rename protocol-designer/src/step-generation/{ => commandCreators/atomic}/blowout.js (87%) rename protocol-designer/src/step-generation/{ => commandCreators/atomic}/delay.js (80%) rename protocol-designer/src/step-generation/{ => commandCreators/atomic}/dispense.js (78%) rename protocol-designer/src/step-generation/{ => commandCreators/atomic}/dropAllTips.js (80%) rename protocol-designer/src/step-generation/{ => commandCreators/atomic}/dropTip.js (81%) create mode 100644 protocol-designer/src/step-generation/commandCreators/atomic/index.js rename protocol-designer/src/step-generation/{ => commandCreators/atomic}/replaceTip.js (85%) rename protocol-designer/src/step-generation/{ => commandCreators/atomic}/touchTip.js (86%) rename protocol-designer/src/step-generation/{ => commandCreators/compound}/consolidate.js (67%) rename protocol-designer/src/step-generation/{ => commandCreators/compound}/distribute.js (77%) create mode 100644 protocol-designer/src/step-generation/commandCreators/compound/index.js rename protocol-designer/src/step-generation/{ => commandCreators/compound}/mix.js (63%) rename protocol-designer/src/step-generation/{ => commandCreators/compound}/transfer.js (68%) create mode 100644 protocol-designer/src/step-generation/commandCreators/index.js create mode 100644 protocol-designer/src/step-generation/getNextRobotStateAndWarnings/forAspirateDispense.js create mode 100644 protocol-designer/src/step-generation/getNextRobotStateAndWarnings/index.js create mode 100644 protocol-designer/src/step-generation/test-with-flow/blowoutUtil.test.js create mode 100644 protocol-designer/src/step-generation/test-with-flow/getNextRobotStateAndWarnings.test.js rename protocol-designer/src/step-generation/test-with-flow/{aspirateUpdateLiquidState.test.js => getNextRobotStateAndWarningsForAspDisp.test.js} (75%) create mode 100644 protocol-designer/src/step-generation/test-with-flow/testMatchers.js delete mode 100644 protocol-designer/src/steplist/fieldLevel/types.js rename protocol-designer/src/top-selectors/well-contents/__tests__/{wellContentsAllLabware.test.js => getWellContentsAllLabware.test.js} (89%) rename protocol-designer/src/top-selectors/well-contents/{wellContentsAllLabware.js => getWellContentsAllLabware.js} (71%) delete mode 100755 scripts/travis-env.sh delete mode 100755 scripts/travis-install.sh create mode 100644 shared-data/definitions/opentrons-tuberack-1.5ml-eppendorf.json create mode 100644 shared-data/definitions2/Opentrons_24_tuberack_1.5_mL_Eppendorf.json create mode 100644 shared-data/definitions2/biorad_96_wellPlate_pcr_200_uL.json create mode 100644 shared-data/robot-data/moduleSpecs.json diff --git a/.python-version b/.python-version deleted file mode 100644 index 0f44168a4d5..00000000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.6.4 diff --git a/.travis.yml b/.travis.yml old mode 100755 new mode 100644 index 896aaa1be08..23e5a9576cb --- a/.travis.yml +++ b/.travis.yml @@ -1,137 +1,148 @@ -# opentrons travis configuration - -matrix: - fast_finish: false - include: - - os: linux - sudo: false - language: python - python: '3.6' - env: - LINT=true - BUILD_APP=true - BUILD_PD=true - BUILD_COMPONENTS=true - BUILD_API_DOCS=true - addons: - apt: - sources: &common_sources - packages: &common_packages - - g++ - - gcc - - icnsutils # electron-builder dependency - - graphicsmagick # electron-builder dependency - - xvfb - - - os: osx - language: generic - if: | - type != pull_request AND \ - (tag IS present OR branch =~ ^(edge|release_.+)$) - env: - LINT=false - BUILD_APP=true - BUILD_PD=false - BUILD_COMPONENTS=false - BUILD_API_DOCS=false +# opentrons platform travis config +sudo: false cache: pip: true yarn: true - directories: - - $HOME/.pyenv - - $HOME/Library/Caches/Homebrew - -before_install: - # source these scripts because they modify $PATH - - source scripts/travis-env.sh - - source scripts/travis-install.sh - -install: - - make -j 2 install - -before_script: - # Get all branches to allow comparison for mono-repo management tools - - git config --replace-all remote.origin.fetch +refs/heads/*:refs/remotes/origin/* - - git fetch - -script: - - make test - - make coverage - - if [[ $LINT = true ]]; then make lint; fi - - if [[ $BUILD_COMPONENTS = true ]]; then make -C components; fi - - if [[ $BUILD_PD = true ]]; then make -C protocol-designer; fi - - if [[ $BUILD_APP = true ]]; then make -C app-shell dist-$APP_OS_TARGET; fi - - if [[ $BUILD_API_DOCS = true ]]; then (make -C api docs > /dev/null); fi - -deploy: - - provider: pages - skip_cleanup: true - github-token: $GITHUB_TOKEN - keep-history: false - local-dir: api/docs/dist - on: - condition: $BUILD_API_DOCS = true - repo: Opentrons/opentrons - branch: edge - - # app deploy - - provider: s3 - skip_cleanup: true - # TODO(mc, 2018-03-26): use AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY - access_key_id: $AWS_ACCESS_KEY - secret_access_key: $AWS_SECRET_KEY - bucket: $OT_BUCKET_APP - upload-dir: $OT_FOLDER_APP - local-dir: $(pwd)/app-shell/dist/publish - acl: public_read - on: - condition: $BUILD_APP = true - repo: Opentrons/opentrons - all_branches: true - - # protocol designer deploy - - provider: s3 - # TODO(mc, 2018-03-26): use AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY - access_key_id: $AWS_ACCESS_KEY - secret_access_key: $AWS_SECRET_KEY - bucket: opentrons-protocol-designer - skip_cleanup: true - local-dir: $(pwd)/protocol-designer/dist/ - upload-dir: $TRAVIS_BRANCH - acl: public_read - # TODO(mc, 2018-03-26): why is this region not default? - region: us-west-2 - on: - condition: $BUILD_PD = true - repo: Opentrons/opentrons - all_branches: true - - # components library deploy - - provider: s3 - # TODO(mc, 2018-03-26): use AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY - access_key_id: $AWS_ACCESS_KEY - secret_access_key: $AWS_SECRET_KEY - bucket: opentrons-components - skip_cleanup: true - local-dir: $(pwd)/components/dist/ - upload-dir: $TRAVIS_BRANCH - acl: public_read - # TODO(mc, 2018-03-26): why is this region not default? - region: us-west-2 - on: - condition: $BUILD_COMPONENTS = true - repo: Opentrons/opentrons - all_branches: true + +stages: + - test + - name: app + # don't build the app on pull requests + if: type != pull_request + +# base configs +_deploy_s3: &deploy_s3 + provider: s3 + skip_cleanup: true + access_key_id: $AWS_ACCESS_KEY_ID + secret_access_key: $AWS_SECRET_ACCESS_KEY + acl: public_read + on: + repo: Opentrons/opentrons + all_branches: true + +_app_stage_build: &app_stage_build + stage: app + language: node_js + install: + - pip install --user awscli + - make install-js + before_script: + # pull API wheel from S3 + - mkdir -p ./api/dist + - aws s3 sync $OT_CI_TEMP_S3_PATH/api/dist ./api/dist + deploy: + - # deploy Opentrons App to S3 + <<: *deploy_s3 + local-dir: app-shell/dist/publish + bucket: $OT_APP_DEPLOY_BUCKET + upload-dir: $OT_APP_DEPLOY_FOLDER + +jobs: + include: + # test, build, and upload wheels for Python projects + - stage: test + name: 'Python API unit tests, build/deploy API docs' + language: python + python: 3.6 + install: + - pip install awscli + - nvm install + - yarn global add shx@0.2.2 codecov@3.1.0 + - make install-py + script: + - make test-py + - make lint-py + - make -C api docs + after_success: + - make coverage + - aws s3 sync ./api/dist $OT_CI_TEMP_S3_PATH/api/dist + deploy: + # api docs deploy + - provider: pages + skip_cleanup: true + keep-history: false + local-dir: api/docs/dist + github-token: $GITHUB_TOKEN + on: + repo: Opentrons/opentrons + branch: edge + + # test, build, and upload for JavaScript projects + - stage: test + name: 'JS unit tests; build/deploy Protocol Designer, Components Library' + # node version pulled from .nvmrc + language: node_js + install: + - make install-js + script: + - make test-js + - make lint-js lint-css + - make -C components + - make -C protocol-designer + after_success: + - make coverage + deploy: + - # deploy protocol designer to S3 + <<: *deploy_s3 + # TODO(mc, 2018-03-26): why is this region not default? + region: us-west-2 + local-dir: protocol-designer/dist + bucket: opentrons-protocol-designer + upload-dir: $TRAVIS_BRANCH + - # deploy components library to S3 + <<: *deploy_s3 + # TODO(mc, 2018-03-26): why is this region not default? + region: us-west-2 + local-dir: components/dist + bucket: opentrons-components + upload-dir: $TRAVIS_BRANCH + + # typecheck JavaScript projects + - stage: test + name: 'JS type checks' + language: node_js + install: + - make install-js + script: + - make check-js + + - # build the Opentrons App for POSIX (dev branch builds) + <<: *app_stage_build + name: 'Build/deploy Opentrons App for POSIX (unsigned dev builds)' + os: linux + script: make -C app-shell dist-posix + if: tag IS blank AND NOT branch =~ ^(edge|release_.+)$ + + - # build the Opentrons App for Linux (tagged / edge / RC builds) + <<: *app_stage_build + name: 'Build/deploy Opentrons App for Linux' + os: linux + script: make -C app-shell dist-linux + if: tag IS present OR branch =~ ^(edge|release_.+)$ + + - # build the Opentrons App for macOS (tagged / edge / RC builds) + <<: *app_stage_build + name: 'Build/deploy Opentrons App for macOS' + os: osx + script: make -C app-shell dist-osx + if: tag IS present OR branch =~ ^(edge|release_.+)$ env: global: + # include $HOME/.local/bin for `aws` + - PYTHONUSERBASE: $HOME/.local + - PATH: $PYTHONUSERBASE/bin:$PATH + - OT_BUILD: $TRAVIS_BUILD_NUMBER - OT_BRANCH: $TRAVIS_BRANCH - OT_TAG: $TRAVIS_TAG - - OT_BUCKET_APP: opentrons-app - - OT_FOLDER_APP: builds + - OT_CI_TEMP_S3_PATH: s3://opentrons-ci/temp/$OT_BUILD + + - OT_APP_DEPLOY_BUCKET: opentrons-app + - OT_APP_DEPLOY_FOLDER: builds # GITHUB_TOKEN - secure: f/W7kN4gOvVpIanTQh9QtCwiXOk5UrRnUPo2ZU1Qk8zaFVbNj2za2A1xGKMqSyfZKw7guqIwTjWgc/aF9lxRtfU+5fkedJQdxDi5r7jZFxpqmpZOlhyXVY8WAWNqavEkefQInPlpHVAL8M2eV+Pi1cO9FsMhdyy/Wk7qA2nOiA8//9pFRB+0jgSbe1yqIF5DPyL0kbibd3EwmQvuQtnn25qqJXjneenhL6spflLCrnUjq1N/iOlcGd94eBUtk8RaBtMEjOb2D0Mb0DWKMsppoXg4/mZDus6s/PlmBwUJKNCuRtDiEUn5brE14q3OQh/FkDoXMRl69VND2mYp1LOeh5fgLSu6P+YToyHrh4lhXaRAul6l3JmXuoDC3k8hOAr8rPbtiwH7wGY2eRNv59vUejdXof4KHbAN6FTIH934tTe4uvBH79hRMoFY51pHRe6UiC39e/3hwl0pVKLjkV/40wfdEeYA7xhTZQVux+FAfk2krmggokxGEhbAQhWoyRX/wlH2XfEgassGskJ9SbuumNPNOLmEV9OOISFaXoYqVn+SPXy8mN1Pl2sLfaPFtnmmiY20t6yWsHsmfwi+41lv8n0vwCOGq521suDeNyiFhOH2AqG7xm6nHbIv+CiWt2ntKXgV233J17usvfr1zSK07PMDMlV2lvJx3CXj3hA4Yb4= @@ -144,8 +155,3 @@ env: # OT_PD_FULLSTORY_ORG - secure: "N/WWTWYdEPF7UfWIefSnOIKYVj9/q8ti7kCiB9DNfeKIsjJwsmg6S5yrwn6N4B/9ZMSp0yswo442n09CvH4jMG99BodXdYxg3JhuJ5dxWReAUTWO0PTiyihWeFhd2sbQ3VZa+o85OoFWFHO8UCXqcG//iUZ4l05t9DY5CGUBsPnyJTptsjPCb+CFUc+xkckv9RBfhLeyGBDWodJVfjU4xb124f5MBVF67OlHJ20HmbuH/kRNLDXSiRW4BD9UIXyWrIaPZHW612dX6inETz0vhUOJbUftgn8kdpjjBqa1394TjnjW5fey1n73KH4KpaDPZeGJ5GnYRpk9Wvw7uQkWH7xjkXbFq6cqd0vIWWS5uYmdsMsNDjUtTyELqG01rj813jbmcItuzK2tAcuQ5kBPwikLsHYeQY/68GKlws9POd444YQXXiTYgCoHgYq8O3nxaLoMZBgabFq6Rtz0xJb3Hu99PkU6flI4hgT82RZGf32PgYSKznaGps9DGf2as8FU+wui/So89eQwkDyhirzGvC31OlRHdZitjWYvI27nGgiPWheuZR5zAtf6tJeZaZ1N/PZGBwJW6ykfjG+vyRep/IIW5r0ujnBcmgxT7USVpW0E45QolZBS75t29kkTxP0/EHLMavv7QqP3LNpDJpptPrMQ8mLINxlB7FCQ2AQLbDY=" - -notifications: - email: - on_success: change - on_failure: change diff --git a/CHANGELOG.md b/CHANGELOG.md index 71d2fd02760..bf7d6d4fa05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,81 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + + +### Bug Fixes + +* **api:** Fix bad P10S config causing under-aspirations ([#2774](https://github.com/Opentrons/opentrons/issues/2774)) ([9c5e0a2](https://github.com/Opentrons/opentrons/commit/9c5e0a2)) +* **protocol-designer:** fix missing disposal volume in new distribute forms ([#2733](https://github.com/Opentrons/opentrons/issues/2733)) ([5657164](https://github.com/Opentrons/opentrons/commit/5657164)), closes [#2705](https://github.com/Opentrons/opentrons/issues/2705) + + +### Features + +* **protocol-designer:** allow user to re-enable dismissed hints ([#2726](https://github.com/Opentrons/opentrons/issues/2726)) ([af52d1e](https://github.com/Opentrons/opentrons/commit/af52d1e)), closes [#2652](https://github.com/Opentrons/opentrons/issues/2652) +* **protocol-designer:** drag and drop step reordering ([#2714](https://github.com/Opentrons/opentrons/issues/2714)) ([13d6fe3](https://github.com/Opentrons/opentrons/commit/13d6fe3)), closes [#2654](https://github.com/Opentrons/opentrons/issues/2654) +* **protocol-designer:** highlight tips per substep ([#2716](https://github.com/Opentrons/opentrons/issues/2716)) ([eb2c2ce](https://github.com/Opentrons/opentrons/commit/eb2c2ce)), closes [#2537](https://github.com/Opentrons/opentrons/issues/2537) +* **protocol-designer:** new protocol modal defaults and visual updates ([#2739](https://github.com/Opentrons/opentrons/issues/2739)) ([333ad5a](https://github.com/Opentrons/opentrons/commit/333ad5a)), closes [#2721](https://github.com/Opentrons/opentrons/issues/2721) +* **protocol-designer:** place tipracks on protocol creation ([#2750](https://github.com/Opentrons/opentrons/issues/2750)) ([a110a8d](https://github.com/Opentrons/opentrons/commit/a110a8d)), closes [#1327](https://github.com/Opentrons/opentrons/issues/1327) +* **protocol-designer:** remove delay from advanced settings of all step types ([#2731](https://github.com/Opentrons/opentrons/issues/2731)) ([b26abdd](https://github.com/Opentrons/opentrons/commit/b26abdd)), closes [#2579](https://github.com/Opentrons/opentrons/issues/2579) +* **protocol-designer:** remove option of tiprack-1000ul-chem from pd ([#2745](https://github.com/Opentrons/opentrons/issues/2745)) ([3d5f276](https://github.com/Opentrons/opentrons/commit/3d5f276)) + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + + +### Bug Fixes + +* **api:** Fix the flaky tempdeck test ([#2725](https://github.com/Opentrons/opentrons/issues/2725)) ([f721163](https://github.com/Opentrons/opentrons/commit/f721163)) +* **shared-data:** fix total-liquid-volume of opentrons-tuberack-50ml ([#2744](https://github.com/Opentrons/opentrons/issues/2744)) ([aef8cc8](https://github.com/Opentrons/opentrons/commit/aef8cc8)), closes [#2743](https://github.com/Opentrons/opentrons/issues/2743) + + +### Features + +* **protocol-designer:** add tooltip to advanced settings icon ([#2727](https://github.com/Opentrons/opentrons/issues/2727)) ([0deb6b7](https://github.com/Opentrons/opentrons/commit/0deb6b7)), closes [#2706](https://github.com/Opentrons/opentrons/issues/2706) +* **protocol-designer:** make multichannel substeps collapsed by default ([#2729](https://github.com/Opentrons/opentrons/issues/2729)) ([b419a72](https://github.com/Opentrons/opentrons/commit/b419a72)), closes [#2678](https://github.com/Opentrons/opentrons/issues/2678) +* **protocol-designer:** remove label from 200ul/300ul tiprack image ([#2722](https://github.com/Opentrons/opentrons/issues/2722)) ([fe5cf6a](https://github.com/Opentrons/opentrons/commit/fe5cf6a)), closes [#2704](https://github.com/Opentrons/opentrons/issues/2704) + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + + +### Bug Fixes + +* **api:** re-position p1000 droptip/blowout positions ([#2681](https://github.com/Opentrons/opentrons/issues/2681)) ([f0cf01b](https://github.com/Opentrons/opentrons/commit/f0cf01b)) +* **protocol-designer:** de-hydrate disposal and blowout labware in st… ([#2669](https://github.com/Opentrons/opentrons/issues/2669)) ([b6246b2](https://github.com/Opentrons/opentrons/commit/b6246b2)) +* **protocol-designer:** well selection modal refresh on step change ([#2671](https://github.com/Opentrons/opentrons/issues/2671)) ([941916f](https://github.com/Opentrons/opentrons/commit/941916f)) + + +### Features + +* **api:** Add 1.5ml tuberack to old labware definition section ([#2679](https://github.com/Opentrons/opentrons/issues/2679)) ([2739038](https://github.com/Opentrons/opentrons/commit/2739038)) +* **api:** Adds pipette models v1.4 to robot config ([#2689](https://github.com/Opentrons/opentrons/issues/2689)) ([fd9c38a](https://github.com/Opentrons/opentrons/commit/fd9c38a)) +* **protocol-designer:** allow user to set touch-tip offset ([#2691](https://github.com/Opentrons/opentrons/issues/2691)) ([d5b7d8a](https://github.com/Opentrons/opentrons/commit/d5b7d8a)), closes [#2540](https://github.com/Opentrons/opentrons/issues/2540) +* **protocol-designer:** disambiguate left/right pipette names when they match ([#2698](https://github.com/Opentrons/opentrons/issues/2698)) ([2f43a0e](https://github.com/Opentrons/opentrons/commit/2f43a0e)), closes [#2078](https://github.com/Opentrons/opentrons/issues/2078) +* **protocol-designer:** disconnect well selection modal from hovered step state ([#2662](https://github.com/Opentrons/opentrons/issues/2662)) ([973a8a5](https://github.com/Opentrons/opentrons/commit/973a8a5)), closes [#2558](https://github.com/Opentrons/opentrons/issues/2558) +* **protocol-designer:** liquid placement modal performance boost ([#2661](https://github.com/Opentrons/opentrons/issues/2661)) ([ecc8569](https://github.com/Opentrons/opentrons/commit/ecc8569)), closes [#2557](https://github.com/Opentrons/opentrons/issues/2557) +* **protocol-designer:** make settings tab always active ([#2700](https://github.com/Opentrons/opentrons/issues/2700)) ([036e2ee](https://github.com/Opentrons/opentrons/commit/036e2ee)), closes [#2697](https://github.com/Opentrons/opentrons/issues/2697) +* **protocol-designer:** use tip max vol, not pipette max vol ([#2656](https://github.com/Opentrons/opentrons/issues/2656)) ([418665d](https://github.com/Opentrons/opentrons/commit/418665d)), closes [#2160](https://github.com/Opentrons/opentrons/issues/2160) + + +### Performance Improvements + +* **api:** Decrease plunger motor max speed by 20% ([#2682](https://github.com/Opentrons/opentrons/issues/2682)) ([f8b7ccf](https://github.com/Opentrons/opentrons/commit/f8b7ccf)) + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d288aff2f34..c7a25d4a6dc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -181,10 +181,11 @@ And you can run code linting / typechecking with: # lint all code make lint -# lint specific languages +# lint + typecheck specific languages make lint-py make lint-js make lint-css +make check-js ``` ### Opentrons API diff --git a/Makefile b/Makefile index 85aa319c03d..2eac5b2fa1d 100755 --- a/Makefile +++ b/Makefile @@ -84,17 +84,8 @@ term: .PHONY: test test: test-py test-js -# Use lerna to run test only if anything in update-server has changed -# `--scope @opentrons/update-server` tells lerna to use the package.json that -# uses this name (e.g.: the one in update-server/otupdate) -# `--since` gives the name of the upstream branch to check against -# `-- ` (with the space after) tells lerna to execute everything after this -# `-C ..` is here because the scope causes the working directory to change to -# where it finds the package.json specified by --scope, and the Makefile is -# in the parent of that directory .PHONY: test-py test-py: -# lerna exec --scope @opentrons/update-server --since origin/edge -- $(MAKE) -C .. test $(MAKE) -C api test .PHONY: test-js @@ -107,7 +98,7 @@ test-js: # lints and typechecks .PHONY: lint -lint: lint-py lint-js lint-css +lint: lint-py lint-js lint-css check-js .PHONY: lint-py lint-py: @@ -117,12 +108,15 @@ lint-py: .PHONY: lint-js lint-js: eslint '.*.js' '**/*.js' - flow $(if $(CI),check,status) .PHONY: lint-css lint-css: stylelint '**/*.css' +.PHONY: check-js +check-js: + flow $(if $(CI),check,status) + # upload coverage reports .PHONY: coverage coverage: diff --git a/api/Makefile b/api/Makefile index 288c1488ae9..1f41dbf60fa 100755 --- a/api/Makefile +++ b/api/Makefile @@ -44,17 +44,18 @@ ot_sources := $(ot_py_sources) $(ot_shared_data_sources) $(ot_resources) # depend on a PHONY target clean_cmd = shx rm -rf build dist .coverage coverage.xml '*.egg-info' '**/__pycache__' '**/*.pyc' +.PHONY: all +all: lint test + .PHONY: install install: pipenv sync $(pipenv_opts) @$(python) build_tools.py write_local_env -.PHONY: all -all: lint test - .PHONY: clean clean: $(clean_cmd) + pipenv --rm $(wheel_pattern): setup.py $(ot_sources) $(clean_cmd) diff --git a/api/Pipfile b/api/Pipfile index 8e618ea89bf..da79a7cb9ea 100755 --- a/api/Pipfile +++ b/api/Pipfile @@ -1,17 +1,12 @@ [[source]] - url = "https://pypi.python.org/simple" verify_ssl = true name = "pypi" - [requires] - python_version = "3.6" - [dev-packages] - pylama = "==7.4.3" pytest = "==3.4.2" pytest-cov = "==2.5.1" @@ -23,8 +18,10 @@ twine = "==1.8.1" wheel = "==0.30.0" coverage = "==4.4.2" mypy = "*" - +colorama = "*" [packages] - -pytest = "*" +numpy = "*" +pyserial = "==3.2.1" +urwid = "*" +aiohttp = "==2.3.8" diff --git a/api/Pipfile.lock b/api/Pipfile.lock index eadaee594e8..9715b0102f4 100644 --- a/api/Pipfile.lock +++ b/api/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "0577d43bd5e415741a6c066d8920ba19eaa184eb964ee81730d8b4cc7b9f9b8c" + "sha256": "b298dd3c15ef48d0845f4b90f7673fe6a5fb12ca5a851d0b73f822d468281681" }, "pipfile-spec": 6, "requires": { @@ -35,28 +35,15 @@ "sha256:c7b8a47315e8c0b79a008e33eca4299baa002efd4b53ace068f0894133a8933e", "sha256:e81997b2fb4b7f19a80257aa2bb6e35e521d62dcf595599bf34886b115607bad" ], + "index": "pypi", "version": "==2.3.8" }, "async-timeout": { "hashes": [ - "sha256:474d4bc64cee20603e225eb1ece15e248962958b45a3648a9f5cc29e827a610c", - "sha256:b3c0ddc416736619bd4a95ca31de8da6920c3b9a140c64dbef2b2fa7bf521287" + "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f", + "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3" ], - "version": "==3.0.0" - }, - "atomicwrites": { - "hashes": [ - "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", - "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee" - ], - "version": "==1.2.1" - }, - "attrs": { - "hashes": [ - "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", - "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb" - ], - "version": "==18.2.0" + "version": "==3.0.1" }, "chardet": { "hashes": [ @@ -65,26 +52,6 @@ ], "version": "==3.0.4" }, - "colorama": { - "hashes": [ - "sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", - "sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1" - ], - "markers": "sys_platform == 'win32'", - "version": "==0.3.9" - }, - "e1839a8": { - "editable": true, - "path": "." - }, - "funcsigs": { - "hashes": [ - "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca", - "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50" - ], - "markers": "python_version < '3.0'", - "version": "==1.0.2" - }, "idna": { "hashes": [ "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", @@ -92,149 +59,88 @@ ], "version": "==2.7" }, - "idna-ssl": { - "hashes": [ - "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c" - ], - "markers": "python_version < '3.7'", - "version": "==1.1.0" - }, - "more-itertools": { - "hashes": [ - "sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", - "sha256:c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", - "sha256:fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d" - ], - "version": "==4.3.0" - }, "multidict": { "hashes": [ - "sha256:112eeeddd226af681dc82b756ed34aa7b6d98f9c4a15760050298c21d715473d", - "sha256:13b64ecb692effcabc5e29569ba9b5eb69c35112f990a16d6833ec3a9d9f8ec0", - "sha256:1725373fb8f18c2166f8e0e5789851ccf98453c849b403945fa4ef59a16ca44e", - "sha256:2061a50b7cae60a1f987503a995b2fc38e47027a937a355a124306ed9c629041", - "sha256:35b062288a9a478f627c520fd27983160fc97591017d170f966805b428d17e07", - "sha256:467b134bcc227b91b8e2ef8d2931f28b50bf7eb7a04c0403d102ded22e66dbfc", - "sha256:475a3ece8bb450e49385414ebfae7f8fdb33f62f1ac0c12935c1cfb1b7c1076a", - "sha256:49b885287e227a24545a1126d9ac17ae43138610713dc6219b781cc0ad5c6dfc", - "sha256:4c95b2725592adb5c46642be2875c1234c32af841732c5504c17726b92082021", - "sha256:4ea7ed00f4be0f7335c9a2713a65ac3d986be789ce5ebc10821da9664cbe6b85", - "sha256:5e2d5e1d999e941b4a626aea46bdc4206877cf727107fdaa9d46a8a773a6e49b", - "sha256:8039c520ef7bb9ec7c3db3df14c570be6362f43c200ae9854d2422d4ffe175a4", - "sha256:81459a0ebcca09c1fcb8fe887ed13cf267d9b60fe33718fc5fd1a2a1ab49470a", - "sha256:847c3b7b9ca3268e883685dc1347a4d09f84de7bd7597310044d847590447492", - "sha256:8551d1db45f0ca4e8ec99130767009a29a4e0dc6558a4a6808491bcd3472d325", - "sha256:8fa7679ffe615e0c1c7b80946ab4194669be74848719adf2d7867b5e861eb073", - "sha256:a42a36f09f0f907579ff0fde547f2fde8a739a69efe4a2728835979d2bb5e17b", - "sha256:a5fcad0070685c5b2d04b468bf5f4c735f5c176432f495ad055fcc4bc0a79b23", - "sha256:ae22195b2a7494619b73c01129ddcddc0dfaa9e42727404b1d9a77253da3f420", - "sha256:b360e82bdbbd862e1ce2a41cc3bbd0ab614350e813ca74801b34aac0f73465aa", - "sha256:b96417899344c5e96bef757f4963a72d02e52653a4e0f99bbea3a531cedac59f", - "sha256:b9e921140b797093edfc13ac08dc2a4fd016dd711dc42bb0e1aaf180e48425a7", - "sha256:c5022b94fc330e6d177f3eb38097fb52c7df96ca0e04842c068cf0d9fc38b1e6", - "sha256:cf2b117f2a8d951638efc7592fb72d3eeb2d38cc2194c26ba7f00e7190451d92", - "sha256:d79620b542d9d0e23ae9790ca2fe44f1af40ffad9936efa37bd14954bc3e2818", - "sha256:e2860691c11d10dac7c91bddae44f6211b3da4122d9a2ebb509c2247674d6070", - "sha256:e3a293553715afecf7e10ea02da40593f9d7f48fe48a74fc5dd3ce08a0c46188", - "sha256:e465be3fe7e992e5a6e16731afa6f41cb6ca53afccb4f28ea2fa6457783edf15", - "sha256:e6d27895ef922bc859d969452f247bfbe5345d9aba69b9c8dbe1ea7704f0c5d9" - ], - "version": "==4.4.0" - }, - "numpy": { - "hashes": [ - "sha256:130105bfc0b03245115da67b441c48597bf1ed7f5385f8388ce4f75cdf2f91d2", - "sha256:3b21dc40fa1e2450dee8cf54991b0f95c415ac508d5db1227338efcf03c162cd", - "sha256:405ce136edb18c6f1f8c5acc75d7d8fbb875cc8b5015562251b93435099233d3", - "sha256:43ccfed0092def52b924e004780517c762f8fce3ececbd3f8e2580ac0538bb5e", - "sha256:47b4c4da2fe0618b65fd70987a414fdc24c09e1ffdff77f7147a3c6627b07596", - "sha256:4c64d9c389827f310c7f4e7887b741c34c6b2c337ff63a12f66ef0197fdf5366", - "sha256:4eac5f2f624c5e7eecbdb51395ff39a099c48cab607a158f16f288c6fe39a2b3", - "sha256:56e68de63ae738f40669b6a5f0601f9453940a0470a1e9bea16448e5b53f5f28", - "sha256:5cb6341fc885b101978328d3c8d51a069a97a00699a30891106ef7dda56a0d30", - "sha256:5dd60892710df0ef654bbf4d1e3cb53ac79845e55a96e4a26dd47218e06d819a", - "sha256:727d6373355b00b96d9320254a676b878d6cd43ae409186bec27eec3e5e4e6e7", - "sha256:7e9015bc5de54c8bd73ca750ccedfda25d34a25a767caf802740d35a692ec3ab", - "sha256:818d5a1d5752d09929ce1ba1735366d5acc769a1839386dc91f3ac30cf9faf19", - "sha256:92dce120e385767cbe433719b5e3fdb1ac81907140d3984b3187208f79aff19f", - "sha256:95e52d1077abeead6d205c1fc644f075228813859bb625960c1ae1248c4189ba", - "sha256:9cd16915a815c2f04633d14e7640083c1b72e82b325439c91370adfd376c9975", - "sha256:9ce673bb7b6240b94b60b52186f5c0825f4b31e8191c8bc7412a7d0348fca2cd", - "sha256:a65266a4ad6ec8936a1bc85ce51f8600634a31a258b722c9274a80ff189d9542", - "sha256:bcbce5ef18dc826ef67756a0d3669baca815c8d44b26867c6865f714a23d9262", - "sha256:ca917155b35b3bcc68ef1ad82570a29414f5088495ea8f68c65b071c50e64340", - "sha256:cd7892f7d644d1b4ed2ead254d4851616c07ecf82618e3203e2a81747ffb6069", - "sha256:d8dbd7e35e4819e059a044c7545d5602937d6b666dbd9b6eb8ff40037ab0980c", - "sha256:e97cecd783e8e7e70d18a42f6df7f18be14cbcc82fb9b837b03d072d1401ae53" - ], - "version": "==1.12.1" - }, - "pathlib2": { - "hashes": [ - "sha256:8eb170f8d0d61825e09a95b38be068299ddeda82f35e96c3301a8a5e7604cb83", - "sha256:d1aa2a11ba7b8f7b21ab852b1fb5afb277e1bb99d5dfc663380b5015c0d80c5a" - ], - "markers": "python_version < '3.6'", - "version": "==2.3.2" - }, - "pluggy": { - "hashes": [ - "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", - "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" + "sha256:05eeab69bf2b0664644c62bd92fabb045163e5b8d4376a31dfb52ce0210ced7b", + "sha256:0c85880efa7cadb18e3b5eef0aa075dc9c0a3064cbbaef2e20be264b9cf47a64", + "sha256:136f5a4a6a4adeacc4dc820b8b22f0a378fb74f326e259c54d1817639d1d40a0", + "sha256:14906ad3347c7d03e9101749b16611cf2028547716d0840838d3c5e2b3b0f2d3", + "sha256:1ade4a3b71b1bf9e90c5f3d034a87fe4949c087ef1f6cd727fdd766fe8bbd121", + "sha256:22939a00a511a59f9ecc0158b8db728afef57975ce3782b3a265a319d05b9b12", + "sha256:2b86b02d872bc5ba5b3a4530f6a7ba0b541458ab4f7c1429a12ac326231203f7", + "sha256:3c11e92c3dfc321014e22fb442bc9eb70e01af30d6ce442026b0c35723448c66", + "sha256:4ba3bd26f282b201fdbce351f1c5d17ceb224cbedb73d6e96e6ce391b354aacc", + "sha256:4c6e78d042e93751f60672989efbd6a6bc54213ed7ff695fff82784bbb9ea035", + "sha256:4d80d1901b89cc935a6cf5b9fd89df66565272722fe2e5473168927a9937e0ca", + "sha256:4fcf71d33178a00cc34a57b29f5dab1734b9ce0f1c97fb34666deefac6f92037", + "sha256:52f7670b41d4b4d97866ebc38121de8bcb9813128b7c4942b07794d08193c0ab", + "sha256:5368e2b7649a26b7253c6c9e53241248aab9da49099442f5be238fde436f18c9", + "sha256:5bb65fbb48999044938f0c0508e929b14a9b8bf4939d8263e9ea6691f7b54663", + "sha256:60672bb5577472800fcca1ac9dae232d1461db9f20f055184be8ce54b0052572", + "sha256:669e9be6d148fc0283f53e17dd140cde4dc7c87edac8319147edd5aa2a830771", + "sha256:6a0b7a804e8d1716aa2c72e73210b48be83d25ba9ec5cf52cf91122285707bb1", + "sha256:79034ea3da3cf2a815e3e52afdc1f6c1894468c98bdce5d2546fa2342585497f", + "sha256:79247feeef6abcc11137ad17922e865052f23447152059402fc320f99ff544bb", + "sha256:81671c2049e6bf42c7fd11a060f8bc58f58b7b3d6f3f951fc0b15e376a6a5a98", + "sha256:82ac4a5cb56cc9280d4ae52c2d2ebcd6e0668dd0f9ef17f0a9d7c82bd61e24fa", + "sha256:9436267dbbaa49dad18fbbb54f85386b0f5818d055e7b8e01d219661b6745279", + "sha256:94e4140bb1343115a1afd6d84ebf8fca5fb7bfb50e1c2cbd6f2fb5d3117ef102", + "sha256:a2cab366eae8a0ffe0813fd8e335cf0d6b9bb6c5227315f53bb457519b811537", + "sha256:a596019c3eafb1b0ae07db9f55a08578b43c79adb1fe1ab1fd818430ae59ee6f", + "sha256:e8848ae3cd6a784c29fae5055028bee9bffcc704d8bcad09bd46b42b44a833e2", + "sha256:e8a048bfd7d5a280f27527d11449a509ddedf08b58a09a24314828631c099306", + "sha256:f6dd28a0ac60e2426a6918f36f1b4e2620fc785a0de7654cd206ba842eee57fd" ], - "version": "==0.7.1" + "version": "==4.4.2" }, - "py": { + "numpy": { "hashes": [ - "sha256:06a30435d058473046be836d3fc4f27167fd84c45b99704f2fb5509ef61f9af1", - "sha256:50402e9d1c9005d759426988a492e0edaadb7f4e68bcddfea586bc7432d009c6" + "sha256:0df89ca13c25eaa1621a3f09af4c8ba20da849692dcae184cb55e80952c453fb", + "sha256:154c35f195fd3e1fad2569930ca51907057ae35e03938f89a8aedae91dd1b7c7", + "sha256:18e84323cdb8de3325e741a7a8dd4a82db74fde363dce32b625324c7b32aa6d7", + "sha256:1e8956c37fc138d65ded2d96ab3949bd49038cc6e8a4494b1515b0ba88c91565", + "sha256:23557bdbca3ccbde3abaa12a6e82299bc92d2b9139011f8c16ca1bb8c75d1e95", + "sha256:24fd645a5e5d224aa6e39d93e4a722fafa9160154f296fd5ef9580191c755053", + "sha256:36e36b6868e4440760d4b9b44587ea1dc1f06532858d10abba98e851e154ca70", + "sha256:3d734559db35aa3697dadcea492a423118c5c55d176da2f3be9c98d4803fc2a7", + "sha256:416a2070acf3a2b5d586f9a6507bb97e33574df5bd7508ea970bbf4fc563fa52", + "sha256:4a22dc3f5221a644dfe4a63bf990052cc674ef12a157b1056969079985c92816", + "sha256:4d8d3e5aa6087490912c14a3c10fbdd380b40b421c13920ff468163bc50e016f", + "sha256:4f41fd159fba1245e1958a99d349df49c616b133636e0cf668f169bce2aeac2d", + "sha256:561ef098c50f91fbac2cc9305b68c915e9eb915a74d9038ecf8af274d748f76f", + "sha256:56994e14b386b5c0a9b875a76d22d707b315fa037affc7819cda08b6d0489756", + "sha256:73a1f2a529604c50c262179fcca59c87a05ff4614fe8a15c186934d84d09d9a5", + "sha256:7da99445fd890206bfcc7419f79871ba8e73d9d9e6b82fe09980bc5bb4efc35f", + "sha256:99d59e0bcadac4aa3280616591fb7bcd560e2218f5e31d5223a2e12a1425d495", + "sha256:a4cc09489843c70b22e8373ca3dfa52b3fab778b57cf81462f1203b0852e95e3", + "sha256:a61dc29cfca9831a03442a21d4b5fd77e3067beca4b5f81f1a89a04a71cf93fa", + "sha256:b1853df739b32fa913cc59ad9137caa9cc3d97ff871e2bbd89c2a2a1d4a69451", + "sha256:b1f44c335532c0581b77491b7715a871d0dd72e97487ac0f57337ccf3ab3469b", + "sha256:b261e0cb0d6faa8fd6863af26d30351fd2ffdb15b82e51e81e96b9e9e2e7ba16", + "sha256:c857ae5dba375ea26a6228f98c195fec0898a0fd91bcf0e8a0cae6d9faf3eca7", + "sha256:cf5bb4a7d53a71bb6a0144d31df784a973b36d8687d615ef6a7e9b1809917a9b", + "sha256:db9814ff0457b46f2e1d494c1efa4111ca089e08c8b983635ebffb9c1573361f", + "sha256:df04f4bad8a359daa2ff74f8108ea051670cafbca533bb2636c58b16e962989e", + "sha256:ecf81720934a0e18526177e645cbd6a8a21bb0ddc887ff9738de07a1df5c6b61", + "sha256:edfa6fba9157e0e3be0f40168eb142511012683ac3dc82420bee4a3f3981b30e" ], - "version": "==1.6.0" + "index": "pypi", + "version": "==1.15.4" }, "pyserial": { "hashes": [ "sha256:1eecfe4022240f2eab5af8d414f0504e072ee68377ba63d3b6fe6e66c26f66d1", "sha256:b05fa0d2f5cc5a9584bed5d695441f6dba127c5b593dfa6e671a0db2de0d959a" ], - "version": "==3.2.1" - }, - "pytest": { - "hashes": [ - "sha256:453cbbbe5ce6db38717d282b758b917de84802af4288910c12442984bde7b823", - "sha256:a8a07f84e680482eb51e244370aaf2caa6301ef265f37c2bdefb3dd3b663f99d" - ], "index": "pypi", - "version": "==3.8.0" - }, - "scandir": { - "hashes": [ - "sha256:04b8adb105f2ed313a7c2ef0f1cf7aff4871aa7a1883fa4d8c44b5551ab052d6", - "sha256:1444134990356c81d12f30e4b311379acfbbcd03e0bab591de2696a3b126d58e", - "sha256:1b5c314e39f596875e5a95dd81af03730b338c277c54a454226978d5ba95dbb6", - "sha256:346619f72eb0ddc4cf355ceffd225fa52506c92a2ff05318cfabd02a144e7c4e", - "sha256:44975e209c4827fc18a3486f257154d34ec6eaec0f90fef0cca1caa482db7064", - "sha256:61859fd7e40b8c71e609c202db5b0c1dbec0d5c7f1449dec2245575bdc866792", - "sha256:a5e232a0bf188362fa00123cc0bb842d363a292de7126126df5527b6a369586a", - "sha256:c14701409f311e7a9b7ec8e337f0815baf7ac95776cc78b419a1e6d49889a383", - "sha256:c7708f29d843fc2764310732e41f0ce27feadde453261859ec0fca7865dfc41b", - "sha256:c9009c527929f6e25604aec39b0a43c3f831d2947d89d6caaab22f057b7055c8", - "sha256:f5c71e29b4e2af7ccdc03a020c626ede51da471173b4a6ad1e904f2b2e04b4bd" - ], - "markers": "python_version < '3.5'", - "version": "==1.9.0" - }, - "six": { - "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" - ], - "version": "==1.11.0" + "version": "==3.2.1" }, "urwid": { "hashes": [ - "sha256:cfcec03e36de25a1073e2e35c2c7b0cc6969b85745715c3a025a31d9786896a1" + "sha256:644d3e3900867161a2fc9287a9762753d66bd194754679adb26aede559bcccbc" ], - "version": "==1.3.1" + "index": "pypi", + "version": "==2.0.1" }, "yarl": { "hashes": [ @@ -271,28 +177,28 @@ "sha256:c7b8a47315e8c0b79a008e33eca4299baa002efd4b53ace068f0894133a8933e", "sha256:e81997b2fb4b7f19a80257aa2bb6e35e521d62dcf595599bf34886b115607bad" ], + "index": "pypi", "version": "==2.3.8" }, "alabaster": { "hashes": [ - "sha256:674bb3bab080f598371f4443c5008cbfeb1a5e622dd312395d2d82af2c54c456", - "sha256:b63b1f4dc77c074d386752ec4a8a7517600f6c0db8cd42980cae17ab7b3275d7" + "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", + "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" ], - "version": "==0.7.11" + "version": "==0.7.12" }, - "async-timeout": { + "args": { "hashes": [ - "sha256:474d4bc64cee20603e225eb1ece15e248962958b45a3648a9f5cc29e827a610c", - "sha256:b3c0ddc416736619bd4a95ca31de8da6920c3b9a140c64dbef2b2fa7bf521287" + "sha256:a785b8d837625e9b61c39108532d95b85274acd679693b71ebb5156848fcf814" ], - "version": "==3.0.0" + "version": "==0.1.0" }, - "atomicwrites": { + "async-timeout": { "hashes": [ - "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", - "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee" + "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f", + "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3" ], - "version": "==1.2.1" + "version": "==3.0.1" }, "attrs": { "hashes": [ @@ -310,10 +216,10 @@ }, "certifi": { "hashes": [ - "sha256:376690d6f16d32f9d1fe8932551d80b23e9d393a8578c5633a2ed39a64861638", - "sha256:456048c7e371c089d0a77a5212fb37a2c2dce1e24146e3b7e0261736aaeaa22a" + "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", + "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" ], - "version": "==2018.8.24" + "version": "==2018.10.15" }, "chardet": { "hashes": [ @@ -322,28 +228,30 @@ ], "version": "==3.0.4" }, + "clint": { + "hashes": [ + "sha256:05224c32b1075563d0b16d0015faaf9da43aa214e4a2140e51f08789e7a4c5aa" + ], + "version": "==0.5.1" + }, "colorama": { "hashes": [ - "sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", - "sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1" + "sha256:a3d89af5db9e9806a779a50296b5fdb466e281147c2c235e8225ecc6dbf7bbf3", + "sha256:c9b54bebe91a6a803e0772c8561d53f2926bfeb17cd141fbabcb08424086595c" ], - "markers": "sys_platform == 'win32'", - "version": "==0.3.9" + "index": "pypi", + "version": "==0.4.0" }, "coverage": { "hashes": [ "sha256:007eeef7e23f9473622f7d94a3e029a45d55a92a1f083f0f3512f5ab9a669b05", - "sha256:0388c12539372bb92d6dde68b4627f0300d948965bbb7fc104924d715fdc0965", "sha256:079248312838c4c8f3494934ab7382a42d42d5f365f0cf7516f938dbb3f53f3f", "sha256:17307429935f96c986a1b1674f78079528833410750321d22b5fb35d1883828e", - "sha256:1afccd7e27cac1b9617be8c769f6d8a6d363699c9b86820f40c74cfb3328921c", "sha256:2ad357d12971e77360034c1596011a03f50c0f9e1ecd12e081342b8d1aee2236", - "sha256:2b4d7f03a8a6632598cbc5df15bbca9f778c43db7cf1a838f4fa2c8599a8691a", "sha256:2e1a5c6adebb93c3b175103c2f855eda957283c10cf937d791d81bef8872d6ca", "sha256:309d91bd7a35063ec7a0e4d75645488bfab3f0b66373e7722f23da7f5b0f34cc", "sha256:358d635b1fc22a425444d52f26287ae5aea9e96e254ff3c59c407426f44574f4", "sha256:3f4d0b3403d3e110d2588c275540649b1841725f5a11a7162620224155d00ba2", - "sha256:43a155eb76025c61fc20c3d03b89ca28efa6f5be572ab6110b2fb68eda96bfea", "sha256:493082f104b5ca920e97a485913de254cbe351900deed72d4264571c73464cd0", "sha256:4c4f368ffe1c2e7602359c2c50233269f3abe1c48ca6b288dcd0fb1d1c679733", "sha256:5ff16548492e8a12e65ff3d55857ccd818584ed587a6c2898a9ebbe09a880674", @@ -354,11 +262,8 @@ "sha256:845fddf89dca1e94abe168760a38271abfc2e31863fbb4ada7f9a99337d7c3dc", "sha256:87d942863fe74b1c3be83a045996addf1639218c2cb89c5da18c06c0fe3917ea", "sha256:9721f1b7275d3112dc7ccf63f0553c769f09b5c25a26ee45872c7f5c09edf6c1", - "sha256:a4497faa4f1c0fc365ba05eaecfb6b5d24e3c8c72e95938f9524e29dadb15e76", "sha256:a7cfaebd8f24c2b537fa6a271229b051cdac9c1734bb6f939ccfc7c055689baa", - "sha256:ab3508df9a92c1d3362343d235420d08e2662969b83134f8a97dc1451cbe5e84", "sha256:b0059630ca5c6b297690a6bf57bf2fdac1395c24b7935fd73ee64190276b743b", - "sha256:b6cebae1502ce5b87d7c6f532fa90ab345cfbda62b95aeea4e431e164d498a3d", "sha256:bd4800e32b4c8d99c3a2c943f1ac430cbf80658d884123d19639bcde90dad44a", "sha256:cdd92dd9471e624cd1d8c1a2703d25f114b59b736b0f1f659a98414e535ffb3d", "sha256:d00e29b78ff610d300b2c37049a41234d48ea4f2d2581759ebcf67caaf731c31", @@ -370,8 +275,7 @@ "sha256:f29841e865590af72c4b90d7b5b8e93fd560f5dea436c1d5ee8053788f9285de", "sha256:f3a5c6d054c531536a83521c00e5d4004f1e126e2e2556ce399bef4180fbe540", "sha256:f87f522bde5540d8a4b11df80058281ac38c44b13ce29ced1e294963dd51a8f8", - "sha256:f8c55dd0f56d3d618dfacf129e010cbe5d5f94b6951c1b2f13ab1a2f79c284da", - "sha256:f98b461cb59f117887aa634a66022c0bd394278245ed51189f63a036516e32de" + "sha256:f8c55dd0f56d3d618dfacf129e010cbe5d5f94b6951c1b2f13ab1a2f79c284da" ], "index": "pypi", "version": "==4.4.2" @@ -391,14 +295,6 @@ ], "version": "==0.14" }, - "funcsigs": { - "hashes": [ - "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca", - "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50" - ], - "markers": "python_version < '3.0'", - "version": "==1.0.2" - }, "idna": { "hashes": [ "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", @@ -429,9 +325,36 @@ }, "markupsafe": { "hashes": [ - "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" + "sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432", + "sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b", + "sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9", + "sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af", + "sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834", + "sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd", + "sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d", + "sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7", + "sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b", + "sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3", + "sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c", + "sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2", + "sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7", + "sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36", + "sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1", + "sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e", + "sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1", + "sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c", + "sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856", + "sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550", + "sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492", + "sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672", + "sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401", + "sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6", + "sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6", + "sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c", + "sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", + "sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1" ], - "version": "==1.0" + "version": "==1.1.0" }, "mccabe": { "hashes": [ @@ -440,55 +363,54 @@ ], "version": "==0.6.1" }, - "more-itertools": { - "hashes": [ - "sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", - "sha256:c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", - "sha256:fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d" - ], - "version": "==4.3.0" - }, "multidict": { "hashes": [ - "sha256:112eeeddd226af681dc82b756ed34aa7b6d98f9c4a15760050298c21d715473d", - "sha256:13b64ecb692effcabc5e29569ba9b5eb69c35112f990a16d6833ec3a9d9f8ec0", - "sha256:1725373fb8f18c2166f8e0e5789851ccf98453c849b403945fa4ef59a16ca44e", - "sha256:2061a50b7cae60a1f987503a995b2fc38e47027a937a355a124306ed9c629041", - "sha256:35b062288a9a478f627c520fd27983160fc97591017d170f966805b428d17e07", - "sha256:467b134bcc227b91b8e2ef8d2931f28b50bf7eb7a04c0403d102ded22e66dbfc", - "sha256:475a3ece8bb450e49385414ebfae7f8fdb33f62f1ac0c12935c1cfb1b7c1076a", - "sha256:49b885287e227a24545a1126d9ac17ae43138610713dc6219b781cc0ad5c6dfc", - "sha256:4c95b2725592adb5c46642be2875c1234c32af841732c5504c17726b92082021", - "sha256:4ea7ed00f4be0f7335c9a2713a65ac3d986be789ce5ebc10821da9664cbe6b85", - "sha256:5e2d5e1d999e941b4a626aea46bdc4206877cf727107fdaa9d46a8a773a6e49b", - "sha256:8039c520ef7bb9ec7c3db3df14c570be6362f43c200ae9854d2422d4ffe175a4", - "sha256:81459a0ebcca09c1fcb8fe887ed13cf267d9b60fe33718fc5fd1a2a1ab49470a", - "sha256:847c3b7b9ca3268e883685dc1347a4d09f84de7bd7597310044d847590447492", - "sha256:8551d1db45f0ca4e8ec99130767009a29a4e0dc6558a4a6808491bcd3472d325", - "sha256:8fa7679ffe615e0c1c7b80946ab4194669be74848719adf2d7867b5e861eb073", - "sha256:a42a36f09f0f907579ff0fde547f2fde8a739a69efe4a2728835979d2bb5e17b", - "sha256:a5fcad0070685c5b2d04b468bf5f4c735f5c176432f495ad055fcc4bc0a79b23", - "sha256:ae22195b2a7494619b73c01129ddcddc0dfaa9e42727404b1d9a77253da3f420", - "sha256:b360e82bdbbd862e1ce2a41cc3bbd0ab614350e813ca74801b34aac0f73465aa", - "sha256:b96417899344c5e96bef757f4963a72d02e52653a4e0f99bbea3a531cedac59f", - "sha256:b9e921140b797093edfc13ac08dc2a4fd016dd711dc42bb0e1aaf180e48425a7", - "sha256:c5022b94fc330e6d177f3eb38097fb52c7df96ca0e04842c068cf0d9fc38b1e6", - "sha256:cf2b117f2a8d951638efc7592fb72d3eeb2d38cc2194c26ba7f00e7190451d92", - "sha256:d79620b542d9d0e23ae9790ca2fe44f1af40ffad9936efa37bd14954bc3e2818", - "sha256:e2860691c11d10dac7c91bddae44f6211b3da4122d9a2ebb509c2247674d6070", - "sha256:e3a293553715afecf7e10ea02da40593f9d7f48fe48a74fc5dd3ce08a0c46188", - "sha256:e465be3fe7e992e5a6e16731afa6f41cb6ca53afccb4f28ea2fa6457783edf15", - "sha256:e6d27895ef922bc859d969452f247bfbe5345d9aba69b9c8dbe1ea7704f0c5d9" - ], - "version": "==4.4.0" + "sha256:05eeab69bf2b0664644c62bd92fabb045163e5b8d4376a31dfb52ce0210ced7b", + "sha256:0c85880efa7cadb18e3b5eef0aa075dc9c0a3064cbbaef2e20be264b9cf47a64", + "sha256:136f5a4a6a4adeacc4dc820b8b22f0a378fb74f326e259c54d1817639d1d40a0", + "sha256:14906ad3347c7d03e9101749b16611cf2028547716d0840838d3c5e2b3b0f2d3", + "sha256:1ade4a3b71b1bf9e90c5f3d034a87fe4949c087ef1f6cd727fdd766fe8bbd121", + "sha256:22939a00a511a59f9ecc0158b8db728afef57975ce3782b3a265a319d05b9b12", + "sha256:2b86b02d872bc5ba5b3a4530f6a7ba0b541458ab4f7c1429a12ac326231203f7", + "sha256:3c11e92c3dfc321014e22fb442bc9eb70e01af30d6ce442026b0c35723448c66", + "sha256:4ba3bd26f282b201fdbce351f1c5d17ceb224cbedb73d6e96e6ce391b354aacc", + "sha256:4c6e78d042e93751f60672989efbd6a6bc54213ed7ff695fff82784bbb9ea035", + "sha256:4d80d1901b89cc935a6cf5b9fd89df66565272722fe2e5473168927a9937e0ca", + "sha256:4fcf71d33178a00cc34a57b29f5dab1734b9ce0f1c97fb34666deefac6f92037", + "sha256:52f7670b41d4b4d97866ebc38121de8bcb9813128b7c4942b07794d08193c0ab", + "sha256:5368e2b7649a26b7253c6c9e53241248aab9da49099442f5be238fde436f18c9", + "sha256:5bb65fbb48999044938f0c0508e929b14a9b8bf4939d8263e9ea6691f7b54663", + "sha256:60672bb5577472800fcca1ac9dae232d1461db9f20f055184be8ce54b0052572", + "sha256:669e9be6d148fc0283f53e17dd140cde4dc7c87edac8319147edd5aa2a830771", + "sha256:6a0b7a804e8d1716aa2c72e73210b48be83d25ba9ec5cf52cf91122285707bb1", + "sha256:79034ea3da3cf2a815e3e52afdc1f6c1894468c98bdce5d2546fa2342585497f", + "sha256:79247feeef6abcc11137ad17922e865052f23447152059402fc320f99ff544bb", + "sha256:81671c2049e6bf42c7fd11a060f8bc58f58b7b3d6f3f951fc0b15e376a6a5a98", + "sha256:82ac4a5cb56cc9280d4ae52c2d2ebcd6e0668dd0f9ef17f0a9d7c82bd61e24fa", + "sha256:9436267dbbaa49dad18fbbb54f85386b0f5818d055e7b8e01d219661b6745279", + "sha256:94e4140bb1343115a1afd6d84ebf8fca5fb7bfb50e1c2cbd6f2fb5d3117ef102", + "sha256:a2cab366eae8a0ffe0813fd8e335cf0d6b9bb6c5227315f53bb457519b811537", + "sha256:a596019c3eafb1b0ae07db9f55a08578b43c79adb1fe1ab1fd818430ae59ee6f", + "sha256:e8848ae3cd6a784c29fae5055028bee9bffcc704d8bcad09bd46b42b44a833e2", + "sha256:e8a048bfd7d5a280f27527d11449a509ddedf08b58a09a24314828631c099306", + "sha256:f6dd28a0ac60e2426a6918f36f1b4e2620fc785a0de7654cd206ba842eee57fd" + ], + "version": "==4.4.2" }, "mypy": { "hashes": [ - "sha256:673ea75fb750289b7d1da1331c125dc62fc1c3a8db9129bb372ae7b7d5bf300a", - "sha256:c770605a579fdd4a014e9f0a34b6c7a36ce69b08100ff728e96e27445cef3b3c" + "sha256:8e071ec32cc226e948a34bbb3d196eb0fd96f3ac69b6843a5aff9bd4efa14455", + "sha256:fb90c804b84cfd8133d3ddfbd630252694d11ccc1eb0166a1b2efb5da37ecab2" ], "index": "pypi", - "version": "==0.620" + "version": "==0.641" + }, + "mypy-extensions": { + "hashes": [ + "sha256:37e0e956f41369209a3d5f34580150bcacfabaa57b33a15c0b25f4b5725e0812", + "sha256:b16cabe759f55e3409a7d231ebd2841378fb0c27a5d1994719e340e4f429ac3e" + ], + "version": "==0.4.1" }, "numpydoc": { "hashes": [ @@ -498,21 +420,6 @@ "index": "pypi", "version": "==0.6.0" }, - "packaging": { - "hashes": [ - "sha256:e9215d2d2535d3ae866c3d6efc77d5b24a0192cce0ff20e42896cc0664f889c0", - "sha256:f019b770dd64e585a99714f1fd5e01c7a8f11b45635aa953fd41c689a657375b" - ], - "version": "==17.1" - }, - "pathlib2": { - "hashes": [ - "sha256:8eb170f8d0d61825e09a95b38be068299ddeda82f35e96c3301a8a5e7604cb83", - "sha256:d1aa2a11ba7b8f7b21ab852b1fb5afb277e1bb99d5dfc663380b5015c0d80c5a" - ], - "markers": "python_version < '3.6'", - "version": "==2.3.2" - }, "pkginfo": { "hashes": [ "sha256:5878d542a4b3f237e359926384f1dde4e099c9f5525d236b1840cf704fa8d474", @@ -522,21 +429,21 @@ }, "pluggy": { "hashes": [ - "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", - "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" + "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", + "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", + "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" ], - "version": "==0.7.1" + "version": "==0.6.0" }, "py": { "hashes": [ - "sha256:06a30435d058473046be836d3fc4f27167fd84c45b99704f2fb5509ef61f9af1", - "sha256:50402e9d1c9005d759426988a492e0edaadb7f4e68bcddfea586bc7432d009c6" + "sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694", + "sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6" ], - "version": "==1.6.0" + "version": "==1.7.0" }, "pycodestyle": { "hashes": [ - "sha256:74abc4e221d393ea5ce1f129ea6903209940c1ecd29e002e8c6933c2b21026e0", "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a" ], @@ -544,11 +451,11 @@ }, "pydocstyle": { "hashes": [ - "sha256:08a870edc94508264ed90510db466c6357c7192e0e866561d740624a8fc7d90c", - "sha256:4d5bcde961107873bae621f3d580c3e35a426d3687ffc6f8fb356f6628da5a97", - "sha256:af9fcccb303899b83bec82dc9a1d56c60fc369973223a5e80c3dfa9bdf984405" + "sha256:2258f9b0df68b97bf3a6c29003edc5238ff8879f1efb6f1999988d934e432bd8", + "sha256:5741c85e408f9e0ddf873611085e819b809fca90b619f5fd7f34bd4959da3dd4", + "sha256:ed79d4ec5e92655eccc21eb0c6cf512e69512b4a97d215ace46d17e4990f2039" ], - "version": "==2.1.1" + "version": "==3.0.0" }, "pyflakes": { "hashes": [ @@ -572,25 +479,13 @@ "index": "pypi", "version": "==7.4.3" }, - "pyparsing": { - "hashes": [ - "sha256:0832bcf47acd283788593e7a0f542407bd9550a55a8a8435214a1960e04bcb04", - "sha256:281683241b25fe9b80ec9d66017485f6deff1af5cde372469134b56ca8447a07", - "sha256:8f1e18d3fd36c6795bb7e02a39fd05c611ffc2596c1e0d995d34d67630426c18", - "sha256:9e8143a3e15c13713506886badd96ca4b579a87fbdf49e550dbfc057d6cb218e", - "sha256:b8b3117ed9bdf45e14dcc89345ce638ec7e0e29b2b579fa1ecf32ce45ebac8a5", - "sha256:e4d45427c6e20a59bf4f88c639dcc03ce30d193112047f94012102f235853a58", - "sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010" - ], - "version": "==2.2.0" - }, "pytest": { "hashes": [ - "sha256:453cbbbe5ce6db38717d282b758b917de84802af4288910c12442984bde7b823", - "sha256:a8a07f84e680482eb51e244370aaf2caa6301ef265f37c2bdefb3dd3b663f99d" + "sha256:062027955bccbc04d2fcd5d79690947e018ba31abe4c90b2c6721abec734261b", + "sha256:117bad36c1a787e1a8a659df35de53ba05f9f3398fb9e4ac17e80ad5903eb8c5" ], "index": "pypi", - "version": "==3.8.0" + "version": "==3.4.2" }, "pytest-aiohttp": { "hashes": [ @@ -610,17 +505,17 @@ }, "pytz": { "hashes": [ - "sha256:a061aa0a9e06881eb8b3b2b43f05b9439d6583c206d0a6c340ff72a7b6669053", - "sha256:ffb9ef1de172603304d9d2819af6f5ece76f2e85ec10692a524dd876e72bf277" + "sha256:31cb35c89bd7d333cd32c5f278fca91b523b0834369e757f4c5641ea252236ca", + "sha256:8e0f8568c118d3077b46be7d654cc8167fa916092e28320cde048e54bfc9f1e6" ], - "version": "==2018.5" + "version": "==2018.7" }, "requests": { "hashes": [ - "sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1", - "sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a" + "sha256:65b3a120e4329e33c9889db89c80976c5272f56ea92d3e74da8a463992e3ff54", + "sha256:ea881206e59f41dbd0bd445437d792e43906703fff75ca8ff43ccdb11f33f263" ], - "version": "==2.19.1" + "version": "==2.20.1" }, "requests-toolbelt": { "hashes": [ @@ -629,23 +524,6 @@ ], "version": "==0.8.0" }, - "scandir": { - "hashes": [ - "sha256:04b8adb105f2ed313a7c2ef0f1cf7aff4871aa7a1883fa4d8c44b5551ab052d6", - "sha256:1444134990356c81d12f30e4b311379acfbbcd03e0bab591de2696a3b126d58e", - "sha256:1b5c314e39f596875e5a95dd81af03730b338c277c54a454226978d5ba95dbb6", - "sha256:346619f72eb0ddc4cf355ceffd225fa52506c92a2ff05318cfabd02a144e7c4e", - "sha256:44975e209c4827fc18a3486f257154d34ec6eaec0f90fef0cca1caa482db7064", - "sha256:61859fd7e40b8c71e609c202db5b0c1dbec0d5c7f1449dec2245575bdc866792", - "sha256:a5e232a0bf188362fa00123cc0bb842d363a292de7126126df5527b6a369586a", - "sha256:c14701409f311e7a9b7ec8e337f0815baf7ac95776cc78b419a1e6d49889a383", - "sha256:c7708f29d843fc2764310732e41f0ce27feadde453261859ec0fca7865dfc41b", - "sha256:c9009c527929f6e25604aec39b0a43c3f831d2947d89d6caaab22f057b7055c8", - "sha256:f5c71e29b4e2af7ccdc03a020c626ede51da471173b4a6ad1e904f2b2e04b4bd" - ], - "markers": "python_version < '3.5'", - "version": "==1.9.0" - }, "six": { "hashes": [ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", @@ -668,20 +546,6 @@ "index": "pypi", "version": "==1.4.8" }, - "sphinxcontrib-websupport": { - "hashes": [ - "sha256:68ca7ff70785cbe1e7bccc71a48b5b6d965d79ca50629606c7861a21b206d9dd", - "sha256:9de47f375baf1ea07cdb3436ff39d7a9c76042c10a769c52353ec46e4e8fc3b9" - ], - "version": "==1.1.0" - }, - "tqdm": { - "hashes": [ - "sha256:5ef526702c0d265d5a960a3b27f3971fac13c26cf0fb819294bfa71fc6026c88", - "sha256:a3364bd83ce4777320b862e3c8a93d7da91e20a95f06ef79bed7dd71c654cafa" - ], - "version": "==4.25.0" - }, "twine": { "hashes": [ "sha256:3202d943a144962a821d9c5e92e07f9442dbbe6d6f18eae74e2a725b9980c559", @@ -718,21 +582,12 @@ ], "version": "==1.1.0" }, - "typing": { - "hashes": [ - "sha256:4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d", - "sha256:57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4", - "sha256:a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a" - ], - "markers": "python_version < '3.5'", - "version": "==3.6.6" - }, "urllib3": { "hashes": [ - "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", - "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" + "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", + "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" ], - "version": "==1.23" + "version": "==1.24.1" }, "wheel": { "hashes": [ diff --git a/api/README.rst b/api/README.rst index 97bddfd1b9c..bbf5dcaf289 100755 --- a/api/README.rst +++ b/api/README.rst @@ -106,6 +106,25 @@ Below is a short protocol that will pick up a tip and use it to move 100ul volum Using This Repo Outside Of A Robot ---------------------------------- -The code in this subdirectory can be used outside of a robot to check protocols; however, because the code requires extra shared data files and dependencies, you cannot simply run a python interpreter. +The code in this subdirectory can be used outside of a robot to check protocols; however, because the code requires extra shared data files and dependencies, you cannot simply run a python interpreter - it must be installed. -To use the opentrons API locally, please run ``make install`` to set up your system. Then, running ``make local-shell`` will give you a shell with the opentrons module all set up and ready to be imported. +There are two ways to install the Opentrons software. The first is to create a virtual environment unique to this particular checkout of the Opentrons software; this is useful to avoid affecting the rest of your system. The second way is to install the Opentrons software to your entire system, and is much easier to use with other Python packages like Jupyter. + +Before either step is taken, please follow the instructions in the Environment and Repository section of CONTRIBUTING.md in the repository root, up to and including running ``make install``. + + +Virtual Environment Setup +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once ``make install`` has been run, the virtual environment is ready to use. For more information on virtual environments see the Python documentation at https://docs.python.org/3/library/venv.html . The API Makefile contains a useful command to ensure that the version of the API installed to the virtual environment is up to date and start the virtual environment: ``make local-shell``. After running ``make local-shell``, the terminal in which you ran it is now in the virtual environment, and other Python scripts or applications started from that terminal will be able to see the Opentrons software. + +In addition to running scripts that ``import opentrons``, the local installation makes it easy to run an API server locally on your machine. This is only important if you want to interact with the system the same way the opentrons app does; if you only want to test protocols, you can simply run the protocol in the virtual environment. To run the server, do ``make dev``. + +Systemwide Setup +~~~~~~~~~~~~~~~~ + +Sometimes it can be inconvenient to activate a virtual environment and run things from it every time you want to use the API to simulate a protocol. This workflow is easier in that case, and is best used when you do not intend to modify the API. In that case, in addition to running ``make install``, we recommend that you check out the latest release of the API rather than using the ``edge`` branch. Instead, go to the root of the repository on GitHub at https://github.com/Opentrons/opentrons , click the branch dropdown, click the tags tab, and find the numerically highest tag, then check that out locally. + +Once the most recent tag is checked out, in this directory run ``make wheel``. This command builds the API into an installable Python object. Then, in this directory run ``pip install dist/opentrons-*.whl``. This command installs the API on your system. Finally, set the environment variable ``ENABLE_VIRTUAL_SMOOTHIE=true``. This prevents the API from accessing your computer as it would the robot. If you see errors about the directory ``data``, it means you have not set the environment variable. + +Once the API is installed and the environment variable is set, you should be able to ``import opentrons`` from anywhere on your system, including from inside Jupyter. diff --git a/api/docs/source/labware.rst b/api/docs/source/labware.rst index 844496fa527..380ed39f95c 100644 --- a/api/docs/source/labware.rst +++ b/api/docs/source/labware.rst @@ -596,15 +596,15 @@ You can access a specific row or column by using the ``rows()`` and ``cols()`` m row = plate.rows('A') column = plate.cols('1') - print('Column "A" has', len(column), 'wells') - print('Row "1" has', len(row), 'wells') + print('Column "1" has', len(column), 'wells') + print('Row "A" has', len(row), 'wells') will print out... .. code-block:: python - Column "A" has 8 wells - Row "1" has 12 wells + Column "1" has 8 wells + Row "A" has 12 wells The ``rows()`` or ``cols()`` methods can be used in combination with the ``wells()`` method to access wells within that row or column. In the example below, both lines refer to well ``'A1'``. diff --git a/api/docs/source/robot.rst b/api/docs/source/robot.rst index d9a3fa2e1dd..9a21afee78b 100644 --- a/api/docs/source/robot.rst +++ b/api/docs/source/robot.rst @@ -46,7 +46,7 @@ The speed of the robot's motors can be set using ``robot.head_speed()``. The uni The ``combined_speed`` parameter sets the speed across all axes to either the specified value or the axis max, whichever is lower. Defaults are specified by ``DEFAULT_MAX_SPEEDS`` in `robot_configs.py`__. -__ https://github.com/Opentrons/opentrons/blob/edge/api/opentrons/robot/robot_configs.py +__ https://github.com/Opentrons/opentrons/blob/edge/api/src/opentrons/config/robot_configs.py .. code-block:: python diff --git a/api/pytest.ini b/api/pytest.ini index add3cc70986..205778ea975 100644 --- a/api/pytest.ini +++ b/api/pytest.ini @@ -1,2 +1,5 @@ [pytest] -addopts = --cov --cov-report term-missing:skip-covered --cov-report xml:coverage.xml \ No newline at end of file +addopts = --cov --cov-report term-missing:skip-covered --cov-report xml:coverage.xml +markers = + api1_only: Test only functions using API version 1 (legacy_api) + api2_only: Test only functions using API version 2 (protocol API and hardware control) \ No newline at end of file diff --git a/api/src/opentrons/CHANGELOG.md b/api/src/opentrons/CHANGELOG.md index 6a54e868f25..84af75aa25c 100644 --- a/api/src/opentrons/CHANGELOG.md +++ b/api/src/opentrons/CHANGELOG.md @@ -3,6 +3,47 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + +### Bug Fixes + +* **api:** Fix bad P10S config causing under-aspirations ([#2774](https://github.com/Opentrons/opentrons/issues/2774)) ([9c5e0a2](https://github.com/Opentrons/opentrons/commit/9c5e0a2)) + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + + +### Bug Fixes + +* **shared-data:** fix total-liquid-volume of opentrons-tuberack-50ml ([#2744](https://github.com/Opentrons/opentrons/issues/2744)) ([aef8cc8](https://github.com/Opentrons/opentrons/commit/aef8cc8)), closes [#2743](https://github.com/Opentrons/opentrons/issues/2743) + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + + +### Features + +* **api:** Add 1.5ml tuberack to old labware definition section ([#2679](https://github.com/Opentrons/opentrons/issues/2679)) ([2739038](https://github.com/Opentrons/opentrons/commit/2739038)) +* **api:** Adds pipette models v1.4 to robot config ([#2689](https://github.com/Opentrons/opentrons/issues/2689)) ([fd9c38a](https://github.com/Opentrons/opentrons/commit/fd9c38a)) + + +### Performance Improvements + +* **api:** Decrease plunger motor max speed by 20% ([#2682](https://github.com/Opentrons/opentrons/issues/2682)) ([f8b7ccf](https://github.com/Opentrons/opentrons/commit/f8b7ccf)) + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/api/src/opentrons/__init__.py b/api/src/opentrons/__init__.py index f9fe8a63acd..e56d943f90d 100755 --- a/api/src/opentrons/__init__.py +++ b/api/src/opentrons/__init__.py @@ -1,10 +1,24 @@ import os import sys import json -from opentrons.data_storage import database_migration -from opentrons.config import feature_flags as ff - HERE = os.path.abspath(os.path.dirname(__file__)) +from opentrons.data_storage import database_migration # noqa(E402) +from opentrons.config import feature_flags as ff # noqa(E402) +if not ff.split_labware_definitions(): + database_migration.check_version_and_perform_necessary_migrations() + +import opentrons.hardware_control.adapters as adapters # noqa(E402) +from .protocol_api.back_compat import (build_globals as bcbuild, # noqa(E402) + set_globals, + reset as resetv2) +from .protocol_api.contexts import ProtocolContext # noqa(E402) +from .legacy_api.api import (robot as robotv1, # noqa(E402) + reset as resetv1, + instruments as instrumentsv1, + containers as containersv1, + labware as labwarev1, + modules as modulesv1) + try: with open(os.path.join(HERE, 'package.json')) as pkg: @@ -19,31 +33,46 @@ 'opentrons requires Python 3.5 or above, this is {0}.{1}'.format( version[0], version[1])) -if not ff.split_labware_definitions(): - database_migration.check_version_and_perform_necessary_migrations() -if ff.use_protocol_api_v2(): - import opentrons.hardware_control as hardware_control - try: - hardware = hardware_control.API.build_hardware_controller() - """ The global singleton of :py:class:`.hardware_control.API`. - - If this is running on a real robot (and no other Opentrons API server - is running and connected to the robot's hardware) it will be connected - to the actual hardware. Otherwise, it will be a simulator. - """ - except RuntimeError: - hardware = hardware_control.API.build_hardware_simulator() - from opentrons.protocol_api.back_compat\ - import robot, reset, instruments, containers, labware, modules -else: - from .legacy_api.api import (robot, # type: ignore - reset, # type: ignore - instruments, # type: ignore - containers, # type: ignore - labware, # type: ignore - modules) # type: ignore +def build_globals(version=None, loop=None): + if version is None: + checked_version = 2 if ff.use_protocol_api_v2() else 1 + else: + checked_version = version + if checked_version == 1: + return robotv1, resetv1, instrumentsv1, containersv1,\ + labwarev1, modulesv1, robotv1 + elif checked_version == 2: + hw = adapters.SingletonAdapter(loop) + rob, instr, con, lw, mod = bcbuild(hw, loop) + set_globals(rob, instr, lw, mod) + return rob, resetv2, instr, lw, lw, mod, hw + else: + raise RuntimeError("Bad API version {}; only 1 and 2 are valid" + .format(version)) + + +def reset_globals(version=None, loop=None): + """ Reinitialize the global singletons with a given API version. + + :param version: 1 or 2. If `None`, pulled from the `useProtocolApiV2` + advanced setting. + """ + global containers + global instruments + global labware + global robot + global reset + global modules + global hardware + + robot, reset, instruments, containers, labware, modules, hardware\ + = build_globals(version, loop) + + +robot, reset, instruments, containers, labware, modules, hardware\ + = build_globals() __all__ = ['containers', 'instruments', 'labware', 'robot', 'reset', - '__version__', 'modules'] + '__version__', 'modules', 'hardware', 'HERE'] diff --git a/api/src/opentrons/api/calibration.py b/api/src/opentrons/api/calibration.py index cbb0867e4b3..5b89ff60d09 100755 --- a/api/src/opentrons/api/calibration.py +++ b/api/src/opentrons/api/calibration.py @@ -19,7 +19,8 @@ class CalibrationManager: """ TOPIC = 'calibration' - def __init__(self, loop=None): + def __init__(self, hardware, loop=None): + self._hardware = hardware self._loop = loop self.state = None diff --git a/api/src/opentrons/api/routers.py b/api/src/opentrons/api/routers.py index 1d7a70e59f9..a4904f47558 100644 --- a/api/src/opentrons/api/routers.py +++ b/api/src/opentrons/api/routers.py @@ -4,7 +4,7 @@ class MainRouter: - def __init__(self, loop=None): + def __init__(self, hardware=None, loop=None): self._notifications = Notifications(loop=loop) self._unsubscribe = [] self._unsubscribe += [subscribe( @@ -14,8 +14,9 @@ def __init__(self, loop=None): CalibrationManager.TOPIC, self._notifications.on_notify)] - self.session_manager = SessionManager(loop=loop) - self.calibration_manager = CalibrationManager(loop=loop) + self.session_manager = SessionManager(hardware) + self.calibration_manager = CalibrationManager(hardware=hardware, + loop=loop) @property def notifications(self): diff --git a/api/src/opentrons/api/session.py b/api/src/opentrons/api/session.py index bb1d6b23a9d..d4394e8e7f0 100755 --- a/api/src/opentrons/api/session.py +++ b/api/src/opentrons/api/session.py @@ -1,4 +1,5 @@ import ast +import asyncio import logging from copy import copy from time import time @@ -10,7 +11,7 @@ from opentrons.legacy_api.containers.placeable import Module as ModulePlaceable from opentrons.commands import tree, types from opentrons.protocols import execute_protocol -from opentrons import robot, modules +from opentrons.config import feature_flags as ff from .models import Container, Instrument, Module @@ -20,33 +21,32 @@ class SessionManager(object): - def __init__(self, loop=None): + def __init__(self, hardware): self.session = None self._session_lock = False - for module in robot.modules: - module.disconnect() - robot.modules = modules.discover_and_connect() + self._hardware = hardware - def create(self, name, text): + async def create(self, name, text): if self._session_lock: raise Exception( 'Cannot create session while simulation in progress') self._session_lock = True try: - self.session = Session(name=name, text=text) + self.session = await Session.build_and_prep( + name=name, text=text, hardware=self._hardware) finally: self._session_lock = False return self.session - def clear(self): + async def clear(self): if self._session_lock: raise Exception( 'Cannot clear session while simulation in progress') if self.session: - robot.reset() + self._hardware.reset() self.session = None def get_session(self): @@ -56,10 +56,17 @@ def get_session(self): class Session(object): TOPIC = 'session' - def __init__(self, name, text): + @classmethod + async def build_and_prep(cls, name, text, hardware): + sess = cls(name, text, hardware) + await sess.prepare() + return sess + + def __init__(self, name, text, hardware): self.name = name self.protocol_text = text self._protocol = None + self._hardware = hardware self.state = None self.commands = [] self.command_log = {} @@ -76,10 +83,12 @@ def __init__(self, name, text): self.startTime = None - for module in robot.modules: - module.disconnect() - robot.modules = modules.discover_and_connect() - self.refresh() + async def prepare(self): + if ff.use_protocol_api_v2(): + await self._hardware.discover_modules() + else: + self._hardware.discover_modules() + await self.refresh() def get_instruments(self): return [ @@ -117,8 +126,11 @@ def clear_logs(self): self.command_log.clear() self.errors.clear() - def _simulate(self): - self._reset() + async def _simulate(self): + if ff.use_protocol_api_v2(): + raise NotImplementedError( + "Need to implement new api in protocols") + await self._reset() stack = [] res = [] @@ -153,11 +165,13 @@ def on_command(message): try: # ensure actual pipettes are cached before driver is disconnected - robot.cache_instrument_models() - # TODO (artyom, 20171005): this will go away - # once robot / driver simulation flow is fixed - robot.disconnect() + self._hardware.cache_instrument_models() + + if not ff.use_protocol_api_v2(): + # TODO (artyom, 20171005): this will go away + # once robot / driver simulation flow is fixed + self._hardware.disconnect() if self._is_json_protocol: execute_protocol(self._protocol) else: @@ -166,7 +180,8 @@ def on_command(message): # physically attached pipettes are re-cached during robot.connect() # which is important, because during a simulation, the robot could # think that it holds a pipette model that it actually does not - robot.connect() + if not ff.use_protocol_api_v2(): + self._hardware.connect() unsubscribe() instruments, containers, modules, interactions = _accumulate( @@ -181,12 +196,13 @@ def on_command(message): # we have to clear the tips if they are left on after simulation # to ensure that the instruments are in the expected state at the # beginning of the labware calibration flow - robot.clear_tips() + if not ff.use_protocol_api_v2(): + self._hardware.clear_tips() return res - def refresh(self): - self._reset() + async def refresh(self): + await self._reset() self._is_json_protocol = self.name.endswith('.json') if self._is_json_protocol: @@ -196,35 +212,32 @@ def refresh(self): else: parsed = ast.parse(self.protocol_text) self._protocol = compile(parsed, filename=self.name, mode='exec') - commands = self._simulate() + commands = await self._simulate() self.commands = tree.from_list(commands) self.containers = self.get_containers() self.instruments = self.get_instruments() self.modules = self.get_modules() self.startTime = None - self.set_state('loaded') - return self def stop(self): - robot.stop() + self._hardware.stop() self.set_state('stopped') return self def pause(self): - robot.pause() + self._hardware.pause() self.set_state('paused') return self def resume(self): - - robot.resume() + self._hardware.resume() self.set_state('running') return self - def run(self): + async def run(self): def on_command(message): if message['$'] == 'before': self.log_append() @@ -233,7 +246,10 @@ def on_command(message): if message['name'] == types.RESUME: self.set_state('running') - self._reset() + if ff.use_protocol_api_v2(): + raise NotImplementedError("Need to implement new API in protocols") + + await self._reset() _unsubscribe = subscribe(types.COMMAND, on_command) self.startTime = now() @@ -241,13 +257,13 @@ def on_command(message): try: self.resume() - self._pre_run_hooks() + await self._pre_run_hooks() if self._is_json_protocol: execute_protocol(self._protocol) else: exec(self._protocol, {}) self.set_state('finished') - robot.home() + self._hardware.home() except Exception as e: log.exception("Exception during run:") self.error_append(e) @@ -258,14 +274,17 @@ def on_command(message): return self - def identify(self): - robot.identify() + async def identify(self): + if ff.use_protocol_api_v2(): + asyncio.ensure_future(self._hardware.identify()) + else: + self._hardware.identify() def turn_on_rail_lights(self): - robot.turn_on_rail_lights() + self._hardware.set_lights(rails=True) def turn_off_rail_lights(self): - robot.turn_off_rail_lights() + self._hardware.set_lights(rails=False) def set_state(self, state): log.debug("State set to {}".format(state)) @@ -290,8 +309,11 @@ def error_append(self, error): ) # self._on_state_changed() - def _reset(self): - robot.reset() + async def _reset(self): + if ff.use_protocol_api_v2(): + await self._hardware.reset() + else: + self._hardware.reset() self.clear_logs() def _snapshot(self): @@ -318,8 +340,11 @@ def _snapshot(self): def _on_state_changed(self): publish(Session.TOPIC, self._snapshot()) - def _pre_run_hooks(self): - robot.home_z() + async def _pre_run_hooks(self): + if ff.use_protocol_api_v2(): + await self._hardware.home_z() + else: + self._hardware.home_z() def _accumulate(iterable): diff --git a/api/src/opentrons/broker/broker.py b/api/src/opentrons/broker/broker.py index 48343a188df..4ef1ebbd552 100644 --- a/api/src/opentrons/broker/broker.py +++ b/api/src/opentrons/broker/broker.py @@ -1,7 +1,6 @@ import asyncio from asyncio import Queue -from concurrent import futures from contextlib import contextmanager subscriptions: dict = {} @@ -22,22 +21,9 @@ def snooze(self): self.snoozed = False def on_notify(self, message): - def thread_has_event_loop(): - try: - asyncio.get_event_loop() - except RuntimeError: - return False - else: - return True - if self.snoozed: return - - future = asyncio.run_coroutine_threadsafe( - self.queue.put(message), self.loop) - - if not thread_has_event_loop(): - futures.wait([future]) + self.queue.put_nowait(message) async def __anext__(self): return await self.queue.get() diff --git a/api/src/opentrons/config/containers/default-containers.json b/api/src/opentrons/config/containers/default-containers.json index c457105d50f..c06b9c220cd 100644 --- a/api/src/opentrons/config/containers/default-containers.json +++ b/api/src/opentrons/config/containers/default-containers.json @@ -23045,7 +23045,7 @@ "z": 6.95, "depth": 112.85, "diameter": 17, - "total-liquid-volume": 15000 + "total-liquid-volume": 50000 }, "B1": { "x": 35, @@ -23053,7 +23053,7 @@ "z": 6.95, "depth": 112.85, "diameter": 17, - "total-liquid-volume": 15000 + "total-liquid-volume": 50000 }, "A2": { "x": 0, @@ -23061,7 +23061,7 @@ "z": 6.95, "depth": 112.85, "diameter": 17, - "total-liquid-volume": 15000 + "total-liquid-volume": 50000 }, "B2": { "x": 35, @@ -23069,7 +23069,7 @@ "z": 6.95, "depth": 112.85, "diameter": 17, - "total-liquid-volume": 15000 + "total-liquid-volume": 50000 }, "A3": { "x": 0, @@ -23077,7 +23077,7 @@ "z": 6.95, "depth": 112.85, "diameter": 17, - "total-liquid-volume": 15000 + "total-liquid-volume": 50000 }, "B3": { "x": 35, @@ -23085,7 +23085,7 @@ "z": 6.95, "depth": 112.85, "diameter": 17, - "total-liquid-volume": 15000 + "total-liquid-volume": 50000 } } }, @@ -23580,6 +23580,208 @@ } } }, + + "opentrons-tuberack-1.5ml-eppendorf": { + "origin-offset": { + "x": 21.07, + "y": 18.21 + }, + "locations": { + "A1": { + "x": 0, + "y": 0, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "B1": { + "x": 19.28, + "y": 0, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "C1": { + "x": 38.56, + "y": 0, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "D1": { + "x": 57.84, + "y": 0, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "A2": { + "x": 0, + "y": 19.89, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "B2": { + "x": 19.28, + "y": 19.89, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "C2": { + "x": 38.56, + "y": 19.89, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "D2": { + "x": 57.84, + "y": 19.89, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "A3": { + "x": 0, + "y": 39.78, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "B3": { + "x": 19.28, + "y": 39.78, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "C3": { + "x": 38.56, + "y": 39.78, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "D3": { + "x": 57.84, + "y": 39.78, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "A4": { + "x": 0, + "y": 59.67, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "B4": { + "x": 19.28, + "y": 59.67, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "C4": { + "x": 38.56, + "y": 59.67, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "D4": { + "x": 57.84, + "y": 59.67, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "A5": { + "x": 0, + "y": 79.56, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "B5": { + "x": 19.28, + "y": 79.56, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "C5": { + "x": 38.56, + "y": 79.56, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "D5": { + "x": 57.84, + "y": 79.56, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "A6": { + "x": 0, + "y": 99.45, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "B6": { + "x": 19.28, + "y": 99.45, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "C6": { + "x": 38.56, + "y": 99.45, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + }, + "D6": { + "x": 57.84, + "y": 99.45, + "z": 43.3, + "depth": 37.0, + "diameter": 9, + "total-liquid-volume": 1500 + } + } + }, + "opentrons-aluminum-block-2ml-eppendorf": { "origin-offset": { "x": 25.88, diff --git a/api/src/opentrons/config/robot_configs.py b/api/src/opentrons/config/robot_configs.py index 6d71d78724f..fb49576f18a 100755 --- a/api/src/opentrons/config/robot_configs.py +++ b/api/src/opentrons/config/robot_configs.py @@ -52,8 +52,8 @@ Y_MAX_SPEED = 400 Z_MAX_SPEED = 125 A_MAX_SPEED = 125 -B_MAX_SPEED = 50 -C_MAX_SPEED = 50 +B_MAX_SPEED = 40 +C_MAX_SPEED = 40 DEFAULT_MAX_SPEEDS = { 'X': X_MAX_SPEED, diff --git a/api/src/opentrons/drivers/rpi_drivers/gpio.py b/api/src/opentrons/drivers/rpi_drivers/gpio.py index ee6232494d8..aba1a2de05c 100755 --- a/api/src/opentrons/drivers/rpi_drivers/gpio.py +++ b/api/src/opentrons/drivers/rpi_drivers/gpio.py @@ -1,5 +1,6 @@ from os import system from sys import platform +from typing import Tuple """ Raspberry Pi GPIO control module @@ -150,3 +151,47 @@ def initialize(): for pin in sorted(INPUT_PINS.values()): _enable_pin(pin, IN) + + +def turn_on_blue_button_light(): + set_button_light(blue=True) + + +def set_button_light(red=False, green=False, blue=False): + color_pins = { + OUTPUT_PINS['RED_BUTTON']: red, + OUTPUT_PINS['GREEN_BUTTON']: green, + OUTPUT_PINS['BLUE_BUTTON']: blue + } + for pin, state in color_pins.items(): + if state: + set_high(pin) + else: + set_low(pin) + + +def get_button_light() -> Tuple[bool, bool, bool]: + return (read(OUTPUT_PINS['RED_BUTTON']) == 1, + read(OUTPUT_PINS['GREEN_BUTTON']) == 1, + read(OUTPUT_PINS['BLUE_BUTTON']) == 1) + + +def set_rail_lights(on=True): + if on: + set_high(OUTPUT_PINS['FRAME_LEDS']) + else: + set_low(OUTPUT_PINS['FRAME_LEDS']) + + +def get_rail_lights() -> bool: + value = read(OUTPUT_PINS['FRAME_LEDS']) + return True if value == 1 else False + + +def read_button(): + # button is normal-HIGH, so invert + return not bool(read(INPUT_PINS['BUTTON_INPUT'])) + + +def read_window_switches(): + return bool(read(INPUT_PINS['WINDOW_INPUT'])) diff --git a/api/src/opentrons/drivers/smoothie_drivers/driver_3_0.py b/api/src/opentrons/drivers/smoothie_drivers/driver_3_0.py index a743e6e5ad2..fe265e05c96 100755 --- a/api/src/opentrons/drivers/smoothie_drivers/driver_3_0.py +++ b/api/src/opentrons/drivers/smoothie_drivers/driver_3_0.py @@ -1,13 +1,15 @@ +import asyncio from os import environ import logging from time import sleep from threading import Event -from typing import Dict, Optional +from typing import Any, Dict, Optional from serial.serialutil import SerialException from opentrons.drivers import serial_communication from opentrons.drivers.rpi_drivers import gpio +from opentrons.system import smoothie_update ''' - Driver is responsible for providing an interface for motion control - Driver is the only system component that knows about GCODES or how smoothie @@ -1305,44 +1307,39 @@ def probe_axis(self, axis, probing_distance) -> Dict[str, float]: else: raise RuntimeError("Cant probe axis {}".format(axis)) - # TODO (ben 20180320): we should probably move these to the gpio driver def turn_on_blue_button_light(self): - self._set_button_light(blue=True) + gpio.set_button_light(blue=True) def turn_on_red_button_light(self): - self._set_button_light(red=True) + gpio.set_button_light(red=True) def turn_off_button_light(self): - self._set_button_light(red=False, green=False, blue=False) - - def _set_button_light(self, red=False, green=False, blue=False): - color_pins = { - gpio.OUTPUT_PINS['RED_BUTTON']: red, - gpio.OUTPUT_PINS['GREEN_BUTTON']: green, - gpio.OUTPUT_PINS['BLUE_BUTTON']: blue - } - for pin, state in color_pins.items(): - if state: - gpio.set_high(pin) - else: - gpio.set_low(pin) + gpio.set_button_light(red=False, green=False, blue=False) def turn_on_rail_lights(self): - gpio.set_high(gpio.OUTPUT_PINS['FRAME_LEDS']) + gpio.set_rail_lights(True) def turn_off_rail_lights(self): - gpio.set_low(gpio.OUTPUT_PINS['FRAME_LEDS']) + gpio.set_rail_lights(False) def get_rail_lights_on(self): - value = gpio.read(gpio.OUTPUT_PINS['FRAME_LEDS']) - return True if value == 1 else False + return gpio.get_rail_lights() def read_button(self): - # button is normal-HIGH, so invert - return not bool(gpio.read(gpio.INPUT_PINS['BUTTON_INPUT'])) + return gpio.read_button() def read_window_switches(self): - return bool(gpio.read(gpio.INPUT_PINS['WINDOW_INPUT'])) + return gpio.read_window_switches() + + def set_lights(self, button=None, rails=None): + if button is not None: + gpio.set_button_light(blue=button) + if rails is not None: + gpio.set_rail_lights(rails) + + def get_lights(self): + return {'button': gpio.get_button_light()[2], + 'rails': gpio.get_rail_lights()} def kill(self): """ @@ -1410,4 +1407,56 @@ def _smoothie_hard_halt(self): gpio.set_high(gpio.OUTPUT_PINS['HALT']) sleep(0.25) + async def update_firmware(self, + filename: str, + loop: asyncio.AbstractEventLoop = None, + explicit_modeset: bool = True) -> str: + """ + Program the smoothie board with a given hex file. + + If explicit_modeset is True (default), explicitly place the smoothie in + programming mode. + + If explicit_modeset is False, assume the smoothie is already in + programming mode. + """ + # ensure there is a reference to the port + if self.simulating: + return 'Did nothing (simulating)' + + smoothie_update._ensure_programmer_executable() + + if not self.is_connected(): + self._connect_to_port() + + # get port name + port = self._connection.port + + if explicit_modeset: + # set smoothieware into programming mode + self._smoothie_programming_mode() + # close the port so other application can access it + self._connection.close() + + # run lpc21isp, THIS WILL TAKE AROUND 1 MINUTE TO COMPLETE + update_cmd = 'lpc21isp -wipe -donotstart {0} {1} {2} 12000'.format( + filename, port, self._config.serial_speed) + kwargs: Dict[str, Any] = {'stdout': asyncio.subprocess.PIPE} + if loop: + kwargs['loop'] = loop + proc = await asyncio.create_subprocess_shell( + update_cmd, **kwargs) + rd: bytes = await proc.stdout.read() # type: ignore + res = rd.decode().strip() + await proc.communicate() + + # re-open the port + self._connection.open() + # reset smoothieware + self._smoothie_reset() + # run setup gcodes + self._setup() + + return res + # ----------- END Public interface ------------ # diff --git a/api/src/opentrons/hardware_control/__init__.py b/api/src/opentrons/hardware_control/__init__.py index 58c21fdf613..afab82d721d 100644 --- a/api/src/opentrons/hardware_control/__init__.py +++ b/api/src/opentrons/hardware_control/__init__.py @@ -26,7 +26,7 @@ # implies windows Controller = None # type: ignore from . import modules -from .types import Axis +from .types import Axis, HardwareAPILike, CriticalPoint mod_log = logging.getLogger(__name__) @@ -52,7 +52,7 @@ class MustHomeError(RuntimeError): DROP_TIP_RELEASE_DISTANCE = 20 -class API: +class API(HardwareAPILike): """ This API is the primary interface to the hardware controller. Because the hardware manager controls access to the system's hardware @@ -93,22 +93,32 @@ def __init__(self, self._last_moved_mount: Optional[top_types.Mount] = None @classmethod - def build_hardware_controller( + async def build_hardware_controller( cls, config: robot_configs.robot_config = None, port: str = None, - loop: asyncio.AbstractEventLoop = None) -> 'API': + loop: asyncio.AbstractEventLoop = None, + force: bool = False) -> 'API': """ Build a hardware controller that will actually talk to hardware. This method should not be used outside of a real robot, and on a real robot only one true hardware controller may be active at one time. + + :param config: A config to preload. If not specified, load the default. + :param port: A port to connect to. If not specified, the default port + (found by scanning for connected FT232Rs). + :param loop: An event loop to use. If not specified, use the result of + :py:meth:`asyncio.get_event_loop`. + :param force: If `True`, connect even if a lockfile is present. See + :py:meth:`Controller.__init__`. """ if None is Controller: raise RuntimeError( 'The hardware controller may only be instantiated on a robot') - backend = Controller(config, loop) - backend.connect(port) - return cls(backend, config=config, loop=loop) + checked_loop = loop or asyncio.get_event_loop() + backend = Controller(config, checked_loop, force=force) + await backend.connect(port) + return cls(backend, config=config, loop=checked_loop) @classmethod def build_hardware_simulator( @@ -132,33 +142,67 @@ def build_hardware_simulator( config, loop), config=config, loop=loop) + @property + def loop(self) -> asyncio.AbstractEventLoop: + """ The event loop used by this instance. """ + return self._loop + + @property + def is_simulator(self) -> bool: + """ `True` if this is a simulator; `False` otherwise. """ + return isinstance(self._backend, Simulator) + # Query API - @_log_call - def get_connected_hardware(self): - """ Get the cached hardware connected to the robot. + @property + def fw_version(self) -> str: + """ Return the firmware version of the connected hardware. + + The version is a string retrieved directly from the attached hardware + (or possibly simulator). """ - pass + from_backend = self._backend.fw_version + if from_backend is None: + return 'unknown' + else: + return from_backend # Incidentals (i.e. not motion) API @_log_call - async def turn_on_button_light(self): - pass + def set_lights(self, button: bool = None, rails: bool = None): + """ Control the robot lights. - @_log_call - async def turn_off_button_light(self): - pass + :param button: If specified, turn the button light on (`True`) or + off (`False`). If not specified, do not change the + button light. + :param rails: If specified, turn the rail lights on (`True`) or + off (`False`). If not specified, do not change the + rail lights. + """ + self._backend.set_lights(button, rails) @_log_call - async def turn_on_rail_lights(self): - pass + def get_lights(self) -> Dict[str, bool]: + """ Return the current status of the robot lights. - @_log_call - async def turn_off_rail_lights(self): - pass + :returns: A dict of the lights: `{'button': bool, 'rails': bool}` + """ + return self._backend.get_lights() @_log_call - async def identify(self, seconds): - pass + async def identify(self, duration_s: int = 5): + """ Blink the button light to identify the robot. + + :param int duration_s: The duration to blink for, in seconds. + """ + count = duration_s * 4 + on = False + for sec in range(count): + then = self._loop.time() + self.set_lights(button=on) + on = not on + now = self._loop.time() + await asyncio.sleep(max(0, 0.25-(now-then))) + self.set_lights(button=True) @_log_call async def cache_instruments(self, @@ -190,7 +234,8 @@ async def cache_instruments(self, def attached_instruments(self): configs = ['name', 'min_volume', 'max_volume', 'channels', 'aspirate_flow_rate', 'dispense_flow_rate', - 'pipette_id', 'current_volume', 'display_name'] + 'pipette_id', 'current_volume', 'display_name', + 'tip_length'] instruments = {top_types.Mount.LEFT: {}, top_types.Mount.RIGHT: {}} for mount in top_types.Mount: @@ -202,26 +247,78 @@ def attached_instruments(self): instruments[mount][key] = instr_dict[key] return instruments + @property + def attached_modules(self): + return self._attached_modules + @_log_call - async def update_smoothie_firmware(self, firmware_file): - pass + async def update_firmware( + self, + firmware_file: str, + loop: asyncio.AbstractEventLoop = None, + explicit_modeset: bool = True) -> str: + """ Update the firmware on the Smoothie board. + + :param firmware_file: The path to the firmware file. + :param explicit_modeset: `True` to force the smoothie into programming + mode; `False` to assume it is already in + programming mode. + :param loop: An asyncio event loop to use; if not specified, the one + associated with this instance will be used. + :returns: The stdout of the tool used to update the smoothie + """ + if None is loop: + checked_loop = self._loop + else: + checked_loop = loop + return await self._backend.update_firmware(firmware_file, + checked_loop, + explicit_modeset) # Global actions API @_log_call - async def pause(self): - pass + def pause(self): + """ + Pause motion of the robot after a current motion concludes. + + Individual calls to :py:meth:`move` + (which :py:meth:`aspirate` and :py:meth:`dispense` and other + calls may depend on) are considered atomic and will always complete if + they have been called prior to a call to this method. However, + subsequent calls to :py:meth:`move` that occur when the system + is paused will not proceed until the system is resumed with + :py:meth:`resume`. + """ + self._backend.pause() @_log_call - async def resume(self): - pass + def resume(self): + """ + Resume motion after a call to :py:meth:`pause`. + """ + self._backend.resume() @_log_call async def halt(self): - pass + """ Immediately stop motion, reset, and home. + + This will cancel motion (after the current call to :py:meth:`move`; + see :py:meth:`pause` for more detail), then home and reset the + robot. + """ + self._backend.halt() + await self.reset() + await self.home() @_log_call async def reset(self): - pass + """ Reset the stored state of the system. + + This will re-scan instruments and models, clearing any cached + information about their presence or state. + """ + await self.cache_instruments() + await self.discover_modules() # Gantry/frame (i.e. not pipette) action API @_log_call @@ -260,8 +357,15 @@ async def home(self, axes: List[Axis] = None): """ # Initialize/update current_position checked_axes = axes or [ax for ax in Axis] - smoothie_axes = [ax.name.upper() for ax in checked_axes] - smoothie_pos = self._backend.home(smoothie_axes) + gantry = [ax for ax in checked_axes if ax in Axis.gantry_axes()] + smoothie_gantry = [ax.name.upper() for ax in gantry] + smoothie_pos = {} + if smoothie_gantry: + smoothie_pos.update(self._backend.home(smoothie_gantry)) + plungers = [ax for ax in checked_axes if ax not in Axis.gantry_axes()] + smoothie_plungers = [ax.name.upper() for ax in plungers] + if smoothie_plungers: + smoothie_pos.update(self._backend.home(smoothie_plungers)) self._current_position = self._deck_from_smoothie(smoothie_pos) def _deck_from_smoothie( @@ -305,12 +409,23 @@ def _deck_from_smoothie( deck_pos.update(plunger_axes) return deck_pos - def current_position(self, mount: top_types.Mount) -> Dict[Axis, float]: + def current_position( + self, + mount: top_types.Mount, + critical_point: CriticalPoint = None) -> Dict[Axis, float]: """ Return the postion (in deck coords) of the critical point of the specified mount. This returns cached position to avoid hitting the smoothie driver unless ``refresh`` is ``True``. + + If `critical_point` is specified, that critical point will be applied + instead of the default one. For instance, if + `critical_point=CriticalPoints.MOUNT` then the position of the mount + will be returned. If the critical point specified does not exist, then + the next one down is returned - for instance, if there is no tip on the + specified mount but `CriticalPoint.TIP` was specified, the position of + the nozzle will be returned. """ if not self._current_position: raise MustHomeError @@ -320,7 +435,7 @@ def current_position(self, mount: top_types.Mount) -> Dict[Axis, float]: offset = top_types.Point(*self.config.mount_offset) z_ax = Axis.by_mount(mount) plunger_ax = Axis.of_plunger(mount) - cp = self._critical_point_for(mount) + cp = self._critical_point_for(mount, critical_point) return { Axis.X: self._current_position[Axis.X] + offset[0] + cp.x, Axis.Y: self._current_position[Axis.Y] + offset[1] + cp.y, @@ -328,13 +443,19 @@ def current_position(self, mount: top_types.Mount) -> Dict[Axis, float]: plunger_ax: self._current_position[plunger_ax] } - def gantry_position(self, mount: top_types.Mount) -> top_types.Point: + def gantry_position( + self, + mount: top_types.Mount, + critical_point: CriticalPoint = None) -> top_types.Point: """ Return the position of the critical point as pertains to the gantry This ignores the plunger position and gives the Z-axis a predictable name (as :py:attr:`.Point.z`). + + `critical_point` specifies an override to the current critical point to + use (see :py:meth:`current_position`). """ - cur_pos = self.current_position(mount) + cur_pos = self.current_position(mount, critical_point) return top_types.Point(x=cur_pos[Axis.X], y=cur_pos[Axis.Y], z=cur_pos[Axis.by_mount(mount)]) @@ -342,7 +463,8 @@ def gantry_position(self, mount: top_types.Mount) -> top_types.Point: @_log_call async def move_to( self, mount: top_types.Mount, abs_position: top_types.Point, - speed: float = None): + speed: float = None, + critical_point: CriticalPoint = None): """ Move the critical point of the specified mount to a location relative to the deck, at the specified speed. 'speed' sets the speed of all robot axes to the given value. So, if multiple axes are to be @@ -359,6 +481,20 @@ async def move_to( pipette tip, the critical point is the end of the pipette tip for a single pipette or the end of the tip of the backmost nozzle of a multipipette + + :param mount: The mount to move + :param abs_position: The target absolute position in + :ref:`protocol-api-deck-coords` to move the + critical point to + :param speed: An overall head speed to use during the move + :param critical_point: The critical point to move. In most situations + this is not needed. If not specified, the + current critical point will be moved. If + specified, the critical point must be one that + actually exists - that is, specifying + :py:attr:`.CriticalPoint.NOZZLE` when no pipette + is attached or :py:attr:`.CriticalPoint.TIP` + when no tip is applied will result in an error. """ if not self._current_position: raise MustHomeError @@ -370,7 +506,7 @@ async def move_to( offset = top_types.Point(*self.config.mount_offset) else: offset = top_types.Point(0, 0, 0) - cp = self._critical_point_for(mount) + cp = self._critical_point_for(mount, critical_point) target_position = OrderedDict( ((Axis.X, abs_position.x - offset.x - cp.x), (Axis.Y, abs_position.y - offset.y - cp.y), @@ -432,12 +568,12 @@ async def _move_plunger(self, mount: top_types.Mount, dist: float, (pl_axis, dist)) ) try: - await self._move(all_axes_pos, speed) + await self._move(all_axes_pos, speed, False) except KeyError: raise MustHomeError async def _move(self, target_position: 'OrderedDict[Axis, float]', - speed: float = None): + speed: float = None, home_flagged_axes: bool = True): """ Worker function to apply robot motion. Robot motion means the kind of motions that are relevant to the robot, @@ -502,7 +638,8 @@ async def _move(self, target_position: 'OrderedDict[Axis, float]', deck_mins[ax], deck_max[ax], bounds[ax.name][0], bounds[ax.name][1])) try: - self._backend.move(smoothie_pos, speed=speed) + self._backend.move(smoothie_pos, speed=speed, + home_flagged_axes=home_flagged_axes) except Exception: self._log.exception('Move failed') self._current_position.clear() @@ -510,6 +647,15 @@ async def _move(self, target_position: 'OrderedDict[Axis, float]', else: self._current_position.update(target_position) + @property + def engaged_axes(self) -> Dict[Axis, bool]: + """ Which axes are engaged and holding. """ + return {Axis[ax]: eng + for ax, eng in self._backend.engaged_axes().items()} + + async def disengage_axes(self, which: List[Axis]): + self._backend.disengage_axes([ax.name for ax in which]) + @_log_call async def retract(self, mount: top_types.Mount, margin: float): """ Pull the specified mount up to its home position. @@ -520,16 +666,21 @@ async def retract(self, mount: top_types.Mount, margin: float): smoothie_pos = self._backend.fast_home(smoothie_ax, margin) self._current_position = self._deck_from_smoothie(smoothie_pos) - def _critical_point_for(self, mount: top_types.Mount) -> top_types.Point: + def _critical_point_for( + self, mount: top_types.Mount, + cp_override: CriticalPoint = None) -> top_types.Point: """ Return the current critical point of the specified mount. The mount's critical point is the position of the mount itself, if no pipette is attached, or the pipette's critical point (which depends on tip status). + + If `cp_override` is specified, and that critical point actually exists, + it will be used instead. Invalid `cp_override`s are ignored. """ pip = self._attached_instruments[mount] - if pip is not None: - return pip.critical_point + if pip is not None and cp_override != CriticalPoint.MOUNT: + return pip.critical_point(cp_override) else: # TODO: The smoothie’s z/a home position is calculated to provide # the offset for a P300 single. Here we should decide whether we diff --git a/api/src/opentrons/hardware_control/adapters.py b/api/src/opentrons/hardware_control/adapters.py index c2dbf8b55bf..6a394c4b284 100644 --- a/api/src/opentrons/hardware_control/adapters.py +++ b/api/src/opentrons/hardware_control/adapters.py @@ -1,18 +1,19 @@ """ Adapters for the :py:class:`.hardware_control.API` instances. """ import asyncio +import copy import functools -from typing import TYPE_CHECKING +from typing import List -if TYPE_CHECKING: - import hardware_control # noqa(F401): Avoid circular dependency +from . import API +from .types import Axis, HardwareAPILike def sync_call(loop, to_call, *args, **kwargs): - loop.run_until_complete(to_call(*args, **kwargs)) + return loop.run_until_complete(to_call(*args, **kwargs)) -class SynchronousAdapter: +class SynchronousAdapter(HardwareAPILike): """ A wrapper to make every call into :py:class:`.hardware_control.API` synchronous. @@ -26,7 +27,7 @@ class SynchronousAdapter: >>> synch.home() """ - def __init__(self, api: 'hardware_control.API') -> None: + def __init__(self, api: API) -> None: """ Build the SynchronousAdapter. :param api: The API instance to wrap @@ -55,3 +56,86 @@ def __getattribute__(self, attr_name): return functools.partial(sync_call, loop, attr) return attr + + +class SingletonAdapter(HardwareAPILike): + """ A wrapper to use as a global singleton to control hardware. + + This wrapper adds some useful utility functions to defer initialization + of true hardware controllers (to cut down on work at module import time) + and in general ease the transition away from the direct use of the old + robot singleton. + + When the :py:class:`SingletonAdapter` is initialized, it will make a + hardware simulator instance. When :py:meth:`connect` is called, this + simulator will be replaced with a new controller that connects to the + hardware with the specified arguments. + + Attribute accesses are passed on to the embedded + :py:class:`.hardware_control.API`. + """ + + def __init__(self, loop: asyncio.AbstractEventLoop = None) -> None: + self._api = API.build_hardware_simulator(loop=loop) + + def __getattr__(self, attr_name): + return getattr(self._api, attr_name) + + def connect(self, port: str = None, force: bool = False): + """ Connect to hardware. + + :param port: The port to connect to. May be `None`, in which case the + hardware will connect to the first serial port it sees + with the device name `FT232R`; or port name compatible + with `serial.Serial`_. # noqa(E501) + :param force: If `True`, connect even if a lockfile is established. See + :py:meth:`.controller.Controller.__init__`. This should + only ever be specified as `True` by the main software + starting. + """ + old_api = object.__getattribute__(self, '_api') + loop = old_api._loop + new_api = loop.run_until_complete(API.build_hardware_controller( + loop=loop, + port=port, + config=copy.copy(old_api.config), + force=force)) + old_api._loop.run_until_complete(new_api.cache_instruments()) + setattr(self, '_api', new_api) + + def disconnect(self): + """ Disconnect from connected hardware. """ + old_api = object.__getattribute__(self, '_api') + new_api = API.build_hardware_simulator( + loop=old_api._loop, + config=copy.copy(old_api.config)) + setattr(self, '_api', new_api) + + def is_connected(self): + """ `True` if connected (e.g. has a real controller backing it). """ + api = object.__getattribute__(self, '_api') + return api.is_simulator + + async def disengage_axes(self, which: List[str]): + api = object.__getattribute__(self, '_api') + await api.disengage_axes([Axis[ax.upper()] for ax in which]) + + def get_attached_pipettes(self): + """ Mimic the behavior of robot.get_attached_pipettes""" + api = object.__getattribute__(self, '_api') + instrs = {} + for mount, data in api.attached_instruments.items(): + instrs[mount.name.lower()] = { + 'model': data.get('name', None), + 'id': data.get('pipette_id', None), + 'mount_axis': Axis.by_mount(mount), + 'plunger_axis': Axis.of_plunger(mount) + } + if data.get('name'): + instrs[mount.name.lower()]['tip_length'] \ + = data.get('tip_length', None) + + return instrs + + def stop(self): + self._api._loop.run_until_complete(self._api.halt()) diff --git a/api/src/opentrons/hardware_control/controller.py b/api/src/opentrons/hardware_control/controller.py index 88d85becb5c..987f33bb93b 100644 --- a/api/src/opentrons/hardware_control/controller.py +++ b/api/src/opentrons/hardware_control/controller.py @@ -1,15 +1,17 @@ import asyncio -import os +from contextlib import contextmanager import fcntl +import os import threading from typing import Any, Dict, List, Optional, Tuple + from opentrons.util import environment from opentrons.drivers.smoothie_drivers import driver_3_0 +from opentrons.drivers.rpi_drivers import gpio from opentrons.config import robot_configs from opentrons.types import Mount -from contextlib import contextmanager -from . import modules +from . import modules _lock = threading.Lock() @@ -22,7 +24,7 @@ class _Locker: """ LOCK_FILE_PATH = environment.settings['HARDWARE_CONTROLLER_LOCKFILE'] - def __init__(self): + def __init__(self, force=False): global _lock self._thread_lock_acquired = _lock.acquire(blocking=False) @@ -56,21 +58,35 @@ class Controller: may be active at any time. """ - def __init__(self, config, loop): + def __init__(self, config, loop, force=False): """ Build a Controller instance. If another controller is already instantiated on the system (or if this is instantiated somewhere other than a robot) then this method will raise a RuntimeError. + + If `force` is specified as `True`, delete the lockfile and connect + anyway. This is intended specifically for the purpose of fixing an + issue where the update server connects to get the smoothie firmware + version but does not disconnect. It should only be specified true + by the opentrons main server process. """ if not os.environ.get('RUNNING_ON_PI'): raise RuntimeError('{} may only be instantiated on a robot' .format(self.__class__.__name__)) - self._lock = _Locker() + try: + self._lock = _Locker() + except RuntimeError: + if force: + self._lock = None + else: + raise + self.config = config or robot_configs.load() self._smoothie_driver = driver_3_0.SmoothieDriver_3_0_0( config=self.config) self._attached_modules = {} + self._cached_fw_version: Optional[str] = None def move(self, target_position: Dict[str, float], home_flagged_axes: bool = True, speed: float = None): @@ -157,8 +173,9 @@ async def update_module( return await modules.update_firmware( module, firmware_file, loop) - def connect(self, port: str = None): + async def connect(self, port: str = None): self._smoothie_driver.connect(port) + await self.update_fw_version() @contextmanager def _set_temp_speed(self, speed): @@ -175,6 +192,48 @@ def _set_temp_speed(self, speed): @property def axis_bounds(self) -> Dict[str, Tuple[float, float]]: """ The (minimum, maximum) bounds for each axis. """ - return {ax: (0, pos) for ax, pos + return {ax: (0, pos+.05) for ax, pos in self._smoothie_driver.homed_position.items() if ax not in 'BC'} + + @property + def fw_version(self) -> Optional[str]: + return self._cached_fw_version + + async def update_fw_version(self): + self._cached_fw_version = self._smoothie_driver.get_fw_version() + + async def update_firmware(self, + filename: str, + loop: asyncio.AbstractEventLoop, + modeset: bool) -> str: + msg = await self._smoothie_driver.update_firmware( + filename, loop, modeset) + self.update_fw_version() + return msg + + def engaged_axes(self) -> Dict[str, bool]: + return self._smoothie_driver.engaged_axes + + def disengage_axes(self, axes: List[str]): + self._smoothie_driver.disengage_axis(''.join(axes)) + + def set_lights(self, button: Optional[bool], rails: Optional[bool]): + if button is not None: + gpio.set_button_light(blue=button) + if rails is not None: + gpio.set_rail_lights(rails) + + def get_lights(self) -> Dict[str, bool]: + return {'button': gpio.get_button_light()[2], + 'rails': gpio.get_rail_lights()} + + def pause(self): + self._smoothie_driver.pause() + + def resume(self): + self._smoothie_driver.resume() + + def halt(self): + self._smoothie_driver.kill() + self._smoothie_driver.resume() diff --git a/api/src/opentrons/hardware_control/modules/magdeck.py b/api/src/opentrons/hardware_control/modules/magdeck.py index 97be7f7f5d5..353f3a54d3e 100644 --- a/api/src/opentrons/hardware_control/modules/magdeck.py +++ b/api/src/opentrons/hardware_control/modules/magdeck.py @@ -12,6 +12,7 @@ class MissingDevicePortError(Exception): class SimulatingDriver: def __init__(self): self._port = None + self._height = 0 def probe_plate(self): pass @@ -20,7 +21,7 @@ def home(self): pass def move(self, location): - pass + self._height = location def get_device_info(self): return {'serial': 'dummySerial', @@ -36,6 +37,10 @@ def disconnect(self): def enter_programming_mode(self): pass + @property + def plate_height(self): + return self._height + class MagDeck(mod_abc.AbstractModule): """ @@ -51,6 +56,10 @@ def build(cls, port, simulating=False): def name(cls) -> str: return 'magdeck' + @classmethod + def display_name(cls) -> str: + return 'Magnetic Deck' + def __init__(self, port, simulating): self._engaged = False self._port = port @@ -101,7 +110,9 @@ def status(self): def live_data(self): return { 'status': self.status, - 'data': {} + 'data': { + 'engaged': self._engaged + } } @property diff --git a/api/src/opentrons/hardware_control/modules/mod_abc.py b/api/src/opentrons/hardware_control/modules/mod_abc.py index 20ec2bedeb4..7cd5f5eb18a 100644 --- a/api/src/opentrons/hardware_control/modules/mod_abc.py +++ b/api/src/opentrons/hardware_control/modules/mod_abc.py @@ -68,3 +68,9 @@ async def prep_for_update(self) -> str: def name(cls) -> str: """ A name for this kind of module. """ pass + + @classmethod + @abc.abstractmethod + def display_name(cls) -> str: + """ A user-facing name for this kind of module. """ + pass diff --git a/api/src/opentrons/hardware_control/modules/tempdeck.py b/api/src/opentrons/hardware_control/modules/tempdeck.py index 2f906d9599e..1e85d943176 100644 --- a/api/src/opentrons/hardware_control/modules/tempdeck.py +++ b/api/src/opentrons/hardware_control/modules/tempdeck.py @@ -42,7 +42,7 @@ def temperature(self): @property def target(self): - return self._target_temp + return self._target_temp if self._active else None @property def status(self): @@ -86,6 +86,10 @@ def build(cls, port, simulating=False): def name(cls) -> str: return 'tempdeck' + @classmethod + def display_name(cls) -> str: + return 'Temperature Deck' + def __init__(self, port, simulating): if simulating: self._driver = SimulatingDriver() diff --git a/api/src/opentrons/hardware_control/pipette.py b/api/src/opentrons/hardware_control/pipette.py index 863a0075ba0..5addad78118 100644 --- a/api/src/opentrons/hardware_control/pipette.py +++ b/api/src/opentrons/hardware_control/pipette.py @@ -4,6 +4,7 @@ from opentrons.types import Point from opentrons.config import pipette_config +from .types import CriticalPoint class Pipette: @@ -35,16 +36,23 @@ def name(self) -> str: def pipette_id(self) -> Optional[str]: return self._pipette_id - @property - def critical_point(self) -> Point: + def critical_point(self, cp_override: CriticalPoint = None) -> Point: """ The vector from the pipette's origin to its critical point. The critical point for a pipette is the end of the nozzle if no tip is attached, or the end of the tip if a tip is attached. + + If `cp_override` is specified and valid - so is either + :py:attr:`CriticalPoint.NOZZLE` or :py:attr:`CriticalPoint.TIP` when + we have a tip - the specified critical point will be used. """ + if cp_override == CriticalPoint.NOZZLE: + tip_length = 0.0 + else: + tip_length = self.current_tip_length return Point(self.config.model_offset[0], self.config.model_offset[1], - self.config.model_offset[2] - self.current_tip_length) + self.config.model_offset[2] - tip_length) @property def current_volume(self) -> float: diff --git a/api/src/opentrons/hardware_control/simulator.py b/api/src/opentrons/hardware_control/simulator.py index fb92aa566dd..a251483e65c 100644 --- a/api/src/opentrons/hardware_control/simulator.py +++ b/api/src/opentrons/hardware_control/simulator.py @@ -1,5 +1,7 @@ import asyncio import copy +import logging +from threading import Event from typing import Dict, Optional, List, Tuple from contextlib import contextmanager from opentrons import types @@ -7,6 +9,9 @@ from . import modules +MODULE_LOG = logging.getLogger(__name__) + + def find_config(prefix: str) -> str: """ Find the most recent config matching `prefix` """ matches = [conf for conf in configs if conf.startswith(prefix)] @@ -39,20 +44,36 @@ def __init__( for idx, mod in enumerate(attached_modules)] self._position = copy.copy(_HOME_POSITION) + # Engaged axes start all true in smoothie for some reason so we + # imitate that here + self._engaged_axes = {ax: True for ax in _HOME_POSITION} + self._lights = {'button': False, 'rails': False} + self._run_flag = Event() + self._log = MODULE_LOG.getChild(repr(self)) def move(self, target_position: Dict[str, float], home_flagged_axes: bool = True, speed: float = None): + if self._run_flag.is_set(): + self._log.warning("Move to {} would be blocked by pause" + .format(target_position)) self._position.update(target_position) + self._engaged_axes.update({ax: True + for ax in target_position}) def home(self, axes: List[str] = None) -> Dict[str, float]: + if self._run_flag.is_set(): + self._log.warning("Home would be blocked by pause") # driver_3_0-> HOMED_POSITION checked_axes = axes or 'XYZABC' self._position.update({ax: _HOME_POSITION[ax] for ax in checked_axes}) + self._engaged_axes.update({ax: True + for ax in checked_axes}) return self._position def fast_home(self, axis: str, margin: float) -> Dict[str, float]: self._position[axis] = _HOME_POSITION[axis] + self._engaged_axes[axis] = True return self._position def get_attached_instruments( @@ -129,5 +150,42 @@ async def update_module( @property def axis_bounds(self) -> Dict[str, Tuple[float, float]]: """ The (minimum, maximum) bounds for each axis. """ - return {ax: (0, pos) for ax, pos in _HOME_POSITION.items() + return {ax: (0, pos+0.5) for ax, pos in _HOME_POSITION.items() if ax not in 'BC'} + + @property + def fw_version(self) -> Optional[str]: + return 'Virtual Smoothie' + + async def update_fw_version(self): + pass + + async def update_firmware(self, filename, loop, modeset) -> str: + return 'Did nothing (simulating)' + + def engaged_axes(self): + return self._engaged_axes + + def disengage_axes(self, axes: List[str]): + self._engaged_axes.update({ax: False for ax in axes}) + + def set_lights(self, button: Optional[bool], rails: Optional[bool]): + if button is not None: + self._lights['button'] = button + if rails is not None: + self._lights['rails'] = rails + + def get_lights(self) -> Dict[str, bool]: + return self._lights + + async def identify(self): + pass + + def pause(self): + self._run_flag.clear() + + def resume(self): + self._run_flag.set() + + def halt(self): + self._run_flag.set() diff --git a/api/src/opentrons/hardware_control/types.py b/api/src/opentrons/hardware_control/types.py index 1334bc836e9..03e7cf2c142 100644 --- a/api/src/opentrons/hardware_control/types.py +++ b/api/src/opentrons/hardware_control/types.py @@ -30,3 +30,18 @@ def of_plunger(cls, mount: opentrons.types.Mount): pm = {opentrons.types.Mount.LEFT: cls.B, opentrons.types.Mount.RIGHT: cls.C} return pm[mount] + + def __str__(self): + return self.name + + +class HardwareAPILike: + """ A dummy class useful in isinstance checks to accept an API or adapter + """ + pass + + +class CriticalPoint(enum.Enum): + MOUNT = enum.auto() + NOZZLE = enum.auto() + TIP = enum.auto() diff --git a/api/src/opentrons/legacy_api/modules/magdeck.py b/api/src/opentrons/legacy_api/modules/magdeck.py index 0ffe1d48998..036fdc3280c 100644 --- a/api/src/opentrons/legacy_api/modules/magdeck.py +++ b/api/src/opentrons/legacy_api/modules/magdeck.py @@ -72,18 +72,33 @@ def disengage(self): self._driver.home() self._engaged = False + @classmethod + def name(cls): + return 'magdeck' + + @classmethod + def display_name(cls): + return 'Magnetic Deck' + # TODO: there should be a separate decoupled set of classes that # construct the http api response entity given the model instance. def to_dict(self): return { - 'name': 'magdeck', + 'name': self.name(), 'port': self.port, 'serial': self.device_info and self.device_info.get('serial'), 'model': self.device_info and self.device_info.get('model'), 'fwVersion': self.device_info and self.device_info.get('version'), - 'displayName': 'Magnetic Deck', + 'displayName': self.display_name(), + **self.live_data() + } + + def live_data(self): + return { 'status': self.status, - 'data': {'engaged': self._engaged} + 'data': { + 'engaged': self._engaged + } } @property diff --git a/api/src/opentrons/legacy_api/modules/tempdeck.py b/api/src/opentrons/legacy_api/modules/tempdeck.py index 9c8f766f794..c5573188708 100644 --- a/api/src/opentrons/legacy_api/modules/tempdeck.py +++ b/api/src/opentrons/legacy_api/modules/tempdeck.py @@ -49,16 +49,24 @@ def wait_for_temp(self): while self.status != 'holding at target': pass + @classmethod + def name(cls): + return 'tempdeck' + + @classmethod + def display_name(cls): + return 'Temperature Deck' + # TODO: there should be a separate decoupled set of classes that construct # the http api response entity given the model instance. def to_dict(self): return { - 'name': 'tempdeck', + 'name': self.name(), 'port': self.port, 'serial': self.device_info and self.device_info.get('serial'), 'model': self.device_info and self.device_info.get('model'), 'fwVersion': self.device_info and self.device_info.get('version'), - 'displayName': 'Temperature Deck', + 'displayName': self.display_name(), **self.live_data() } diff --git a/api/src/opentrons/legacy_api/robot/robot.py b/api/src/opentrons/legacy_api/robot/robot.py index 0a863ff3513..80ee9339ef4 100755 --- a/api/src/opentrons/legacy_api/robot/robot.py +++ b/api/src/opentrons/legacy_api/robot/robot.py @@ -1,3 +1,4 @@ +import asyncio import os import logging from functools import lru_cache @@ -14,7 +15,7 @@ from opentrons.trackers import pose_tracker from opentrons.config import feature_flags as fflags from opentrons.config.robot_configs import load -from opentrons.legacy_api import containers +from opentrons.legacy_api import containers, modules from opentrons.legacy_api.containers import Container from .mover import Mover from opentrons.config import pipette_config @@ -60,7 +61,7 @@ def _setup_container(container_name): return container -class Robot(object): +class Robot(): """ This class is the main interface to the robot. @@ -281,6 +282,12 @@ def turn_off_rail_lights(self): def get_rail_lights_on(self): return self._driver.get_rail_lights_on() + def get_lights(self): + return self._driver.get_lights() + + def set_lights(self, button=None, rails=None): + self._driver.set_lights(button=button, rails=rails) + def identify(self, seconds): """ Identify a robot by flashing the light around the frame button for 10s @@ -967,3 +974,31 @@ def update_config(self, **kwargs): of the configuration. """ self.config._replace(**kwargs) + + async def update_firmware(self, + filename, + loop=None, + explicit_modeset=True): + if self.is_simulating(): + return + if loop is None: + checked_loop = asyncio.get_event_loop() + else: + checked_loop = loop + msg = await self._driver.update_firmware( + filename, checked_loop, explicit_modeset) + self.fw_version = self._driver.get_fw_version() + return msg + + @property + def engaged_axes(self): + """ Which axes are engaged and holding. """ + return self._driver.engaged_axes + + async def disengage_axes(self, axes): + self._driver.disengage_axis(''.join(axes)) + + def discover_modules(self): + for module in self.modules: + module.disconnect() + self.modules = modules.discover_and_connect() diff --git a/api/src/opentrons/main.py b/api/src/opentrons/main.py index 4c3606e2c2e..aeacbdef35b 100644 --- a/api/src/opentrons/main.py +++ b/api/src/opentrons/main.py @@ -5,9 +5,8 @@ from opentrons import HERE from opentrons import server from opentrons.server.main import build_arg_parser -from opentrons.server.endpoints import update from argparse import ArgumentParser -from opentrons import robot, __version__ +from opentrons import hardware, __version__ from opentrons.config import feature_flags as ff from logging.config import dictConfig from opentrons.util import environment @@ -23,7 +22,7 @@ def log_init(): OT_LOG_LEVEL environment variable otherwise defaults to DEBUG. """ fallback_log_level = 'INFO' - ot_log_level = robot.config.log_level + ot_log_level = hardware.config.log_level if ot_log_level not in logging._nameToLevel: log.info("OT Log Level {} not found. Defaulting to {}".format( ot_log_level, fallback_log_level)) @@ -83,7 +82,7 @@ def log_init(): 'handlers': ['debug', 'api'], 'level': level_value }, - 'opentrons.robot.robot_configs': { + 'opentrons.config.robot_configs': { 'handlers': ['debug', 'api'], 'level': level_value }, @@ -94,6 +93,14 @@ def log_init(): 'opentrons.drivers.serial_communication': { 'handlers': ['serial'], 'level': logging.DEBUG + }, + 'opentrons.protocol_api.contexts': { + 'handlers': ['api'], + 'level': level_value + }, + 'opentrons.hardware_control': { + 'handlers': ['api', 'debug'], + 'level': level_value } } ) @@ -111,17 +118,19 @@ def _find_smoothie_file(): .format(os.path.join(HERE, 'resources'))) -def _sync_do_smoothie_install(explicit_modeset, filename): - loop = asyncio.get_event_loop() - loop.run_until_complete(update._update_firmware(filename, - loop, - explicit_modeset)) +def _sync_do_smoothie_install(explicit_modeset, filename, loop): + loop.run_until_complete(hardware.update_firmware(filename, + loop, + explicit_modeset)) -def initialize_robot(): +def initialize_robot(loop): packed_smoothie_fw_file, packed_smoothie_fw_ver = _find_smoothie_file() try: - robot.connect() + if ff.use_protocol_api_v2(): + hardware.connect(force=True) + else: + hardware.connect() except Exception as e: # The most common reason for this exception (aside from hardware # failures such as a disconnected smoothie) is that the smoothie @@ -133,20 +142,19 @@ def initialize_robot(): fw_version = None else: explicit_modeset = True - fw_version = robot.fw_version - + fw_version = hardware.fw_version + log.info("Smoothie FW version: {}".format(fw_version)) if fw_version != packed_smoothie_fw_ver: log.info("Executing smoothie update: current vers {}, packed vers {}" .format(fw_version, packed_smoothie_fw_ver)) - _sync_do_smoothie_install(explicit_modeset, packed_smoothie_fw_file) - - if robot.is_connected(): - robot.fw_version = robot._driver.get_fw_version() + loop.run_until_complete( + hardware.update_firmware(packed_smoothie_fw_file, + explicit_modeset=explicit_modeset)) + if hardware.is_connected(): log.info("FW Update complete!") else: raise RuntimeError( "Could not connect to motor driver after fw update") - else: log.info("FW version OK: {}".format(packed_smoothie_fw_ver)) @@ -160,30 +168,36 @@ def run(**kwargs): the use of different length args """ log_init() - try: - robot.connect() - except Exception as e: - log.exception("Error while connecting to motor-driver: {}".format(e)) - + loop = asyncio.get_event_loop() log.info("API server version: {}".format(__version__)) - log.info("Smoothie FW version: {}".format(robot.fw_version)) - if not os.environ.get("ENABLE_VIRTUAL_SMOOTHIE"): - initialize_robot() + initialize_robot(loop) if not ff.disable_home_on_boot(): log.info("Homing Z axes") - robot.home_z() + if ff.use_protocol_api_v2(): + loop.run_until_complete(hardware.home_z()) + else: + hardware.home_z() udev.setup_rules_file() # Explicitly unlock resin updates in case a prior server left them locked resin.unlock_updates() - server.run(kwargs.get('hostname'), kwargs.get('port'), kwargs.get('path')) + server.run(kwargs.get('hostname'), kwargs.get('port'), kwargs.get('path'), + loop) def main(): - """This application creates and starts the server for both the RPC routes - handled by opentrons.server.rpc and HTTP endpoints defined here + """ The main entrypoint for the Opentrons robot API server stack. + + This function + - creates and starts the server for both the RPC routes + handled by :py:mod:`opentrons.server.rpc` and the HTTP routes handled + by :py:mod:`opentrons.server.http` + - initializes the hardware interaction handled by either + :py:mod:`opentrons.legacy_api` or :py:mod:`opentrons.hardware_control` + + This function does not return until the server is brought down. """ arg_parser = ArgumentParser( diff --git a/api/src/opentrons/package.json b/api/src/opentrons/package.json index fa322d3f439..6ca2a65c6fd 100644 --- a/api/src/opentrons/package.json +++ b/api/src/opentrons/package.json @@ -1,6 +1,6 @@ { "name": "@opentrons/api-server", - "version": "3.6.0-beta.0", + "version": "3.6.1", "description": "Opentrons API server application", "repository": { "type": "git", diff --git a/api/src/opentrons/protocol_api/__init__.py b/api/src/opentrons/protocol_api/__init__.py index 3622c31bb2b..2b10e2a9330 100644 --- a/api/src/opentrons/protocol_api/__init__.py +++ b/api/src/opentrons/protocol_api/__init__.py @@ -8,7 +8,10 @@ import os from . import back_compat, labware -from .contexts import ProtocolContext, InstrumentContext +from .contexts import (ProtocolContext, + InstrumentContext, + TemperatureModuleContext, + MagneticModuleContext) MODULE_LOG = logging.getLogger(__name__) @@ -48,5 +51,7 @@ def run(protocol_bytes: bytes = None, __all__ = ['run', 'ProtocolContext', 'InstrumentContext', + 'TemperatureModuleContext', + 'MagneticModuleContext', 'back_compat', 'labware'] diff --git a/api/src/opentrons/protocol_api/back_compat.py b/api/src/opentrons/protocol_api/back_compat.py index 8335af462a1..b72f25edd07 100644 --- a/api/src/opentrons/protocol_api/back_compat.py +++ b/api/src/opentrons/protocol_api/back_compat.py @@ -1,9 +1,11 @@ -""" A backwards-compatibility shim for the new protocol API +""" A backwards-compatibility shim for the new protocol API. +This should not be imported directly; it is used to provide backwards +compatible singletons in opentrons/__init__.py. """ import importlib.util -from typing import Union, Any, List +from typing import Any, List import opentrons.hardware_control as hc from opentrons.config.pipette_config import configs @@ -13,7 +15,6 @@ def run(protocol_bytes: bytes, context: ProtocolContext): - reset() source = importlib.util.decode_source(protocol_bytes) exec(source) @@ -33,10 +34,13 @@ class BCRobot: For more information see :py:class:`.ProtocolContext`. """ - def __init__(self, protocol_ctx: ProtocolContext) -> None: + def __init__(self, + hardware: hc.adapters.SingletonAdapter, + protocol_ctx: ProtocolContext) -> None: + self._hardware = hardware self._ctx = protocol_ctx - def connect(self, port: Union[str, hc.API] = None, + def connect(self, port: str = None, options: Any = None): """ Connect to the robot hardware. @@ -50,21 +54,16 @@ def connect(self, port: Union[str, hc.API] = None, a simulator (depending on whether the protocol is being simulated or run) this should be unnecessary. - :param port: The port to connect to the smoothie board; the magic + :param port: The port to connect to the smoothie board or the magic string ``"Virtual Smoothie"``, which will initialize and - connect to a simulator; or an initialized hardware control - API. + connect to a simulator :param options: Ignored. """ - if isinstance(port, str) and port == 'Virtual Smoothie': - self._ctx.connect(hc.API.build_hardware_simulator()) - elif isinstance(port, hc.API): - self._ctx.connect(port) - else: - try: - self._ctx.connect(hc.API.build_hardware_controller(port=port)) - except RuntimeError: - self._ctx.connect(hc.API.build_hardware_simulator()) + self._hardware.connect(port) + + @property + def fw_version(self): + return self._hardware.fw_version def __getattr__(self, name): """ Provide transparent access to the protocol context """ @@ -216,15 +215,41 @@ def load(self, *args, **wargs): pass -robot = BCRobot(ProtocolContext()) -labware = BCLabware(robot._ctx) -containers = labware -instruments = BCInstruments(robot._ctx) -modules = BCModules(robot._ctx) +def build_globals(hardware=None, loop=None): + hw = hardware or hc.adapters.SingletonAdapter(loop) + ctx = ProtocolContext(loop) + rob = BCRobot(hw, ctx) + instr = BCInstruments(ctx) + lw = BCLabware(ctx) + mod = BCModules(ctx) + + return rob, instr, lw, lw, mod + + +def set_globals(rob, instr, lw, mod): + global robot + global instruments + global labware + global containers + global modules + robot = rob + instruments = instr + labware = lw + containers = lw + modules = mod + + +def reset_globals(hardware=None, loop=None): + robot, instruments, containers, labware, modules = build_globals(hardware, + loop) + set_globals(robot, instruments, containers, modules) def reset(): - return robot + global robot + robot.reset() + +robot, instruments, containers, labware, modules = build_globals() -__all__ = ['containers', 'instruments', 'labware', 'robot', 'reset', 'modules'] +__all__ = ['robot', 'reset', 'instruments', 'containers', 'labware', 'modules'] diff --git a/api/src/opentrons/protocol_api/contexts.py b/api/src/opentrons/protocol_api/contexts.py index fc9e3ef2b3a..0c9f346fa2f 100644 --- a/api/src/opentrons/protocol_api/contexts.py +++ b/api/src/opentrons/protocol_api/contexts.py @@ -2,15 +2,17 @@ import logging from typing import Any, Dict, List, Optional, Union, Tuple -from .labware import Well, Labware, load +from .labware import Well, Labware, load, load_module, ModuleGeometry from opentrons import types, hardware_control as hc import opentrons.config.robot_configs as rc -from opentrons.hardware_control import adapters +from opentrons.hardware_control import adapters, modules from . import geometry MODULE_LOG = logging.getLogger(__name__) +ModuleTypes = Union['TemperatureModuleContext', 'MagneticModuleContext'] + class OutOfTipsError(Exception): pass @@ -87,10 +89,28 @@ def load_labware_by_name( later in the protocol. """ labware = load(labware_name, - self._deck_layout.position_for(location), - str(location)) + self._deck_layout.position_for(location)) return self.load_labware(labware, location) + def load_module( + self, module_name: str, + location: types.DeckLocation) -> ModuleTypes: + for mod in self._hardware.discover_modules(): + if mod.name() == module_name: + mod_class = {'magdeck': MagneticModuleContext, + 'tempdeck': TemperatureModuleContext}[module_name] + break + else: + raise KeyError(module_name) + geometry = load_module( + module_name, self._deck_layout.position_for(location)) + mod_ctx = mod_class(self, + mod, + geometry, + self._loop) + self._deck_layout[location] = geometry + return mod_ctx + @property def loaded_labwares(self) -> Dict[int, Labware]: """ Get the labwares that have been loaded into the protocol context. @@ -214,6 +234,7 @@ def home(self): """ Homes the robot. """ self._log.debug("home") + self._location_cache = None self._hardware.home() @property @@ -720,3 +741,178 @@ def __repr__(self): def __str__(self): return '{} on {} mount'.format(self.hw_pipette['display_name'], self._mount.name.lower()) + + +class ModuleContext: + """ An object representing a connected module. """ + + def __init__(self, ctx: ProtocolContext, geometry: ModuleGeometry) -> None: + """ Build the ModuleContext. + + This usually should not be instantiated directly; instead, modules + should be loaded using :py:meth:`ProtocolContext.load_module`. + + :param ctx: The parent context for the module + :param geometry: The :py:class:`.ModuleGeometry` for the module + """ + self._geometry = geometry + self._ctx = ctx + + def load_labware(self, labware: Labware) -> Labware: + """ Specify the presence of a piece of labware on the module. + + :param labware: The labware object. This object should be already + initialized and its parent should be set to this + module's geometry. To initialize and load a labware + onto the module in one step, see + :py:meth:`load_labware_by_name`. + :returns: The properly-linked labware object + """ + self._geometry.add_labware(labware) + self._ctx.deck.recalculate_high_z() + return labware + + def load_labware_by_name(self, name: str) -> Labware: + """ Specify the presence of a piece of labware on the module. + + :param name: The name of the labware object. + :returns: The initialized and loaded labware object. + """ + lw = load(name, self._geometry.location) + return self.load_labware(lw) + + @property + def labware(self) -> Optional[Labware]: + """ The labware (if any) present on this module. """ + return self._geometry.labware + + def __repr__(self): + return "{} at {} lw {}".format(self.__class__.__name__, + self._geometry, + self.labware) + + +class TemperatureModuleContext(ModuleContext): + """ An object representing a connected Temperature Module. + + It should not be instantiated directly; instead, it should be + created through :py:meth:`.ProtocolContext.load_module`. + """ + def __init__(self, ctx: ProtocolContext, + hw_module: modules.tempdeck.TempDeck, + geometry: ModuleGeometry, + loop: asyncio.AbstractEventLoop): + self._module = hw_module + self._loop = loop + super().__init__(ctx, geometry) + + def set_temperature(self, celsius: float): + """ Set the target temperature, in C. + + Must be between 4 and 95C based on Opentrons QA. + + :param celsius: The target temperature, in C + """ + return self._module.set_temperature(celsius) + + def deactivate(self): + """ Stop heating (or cooling) and turn off the fan. + """ + return self._module.disengage() + + def wait_for_temp(self): + """ Block until the module reaches its setpoint. + """ + self._loop.run_until_complete(self._module.wait_for_temp()) + + @property + def temperature(self): + """ Current temperature in C""" + return self._module.temperature + + @property + def target(self): + """ Current target temperature in C""" + return self._module.target + + +class MagneticModuleContext(ModuleContext): + """ An object representing a connected Temperature Module. + + It should not be instantiated directly; instead, it should be + created through :py:meth:`.ProtocolContext.load_module`. + """ + def __init__(self, + ctx: ProtocolContext, + hw_module: modules.magdeck.MagDeck, + geometry: ModuleGeometry, + loop: asyncio.AbstractEventLoop) -> None: + self._module = hw_module + self._loop = loop + super().__init__(ctx, geometry) + + def calibrate(self): + """ Calibrate the Magnetic Module. + + The calibration is used to establish the position of the lawbare on + top of the magnetic module. + """ + self._module.calibrate() + + def load_labware(self, labware: Labware) -> Labware: + """ + Load labware onto a Magnetic Module, checking if it is compatible + """ + if labware.magdeck_engage_height is None: + MODULE_LOG.warning( + "This labware ({}) is not explicitly compatible with the" + " Magnetic Module. You will have to specify a height when" + " calling engage().") + return super().load_labware(labware) + + def engage(self, height: float = None, offset: float = None): + """ Raise the Magnetic Module's magnets. + + The destination of the magnets can be specified in several different + ways, based on internally stored default heights for labware: + + - If neither `height` nor `offset` is specified, the magnets will + raise to a reasonable default height based on the specified + labware. + - If `height` is specified, it should be a distance in mm from the + home position of the magnets. + - If `offset` is specified, it should be an offset in mm from the + default position. A positive number moves the magnets higher and + a negative number moves the magnets lower. + + Only certain labwares have defined engage heights for the Magnetic + Module. If a labware that does not have a defined engage height is + loaded on the Magnetic Module (or if no labware is loaded), then + `height` must be specified. + + :param height: The height to raise the magnets to, in mm from home. + :param offset: An offset relative to the default height for the labware + in mm + """ + if height: + dist = height + elif self.labware and self.labware.magdeck_engage_height is not None: + dist = self.labware.magdeck_engage_height + if offset: + dist += offset + else: + raise ValueError( + "Currently loaded labware {} does not have a known engage " + "height; please specify explicitly with the height param" + .format(self.labware)) + self._module.engage(dist) + + def disengage(self): + """ Lower the magnets back into the Magnetic Module. + """ + self._module.disengage() + + @property + def status(self): + """ The status of the module. either 'engaged' or 'disengaged' """ + return self._module.status diff --git a/api/src/opentrons/protocol_api/geometry.py b/api/src/opentrons/protocol_api/geometry.py index 66191adddf7..df9e6be19d9 100644 --- a/api/src/opentrons/protocol_api/geometry.py +++ b/api/src/opentrons/protocol_api/geometry.py @@ -1,10 +1,10 @@ from collections import UserDict import functools import logging -from typing import List, Optional, Tuple +from typing import List, Optional, Tuple, Union from opentrons import types -from .labware import Labware, Well +from .labware import Labware, Well, ModuleGeometry MODULE_LOG = logging.getLogger(__name__) @@ -81,6 +81,9 @@ def _split_loc_labware( to_point] +DeckItem = Union[Labware, ModuleGeometry] + + class Deck(UserDict): def __init__(self): super().__init__() @@ -116,7 +119,7 @@ def _check_name(self, key: object) -> int: else: return key_int - def __getitem__(self, key: types.DeckLocation) -> 'Labware': + def __getitem__(self, key: types.DeckLocation) -> DeckItem: return self.data[self._check_name(key)] def __delitem__(self, key: types.DeckLocation) -> None: @@ -124,17 +127,15 @@ def __delitem__(self, key: types.DeckLocation) -> None: old = self.data[checked_key] self.data[checked_key] = None if old: - self._highest_z = 0.0 - for item in [lw for lw in self.data.values() if lw]: - self._highest_z = max(item.wells()[0].top().z, self._highest_z) + self.recalculate_high_z() - def __setitem__(self, key: types.DeckLocation, val: 'Labware') -> None: + def __setitem__(self, key: types.DeckLocation, val: DeckItem) -> None: key_int = self._check_name(key) if self.data.get(key_int) is not None: raise ValueError('Deck location {} already has an item: {}' .format(key, self.data[key_int])) self.data[key_int] = val - self._highest_z = max(val.wells()[0].top().point.z, self._highest_z) + self._highest_z = max(val.highest_z, self._highest_z) def __contains__(self, key: object) -> bool: try: @@ -143,9 +144,14 @@ def __contains__(self, key: object) -> bool: return False return key_int in self.data - def position_for(self, key: types.DeckLocation) -> types.Point: + def position_for(self, key: types.DeckLocation) -> types.Location: key_int = self._check_name(key) - return self._positions[key_int] + return types.Location(self._positions[key_int], "Slot " + str(key)) + + def recalculate_high_z(self): + self._highest_z = 0.0 + for item in [lw for lw in self.data.values() if lw]: + self._highest_z = max(item.highest_z, self._highest_z) @property def highest_z(self) -> float: diff --git a/api/src/opentrons/protocol_api/labware.py b/api/src/opentrons/protocol_api/labware.py index 655542b036a..ba4154d283c 100644 --- a/api/src/opentrons/protocol_api/labware.py +++ b/api/src/opentrons/protocol_api/labware.py @@ -45,7 +45,7 @@ def __init__(self, well_props: dict, :param well_props: a dict that conforms to the json-schema for a Well :param parent: a :py:class:`.Location` Point representing the absolute position of the parent of the Well (usually the - lower-left corner of a labware) + front-left corner of a labware) """ self._display_name = display_name self._position\ @@ -75,7 +75,7 @@ def __init__(self, well_props: dict, @property def parent(self) -> 'Labware': - return self._parent + return self._parent # type: ignore @property def has_tip(self) -> bool: @@ -88,7 +88,7 @@ def has_tip(self, value: bool): def top(self) -> Location: """ :return: a Point corresponding to the absolute position of the - top-center of the well relative to the deck (with the lower-left corner + top-center of the well relative to the deck (with the front-left corner of slot 1 as (0,0,0)) """ return Location(self._position, self) @@ -96,7 +96,7 @@ def top(self) -> Location: def bottom(self) -> Location: """ :return: a Point corresponding to the absolute position of the - bottom-center of the well (with the lower-left corner of slot 1 as + bottom-center of the well (with the front-left corner of slot 1 as (0,0,0)) """ top = self.top() @@ -106,7 +106,7 @@ def bottom(self) -> Location: def center(self) -> Location: """ :return: a Point corresponding to the absolute position of the center - of the well relative to the deck (with the lower-left corner of slot 1 + of the well relative to the deck (with the front-left corner of slot 1 as (0,0,0)) """ top = self.top() @@ -148,7 +148,7 @@ def _from_center_cartesian( y=center.point.y + (y * (y_size / 2.0)), z=center.point.z + (z * (z_size / 2.0))) - def __str__(self): + def __repr__(self): return self._display_name def __eq__(self, other: object) -> bool: @@ -167,25 +167,22 @@ class Labware: tip rack, etc. It defines the physical geometry of the labware, and provides methods for accessing wells within the labware. """ - def __init__( - self, definition: dict, parent: Point, parent_name: str) -> None: + def __init__(self, definition: dict, parent: Location) -> None: """ :param definition: A dict representing all required data for a labware, - including metadata such as the display name of the labware, a - definition of the order to iterate over wells, the shape of wells - (shape, physical dimensions, etc), and so on. The correct shape of - this definition is governed by the "labware-designer" project in - the Opentrons/opentrons repo. - :param parent: A Point representing the critical point for the object - upon which the labware is mounted (often the lower-left corner of - a slot on the deck) - :param parent_name: A string with the debug name of the parent, usually - either the name of the slot or another device that can have a - labware mounted on it (e.g.: "Slot 5" or "Temperature Module in - Slot 4") + including metadata such as the display name of the + labware, a definition of the order to iterate over + wells, the shape of wells (shape, physical + dimensions, etc), and so on. The correct shape of + this definition is handled by the "labware-designer" + project in the Opentrons/opentrons repo. + :param parent: A :py:class:`.Location` representing the location where + the front and left most point of the outside of the + labware is (often the front-left corner of a slot on the + deck). """ self._display_name = "{} on {}".format( - definition['metadata']['displayName'], parent_name) + definition['metadata']['displayName'], str(parent.labware)) self._calibrated_offset: Point = Point(0, 0, 0) self._wells: List[Well] = [] # Directly from definition @@ -198,13 +195,25 @@ def __init__( self._ordering = [well for col in definition['ordering'] for well in col] - self._offset = Point(x=offset['x'] + parent.x, - y=offset['y'] + parent.y, - z=offset['z'] + parent.z) + self._offset\ + = Point(offset['x'], offset['y'], offset['z']) + parent.point # Applied properties self.set_calibration(self._calibrated_offset) self._pattern = re.compile(r'^([A-Z]+)([1-9][0-9]*)$', re.X) + self._definition = definition + + @property + def name(self) -> str: + """ The canonical name of the labware, which is used to load it """ + return self._definition['parameters']['loadName'] + + @property + def magdeck_engage_height(self) -> Optional[float]: + if not self._parameters['isMagneticModuleCompatible']: + return None + else: + return self._parameters['magneticModuleEngageHeight'] def _build_wells(self) -> List[Well]: """ @@ -493,6 +502,79 @@ def __getitem__(self, item): raise KeyError +class ModuleGeometry: + """ + This class represents an active peripheral, such as an Opentrons MagBead + Module or Temperature Module. It defines the physical geometry of the + device (primarily the offset that modifies the position of the labware + mounted on top of it). + """ + def __init__(self, + definition: dict, + parent: Location) -> None: + """ + Create a Module for tracking the position of a module. + + Note that modules do not currently have a concept of calibration apart + from calibration of labware on top of the module. The practical result + of this is that if the module parent :py:class:`.Location` is + incorrect, then acorrect calibration of one labware on the deck would + be incorrect on the module, and vice-versa. Currently, the way around + this would be to correct the :py:class:`.Location` so that the + calibrated labware is targeted accurately in both positions. + + :param definition: A dict containing all the data required to define + the geometry of the module. + :type definition: dict + :param parent: A location representing location of the front left of + the outside of the module (usually the front-left corner + of a slot on the deck). + :type parent: :py:class:`.Location` + """ + self._parent = parent + self._display_name = "{} on {}".format(definition["displayName"], + str(parent.labware)) + self._offset = Point(definition["labwareOffset"]["x"], + definition["labwareOffset"]["y"], + definition["labwareOffset"]["z"]) + self._height = definition["dimensions"]["bareOverallHeight"]\ + + self._parent.point.z + self._over_labware = definition["dimensions"]["overLabwareHeight"] + self._labware: Optional[Labware] = None + self._location = Location( + point=self._offset + self._parent.point, + labware=self) + + def add_labware(self, labware: Labware): + assert not self._labware,\ + '{} is already on this module'.format(self._labware) + self._labware = labware + + def reset_labware(self): + self._labware = None + + @property + def labware(self) -> Optional[Labware]: + return self._labware + + @property + def location(self) -> Location: + """ + :return: a :py:class:`.Location` representing the top of the module + """ + return self._location + + @property + def highest_z(self) -> float: + if self.labware: + return self.labware.highest_z + self._over_labware + else: + return self._height + + def __repr__(self): + return self._display_name + + def save_calibration(labware: Labware, delta: Point): """ Function to be used whenever an updated delta is found for the first well @@ -595,7 +677,7 @@ def _load_definition_by_name(name: str) -> dict: return labware_def -def load(name: str, parent: Point, parent_name: str) -> Labware: +def load(name: str, parent: Location) -> Labware: """ Return a labware object constructed from a labware definition dict looked up by name (definition must have been previously stored locally on the @@ -604,20 +686,15 @@ def load(name: str, parent: Point, parent_name: str) -> Labware: :param name: A string to use for looking up a labware definition previously saved to disc. The definition file must have been saved in a known location with the filename '${name}.json' - :param parent: A Point representing the critical point for the object - upon which the labware is mounted (often the lower-left corner of - a slot on the deck) - :param parent_name: A string with the debug name of the parent, usually - either the name of the slot or another device that can have a - labware mounted on it (e.g.: "Slot 5" or "Temperature Module in - Slot 4") + :param parent: A :py:class:`.Location` representing the location where + the front and left most point of the outside of labware is + (often the front-left corner of a slot on the deck). """ definition = _load_definition_by_name(name) - return load_from_definition(definition, parent, parent_name) + return load_from_definition(definition, parent) -def load_from_definition( - definition: dict, parent: Point, parent_name: str) -> Labware: +def load_from_definition(definition: dict, parent: Location) -> Labware: """ Return a labware object constructed from a provided labware definition dict @@ -627,15 +704,11 @@ def load_from_definition( (shape, physical dimensions, etc), and so on. The correct shape of this definition is governed by the "labware-designer" project in the Opentrons/opentrons repo. - :param parent: A Point representing the critical point for the object - upon which the labware is mounted (often the lower-left corner of - a slot on the deck) - :param parent_name: A string with the debug name of the parent, usually - either the name of the slot or another device that can have a - labware mounted on it (e.g.: "Slot 5" or "Temperature Module in - Slot 4") + :param parent: A :py:class:`.Location` representing the location where + the front and left most point of the outside of labware is + (often the front-left corner of a slot on the deck). """ - labware = Labware(definition, parent, parent_name) + labware = Labware(definition, parent) load_calibration(labware) return labware @@ -652,3 +725,36 @@ def clear_calibrations(): os.remove(os.path.join(persistent_path, target)) except FileNotFoundError: pass + + +def load_module_from_definition( + definition: dict, parent: Location) -> ModuleGeometry: + """ + Return a :py:class:`ModuleGeometry` object from a specified definition + + :param definition: A dict representing all required data for a module's + geometry. + :param parent: A :py:class:`.Location` representing the location where + the front and left most point of the outside of the module + is (often the front-left corner of a slot on the deck). + """ + mod = ModuleGeometry(definition, parent) + # TODO: calibration + return mod + + +def load_module(name: str, parent: Location) -> ModuleGeometry: + """ + Return a :py:class:`ModuleGeometry` object from a definition looked up + by name. + + :param name: A string to use for looking up the definition. The string + must be present as a top-level key in moduleSpecs.json. + :param parent: A :py:class:`.Location` representing the location where + the front and left most point of the outside of the module + is (often the front-left corner of a slot on the deck). + """ + def_path = 'shared_data/robot-data/moduleSpecs.json' + module_def = json.loads( # type: ignore + pkgutil.get_data('opentrons', def_path)) + return load_module_from_definition(module_def[name], parent) diff --git a/api/src/opentrons/resources/scripts/setup_gpio.py b/api/src/opentrons/resources/scripts/setup_gpio.py index 6eae464cd58..193ae047754 100755 --- a/api/src/opentrons/resources/scripts/setup_gpio.py +++ b/api/src/opentrons/resources/scripts/setup_gpio.py @@ -2,7 +2,6 @@ from time import sleep from opentrons.drivers.rpi_drivers import gpio -from opentrons import robot # set the direction of each gpio (in or out) gpio.initialize() @@ -20,4 +19,4 @@ sleep(0.25) # turn light to blue -robot.turn_on_button_light() +gpio.turn_on_blue_button_light() diff --git a/api/src/opentrons/server/__init__.py b/api/src/opentrons/server/__init__.py index 60596b2eab2..a32bb1801be 100644 --- a/api/src/opentrons/server/__init__.py +++ b/api/src/opentrons/server/__init__.py @@ -2,11 +2,17 @@ import logging import traceback -from opentrons.util import environment +from typing import TYPE_CHECKING from aiohttp import web + +from opentrons.util import environment from .rpc import RPCServer from .http import HTTPServer from opentrons.api.routers import MainRouter +import opentrons + +if TYPE_CHECKING: + from opentons.hardware_control.types import HardwareAPILike # noqa(F501) log = logging.getLogger(__name__) log_file_path = environment.get_path('LOG_DIR') @@ -34,20 +40,31 @@ async def error_middleware(request, handler): # Support for running using aiohttp CLI. -# See: https://docs.aiohttp.org/en/stable/web.html#command-line-interface-cli # NOQA -def init(loop=None): +# See: https://docs.aiohttp.org/en/stable/web.html#command-line-interface-cli +def init(loop=None, hardware: 'HardwareAPILike' = None): """ - Builds an application and sets up RPC and HTTP servers with it + Builds an application and sets up RPC and HTTP servers with it. + + :param loop: A specific aiohttp event loop to use. If not specified, the + server will use the default event loop. + :param hardware: The hardware manager or hardware adapter to connect to. + If not specified, the server will use + :py:attr:`opentrons.hardware` """ app = web.Application(loop=loop, middlewares=[error_middleware]) - app['opentronsRpc'] = RPCServer(app, MainRouter()) - app['opentronsHttp'] = HTTPServer(app, log_file_path) + if hardware: + checked_hardware = hardware + else: + checked_hardware = opentrons.hardware + app['com.opentrons.hardware'] = checked_hardware + app['com.opentrons.rpc'] = RPCServer(app, MainRouter(checked_hardware)) + app['com.opentrons.http'] = HTTPServer(app, log_file_path) return app -def run(hostname=None, port=None, path=None): +def run(hostname=None, port=None, path=None, loop=None): """ The arguments are not all optional. Either a path or hostname+port should be specified; you have to specify one. @@ -61,4 +78,4 @@ def run(hostname=None, port=None, path=None): hostname, port)) path = None - web.run_app(init(), host=hostname, port=port, path=path) + web.run_app(init(loop), host=hostname, port=port, path=path) diff --git a/api/src/opentrons/server/endpoints/__init__.py b/api/src/opentrons/server/endpoints/__init__.py index db00d9ace8f..6955227151a 100644 --- a/api/src/opentrons/server/endpoints/__init__.py +++ b/api/src/opentrons/server/endpoints/__init__.py @@ -2,7 +2,7 @@ import json import logging from aiohttp import web -from opentrons import robot, __version__ +from opentrons import __version__ log = logging.getLogger(__name__) @@ -17,7 +17,7 @@ async def health(request: web.Request) -> web.Response: res = { 'name': NAME, 'api_version': __version__, - 'fw_version': robot.fw_version, + 'fw_version': request.app['com.opentrons.hardware'].fw_version, 'logs': static_paths, 'system_version': os.environ.get('OT_SYSTEM_VERSION', 'unknown') } diff --git a/api/src/opentrons/server/endpoints/control.py b/api/src/opentrons/server/endpoints/control.py index 5bb75a2a1fe..daaadc41717 100644 --- a/api/src/opentrons/server/endpoints/control.py +++ b/api/src/opentrons/server/endpoints/control.py @@ -4,13 +4,23 @@ import logging from aiohttp import web from threading import Thread -from opentrons import robot, instruments, modules + +from opentrons import instruments from opentrons.config import pipette_config from opentrons.trackers import pose_tracker +from opentrons.config import feature_flags as ff +from opentrons.types import Mount, Point +from opentrons.hardware_control.types import Axis, CriticalPoint + log = logging.getLogger(__name__) +def hw_from_req(req): + """ Utility function to get the hardware resource from requests """ + return req.app['com.opentrons.hardware'] + + async def get_attached_pipettes(request): """ Query robot for model strings on 'left' and 'right' mounts, and return a @@ -45,9 +55,23 @@ async def get_attached_pipettes(request): written to on-board memory), or if no pipette is present, the corresponding mount will report `'model': null` """ + hw = hw_from_req(request) if request.url.query.get('refresh') == 'true': - robot.cache_instrument_models() - return web.json_response(robot.get_attached_pipettes()) + if ff.use_protocol_api_v2(): + await hw.cache_instruments() + else: + hw.cache_instrument_models() + response = {} + for mount, data in hw.get_attached_pipettes().items(): + response[mount] = { + 'model': data['model'], + 'mount_axis': str(data['mount_axis']).lower(), + 'plunger_axis': str(data['plunger_axis']).lower(), + 'id': data['id'] + } + if 'tip_length' in data: + response[mount]['tip_length'] = data.get('tip_length', 0) + return web.json_response(response, status=200) async def get_attached_modules(request): @@ -80,22 +104,55 @@ async def get_attached_modules(request): "message": "..." } """ - for module in robot.modules: - module.disconnect() - robot.modules = modules.discover_and_connect() - - data = {"modules": list(map(lambda md: md.to_dict(), robot.modules))} - return web.json_response(data, status=200) + hw = hw_from_req(request) + if ff.use_protocol_api_v2(): + hw_mods = await hw.discover_modules() + module_data = [ + { + 'name': mod.name(), + 'displayName': mod.display_name(), + 'port': mod.port, + 'serial': mod.device_info.get('serial'), + 'model': mod.device_info.get('model'), + 'fwVersion': mod.device_info.get('version'), + **mod.live_data + } + for mod in hw_mods + ] + else: + hw.discover_modules() + hw_mods = hw.modules + module_data = [ + { + 'name': mod.name(), + 'displayName': mod.display_name(), + 'port': mod.port, + 'serial': mod.device_info and mod.device_info.get('serial'), + 'model': mod.device_info and mod.device_info.get('model'), + 'fwVersion': mod.device_info + and mod.device_info.get('version'), + **mod.live_data() + } + for mod in hw_mods + ] + return web.json_response(data={"modules": module_data}, + status=200) async def get_module_data(request): """ Query a module (by its serial number) for its live data """ + hw = hw_from_req(request) requested_serial = request.match_info['serial'] res = None - for module in robot.modules: + if ff.use_protocol_api_v2(): + hw_mods = await hw.discover_modules() + else: + hw_mods = hw.modules + + for module in hw_mods: is_serial_match = module.device_info.get('serial') == requested_serial if is_serial_match and hasattr(module, 'live_data'): res = module.live_data() @@ -116,9 +173,10 @@ async def get_engaged_axes(request): Response shape example: {"x": {"enabled": true}, "y": {"enabled": false}, ...} """ + hw = hw_from_req(request) return web.json_response( - {k.lower(): {'enabled': v} - for k, v in robot._driver.engaged_axes.items()}) + {str(k).lower(): {'enabled': v} + for k, v in hw.engaged_axes.items()}) async def disengage_axes(request): @@ -129,15 +187,16 @@ async def disengage_axes(request): to disengage (["x", "y", "z", "a", "b", "c"]) :return: message and status code """ + hw = hw_from_req(request) data = await request.text() axes = json.loads(data).get('axes') invalid_axes = [ax for ax in axes if ax.lower() not in 'xyzabc'] if invalid_axes: - message = "Invalid axes: {}".format(invalid_axes) + message = "Invalid axes: {}".format(', '.join(invalid_axes)) status = 400 else: - robot._driver.disengage_axis("".join(axes)) - message = "Disengaged axes: {}".format(axes) + await hw.disengage_axes([ax.upper() for ax in axes]) + message = "Disengaged axes: {}".format(', '.join(axes)) status = 200 return web.json_response({"message": message}, status=status) @@ -216,6 +275,7 @@ async def move(request): If 'target' is 'pipette', body must also contain: - 'model': must be a valid pipette model (as defined in `pipette_config`) """ + hw = hw_from_req(request) req = await request.text() data = json.loads(req) @@ -224,19 +284,40 @@ async def move(request): status = 400 else: status = 200 - if target == 'mount': - message = _move_mount(mount, point) - elif target == 'pipette': - pipette, _ = _fetch_or_create_pipette(mount, model) - pipette.move_to((robot.deck, point), strategy='arc') - new_position = tuple( - pose_tracker.absolute(pipette.robot.poses, pipette)) - message = "Move complete. New position: {}".format(new_position) + if ff.use_protocol_api_v2(): + await hw.cache_instruments() + if target == 'mount': + critical_point = CriticalPoint.MOUNT + else: + critical_point = None + mount = Mount[mount.upper()] + target = Point(*point) + await hw.home_z() + pos = hw.gantry_position(mount, critical_point) + await hw.move_to(mount, target._replace(z=pos.z), + critical_point=critical_point) + await hw.move_to(mount, target, + critical_point=critical_point) + message = 'Move complete. New position: {}'\ + .format(hw.gantry_position(mount)) + else: + if target == 'mount': + message = _move_mount(hw, mount, point) + elif target == 'pipette': + message = _move_pipette(hw, mount, model, point) return web.json_response({"message": message}, status=status) -def _fetch_or_create_pipette(mount, model=None): +def _move_pipette(robot, mount, model, point): + pipette, _ = _fetch_or_create_pipette(robot, mount, model) + pipette.move_to((robot.deck, point), strategy='arc') + new_position = tuple( + pose_tracker.absolute(pipette.robot.poses, pipette)) + return "Move complete. New position: {}".format(new_position) + + +def _fetch_or_create_pipette(robot, mount, model=None): existing_pipettes = robot.get_instruments() pipette = None should_remove = True @@ -257,7 +338,7 @@ def _fetch_or_create_pipette(mount, model=None): return pipette, should_remove -def _move_mount(mount, point): +def _move_mount(robot, mount, point): """ The carriage moves the mount in the Z axis, and the gantry moves in X and Y @@ -306,33 +387,37 @@ async def home(request): } :return: A success or non-success message. """ + hw = hw_from_req(request) req = await request.text() data = json.loads(req) - target = data.get('target') - - if target in ['robot', 'pipette']: - - if target == 'robot': - robot.home() - - status = 200 - message = "Homing robot." + if target == 'robot': + if ff.use_protocol_api_v2(): + await hw.home() else: - mount = data.get('mount') - if mount in ['left', 'right']: - pipette, should_remove = _fetch_or_create_pipette(mount) + hw.home() + status = 200 + message = "Homing robot." + elif target == 'pipette': + mount = data.get('mount') + if mount in ['left', 'right']: + if ff.use_protocol_api_v2(): + await hw.home([Axis.by_mount(Mount[mount.upper()])]) + await hw.home_plunger(Mount[mount.upper()]) + status = 200 + message = 'Pipette on {} homed successfuly'.format(mount) + else: + pipette, should_remove = _fetch_or_create_pipette(hw, + mount) pipette.home() if should_remove: - robot.remove_instrument(mount) - + hw.remove_instrument(mount) status = 200 message = "Pipette on {} homed successfully.".format(mount) - else: - status = 400 - message = "Expected 'left' or 'right' as values for mount" \ - "got {} instead.".format(mount) - + else: + status = 400 + message = "Expected 'left' or 'right' as values for mount" \ + "got {} instead.".format(mount) else: status = 400 message = "Expected 'robot' or 'pipette' got {}.".format(target) @@ -341,16 +426,22 @@ async def home(request): async def identify(request): - Thread(target=lambda: robot.identify( - int(request.query.get('seconds', '10')))).start() + hw = hw_from_req(request) + blink_time = int(request.query.get('seconds', '10')) + if ff.use_protocol_api_v2(): + asyncio.ensure_future(hw.identify(blink_time)) + else: + Thread(target=lambda: hw.identify(blink_time)).start() return web.json_response({"message": "identifying"}) async def get_rail_lights(request): - return web.json_response({'on': robot.get_rail_lights_on()}) + hw = hw_from_req(request) + return web.json_response({'on': hw.get_lights()['rails']}) async def set_rail_lights(request): + hw = hw_from_req(request) data = await request.json() on = data.get('on') @@ -359,7 +450,7 @@ async def set_rail_lights(request): {'message': '"on" must be true or false, got {}'.format(on)}, status=400) - robot.turn_on_rail_lights() if on else robot.turn_off_rail_lights() + hw.set_lights(rails=on) return web.json_response({'on': on}) diff --git a/api/src/opentrons/server/endpoints/serverlib_fallback.py b/api/src/opentrons/server/endpoints/serverlib_fallback.py index 8550b04e09b..1a0bb9cf043 100644 --- a/api/src/opentrons/server/endpoints/serverlib_fallback.py +++ b/api/src/opentrons/server/endpoints/serverlib_fallback.py @@ -9,6 +9,8 @@ from threading import Thread from typing import Dict, Any +from opentrons import robot + log = logging.getLogger(__name__) ignore_file = 'ignore.json' if os.environ.get('RUNNING_ON_PI'): @@ -51,8 +53,6 @@ async def install_py(data, loop): async def install_smoothie_firmware(data, loop): - from opentrons.server.endpoints.update import _update_firmware - filename = data.filename log.info('Flashing image "{}", this will take about 1 minute'.format( filename)) @@ -61,13 +61,12 @@ async def install_smoothie_firmware(data, loop): with open(filename, 'wb') as wf: wf.write(content) - msg = await _update_firmware(filename, loop) - log.debug('Firmware Update complete') + msg = await robot.update_firmware(filename, loop) + log.info('Firmware Update complete: {}'.format(msg)) try: os.remove(filename) except OSError: pass - log.debug("Result: {}".format(msg)) return {'message': msg, 'filename': filename} diff --git a/api/src/opentrons/server/endpoints/update.py b/api/src/opentrons/server/endpoints/update.py index aeb3876a924..93d30c98d39 100644 --- a/api/src/opentrons/server/endpoints/update.py +++ b/api/src/opentrons/server/endpoints/update.py @@ -1,78 +1,13 @@ import logging import asyncio -import shutil -import os import tempfile from aiohttp import web -from opentrons import robot from opentrons import modules log = logging.getLogger(__name__) UPDATE_TIMEOUT = 15 -def _ensure_programmer_executable(): - """ Find the lpc21isp executable and ensure it is executable - """ - # Find the lpc21isp executable, explicitly allowing the case where it - # is not executable (since that’s exactly what we’re trying to fix) - updater_executable = shutil.which('lpc21isp', - mode=os.F_OK) - # updater_executable might be None; we’re passing it here unchecked - # because if it is None, we’re about to fail when we try to program - # the smoothie, and we want the exception to bubble up. - os.chmod(updater_executable, 0o777) - - -async def _update_firmware(filename, loop, explicit_modeset=True): - """ - This method remains in the API currently because of its use of the robot - singleton's copy of the driver. This should move to the server lib project - eventually and use its own driver object (preferably involving moving the - drivers themselves to the serverlib) - - If explicit_modeset is True (default), explicitly place the smoothie in - programming mode. - - If explicit_modeset is False, assume the smoothie is already in programming - mode. - """ - # ensure there is a reference to the port - if not robot.is_connected(): - robot.connect() - - # get port name - port = str(robot._driver.port) - - if explicit_modeset: - # set smoothieware into programming mode - robot._driver._smoothie_programming_mode() - # close the port so other application can access it - robot._driver._connection.close() - - _ensure_programmer_executable() - - # run lpc21isp, THIS WILL TAKE AROUND 1 MINUTE TO COMPLETE - update_cmd = 'lpc21isp -wipe -donotstart {0} {1} {2} 12000'.format( - filename, port, robot.config.serial_speed) - proc = await asyncio.create_subprocess_shell( - update_cmd, - stdout=asyncio.subprocess.PIPE, - loop=loop) - rd = await proc.stdout.read() - res = rd.decode().strip() - await proc.communicate() - - # re-open the port - robot._driver._connection.open() - # reset smoothieware - robot._driver._smoothie_reset() - # run setup gcodes - robot._driver._setup() - - return res - - async def update_module_firmware(request): """ This handler accepts a POST request with Content-Type: multipart/form-data @@ -85,7 +20,8 @@ async def update_module_firmware(request): data = await request.post() module_serial = request.match_info['serial'] - res = await _update_module_firmware(module_serial, + res = await _update_module_firmware(request.app['com.opentrons.hardware'], + module_serial, data['module_firmware'], request.loop) if 'successful' not in res['message']: @@ -103,7 +39,7 @@ async def update_module_firmware(request): return web.json_response(res, status=status) -async def _update_module_firmware(module_serial, data, loop=None): +async def _update_module_firmware(hw, module_serial, data, loop=None): fw_filename = data.filename content = data.file.read() @@ -112,13 +48,13 @@ async def _update_module_firmware(module_serial, data, loop=None): with tempfile.NamedTemporaryFile(suffix=fw_filename) as fp: fp.write(content) # returns a dict of 'message' & 'avrdudeResponse' - res = await _upload_to_module(module_serial, fp.name, loop=loop) + res = await _upload_to_module(hw, module_serial, fp.name, loop=loop) log.info('Firmware update complete') res['filename'] = fw_filename return res -async def _upload_to_module(serialnum, fw_filename, loop): +async def _upload_to_module(hw, serialnum, fw_filename, loop): """ This method remains in the API currently because of its use of the robot singleton's copy of the api object & driver. This should move to the server @@ -127,13 +63,13 @@ async def _upload_to_module(serialnum, fw_filename, loop): """ # ensure there is a reference to the port - if not robot.is_connected(): - robot.connect() - for module in robot.modules: + if not hw.is_connected(): + hw.connect() + for module in hw.modules: module.disconnect() - robot.modules = modules.discover_and_connect() + hw.modules = modules.discover_and_connect() res = {} - for module in robot.modules: + for module in hw.modules: if module.device_info.get('serial') == serialnum: log.info("Module with serial {} found".format(serialnum)) bootloader_port = await modules.enter_bootloader(module) diff --git a/api/src/opentrons/server/rpc.py b/api/src/opentrons/server/rpc.py index 63d79c7ae53..ecdf76dee16 100755 --- a/api/src/opentrons/server/rpc.py +++ b/api/src/opentrons/server/rpc.py @@ -1,6 +1,7 @@ import asyncio import aiohttp import functools +import inspect import json import logging import traceback @@ -82,10 +83,13 @@ def send_worker(self, socket): _id = id(socket) def task_done(future): - exception = future.result() - if exception: - log.debug('Send task for socket {} result: {}'.format( - _id, exception)) + try: + result = future.result() + except Exception: + log.exception("send_task for socket {} threw:".format(_id)) + else: + log.info('send_task for socket {} result: {}'.format( + _id, result)) log.debug('Send task for {} finished'.format(_id)) async def send_task(socket, queue): @@ -259,7 +263,18 @@ async def process(self, message): log.exception('Error while processing request') def call_and_serialize(self, func, max_depth=0): - call_result = func() + try: + check = func.func + except AttributeError: + check = func + check_unwrapped = inspect.unwrap(check) + if asyncio.iscoroutinefunction(check_unwrapped): + # XXXX: This should really only be called in a new thread (as in + # the normal case where it is called in a threadpool) + loop = asyncio.new_event_loop() + call_result = loop.run_until_complete(func()) + else: + call_result = func() serialized, refs = serialize.get_object_tree( call_result, max_depth=max_depth) self.objects.update(refs) @@ -273,14 +288,12 @@ async def make_call(self, func, token): response['$']['status'] = 'success' except Exception as e: trace = traceback.format_exc() - log.exception('Exception while dispatching a method call:') try: line_no = [ l.split(',')[0].strip() for l in trace.split('line') if '' in l][0] except Exception: - log.exception("Exception while getting line number:") line_no = 'unknown' finally: response['$']['status'] = 'error' diff --git a/api/src/opentrons/system/smoothie_update.py b/api/src/opentrons/system/smoothie_update.py new file mode 100644 index 00000000000..50f38cfece2 --- /dev/null +++ b/api/src/opentrons/system/smoothie_update.py @@ -0,0 +1,16 @@ +""" Functions and variables for the smoothie update process """ +import os +import shutil + + +def _ensure_programmer_executable(): + """ Find the lpc21isp executable and ensure it is executable + """ + # Find the lpc21isp executable, explicitly allowing the case where it + # is not executable (since that’s exactly what we’re trying to fix) + updater_executable = shutil.which('lpc21isp', + mode=os.F_OK) + # updater_executable might be None; we’re passing it here unchecked + # because if it is None, we’re about to fail when we try to program + # the smoothie, and we want the exception to bubble up. + os.chmod(updater_executable, 0o777) diff --git a/api/src/opentrons/tools/write_pipette_memory.py b/api/src/opentrons/tools/write_pipette_memory.py index 348a63e5cfd..05e16c5d072 100644 --- a/api/src/opentrons/tools/write_pipette_memory.py +++ b/api/src/opentrons/tools/write_pipette_memory.py @@ -1,6 +1,10 @@ BAD_BARCODE_MESSAGE = 'Unexpected Serial -> {}' WRITE_FAIL_MESSAGE = 'Data not saved, HOLD BUTTON' +# must iterate through v1.4 and v1.3 first, because v1 barcodes did not +# have characters to specify the version number +VERSIONS = ['v1.4', 'v1.3', 'v1'] + MODELS = { 'v1': { 'P10S': 'p10_single_v1', @@ -19,6 +23,15 @@ 'P3HSV13': 'p300_single_v1.3', 'P3HMV13': 'p300_multi_v1.3', 'P1KSV13': 'p1000_single_v1.3' + }, + 'v1.4': { + 'P10SV14': 'p10_single_v1.4', + 'P10MV14': 'p10_multi_v1.4', + 'P50SV14': 'p50_single_v1.4', + 'P50MV14': 'p50_multi_v1.4', + 'P3HSV14': 'p300_single_v1.4', + 'P3HMV14': 'p300_multi_v1.4', + 'P1KSV14': 'p1000_single_v1.4' } } @@ -79,9 +92,7 @@ def _user_submitted_barcode(max_length): def _parse_model_from_barcode(barcode): - # MUST iterate through v1.3 first, because v1 barcodes did not have - # characters to specify the version number - for version in ['v1.3', 'v1']: + for version in VERSIONS: for barcode_substring in MODELS[version].keys(): if barcode.startswith(barcode_substring): return MODELS[version][barcode_substring] diff --git a/api/src/opentrons/types.py b/api/src/opentrons/types.py index c587b693601..7e6acb2d1b5 100644 --- a/api/src/opentrons/types.py +++ b/api/src/opentrons/types.py @@ -4,7 +4,9 @@ if TYPE_CHECKING: from typing import (Optional, # noqa(F401) Used for typechecking Tuple) - from .labware import Labware, Well # noqa(F401) Used for typechecking + from .labware import (Labware, # noqa(F401) Used for typechecking + Well, + ModuleGeometry) class PipetteNotAttachedError(KeyError): @@ -60,12 +62,15 @@ class Location(NamedTuple): of each item. """ point: Point - labware: 'Union[Labware, Well, None]' + labware: 'Union[Labware, Well, str, ModuleGeometry, None]' class Mount(enum.Enum): LEFT = enum.auto() RIGHT = enum.auto() + def __str__(self): + return self.name + DeckLocation = Union[int, str] diff --git a/api/tests/opentrons/api/test_session.py b/api/tests/opentrons/api/test_session.py index 1abf9578e0b..368277f87e7 100755 --- a/api/tests/opentrons/api/test_session.py +++ b/api/tests/opentrons/api/test_session.py @@ -1,17 +1,28 @@ +import asyncio import itertools + import pytest from opentrons.broker import publish from opentrons.api import Session from opentrons.api.session import _accumulate, _get_labware, _dedupe from tests.opentrons.conftest import state +from opentrons.legacy_api.robot.robot import Robot from functools import partial state = partial(state, 'session') @pytest.fixture -def labware_setup(): +async def run_session(request, session_manager): + if not isinstance(session_manager._hardware, Robot): + pytest.skip('requires api1 only') + return None + return await session_manager.create('dino', 'from opentrons import robot') + + +@pytest.fixture +def labware_setup(hardware): from opentrons import containers, instruments tip_racks = \ @@ -43,8 +54,9 @@ def labware_setup(): return (p50, p1000), tip_racks, plates, commands +@pytest.mark.api1_only async def test_load_from_text(session_manager, protocol): - session = session_manager.create(name='', text=protocol.text) + session = await session_manager.create(name='', text=protocol.text) assert session.name == '' acc = [] @@ -58,8 +70,9 @@ def traverse(commands): assert len(acc) == 75 +@pytest.mark.api1_only async def test_clear_tips(session_manager, tip_clear_protocol): - session = session_manager.create( + session = await session_manager.create( name='', text=tip_clear_protocol.text) assert len(session._instruments) == 1 @@ -76,15 +89,17 @@ async def test_async_notifications(main_router): assert res == {'name': 'foo', 'payload': {'bar': 'baz'}} +@pytest.mark.api1_only async def test_load_protocol_with_error(session_manager): with pytest.raises(Exception) as e: - session = session_manager.create(name='', text='blah') + session = await session_manager.create(name='', text='blah') assert session is None args, = e.value.args assert args == "name 'blah' is not defined" +@pytest.mark.api1_only @pytest.mark.parametrize('protocol_file', ['testosaur.py']) async def test_load_and_run( main_router, @@ -92,14 +107,20 @@ async def test_load_and_run( protocol_file, loop ): - session = main_router.session_manager.create( + session = await main_router.session_manager.create( name='', text=protocol.text) - assert main_router.notifications.queue.qsize() == 0 - assert session.command_log == {} + assert main_router.notifications.queue.qsize() == 1 assert session.state == 'loaded' + assert session.command_log == {} main_router.calibration_manager.tip_probe(session.instruments[0]) - task = loop.run_in_executor(executor=None, func=session.run) + + def run(): + loop = asyncio.new_event_loop() + loop.run_until_complete(session.run()) + + task = loop.run_in_executor(executor=None, + func=run) await task assert len(session.command_log) == 7 @@ -120,16 +141,11 @@ async def test_load_and_run( assert [key for key, _ in itertools.groupby(res)] == \ ['loaded', 'probing', 'ready', 'running', 'finished'] assert main_router.notifications.queue.qsize() == 0, 'Notification should be empty after receiving "finished" state change event' # noqa - session.run() + await session.run() assert len(session.command_log) == 7, \ "Clears command log on the next run" -@pytest.fixture -def run_session(virtual_smoothie_env): - return Session('dino', 'from opentrons import robot') - - def test_init(run_session): assert run_session.state == 'loaded' assert run_session.name == 'dino' @@ -163,14 +179,17 @@ def test_error_append(run_session): ] -def test_get_instruments_and_containers(labware_setup, virtual_smoothie_env): +@pytest.mark.api1_only +async def test_get_instruments_and_containers(labware_setup, + virtual_smoothie_env, + hardware, loop): instruments, tip_racks, plates, commands = labware_setup p50, p1000 = instruments instruments, containers, modules, interactions = \ _accumulate([_get_labware(command) for command in commands]) - session = Session(name='', text='') + session = await Session.build_and_prep(name='', text='', hardware=hardware) # We are calling dedupe directly for testing purposes. # Normally it is called from within a session session._instruments.extend(_dedupe(instruments)) @@ -215,6 +234,7 @@ def test_dedupe(): assert ''.join(_dedupe('aaaaabbbbcbbbbcccaa')) == 'abc' +@pytest.mark.api1_only def test_get_labware(labware_setup): instruments, tip_racks, plates, commands = labware_setup p100, p1000 = instruments @@ -249,8 +269,9 @@ def test_get_labware(labware_setup): ] +@pytest.mark.api1_only async def test_session_model_functional(session_manager, protocol): - session = session_manager.create(name='', text=protocol.text) + session = await session_manager.create(name='', text=protocol.text) assert [container.name for container in session.containers] == \ ['tiprack', 'trough', 'plate', 'tall-fixed-trash'] names = [instrument.name for instrument in session.instruments] @@ -258,6 +279,7 @@ async def test_session_model_functional(session_manager, protocol): # TODO(artyom 20171018): design a small protocol specifically for the test +@pytest.mark.api1_only @pytest.mark.parametrize('protocol_file', ['bradford_assay.py']) async def test_drop_tip_with_trash(session_manager, protocol, protocol_file): """ @@ -267,16 +289,17 @@ async def test_drop_tip_with_trash(session_manager, protocol, protocol_file): is listed as a container for a protocol, as well as a container instruments are interacting with. """ - session = session_manager.create(name='', text=protocol.text) + session = await session_manager.create(name='', text=protocol.text) assert 'tall-fixed-trash' in [c.name for c in session.get_containers()] containers = sum([i.containers for i in session.get_instruments()], []) assert 'tall-fixed-trash' in [c.name for c in containers] +@pytest.mark.api1_only async def test_session_create_error(main_router): with pytest.raises(SyntaxError): - main_router.session_manager.create( + await main_router.session_manager.create( name='', text='syntax error ;(') @@ -285,7 +308,7 @@ async def test_session_create_error(main_router): await main_router.wait_until(lambda _: True) with pytest.raises(ZeroDivisionError): - main_router.session_manager.create( + await main_router.session_manager.create( name='', text='1/0') diff --git a/api/tests/opentrons/conftest.py b/api/tests/opentrons/conftest.py index 50f5e448a96..a40adf6a60c 100755 --- a/api/tests/opentrons/conftest.py +++ b/api/tests/opentrons/conftest.py @@ -3,6 +3,7 @@ # from logging.config import dictConfig import asyncio +import contextlib import os import re import shutil @@ -13,6 +14,7 @@ from uuid import uuid4 as uuid import pytest +import opentrons from opentrons.api import models from opentrons.data_storage import database from opentrons.server import rpc @@ -158,22 +160,69 @@ def split_labware_def(): # -----end feature flag fixtures----------- -@pytest.fixture -async def async_client(virtual_smoothie_env, loop, test_client): - app = init(loop) - cli = await loop.create_task(test_client(app)) - endpoints.session = None - return cli +@contextlib.contextmanager +def using_api2(loop): + oldenv = os.environ.get('OT_FF_useProtocolApi2') + os.environ['OT_FF_useProtocolApi2'] = '1' + opentrons.reset_globals(version=2, loop=loop) + try: + yield opentrons.hardware + finally: + try: + loop.run_until_complete(opentrons.hardware.reset()) + except RuntimeError: + loop.create_task(opentrons.hardware.reset()) + if None is oldenv: + os.environ.pop('OT_FF_useProtocolApi2') + else: + os.environ['OT_FF_useProtocolApi2'] = oldenv + opentrons.reset_globals() + + +@contextlib.contextmanager +def using_api1(loop): + oldenv = os.environ.get('OT_FF_useProtocolApi2') + if oldenv: + os.environ.pop('OT_FF_useProtocolApi2') + opentrons.reset_globals(1) + try: + yield opentrons.hardware + finally: + opentrons.hardware.reset() + if None is not oldenv: + os.environ['OT_FF_useProtocolApi2'] = oldenv + opentrons.reset_globals() + + +@pytest.fixture(params=[using_api1, using_api2]) +async def async_client(request, virtual_smoothie_env, loop, test_client): + if request.node.get_marker('api1_only') and request.param != using_api1: + pytest.skip('requires api1 only') + elif request.node.get_marker('api2_only') and request.param != using_api2: + pytest.skip('requires api2 only') + with request.param(loop) as hw: + app = init(loop) + cli = await loop.create_task(test_client(app)) + setattr(cli, 'hw', hw) + if request.param == using_api1: + setattr(cli, 'version', 1) + elif request.param == using_api2: + setattr(cli, 'version', 2) + else: + raise RuntimeError("Bad version? Bad param? Somethings broken") + endpoints.session = None + yield cli @pytest.fixture -def dc_session(virtual_smoothie_env, monkeypatch): +def dc_session(virtual_smoothie_env, monkeypatch, loop): """ Mock session manager for deck calibation """ - ses = endpoints.SessionManager() - monkeypatch.setattr(endpoints, 'session', ses) - return ses + with using_api1(loop): + ses = endpoints.SessionManager() + monkeypatch.setattr(endpoints, 'session', ses) + yield ses @pytest.fixture @@ -287,24 +336,26 @@ def virtual_smoothie_env(monkeypatch): monkeypatch.setenv('ENABLE_VIRTUAL_SMOOTHIE', 'false') +@pytest.fixture(params=[using_api1, using_api2]) +def hardware(request, loop, virtual_smoothie_env): + if request.node.get_marker('api1_only') and request.param != using_api1: + pytest.skip('requires api1 only') + elif request.node.get_marker('api2_only') and request.param != using_api2: + pytest.skip('requires api2 only') + with request.param(loop) as hw: + yield hw + + @pytest.fixture -def main_router( - loop, - virtual_smoothie_env, - monkeypatch - ): +def main_router(loop, virtual_smoothie_env, hardware): from opentrons.api.routers import MainRouter - from opentrons import robot - - with MainRouter(loop=loop) as router: + with MainRouter(hardware, loop) as router: router.wait_until = partial( wait_until, notifications=router.notifications, loop=loop) yield router - robot.reset() - async def wait_until(matcher, notifications, timeout=1, loop=None): result = [] @@ -396,7 +447,7 @@ def running_on_pi(): '(probably windows)') @pytest.fixture def cntrlr_mock_connect(monkeypatch): - def mock_connect(obj, port=None): + async def mock_connect(obj, port=None): return monkeypatch.setattr(hc.Controller, 'connect', mock_connect) diff --git a/api/tests/opentrons/database/test_labware_definitions.py b/api/tests/opentrons/database/test_labware_definitions.py index 6885a2c8eef..de02ce5cfc5 100755 --- a/api/tests/opentrons/database/test_labware_definitions.py +++ b/api/tests/opentrons/database/test_labware_definitions.py @@ -76,7 +76,7 @@ def test_list_labware(): # Minor spot-checks, function is simple. Values will need to be updated if # labware is added to library lw = ldef.list_all_labware() - assert len(lw) == 54 + assert len(lw) == 55 assert lw[0] == '12-well-plate' assert lw[-1] == 'wheaton_vial_rack' diff --git a/api/tests/opentrons/drivers/module_drivers/test_temp_deck_driver.py b/api/tests/opentrons/drivers/module_drivers/test_temp_deck_driver.py index 65e453fd2b2..948173e05af 100644 --- a/api/tests/opentrons/drivers/module_drivers/test_temp_deck_driver.py +++ b/api/tests/opentrons/drivers/module_drivers/test_temp_deck_driver.py @@ -8,6 +8,8 @@ # If you send a commmand to the serial comm module and it never sees the # expected ACK, then it'll eventually time out and return an error +import time + def test_get_temp_deck_temperature(): # Get the curent and target temperatures @@ -52,21 +54,33 @@ def test_fail_get_temp_deck_temperature(): temp_deck = TempDeck() temp_deck.simulating = False + done = False + def _mock_send_command1(self, command, timeout=None): + nonlocal done + done = True return 'T:none C:90' temp_deck._send_command = types.MethodType(_mock_send_command1, temp_deck) temp_deck.update_temperature() + time.sleep(0.25) + while not done: + time.sleep(0.25) assert temp_deck._temperature == {'current': 90, 'target': None} def _mock_send_command2(self, command, timeout=None): + nonlocal done + done = True return 'Tx:none C:1' # Failure premise temp_deck._send_command = types.MethodType(_mock_send_command2, temp_deck) - + done = False temp_deck.update_temperature() + time.sleep(0.25) + while not done: + time.sleep(0.25) assert temp_deck._temperature == {'current': 90, 'target': None} diff --git a/api/tests/opentrons/drivers/test_driver.py b/api/tests/opentrons/drivers/test_driver.py index 0886a26ae8e..bbf42dfca48 100755 --- a/api/tests/opentrons/drivers/test_driver.py +++ b/api/tests/opentrons/drivers/test_driver.py @@ -216,7 +216,7 @@ def _parse_position_response(arg): ['M907 A0.1 B0.05 C0.05 X0.3 Y0.8 Z0.1 G4P0.005 G91 G0Y-28 G0Y10 G90 M400'], # NOQA ['M203.1 X80 M400'], ['M907 A0.1 B0.05 C0.05 X1.25 Y0.3 Z0.1 G4P0.005 G28.2X M400'], - ['M203.1 A125 B50 C50 X600 Y400 Z125 M400'], + ['M203.1 A125 B40 C40 X600 Y400 Z125 M400'], ['M907 A0.1 B0.05 C0.05 X0.3 Y0.3 Z0.1 G4P0.005 M400'], ['M203.1 Y80 M400'], ['M907 A0.1 B0.05 C0.05 X0.3 Y1.25 Z0.1 G4P0.005 G28.2Y M400'], @@ -224,7 +224,7 @@ def _parse_position_response(arg): ['G91 G0Y-3 G90 M400'], ['G28.2Y M400'], ['G91 G0Y-3 G90 M400'], - ['M203.1 A125 B50 C50 X600 Y400 Z125 M400'], + ['M203.1 A125 B40 C40 X600 Y400 Z125 M400'], ['M907 A0.1 B0.05 C0.05 X0.3 Y0.3 Z0.1 G4P0.005 M400'], ['M114.2 M400'] ] @@ -833,7 +833,7 @@ def send_command_mock(self, command, timeout=None): 'M119', # get the switch status 'M907 A0.1 B0.5 C0.5 X0.3 Y0.3 Z0.1 G4P0.005 G0B-1C-1', # move 'M907 A0.1 B0.05 C0.05 X0.3 Y0.3 Z0.1 G4P0.005', # set plunger current - 'M203.1 A125 B50 C50 X600 Y400 Z125' # return to normal speed + 'M203.1 A125 B40 C40 X600 Y400 Z125' # return to normal speed ] # from pprint import pprint # pprint(current_log) @@ -846,7 +846,7 @@ def send_command_mock(self, command, timeout=None): 'M203.1 A1 X1 Y1 Z1', # slow them down 'M119', # get the switch status 'M907 A0.8 B0.05 C0.05 X1.25 Y1.25 Z0.8 G4P0.005 G0A-1X-1Y-1Z-1', - 'M203.1 A125 B50 C50 X600 Y400 Z125' # return to normal speed + 'M203.1 A125 B40 C40 X600 Y400 Z125' # return to normal speed ] # from pprint import pprint # pprint(current_log) @@ -874,7 +874,7 @@ def send_command_mock(self, command, timeout=None): 'M907 A0.1 B0.05 C0.05 X0.3 Y0.3 Z0.1 G4P0.005', # low current B 'M907 A0.1 B0.05 C0.5 X0.3 Y0.3 Z0.1 G4P0.005 G28.2C', # HOME C 'M907 A0.1 B0.05 C0.05 X0.3 Y0.3 Z0.1 G4P0.005', # low current C - 'M203.1 A125 B50 C50 X600 Y400 Z125' # reset max-speeds + 'M203.1 A125 B40 C40 X600 Y400 Z125' # reset max-speeds ] # from pprint import pprint # pprint(current_log) @@ -900,7 +900,7 @@ def send_command_mock(self, command, timeout=None): 'M119', # get switch status 'M907 A0.1 B0.5 C0.5 X0.3 Y0.3 Z0.1 G4P0.005 G28.2BC', # HOME BC 'M907 A0.1 B0.05 C0.05 X0.3 Y0.3 Z0.1 G4P0.005', # low current BC - 'M203.1 A125 B50 C50 X600 Y400 Z125' # reset max-speeds + 'M203.1 A125 B40 C40 X600 Y400 Z125' # reset max-speeds ] # from pprint import pprint # pprint(current_log) diff --git a/api/tests/opentrons/hardware_control/modules/test_hc_tempdeck.py b/api/tests/opentrons/hardware_control/modules/test_hc_tempdeck.py index 6d0235925e3..3ec9033b37f 100644 --- a/api/tests/opentrons/hardware_control/modules/test_hc_tempdeck.py +++ b/api/tests/opentrons/hardware_control/modules/test_hc_tempdeck.py @@ -11,7 +11,7 @@ def test_sim_initialization(): def test_sim_state(): temp = modules.build('', 'tempdeck', True) assert temp.temperature == 0 - assert temp.target == 0 + assert temp.target is None assert temp.status == 'idle' assert temp.live_data['status'] == temp.status assert temp.live_data['data']['currentTemp'] == temp.temperature @@ -31,7 +31,7 @@ async def test_sim_update(): await asyncio.wait_for(temp.wait_for_temp(), timeout=0.2) temp.disengage() assert temp.temperature == 0 - assert temp.target == 0 + assert temp.target is None assert temp.status == 'idle' diff --git a/api/tests/opentrons/hardware_control/test_instantiation.py b/api/tests/opentrons/hardware_control/test_instantiation.py index 23e3bd95996..87a8538cd37 100644 --- a/api/tests/opentrons/hardware_control/test_instantiation.py +++ b/api/tests/opentrons/hardware_control/test_instantiation.py @@ -1,3 +1,4 @@ +import asyncio import subprocess import threading import pytest @@ -8,50 +9,56 @@ allow_module_level=True) -def test_controller_runs_only_on_pi(): +async def test_controller_runs_only_on_pi(): with pytest.raises(RuntimeError): - c = hc.API.build_hardware_controller() # noqa + c = await hc.API.build_hardware_controller() # noqa -def test_controller_instantiates(hardware_controller_lockfile, running_on_pi, - cntrlr_mock_connect, loop): - c = hc.API.build_hardware_controller(loop=loop) +async def test_controller_instantiates(hardware_controller_lockfile, + running_on_pi, + cntrlr_mock_connect, loop): + c = await hc.API.build_hardware_controller(loop=loop) assert None is not c -def test_controller_unique_per_thread(hardware_controller_lockfile, - running_on_pi, - cntrlr_mock_connect, loop): - c = hc.API.build_hardware_controller(loop=loop) # noqa +async def test_controller_unique_per_thread(hardware_controller_lockfile, + running_on_pi, + cntrlr_mock_connect, loop): + c = await hc.API.build_hardware_controller(loop=loop) # noqa with pytest.raises(RuntimeError): - _ = hc.API.build_hardware_controller(loop=loop) # noqa + _ = await hc.API.build_hardware_controller(loop=loop) # noqa def _create_in_new_thread(): + loop = asyncio.new_event_loop() with pytest.raises(RuntimeError): - _ = hc.API.build_hardware_controller(loop=loop) # noqa + _ = loop.run_until_complete( # noqa(F841) + c.API.build_hardware_controller(loop=loop)) thread = threading.Thread(target=_create_in_new_thread) thread.start() thread.join() async def _create_in_coroutine(): - _ = hc.API.build_hardware_controller(loop=loop) # noqa + _ = await hc.API.build_hardware_controller(loop=loop) # noqa fut = _create_in_coroutine() with pytest.raises(RuntimeError): loop.run_until_complete(fut) -def test_controller_unique_per_proc(hardware_controller_lockfile, - running_on_pi, cntrlr_mock_connect, loop): - c = hc.API.build_hardware_controller(loop=loop) # noqa +async def test_controller_unique_per_proc(hardware_controller_lockfile, + running_on_pi, + cntrlr_mock_connect, loop): + c = await hc.API.build_hardware_controller(loop=loop) # noqa script = '''import os +import asyncio os.environ.pop('RUNNING_ON_PI') import opentrons.hardware_control as hc os.environ['RUNNING_ON_PI'] = '1' +loop = asyncio.get_event_loop() try: - hc.API.build_hardware_controller() + loop.run_until_complete(hc.API.build_hardware_controller()) except RuntimeError: print('ok') except Exception as e: diff --git a/api/tests/opentrons/hardware_control/test_instruments.py b/api/tests/opentrons/hardware_control/test_instruments.py index 8b6c6eb5ae8..6746b674353 100644 --- a/api/tests/opentrons/hardware_control/test_instruments.py +++ b/api/tests/opentrons/hardware_control/test_instruments.py @@ -24,17 +24,19 @@ def dummy_instruments(): return dummy_instruments_attached -async def test_cache_instruments(dummy_instruments, loop): - expected_keys = [ - 'name', 'min_volume', 'max_volume', 'aspirate_flow_rate', 'channels', - 'dispense_flow_rate', 'pipette_id', 'current_volume', 'display_name'] +instrument_keys = sorted([ + 'name', 'min_volume', 'max_volume', 'aspirate_flow_rate', 'channels', + 'dispense_flow_rate', 'pipette_id', 'current_volume', 'display_name', + 'tip_length']) + +async def test_cache_instruments(dummy_instruments, loop): hw_api = hc.API.build_hardware_simulator( attached_instruments=dummy_instruments, loop=loop) await hw_api.cache_instruments() assert sorted(hw_api.attached_instruments[types.Mount.LEFT].keys()) == \ - sorted(expected_keys) + instrument_keys @pytest.mark.skipif(not hc.Controller, @@ -43,11 +45,7 @@ async def test_cache_instruments(dummy_instruments, loop): async def test_cache_instruments_hc(monkeypatch, dummy_instruments, hardware_controller_lockfile, running_on_pi, cntrlr_mock_connect, loop): - expected_keys = [ - 'name', 'min_volume', 'max_volume', 'aspirate_flow_rate', 'channels', - 'dispense_flow_rate', 'pipette_id', 'current_volume', 'display_name'] - - hw_api_cntrlr = hc.API.build_hardware_controller(loop=loop) + hw_api_cntrlr = await hc.API.build_hardware_controller(loop=loop) def mock_driver_model(mount): attached_pipette = {'left': LEFT_PIPETTE_MODEL, 'right': None} @@ -66,7 +64,7 @@ def mock_driver_id(mount): assert sorted( hw_api_cntrlr.attached_instruments[types.Mount.LEFT].keys()) == \ - sorted(expected_keys) + instrument_keys # If we pass a conflicting expectation we should get an error with pytest.raises(RuntimeError): @@ -77,14 +75,10 @@ def mock_driver_id(mount): {types.Mount.LEFT: LEFT_PIPETTE_PREFIX}) assert sorted( hw_api_cntrlr.attached_instruments[types.Mount.LEFT].keys()) == \ - sorted(expected_keys) + instrument_keys async def test_cache_instruments_sim(loop, dummy_instruments): - expected_keys = [ - 'name', 'min_volume', 'max_volume', 'aspirate_flow_rate', 'channels', - 'dispense_flow_rate', 'pipette_id', 'current_volume', 'display_name'] - sim = hc.API.build_hardware_simulator(loop=loop) # With nothing specified at init or expected, we should have nothing await sim.cache_instruments() @@ -106,7 +100,7 @@ async def test_cache_instruments_sim(loop, dummy_instruments): await sim.cache_instruments() assert sorted( sim.attached_instruments[types.Mount.LEFT].keys()) == \ - sorted(expected_keys) + instrument_keys # If we specify conflicting expectations and init arguments we should # get a RuntimeError with pytest.raises(RuntimeError): @@ -121,7 +115,7 @@ async def test_aspirate(dummy_instruments, loop): aspirate_ul = 3.0 aspirate_rate = 2 await hw_api.aspirate(types.Mount.LEFT, aspirate_ul, aspirate_rate) - new_plunger_pos = 5.660769 + new_plunger_pos = 6.05285 assert hw_api.current_position(types.Mount.LEFT)[Axis.B] == new_plunger_pos diff --git a/api/tests/opentrons/hardware_control/test_modules.py b/api/tests/opentrons/hardware_control/test_modules.py index b662a5d5453..68c8c8c3aaf 100644 --- a/api/tests/opentrons/hardware_control/test_modules.py +++ b/api/tests/opentrons/hardware_control/test_modules.py @@ -59,7 +59,7 @@ async def new_update_module(mod, ff, loop=None): reason='hardware controller not available') async def test_module_update_integration(monkeypatch, loop, cntrlr_mock_connect, running_on_pi): - api = hardware_control.API.build_hardware_controller(loop=loop) + api = await hardware_control.API.build_hardware_controller(loop=loop) def mock_get_modules(): return [('port1', 'tempdeck')] diff --git a/api/tests/opentrons/hardware_control/test_moves.py b/api/tests/opentrons/hardware_control/test_moves.py index 04873630824..9fecdda58ff 100644 --- a/api/tests/opentrons/hardware_control/test_moves.py +++ b/api/tests/opentrons/hardware_control/test_moves.py @@ -1,7 +1,7 @@ import pytest from opentrons import types from opentrons import hardware_control as hc -from opentrons.hardware_control.types import Axis +from opentrons.hardware_control.types import Axis, CriticalPoint @pytest.fixture @@ -144,6 +144,20 @@ async def test_critical_point_applied(hardware_api, monkeypatch): Axis.C: 19} assert hardware_api.current_position(types.Mount.RIGHT) == target p10_tip_length = 33 + # Specifiying critical point overrides as mount should not use model offset + await hardware_api.move_to(types.Mount.RIGHT, types.Point(0, 0, 0), + critical_point=CriticalPoint.MOUNT) + assert hardware_api._current_position == {Axis.X: 0.0, Axis.Y: 0.0, + Axis.Z: 218, + Axis.A: 0, + Axis.B: 19, Axis.C: 19} + assert hardware_api.current_position(types.Mount.RIGHT, + critical_point=CriticalPoint.MOUNT)\ + == {Axis.X: 0.0, Axis.Y: 0.0, Axis.A: 0, Axis.C: 19} + # Specifying the critical point as nozzle should have the same behavior + await hardware_api.move_to(types.Mount.RIGHT, types.Point(0, 0, 0), + critical_point=CriticalPoint.NOZZLE) + assert hardware_api._current_position == target_no_offset await hardware_api.pick_up_tip(types.Mount.RIGHT, p10_tip_length) # Now the current position (with offset applied) should change # pos_after_pickup + model_offset + critical point @@ -181,7 +195,7 @@ async def test_deck_cal_applied(monkeypatch, loop): [0, 0, 0, 1]] called_with = None - def mock_move(position, speed=None): + def mock_move(position, speed=None, home_flagged_axes=True): nonlocal called_with called_with = position diff --git a/api/tests/opentrons/hardware_control/test_pipette.py b/api/tests/opentrons/hardware_control/test_pipette.py index 13549751f0e..3e18aae4634 100644 --- a/api/tests/opentrons/hardware_control/test_pipette.py +++ b/api/tests/opentrons/hardware_control/test_pipette.py @@ -1,6 +1,6 @@ import pytest from opentrons.types import Point -from opentrons.hardware_control import pipette +from opentrons.hardware_control import pipette, types from opentrons.config import pipette_config @@ -25,13 +25,19 @@ def test_critical_points(): loaded = pipette_config.load(config) pip = pipette.Pipette(config, 'testID') mod_offset = Point(*loaded.model_offset) - assert pip.critical_point == mod_offset + assert pip.critical_point() == mod_offset + assert pip.critical_point(types.CriticalPoint.NOZZLE) == mod_offset + assert pip.critical_point(types.CriticalPoint.TIP) == mod_offset tip_length = 25.0 pip.add_tip(tip_length) new = mod_offset._replace(z=mod_offset.z - tip_length) - assert pip.critical_point == new + assert pip.critical_point() == new + assert pip.critical_point(types.CriticalPoint.NOZZLE) == mod_offset + assert pip.critical_point(types.CriticalPoint.TIP) == new pip.remove_tip() - assert pip.critical_point == mod_offset + assert pip.critical_point() == mod_offset + assert pip.critical_point(types.CriticalPoint.NOZZLE) == mod_offset + assert pip.critical_point(types.CriticalPoint.TIP) == mod_offset def test_volume_tracking(): diff --git a/api/tests/opentrons/integration/test_api.py b/api/tests/opentrons/integration/test_api.py index be1a0d32b31..4724309cfb8 100755 --- a/api/tests/opentrons/integration/test_api.py +++ b/api/tests/opentrons/integration/test_api.py @@ -26,12 +26,13 @@ def test_smoke(virtual_smoothie_env, smoke): assert coords +@pytest.mark.api1_only @pytest.mark.parametrize('protocol_file', ['multi-single.py']) async def test_multi_single(main_router, protocol, protocol_file, dummy_db): robot.connect() robot.home() - session = main_router.session_manager.create( + session = await main_router.session_manager.create( name='', text=protocol.text) await main_router.wait_until(state('session', 'loaded')) @@ -50,6 +51,7 @@ async def test_multi_single(main_router, protocol, protocol_file, dummy_db): # assert (110.0, 144.0, 58.0) in coords +@pytest.mark.api1_only @pytest.mark.parametrize('protocol_file', ['multi-single.py']) async def test_load_jog_save_run( main_router, protocol, protocol_file, dummy_db, monkeypatch): @@ -57,7 +59,7 @@ async def test_load_jog_save_run( temp = tempfile.gettempdir() monkeypatch.setenv('USER_DEFN_ROOT', temp) - session = main_router.session_manager.create( + session = await main_router.session_manager.create( name='', text=protocol.text) await main_router.wait_until(state('session', 'loaded')) diff --git a/api/tests/opentrons/integration/test_server.py b/api/tests/opentrons/integration/test_server.py index 0e9a3657ff2..bcd47ad4b27 100755 --- a/api/tests/opentrons/integration/test_server.py +++ b/api/tests/opentrons/integration/test_server.py @@ -1,11 +1,14 @@ import pytest +import logging from opentrons.server import rpc # TODO: Modify test protocols to get a Well to use the `wells` method # Setting root to None tells session to use session_manager as root +@pytest.mark.api1_only @pytest.mark.parametrize('root', [None]) -async def test_notifications(session, session_manager, protocol, root, connect): # noqa +async def test_notifications(session, session_manager, protocol, root, connect, caplog): # noqa + caplog.set_level(logging.INFO) root = session_manager await session.socket.receive_json() # Skip init @@ -15,9 +18,10 @@ async def test_notifications(session, session_manager, protocol, root, connect): args=[protocol.filename, protocol.text] ) - await session.socket.receive_json() # Skip ack + res = await session.socket.receive_json() # Skip ack res = await session.socket.receive_json() # Get notification + assert res['$']['type'] == rpc.NOTIFICATION_MESSAGE assert res['data']['v']['payload']['v']['state'] == 'loaded' res = await session.socket.receive_json() # Get call result diff --git a/api/tests/opentrons/protocol_api/test_accessor_fn.py b/api/tests/opentrons/protocol_api/test_accessor_fn.py index 6be2e340811..2dcd23b0e4f 100644 --- a/api/tests/opentrons/protocol_api/test_accessor_fn.py +++ b/api/tests/opentrons/protocol_api/test_accessor_fn.py @@ -1,5 +1,5 @@ from opentrons.protocol_api import labware -from opentrons.types import Point +from opentrons.types import Point, Location minimalLabwareDef = { "metadata": { @@ -121,8 +121,8 @@ def test_labware_init(): - deck = Point(0, 0, 0) - fake_labware = labware.Labware(minimalLabwareDef, deck, 'deck') + deck = Location(Point(0, 0, 0), 'deck') + fake_labware = labware.Labware(minimalLabwareDef, deck) ordering = [well for col in minimalLabwareDef['ordering'] for well in col] assert fake_labware._ordering == ordering assert fake_labware._well_definition == minimalLabwareDef['wells'] @@ -130,16 +130,16 @@ def test_labware_init(): def test_well_pattern(): - deck = Point(0, 0, 0) - fake_labware = labware.Labware(minimalLabwareDef, deck, 'deck') + deck = Location(Point(0, 0, 0), 'deck') + fake_labware = labware.Labware(minimalLabwareDef, deck) assert fake_labware._pattern.match('A1') assert fake_labware._pattern.match('A10') assert not fake_labware._pattern.match('A0') def test_wells_accessor(): - deck = Point(0, 0, 0) - fake_labware = labware.Labware(minimalLabwareDef, deck, 'deck') + deck = Location(Point(0, 0, 0), 'deck') + fake_labware = labware.Labware(minimalLabwareDef, deck) depth1 = minimalLabwareDef['wells']['A1']['depth'] depth2 = minimalLabwareDef['wells']['A2']['depth'] x = minimalLabwareDef['wells']['A2']['x'] @@ -152,8 +152,8 @@ def test_wells_accessor(): def test_wells_index_accessor(): - deck = Point(0, 0, 0) - fake_labware = labware.Labware(minimalLabwareDef, deck, 'deck') + deck = Location(Point(0, 0, 0), 'deck') + fake_labware = labware.Labware(minimalLabwareDef, deck) depth1 = minimalLabwareDef['wells']['A1']['depth'] depth2 = minimalLabwareDef['wells']['A2']['depth'] x = minimalLabwareDef['wells']['A2']['x'] @@ -166,8 +166,8 @@ def test_wells_index_accessor(): def test_rows_accessor(): - deck = Point(0, 0, 0) - fake_labware = labware.Labware(minimalLabwareDef2, deck, 'deck') + deck = Location(Point(0, 0, 0), 'deck') + fake_labware = labware.Labware(minimalLabwareDef2, deck) depth1 = minimalLabwareDef2['wells']['A1']['depth'] x1 = minimalLabwareDef2['wells']['A1']['x'] y1 = minimalLabwareDef2['wells']['A1']['y'] @@ -182,8 +182,8 @@ def test_rows_accessor(): def test_row_index_accessor(): - deck = Point(0, 0, 0) - fake_labware = labware.Labware(minimalLabwareDef2, deck, 'deck') + deck = Location(Point(0, 0, 0), 'deck') + fake_labware = labware.Labware(minimalLabwareDef2, deck) depth1 = minimalLabwareDef2['wells']['A1']['depth'] x1 = minimalLabwareDef2['wells']['A1']['x'] y1 = minimalLabwareDef2['wells']['A1']['y'] @@ -198,8 +198,8 @@ def test_row_index_accessor(): def test_cols_accessor(): - deck = Point(0, 0, 0) - fake_labware = labware.Labware(minimalLabwareDef, deck, 'deck') + deck = Location(Point(0, 0, 0), 'deck') + fake_labware = labware.Labware(minimalLabwareDef, deck) depth1 = minimalLabwareDef['wells']['A1']['depth'] depth2 = minimalLabwareDef['wells']['A2']['depth'] x = minimalLabwareDef['wells']['A2']['x'] @@ -212,8 +212,8 @@ def test_cols_accessor(): def test_col_index_accessor(): - deck = Point(0, 0, 0) - fake_labware = labware.Labware(minimalLabwareDef, deck, 'deck') + deck = Location(Point(0, 0, 0), 'deck') + fake_labware = labware.Labware(minimalLabwareDef, deck) depth1 = minimalLabwareDef['wells']['A1']['depth'] depth2 = minimalLabwareDef['wells']['A2']['depth'] x = minimalLabwareDef['wells']['A2']['x'] diff --git a/api/tests/opentrons/protocol_api/test_context.py b/api/tests/opentrons/protocol_api/test_context.py index 1c2bc9ec96a..aaf31d29329 100644 --- a/api/tests/opentrons/protocol_api/test_context.py +++ b/api/tests/opentrons/protocol_api/test_context.py @@ -123,16 +123,16 @@ def test_pick_up_and_drop_tip(loop, load_my_labware): pipette: Pipette = ctx._hardware._attached_instruments[mount] model_offset = Point(*pipette.config.model_offset) - assert pipette.critical_point == model_offset + assert pipette.critical_point() == model_offset target_location = tiprack.wells_by_index()['A1'].top() instr.pick_up_tip(target_location) new_offset = model_offset - Point(0, 0, tip_lenth) - assert pipette.critical_point == new_offset + assert pipette.critical_point() == new_offset instr.drop_tip(target_location) - assert pipette.critical_point == model_offset + assert pipette.critical_point() == model_offset def test_pick_up_tip_no_location(loop, load_my_labware): @@ -153,16 +153,16 @@ def test_pick_up_tip_no_location(loop, load_my_labware): pipette: Pipette = ctx._hardware._attached_instruments[mount] model_offset = Point(*pipette.config.model_offset) - assert pipette.critical_point == model_offset + assert pipette.critical_point() == model_offset instr.pick_up_tip() new_offset = model_offset - Point(0, 0, tip_lenth1) - assert pipette.critical_point == new_offset + assert pipette.critical_point() == new_offset # TODO: remove argument and verify once trash container is added instr.drop_tip(tiprack1.wells()[0].top()) - assert pipette.critical_point == model_offset + assert pipette.critical_point() == model_offset for well in tiprack1.wells(): if well.has_tip: @@ -247,3 +247,95 @@ def fake_move(mount, loc): move_called_with = None instr.dispense(2.0) assert move_called_with is None + + +def test_load_module(loop, monkeypatch): + ctx = papi.ProtocolContext(loop) + ctx._hardware._backend._attached_modules = [('mod0', 'tempdeck')] + ctx.home() + mod = ctx.load_module('tempdeck', 1) + assert isinstance(mod, papi.TemperatureModuleContext) + + +def test_tempdeck(loop, monkeypatch): + ctx = papi.ProtocolContext(loop) + ctx._hardware._backend._attached_modules = [('mod0', 'tempdeck')] + mod = ctx.load_module('tempdeck', 1) + assert ctx.deck[1] == mod._geometry + assert mod.target is None + mod.set_temperature(20) + assert mod.target == 20 + mod.wait_for_temp() + assert mod.temperature == 20 + mod.deactivate() + assert mod.target is None + mod.set_temperature(0) + assert mod.target == 0 + + +def test_magdeck(loop, monkeypatch): + ctx = papi.ProtocolContext(loop) + ctx._hardware._backend._attached_modules = [('mod0', 'magdeck')] + mod = ctx.load_module('magdeck', 1) + assert ctx.deck[1] == mod._geometry + assert mod.status == 'disengaged' + with pytest.raises(ValueError): + mod.engage() + mod.engage(2) + assert mod.status == 'engaged' + mod.disengage() + assert mod.status == 'disengaged' + mod.calibrate() + + +def test_module_load_labware(loop, monkeypatch): + ctx = papi.ProtocolContext(loop) + labware_name = 'generic_96_wellPlate_380_uL' + labware_def = json.loads( + pkgutil.get_data('opentrons', + 'shared_data/definitions2/{}.json'.format( + labware_name))) + ctx._hardware._backend._attached_modules = [('mod0', 'tempdeck')] + mod = ctx.load_module('tempdeck', 1) + assert mod.labware is None + lw = mod.load_labware_by_name(labware_name) + lw_offset = Point(labware_def['cornerOffsetFromSlot']['x'], + labware_def['cornerOffsetFromSlot']['y'], + labware_def['cornerOffsetFromSlot']['z']) + assert lw._offset == lw_offset + mod._geometry.location.point + assert lw.name == labware_name + mod2 = ctx.load_module('tempdeck', 2) + lw2 = mod2.load_labware_by_name(labware_name) + assert lw2._offset == lw_offset + mod2._geometry.location.point + assert lw2.name == labware_name + + +def test_magdeck_labware_props(loop): + ctx = papi.ProtocolContext(loop) + labware_name = 'biorad_96_wellPlate_pcr_200_uL' + labware_def = json.loads( + pkgutil.get_data('opentrons', + 'shared_data/definitions2/{}.json'.format( + labware_name))) + ctx._hardware._backend._attached_modules = [('mod0', 'magdeck')] + mod = ctx.load_module('magdeck', 1) + assert mod.labware is None + mod.load_labware_by_name(labware_name) + mod.engage() + lw_offset = labware_def['parameters']['magneticModuleEngageHeight'] + assert mod._module._driver.plate_height == lw_offset + mod.disengage() + mod.engage(offset=2) + assert mod._module._driver.plate_height == lw_offset + 2 + mod.disengage() + mod.engage(height=3) + assert mod._module._driver.plate_height == 3 + mod._geometry.reset_labware() + labware_name = 'generic_96_wellPlate_380_uL' + mod.load_labware_by_name(labware_name) + with pytest.raises(ValueError): + mod.engage() + with pytest.raises(ValueError): + mod.engage(offset=1) + mod.engage(height=2) + assert mod._module._driver.plate_height == 2 diff --git a/api/tests/opentrons/protocol_api/test_geometry.py b/api/tests/opentrons/protocol_api/test_geometry.py index 02bb48bde37..e64c891e0da 100644 --- a/api/tests/opentrons/protocol_api/test_geometry.py +++ b/api/tests/opentrons/protocol_api/test_geometry.py @@ -13,7 +13,7 @@ def test_slot_names(): for method in (slots_by_int, slots_by_str): d = Deck() for idx, slot in enumerate(method): - lw = labware.load(labware_name, d.position_for(slot), str(slot)) + lw = labware.load(labware_name, d.position_for(slot)) assert slot in d d[slot] = lw with pytest.raises(ValueError): @@ -21,6 +21,9 @@ def test_slot_names(): del d[slot] assert slot in d assert d[slot] is None + mod = labware.load_module('tempdeck', d.position_for(slot)) + d[slot] = mod + assert mod == d[slot] assert 'hasasdaia' not in d with pytest.raises(ValueError): @@ -30,11 +33,18 @@ def test_slot_names(): def test_highest_z(): deck = Deck() assert deck.highest_z == 0 - lw = labware.load(labware_name, deck.position_for(1), '1') + lw = labware.load(labware_name, deck.position_for(1)) deck[1] = lw assert deck.highest_z == lw.wells()[0].top().point.z del deck[1] assert deck.highest_z == 0 + mod = labware.load_module('tempdeck', deck.position_for(8)) + deck[8] = mod + assert deck.highest_z == mod.highest_z + lw = labware.load(labware_name, mod.location) + mod.add_labware(lw) + deck.recalculate_high_z() + assert deck.highest_z == mod.highest_z def check_arc_basic(arc, from_loc, to_loc): @@ -53,7 +63,7 @@ def check_arc_basic(arc, from_loc, to_loc): def test_direct_movs(): deck = Deck() - lw1 = labware.load(labware_name, deck.position_for(1), 'lw1') + lw1 = labware.load(labware_name, deck.position_for(1)) same_place = plan_moves(lw1.wells()[0].top(), lw1.wells()[0].top(), deck) assert same_place == [lw1.wells()[0].top().point] @@ -64,8 +74,8 @@ def test_direct_movs(): def test_basic_arc(): deck = Deck() - lw1 = labware.load(labware_name, deck.position_for(1), 'lw1') - lw2 = labware.load(labware_name, deck.position_for(2), 'lw2') + lw1 = labware.load(labware_name, deck.position_for(1)) + lw2 = labware.load(labware_name, deck.position_for(2)) # same-labware moves should use the smaller safe z same_lw = plan_moves(lw1.wells()[0].top(), lw1.wells()[8].bottom(), @@ -89,8 +99,8 @@ def test_no_labware_loc(): labware_def = labware._load_definition_by_name(labware_name) deck = Deck() - lw1 = labware.load(labware_name, deck.position_for(1), 'lw1') - lw2 = labware.load(labware_name, deck.position_for(2), 'lw2') + lw1 = labware.load(labware_name, deck.position_for(1)) + lw2 = labware.load(labware_name, deck.position_for(2)) # Various flavors of locations without labware should work no_lw = lw1.wells()[0].top()._replace(labware=None) @@ -116,7 +126,7 @@ def test_no_labware_loc(): def test_arc_tall_point(): deck = Deck() - lw1 = labware.load(labware_name, deck.position_for(1), 'lw1') + lw1 = labware.load(labware_name, deck.position_for(1)) tall_z = 100 old_top = lw1.wells()[0].top() tall_point = old_top.point._replace(z=tall_z) diff --git a/api/tests/opentrons/protocol_api/test_labware.py b/api/tests/opentrons/protocol_api/test_labware.py index a2fb6341c0c..282c6bdca0d 100644 --- a/api/tests/opentrons/protocol_api/test_labware.py +++ b/api/tests/opentrons/protocol_api/test_labware.py @@ -1,5 +1,8 @@ import json import pkgutil + +import pytest + from opentrons.protocol_api import labware from opentrons.types import Point, Location @@ -114,7 +117,7 @@ def test_from_center_cartesian(): def test_backcompat(): labware_name = 'generic_96_wellPlate_380_uL' labware_def = labware._load_definition_by_name(labware_name) - lw = labware.Labware(labware_def, Point(0, 0, 0), 'Test Slot') + lw = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) # Note that this test uses the display name of wells to test for equality, # because dimensional parameters could be subject to modification through @@ -174,7 +177,7 @@ def test_backcompat(): def test_well_parent(): labware_name = 'generic_96_wellPlate_380_uL' labware_def = labware._load_definition_by_name(labware_name) - lw = labware.Labware(labware_def, Point(0, 0, 0), 'Test Slot') + lw = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) parent = Location(Point(7, 8, 9), lw) well_name = 'circular_well_json' has_tip = True @@ -194,7 +197,8 @@ def test_well_parent(): def test_tip_tracking_init(): labware_name = 'Opentrons_96_tiprack_300_uL' labware_def = labware._load_definition_by_name(labware_name) - tiprack = labware.Labware(labware_def, Point(0, 0, 0), 'Test Slot') + tiprack = labware.Labware(labware_def, + Location(Point(0, 0, 0), 'Test Slot')) assert tiprack.is_tiprack for well in tiprack.wells(): assert well.has_tip @@ -204,7 +208,7 @@ def test_tip_tracking_init(): pkgutil.get_data('opentrons', 'shared_data/definitions2/{}.json'.format( labware_name))) - lw = labware.Labware(labware_def, Point(0, 0, 0), 'Test Slot') + lw = labware.Labware(labware_def, Location(Point(0, 0, 0), 'Test Slot')) assert not lw.is_tiprack for well in lw.wells(): assert not well.has_tip @@ -213,7 +217,8 @@ def test_tip_tracking_init(): def test_use_tips(): labware_name = 'Opentrons_96_tiprack_300_uL' labware_def = labware._load_definition_by_name(labware_name) - tiprack = labware.Labware(labware_def, Point(0, 0, 0), 'Test Slot') + tiprack = labware.Labware(labware_def, + Location(Point(0, 0, 0), 'Test Slot')) well_list = tiprack.wells() # Test only using one tip @@ -251,7 +256,8 @@ def test_use_tips(): def test_select_next_tip(): labware_name = 'Opentrons_96_tiprack_300_uL' labware_def = labware._load_definition_by_name(labware_name) - tiprack = labware.Labware(labware_def, Point(0, 0, 0), 'Test Slot') + tiprack = labware.Labware(labware_def, + Location(Point(0, 0, 0), 'Test Slot')) well_list = tiprack.wells() next_one = tiprack.next_tip() @@ -294,3 +300,48 @@ def test_select_next_tip(): assert next_five == well_list[16] next_eight = tiprack.next_tip(8) assert next_eight == well_list[16] + + +def test_module_load(): + module_names = ['tempdeck', 'magdeck'] + module_defs = json.loads( + pkgutil.get_data('opentrons', + 'shared_data/robot-data/moduleSpecs.json')) + for name in module_names: + mod = labware.load_module(name, Location(Point(0, 0, 0), 'test')) + mod_def = module_defs[name] + offset = Point(mod_def['labwareOffset']['x'], + mod_def['labwareOffset']['y'], + mod_def['labwareOffset']['z']) + high_z = mod_def['dimensions']['bareOverallHeight'] + assert mod.highest_z == high_z + assert mod.location.point == offset + mod = labware.load_module(name, Location(Point(1, 2, 3), 'test')) + assert mod.highest_z == high_z + 3 + assert mod.location.point == (offset + Point(1, 2, 3)) + mod2 = labware.load_module_from_definition(mod_def, + Location(Point(3, 2, 1), + 'test2')) + assert mod2.highest_z == high_z + 1 + assert mod2.location.point == (offset + Point(3, 2, 1)) + + +def test_module_load_labware(): + module_names = ['tempdeck', 'magdeck'] + labware_name = 'generic_96_wellPlate_380_uL' + labware_def = labware._load_definition_by_name(labware_name) + for name in module_names: + mod = labware.load_module(name, Location(Point(0, 0, 0), 'test')) + old_z = mod.highest_z + lw = labware.load_from_definition(labware_def, mod.location) + mod.add_labware(lw) + assert mod.labware == lw + assert mod.highest_z ==\ + (mod.location.point.z + + labware_def['dimensions']['overallHeight'] + + mod._over_labware) + with pytest.raises(AssertionError): + mod.add_labware(lw) + mod.reset_labware() + assert mod.labware is None + assert mod.highest_z == old_z diff --git a/api/tests/opentrons/protocol_api/test_offsets.py b/api/tests/opentrons/protocol_api/test_offsets.py index 2c09a33fa9a..1897b49c611 100644 --- a/api/tests/opentrons/protocol_api/test_offsets.py +++ b/api/tests/opentrons/protocol_api/test_offsets.py @@ -4,7 +4,7 @@ import json import time from opentrons.protocol_api import labware -from opentrons.types import Point +from opentrons.types import Point, Location import pytest minimalLabwareDef = { @@ -80,7 +80,8 @@ def mock_set_calibration(self, delta): labware.Labware, 'set_calibration', mock_set_calibration) - test_labware = labware.Labware(minimalLabwareDef, Point(0, 0, 0), 'deck') + test_labware = labware.Labware(minimalLabwareDef, + Location(Point(0, 0, 0), 'deck')) labware.save_calibration(test_labware, Point(1, 1, 1)) assert os.path.exists(path) @@ -90,7 +91,8 @@ def mock_set_calibration(self, delta): def test_save_tip_length(monkeypatch, clear_calibration): assert not os.path.exists(path) - test_labware = labware.Labware(minimalLabwareDef, Point(0, 0, 0), 'deck') + test_labware = labware.Labware(minimalLabwareDef, + Location(Point(0, 0, 0), 'deck')) calibrated_length = 22.0 labware.save_tip_length(test_labware, calibrated_length) assert os.path.exists(path) @@ -104,7 +106,8 @@ def fake_time(): return 1 monkeypatch.setattr(time, 'time', fake_time) - test_labware = labware.Labware(minimalLabwareDef, Point(0, 0, 0), 'deck') + test_labware = labware.Labware(minimalLabwareDef, + Location(Point(0, 0, 0), 'deck')) labware.save_calibration(test_labware, Point(1, 1, 1)) expected = {"default": {"offset": [1, 1, 1], "lastModified": 1}} @@ -125,7 +128,8 @@ def mock_set_calibration(self, delta): labware.Labware, 'set_calibration', mock_set_calibration) - test_labware = labware.Labware(minimalLabwareDef, Point(0, 0, 0), 'deck') + test_labware = labware.Labware(minimalLabwareDef, + Location(Point(0, 0, 0), 'deck')) test_offset = Point(1, 1, 1) test_tip_length = 34.5 @@ -144,7 +148,8 @@ def mock_set_calibration(self, delta): def test_wells_rebuilt_with_offset(): - test_labware = labware.Labware(minimalLabwareDef, Point(0, 0, 0), 'deck') + test_labware = labware.Labware(minimalLabwareDef, + Location(Point(0, 0, 0), 'deck')) old_wells = test_labware._wells assert test_labware._offset == Point(10, 10, 5) assert test_labware._calibrated_offset == Point(10, 10, 5) diff --git a/api/tests/opentrons/server/calibration_integration_test.py b/api/tests/opentrons/server/calibration_integration_test.py index 38e219ebcd4..41787b05a71 100644 --- a/api/tests/opentrons/server/calibration_integration_test.py +++ b/api/tests/opentrons/server/calibration_integration_test.py @@ -1,4 +1,6 @@ import numpy as np +import pytest + from opentrons import robot from opentrons import deck_calibration as dc from opentrons.deck_calibration import endpoints @@ -16,6 +18,7 @@ # should be replaced with something that accurately reflects actual robot # operation, and then these tests should be revised to match expected reality. +@pytest.mark.api1_only async def test_transform_from_moves(async_client, monkeypatch): test_mount, test_model = ('left', 'p300_multi_v1') # test_mount, test_model = ('right', 'p300_single_v1') diff --git a/api/tests/opentrons/server/test_calibration_endpoints.py b/api/tests/opentrons/server/test_calibration_endpoints.py index a5a44a31113..215e729f392 100644 --- a/api/tests/opentrons/server/test_calibration_endpoints.py +++ b/api/tests/opentrons/server/test_calibration_endpoints.py @@ -1,5 +1,8 @@ import json + import numpy as np +import pytest + from opentrons import robot, instruments from opentrons import deck_calibration as dc from opentrons.deck_calibration import endpoints @@ -169,6 +172,7 @@ async def test_transform_calculation(dc_session): # ------------ Session and token tests ---------------------- +@pytest.mark.api1_only async def test_create_session(async_client, monkeypatch): """ Tests that the POST request to initiate a session manager for factory @@ -212,6 +216,7 @@ def dummy_read_model(mount): assert resp.status == 201 +@pytest.mark.api1_only async def test_create_session_fail(async_client, monkeypatch): """ Tests that the GET request to initiate a session manager for factory @@ -248,6 +253,7 @@ def dummy_get_pipettes(self): assert endpoints.session is None +@pytest.mark.api1_only async def test_release(async_client, monkeypatch): """ Tests that the GET request to initiate a session manager for factory @@ -284,6 +290,7 @@ def dummy_read_model(mount): assert resp3.status == 201 +@pytest.mark.api1_only async def test_forcing_new_session(async_client, monkeypatch): """ Tests that the GET request to initiate a session manager for factory @@ -327,6 +334,7 @@ def uuid_mock(): assert text2 == expected2 +@pytest.mark.api1_only async def test_incorrect_token(async_client, monkeypatch): """ Test that putting in an incorrect token for a POST request does not work @@ -362,6 +370,7 @@ def uuid_mock(): # ------------ Router tests (integration) ---------------------- # TODO(mc, 2018-05-02): this does not adequately test z to smoothie axis logic +@pytest.mark.api1_only async def test_set_and_jog_integration(async_client, monkeypatch): """ Test that the jog function works. diff --git a/api/tests/opentrons/server/test_control_endpoints.py b/api/tests/opentrons/server/test_control_endpoints.py index 475550900e2..ae74ea3d4cd 100644 --- a/api/tests/opentrons/server/test_control_endpoints.py +++ b/api/tests/opentrons/server/test_control_endpoints.py @@ -1,22 +1,19 @@ import json from copy import deepcopy -from opentrons import robot, modules -from opentrons.server import init + +import pytest + +from opentrons import robot, types +from opentrons.legacy_api import modules as legacy_modules + +# from opentrons.server import init from opentrons.drivers.smoothie_drivers.driver_3_0 import SmoothieDriver_3_0_0 from opentrons import instruments from opentrons.config import pipette_config async def test_get_pipettes_uncommissioned( - virtual_smoothie_env, loop, test_client, monkeypatch): - app = init(loop) - cli = await loop.create_task(test_client(app)) - - def mock_parse_fail(self, gcode, mount): - pass - - monkeypatch.setattr( - SmoothieDriver_3_0_0, '_read_from_pipette', mock_parse_fail) + virtual_smoothie_env, loop, async_client, monkeypatch): expected = { "left": { @@ -33,31 +30,45 @@ def mock_parse_fail(self, gcode, mount): } } - robot._driver.simulating = False - resp = await cli.get('/pipettes?refresh=true') - robot._driver.simulating = True + if async_client.version == 1: + def mock_parse_fail(self, gcode, mount): + pass + + monkeypatch.setattr( + SmoothieDriver_3_0_0, '_read_from_pipette', mock_parse_fail) + robot._driver.simulating = False + else: + async_client.hw._backend._attached_instruments[types.Mount.LEFT]\ + = {'model': None, 'id': None} + + resp = await async_client.get('/pipettes?refresh=true') + if async_client.version == 1: + robot._driver.simulating = True text = await resp.text() assert resp.status == 200 assert json.loads(text) == expected -async def test_get_pipettes( - virtual_smoothie_env, loop, test_client, monkeypatch): +async def test_get_pipettes(async_client, monkeypatch): test_model = 'p300_multi_v1' test_id = '123abc' - def dummy_read_model(mount): - return test_model - - def dummy_read_id(mount): - return test_id - - monkeypatch.setattr(robot._driver, 'read_pipette_model', dummy_read_model) - monkeypatch.setattr(robot._driver, 'read_pipette_id', dummy_read_id) - robot.reset() - - app = init(loop) - cli = await loop.create_task(test_client(app)) + if async_client.version == 1: + def dummy_read_model(mount): + return test_model + + def dummy_read_id(mount): + return test_id + + monkeypatch.setattr( + async_client.hw._driver, 'read_pipette_model', dummy_read_model) + monkeypatch.setattr( + async_client.hw._driver, 'read_pipette_id', dummy_read_id) + else: + async_client.hw._backend._attached_instruments = { + types.Mount.RIGHT: {'model': test_model, 'id': test_id}, + types.Mount.LEFT: {'model': test_model, 'id': test_id} + } model = pipette_config.load(test_model) expected = { @@ -77,53 +88,71 @@ def dummy_read_id(mount): } } - resp = await cli.get('/pipettes?refresh=true') + resp = await async_client.get('/pipettes?refresh=true') text = await resp.text() assert resp.status == 200 assert json.loads(text) == expected -async def test_get_modules( - virtual_smoothie_env, loop, test_client, monkeypatch): - test_module = modules.MagDeck(port="/dev/modules/tty1_magdeck") +@pytest.mark.api2_only +async def test_get_modules_v2( + virtual_smoothie_env, loop, async_client, monkeypatch): + monkeypatch.setattr(async_client.hw._backend, + '_attached_modules', + [('/dev/modules/tty1_magdeck', 'magdeck')]) + await check_modules_response(async_client) + + +@pytest.mark.api1_only +async def test_get_modules_v1( + virtual_smoothie_env, loop, async_client, monkeypatch): + test_module = legacy_modules.MagDeck(port="/dev/modules/tty1_magdeck") def stub_discover_modules(): return [test_module] - monkeypatch.setattr(modules, "discover_and_connect", stub_discover_modules) + monkeypatch.setattr(legacy_modules, + "discover_and_connect", stub_discover_modules) + await check_modules_response(async_client) - app = init(loop) - cli = await loop.create_task(test_client(app)) - expected = { - "modules": [ - test_module.to_dict() - ] - } - - resp = await cli.get('/modules') +async def check_modules_response(async_client): + keys = sorted(['name', 'port', 'serial', 'model', 'fwVersion', + 'displayName', 'status', 'data']) + resp = await async_client.get('/modules') body = await resp.json() assert resp.status == 200 - assert body == expected + assert 'modules' in body + assert len(body['modules']) == 1 + assert sorted(body['modules'][0].keys()) == keys + assert 'engaged' in body['modules'][0]['data'] -async def test_get_cached_pipettes( - virtual_smoothie_env, loop, test_client, monkeypatch): +async def test_get_cached_pipettes(async_client, monkeypatch): test_model = 'p300_multi_v1' test_id = '123abc' - def dummy_read_model(mount): - return test_model - - def dummy_read_id(mount): - return test_id - - monkeypatch.setattr(robot._driver, 'read_pipette_model', dummy_read_model) - monkeypatch.setattr(robot._driver, 'read_pipette_id', dummy_read_id) - robot.reset() + if async_client.version == 1: + def dummy_read_model(mount): + return test_model + + def dummy_read_id(mount): + return test_id + + monkeypatch.setattr( + async_client.hw._driver, 'read_pipette_model', dummy_read_model) + monkeypatch.setattr( + async_client.hw._driver, 'read_pipette_id', dummy_read_id) + else: + async_client.hw._backend._attached_instruments = { + types.Mount.RIGHT: {'model': test_model, 'id': test_id}, + types.Mount.LEFT: {'model': test_model, 'id': test_id} + } - app = init(loop) - cli = await loop.create_task(test_client(app)) + if async_client.version == 1: + async_client.hw.reset() + else: + await async_client.hw.reset() model = pipette_config.load(test_model) expected = { @@ -143,7 +172,7 @@ def dummy_read_id(mount): } } - resp = await cli.get('/pipettes') + resp = await async_client.get('/pipettes') text = await resp.text() assert resp.status == 200 assert json.loads(text) == expected @@ -151,17 +180,24 @@ def dummy_read_id(mount): name1 = 'p10_single_v1.3' model1 = pipette_config.load(name1) id1 = 'fgh876' + if async_client.version == 1: + def dummy_read_model(mount): + return name1 + + def dummy_read_id(mount): + return id1 + + monkeypatch.setattr( + async_client.hw._driver, 'read_pipette_model', dummy_read_model) + monkeypatch.setattr( + async_client.hw._driver, 'read_pipette_id', dummy_read_id) + else: + async_client.hw._backend._attached_instruments = { + types.Mount.RIGHT: {'model': name1, 'id': id1}, + types.Mount.LEFT: {'model': name1, 'id': id1} + } - def dummy_model(mount): - return name1 - - def dummy_id(mount): - return id1 - - monkeypatch.setattr(robot._driver, 'read_pipette_model', dummy_model) - monkeypatch.setattr(robot._driver, 'read_pipette_id', dummy_id) - - resp1 = await cli.get('/pipettes') + resp1 = await async_client.get('/pipettes') text1 = await resp1.text() assert resp1.status == 200 assert json.loads(text1) == expected @@ -183,17 +219,13 @@ def dummy_id(mount): } } - resp2 = await cli.get('/pipettes?refresh=true') + resp2 = await async_client.get('/pipettes?refresh=true') text2 = await resp2.text() assert resp2.status == 200 assert json.loads(text2) == expected2 -async def test_disengage_axes( - virtual_smoothie_env, loop, test_client, monkeypatch): - app = init(loop) - cli = await loop.create_task(test_client(app)) - +async def test_disengage_axes(async_client, monkeypatch): def mock_send(self, command, timeout=None): pass @@ -207,34 +239,34 @@ def mock_send(self, command, timeout=None): "a": {"enabled": True}, "b": {"enabled": True}, "c": {"enabled": True}} - res0 = await cli.get('/motors/engaged') + res0 = await async_client.get('/motors/engaged') result0 = await res0.text() assert res0.status == 200 assert json.loads(result0) == alltrue - postres = await cli.post('/motors/disengage', json={'axes': ['X', 'B']}) + postres = await async_client.post( + '/motors/disengage', json={'axes': ['X', 'b']}) assert postres.status == 200 xbfalse = deepcopy(alltrue) xbfalse["x"]["enabled"] = False xbfalse["b"]["enabled"] = False - res1 = await cli.get('/motors/engaged') + res1 = await async_client.get('/motors/engaged') result1 = await res1.text() assert res1.status == 200 assert json.loads(result1) == xbfalse - robot.home() - res2 = await cli.get('/motors/engaged') + resp = await async_client.post('/robot/home', + json={'target': 'robot'}) + assert resp.status == 200 + res2 = await async_client.get('/motors/engaged') result2 = await res2.text() assert res2.status == 200 assert json.loads(result2) == alltrue -async def test_robot_info(virtual_smoothie_env, loop, test_client): - app = init(loop) - cli = await loop.create_task(test_client(app)) - - res = await cli.get('/robot/positions') +async def test_robot_info(async_client): + res = await async_client.get('/robot/positions') assert res.status == 200 text = await res.text() @@ -246,27 +278,24 @@ async def test_robot_info(virtual_smoothie_env, loop, test_client): assert len(body['positions']['attach_tip']['point']) == 3 -async def test_home_pipette(virtual_smoothie_env, loop, test_client): - app = init(loop) - cli = await loop.create_task(test_client(app)) - +async def test_home_pipette(async_client): test_data = { 'target': 'pipette', 'mount': 'left'} - res = await cli.post('/robot/home', json=test_data) + res = await async_client.post('/robot/home', json=test_data) assert res.status == 200 - res2 = await cli.post('/robot/home', json=test_data) + res2 = await async_client.post('/robot/home', json=test_data) assert res2.status == 200 -async def test_instrument_reuse(virtual_smoothie_env, loop, test_client, +async def test_instrument_reuse(async_client, monkeypatch): - app = init(loop) - cli = await loop.create_task(test_client(app)) - - robot.reset() + if async_client.version == 1: + async_client.hw.reset() + else: + await async_client.hw.reset() # With no pipette connected before homing pipettes, we should a) not crash # and b) not have any instruments connected afterwards @@ -276,56 +305,56 @@ async def test_instrument_reuse(virtual_smoothie_env, loop, test_client, 'mount': 'left' } - res = await cli.post('/robot/home', json=test_data) + res = await async_client.post('/robot/home', json=test_data) assert res.status == 200 - res = await cli.get('/pipettes') + res = await async_client.get('/pipettes') data = await res.json() assert data['left']['model'] is None # If we do have a pipette connected, if we home we should still have it # connected afterwards test_model = 'p300_multi_v1' + if async_client.version == 1: + + def dummy_read_model(mount): + return test_model + + monkeypatch.setattr(async_client.hw._driver, 'read_pipette_model', + dummy_read_model) + instruments.P300_Multi('left') + else: + async_client.hw._backend._attached_instruments = { + types.Mount.RIGHT: {'model': test_model, 'id': 'dummy-id'}, + types.Mount.LEFT: {'model': test_model, 'id': 'dummy-id'} + } - def dummy_read_model(mount): - return test_model - - monkeypatch.setattr(robot._driver, 'read_pipette_model', dummy_read_model) - instruments.P300_Multi('left') - - res = await cli.get('/pipettes', params=[('refresh', 'true')]) + res = await async_client.get('/pipettes', + params=[('refresh', 'true')]) data = await res.json() assert data['left']['model'] == test_model - res = await cli.post('/robot/home', json=test_data) + res = await async_client.post('/robot/home', json=test_data) assert res.status == 200 - res = await cli.get('/pipettes') + res = await async_client.get('/pipettes') data = await res.json() assert data['left']['model'] == test_model -async def test_home_robot(virtual_smoothie_env, loop, test_client): - - app = init(loop) - cli = await loop.create_task(test_client(app)) - +async def test_home_robot(async_client): test_data = { 'target': 'robot'} - res = await cli.post('/robot/home', json=test_data) + res = await async_client.post('/robot/home', json=test_data) assert res.status == 200 -async def test_home_pipette_bad_request( - virtual_smoothie_env, loop, test_client): - app = init(loop) - cli = await loop.create_task(test_client(app)) - +async def test_home_pipette_bad_request(async_client): test_data = {} - res = await cli.post('/robot/home', json=test_data) + res = await async_client.post('/robot/home', json=test_data) assert res.status == 400 @@ -333,40 +362,37 @@ async def test_home_pipette_bad_request( 'target': 'pipette', 'mount': 'fake_mount'} - res2 = await cli.post('/robot/home', json=test_data_2) + res2 = await async_client.post('/robot/home', json=test_data_2) assert res2.status == 400 test_data_3 = { 'mount': 'left'} - res3 = await cli.post('/robot/home', json=test_data_3) + res3 = await async_client.post('/robot/home', json=test_data_3) assert res3.status == 400 test_data_4 = { 'target': 'pipette'} - res4 = await cli.post('/robot/home', json=test_data_4) + res4 = await async_client.post('/robot/home', json=test_data_4) assert res4.status == 400 -async def test_move_bad_request(virtual_smoothie_env, loop, test_client): - app = init(loop) - cli = await loop.create_task(test_client(app)) - +async def test_move_bad_request(async_client): data0 = { 'target': 'other' } - res = await cli.post('/robot/move', json=data0) + res = await async_client.post('/robot/move', json=data0) assert res.status == 400 data1 = { 'target': 'mount', 'point': (1, 2, 3, 4) } - res = await cli.post('/robot/move', json=data1) + res = await async_client.post('/robot/move', json=data1) assert res.status == 400 data2 = { @@ -374,7 +400,7 @@ async def test_move_bad_request(virtual_smoothie_env, loop, test_client): 'point': (1, 2, 3), 'mount': 'middle' } - res = await cli.post('/robot/move', json=data2) + res = await async_client.post('/robot/move', json=data2) assert res.status == 400 data3 = { @@ -383,14 +409,14 @@ async def test_move_bad_request(virtual_smoothie_env, loop, test_client): 'mount': 'left', 'model': 'p9000+' } - res = await cli.post('/robot/move', json=data3) + res = await async_client.post('/robot/move', json=data3) assert res.status == 400 -async def test_move_mount(virtual_smoothie_env, loop, test_client): - app = init(loop) - cli = await loop.create_task(test_client(app)) - robot.home() +async def test_move_mount(async_client): + resp = await async_client.post('/robot/home', + json={'target': 'robot'}) + assert resp.status == 200 # from opentrons.trackers import pose_tracker # print("Before: {}".format(tuple( # pose_tracker.absolute( @@ -400,7 +426,7 @@ async def test_move_mount(virtual_smoothie_env, loop, test_client): 'point': [100, 200, 50], 'mount': 'right' } - res = await cli.post('/robot/move', json=data) + res = await async_client.post('/robot/move', json=data) assert res.status == 200 # text = await res.text() # print("After: {}".format(tuple( @@ -409,40 +435,72 @@ async def test_move_mount(virtual_smoothie_env, loop, test_client): # print("=-> Result: {}".format(text)) -async def test_move_pipette(virtual_smoothie_env, loop, test_client): - app = init(loop) - cli = await loop.create_task(test_client(app)) - robot.home() +async def test_move_pipette(async_client): + resp = await async_client.post('/robot/home', + json={'target': 'robot'}) + assert resp.status == 200 data = { 'target': 'pipette', 'point': [100, 200, 50], 'mount': 'right', 'model': 'p300_single_v1' } - res = await cli.post('/robot/move', json=data) + res = await async_client.post('/robot/move', json=data) assert res.status == 200 -async def test_move_and_home_existing_pipette( - virtual_smoothie_env, loop, test_client): - from opentrons import instruments - app = init(loop) - cli = await loop.create_task(test_client(app)) - robot.reset() - robot.home() - instruments.P300_Single(mount='right') +async def test_move_and_home_existing_pipette(async_client): + if async_client.version == 1: + async_client.hw.reset() + else: + await async_client.hw.reset() + resp = await async_client.post('/robot/home', json={'target': 'robot'}) + assert resp.status == 200 + if async_client.version == 1: + from opentrons import instruments + instruments.P300_Single(mount='right') move_data = { 'target': 'pipette', 'point': [100, 200, 50], 'mount': 'right', 'model': 'p300_single_v1' } - res = await cli.post('/robot/move', json=move_data) + res = await async_client.post('/robot/move', json=move_data) assert res.status == 200 move_data = { 'target': 'pipette', 'mount': 'right' } - res1 = await cli.post('/robot/home', json=move_data) + res1 = await async_client.post('/robot/home', json=move_data) assert res1.status == 200 + + +@pytest.mark.api2_only +async def test_rail_lights(async_client): + resp = await async_client.get('/robot/lights') + assert resp.status == 200 + data = await resp.json() + assert not data['on'] + + resp = await async_client.post('/robot/lights', + json={'on': True}) + assert resp.status == 200 + data = await resp.json() + assert data['on'] + + resp = await async_client.get('/robot/lights') + assert resp.status == 200 + data = await resp.json() + assert data['on'] + + resp = await async_client.post('/robot/lights', + json={'on': False}) + assert resp.status == 200 + data = await resp.json() + assert not data['on'] + + resp = await async_client.get('/robot/lights') + assert resp.status == 200 + data = await resp.json() + assert not data['on'] diff --git a/api/tests/opentrons/server/test_update_endpoints.py b/api/tests/opentrons/server/test_update_endpoints.py index fc7da3e2f39..a0f631300ef 100644 --- a/api/tests/opentrons/server/test_update_endpoints.py +++ b/api/tests/opentrons/server/test_update_endpoints.py @@ -7,7 +7,7 @@ from opentrons.server import init from opentrons.server.endpoints import update from opentrons.server.endpoints import serverlib_fallback -from opentrons import modules +from opentrons import modules, robot async def test_restart(virtual_smoothie_env, monkeypatch, loop, test_client): @@ -37,10 +37,10 @@ async def test_update(virtual_smoothie_env, monkeypatch, loop, test_client): with open(os.path.join(tmpdir, filename), 'w') as fd: fd.write("test") - async def mock_install(filename, loop): + async def mock_install(filename, loop=None, modeset=True): return msg monkeypatch.setattr(serverlib_fallback, '_install', mock_install) - monkeypatch.setattr(update, '_update_firmware', mock_install) + monkeypatch.setattr(robot, 'update_firmware', mock_install) app = init(loop) cli = await loop.create_task(test_client(app)) diff --git a/api/tests/opentrons/tools/test_qc_scripts.py b/api/tests/opentrons/tools/test_qc_scripts.py index 62c14ff3842..07f08801aa5 100644 --- a/api/tests/opentrons/tools/test_qc_scripts.py +++ b/api/tests/opentrons/tools/test_qc_scripts.py @@ -14,7 +14,14 @@ 'P50MV1318010104': 'p50_multi_v1.3', 'P3HSV1318010105': 'p300_single_v1.3', 'P3HMV1318010106': 'p300_multi_v1.3', - 'P1KSV1318010107': 'p1000_single_v1.3' + 'P1KSV1318010107': 'p1000_single_v1.3', + 'P10SV1418010101': 'p10_single_v1.4', + 'P10MV1418010102': 'p10_multi_v1.4', + 'P50SV1418010103': 'p50_single_v1.4', + 'P50MV1418010104': 'p50_multi_v1.4', + 'P3HSV1418010105': 'p300_single_v1.4', + 'P3HMV1418010106': 'p300_multi_v1.4', + 'P1KSV1418010107': 'p1000_single_v1.4' } diff --git a/app-shell/CHANGELOG.md b/app-shell/CHANGELOG.md index 7fdbf924c39..47a7c7b21d1 100644 --- a/app-shell/CHANGELOG.md +++ b/app-shell/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + +**Note:** Version bump only for package @opentrons/app-shell + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + +**Note:** Version bump only for package @opentrons/app-shell + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + +**Note:** Version bump only for package @opentrons/app-shell + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/app-shell/Makefile b/app-shell/Makefile index 5f4559b0261..6abc24cce84 100644 --- a/app-shell/Makefile +++ b/app-shell/Makefile @@ -20,7 +20,7 @@ ui_dir := ../app discovery_client_dir := ../discovery-client # directories for robot API update bundled in production build -api_dir := ../api +api_dist_dir := ../api/dist # cross-platform noop command noop := cd . @@ -74,16 +74,14 @@ lib: $(babel) .PHONY: deps +deps: wheel = $(wildcard $(api_dist_dir)/*.whl) deps: + $(if $(wheel),@echo "Packaging $(wheel)",$(error API wheel required)) $(MAKE) -C $(ui_dir) $(MAKE) -C $(discovery_client_dir) -.PHONY: api-deps -api-deps: - $(MAKE) -C $(api_dir) wheel - .PHONY: package-deps -package-deps: clean lib deps api-deps +package-deps: clean lib deps package dist-posix dist-osx dist-linux dist-win: export NODE_ENV := production package dist-posix dist-osx dist-linux dist-win: export BUILD_ID := $(build_id) diff --git a/app-shell/build/release-notes.md b/app-shell/build/release-notes.md index 9bc4c9b3768..98d8058f4ef 100644 --- a/app-shell/build/release-notes.md +++ b/app-shell/build/release-notes.md @@ -1,4 +1,4 @@ -# Changes from 3.5.1 to 3.6.0 +# Changes from 3.5.1 to 3.6.1 For more details, please see the full [technical change log][changelog] @@ -7,17 +7,6 @@ For more details, please see the full [technical change log][changelog] ## Opentrons App -### Known issues - -- The app's run log is still having problems displaying the current run step, especially if pauses and resumes are involved ([#2047][2047]) -- The app should prevent you from starting a pipette swap while a protocol is -executing, but it does not ([#2020][2020]) -- If a protocol run encounters an error, the app will suppress the error message instead of displaying it ([#1828][1828]) - -[2047]: https://github.com/Opentrons/opentrons/issues/2047 -[2020]: https://github.com/Opentrons/opentrons/issues/2020 -[1828]: https://github.com/Opentrons/opentrons/issues/1828 - ### Bug fixes - Lost connection alert messages will no longer trigger when your robot is restarting for normal reasons (e.g. software update or deck calibration). Sorry for the confusion this caused! @@ -32,11 +21,40 @@ executing, but it does not ([#2020][2020]) - Please see our support documentation for more details - After tip-probe is completed, the app will now move the pipette out of the way so you have better access to the deck +### Known issues + +- The app's run log is still having problems displaying the current run step, especially if pauses and resumes are involved ([#2047][2047]) +- The app should prevent you from starting a pipette swap while a protocol is +executing, but it does not ([#2020][2020]) +- If a protocol run encounters an error, the app will suppress the error message instead of displaying it ([#1828][1828]) + +[2047]: https://github.com/Opentrons/opentrons/issues/2047 +[2020]: https://github.com/Opentrons/opentrons/issues/2020 +[1828]: https://github.com/Opentrons/opentrons/issues/1828 + ## OT2 and Protocol API +**Important**: This release updates the calibration of the P10 single pipette. + +This update includes a refinement to the aspiration function of the P10 single-channel pipette based on an expanded data set. + +Please note this is a small but material change to the P10's pipetting performance, in particular decreasing the low-volume µl-to-mm conversion factor to address under-aspiration users have reported. + +As always, please reach out to our team with any questions. + +### Bug fixes + +- **Updated the configuration of the P10 single based on an expanded dataset** +- Fixed the iteration order of labware created with `labware.create` to match documentation +- Fixed various misconfigurations with pipette motor current/position settings + +### New features + +- Added support for `v1.4` pipette models + ### Known issues - While the underlying definition is correct, there is a known API bug that is causing the robot to think a "50ml" tube in a "15/50ml" tuberack is the same height as the "15ml" tube @@ -46,13 +64,5 @@ executing, but it does not ([#2020][2020]) 3. Insert plate and calibrate normally - After the plate has been calibrated once, the issue will not reoccur -### Bug fixes - -- Fixed the iteration order of labware created with `labware.create` to match documentation -- Fixed a misconfiguration with the motor current settings for drop-tip - -### New features - -There aren't any new user facing features in this release, but the API team is hard at work putting exciting new stuff in place behind the scenes! diff --git a/app-shell/electron-builder.json b/app-shell/electron-builder.json index 6d1794984e6..c020a3ba22f 100644 --- a/app-shell/electron-builder.json +++ b/app-shell/electron-builder.json @@ -25,7 +25,8 @@ "category": "public.app-category.productivity" }, "win": { - "target": ["nsis"] + "target": ["nsis"], + "publisherName": "Opentrons Labworks Inc." }, "linux": { "target": ["AppImage"], @@ -34,8 +35,8 @@ }, "publish": { "provider": "s3", - "bucket": "${env.OT_BUCKET_APP}", - "path": "${env.OT_FOLDER_APP}" + "bucket": "${env.OT_APP_DEPLOY_BUCKET}", + "path": "${env.OT_APP_DEPLOY_FOLDER}" }, "generateUpdatesFilesForAllChannels": true } diff --git a/app-shell/package.json b/app-shell/package.json index a012c2fe174..bf1493b7d47 100644 --- a/app-shell/package.json +++ b/app-shell/package.json @@ -1,7 +1,7 @@ { "name": "@opentrons/app-shell", "productName": "Opentrons", - "version": "3.6.0-beta.0", + "version": "3.6.1", "description": "Opentrons desktop application", "main": "lib/main.js", "scripts": { @@ -21,10 +21,10 @@ }, "homepage": "https://github.com/Opentrons/opentrons", "devDependencies": { - "@opentrons/app": "3.6.0-beta.0" + "@opentrons/app": "3.6.1" }, "dependencies": { - "@opentrons/discovery-client": "3.6.0-beta.0", + "@opentrons/discovery-client": "3.6.1", "@thi.ng/paths": "^1.3.8", "dateformat": "^3.0.3", "electron-debug": "^2.0.0", diff --git a/app/CHANGELOG.md b/app/CHANGELOG.md index 95e5e46f4c8..5a22a26d179 100644 --- a/app/CHANGELOG.md +++ b/app/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + +**Note:** Version bump only for package @opentrons/app + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + +**Note:** Version bump only for package @opentrons/app + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + +**Note:** Version bump only for package @opentrons/app + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/app/package.json b/app/package.json index bbd2ca161f7..8281dfe3b24 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "@opentrons/app", - "version": "3.6.0-beta.0", + "version": "3.6.1", "description": "Opentrons desktop application UI", "main": "src/index.js", "repository": { @@ -21,8 +21,8 @@ "flow-typed": "^2.5.1" }, "dependencies": { - "@opentrons/components": "3.6.0-beta.0", - "@opentrons/shared-data": "3.6.0-beta.0", + "@opentrons/components": "3.6.1", + "@opentrons/shared-data": "3.6.1", "@thi.ng/paths": "^1.3.8", "classnames": "^2.2.5", "events": "^3.0.0", @@ -31,8 +31,8 @@ "lodash": "^4.17.4", "mixpanel-browser": "^2.22.1", "moment": "^2.19.1", - "react": "^16.2.0", - "react-dom": "^16.2.0", + "react": "^16.6.3", + "react-dom": "^16.6.3", "react-hot-loader": "^3.0.0-beta.7", "react-redux": "^5.0.6", "react-router": "^4.2.0", diff --git a/app/src/components/AppSettings/UpdateApp/RestartAppModal.js b/app/src/components/AppSettings/UpdateApp/RestartAppModal.js new file mode 100644 index 00000000000..f755fb07f18 --- /dev/null +++ b/app/src/components/AppSettings/UpdateApp/RestartAppModal.js @@ -0,0 +1,28 @@ +// @flow +import * as React from 'react' + +import {Portal} from '../../portal' +import {ScrollableAlertModal} from '../../modals' +import UpdateAppMessage from './UpdateAppMessage' + +type Props = { + availableVersion: ?string, + applyUpdate: () => mixed, + closeModal: () => mixed, +} +export default function RestartAppModal (props: Props) { + const {availableVersion, applyUpdate, closeModal} = props + return ( + + + + + + ) +} diff --git a/app/src/components/AppSettings/UpdateApp/UpdateAppMessage.js b/app/src/components/AppSettings/UpdateApp/UpdateAppMessage.js new file mode 100644 index 00000000000..39fffc66a83 --- /dev/null +++ b/app/src/components/AppSettings/UpdateApp/UpdateAppMessage.js @@ -0,0 +1,41 @@ +// @flow + +import * as React from 'react' +import styles from './styles.css' + +type Props = { + downloaded?: boolean, +} + +const UPDATE_MESSAGE = ( +

+ We recommend that you update to the latest version.
+ Please note the following: +

+) + +const RESTART_MESSAGE = ( +

+ Restart your app to complete the update.
+ Please note the following: +

+) + +export default function UpdateAppMessage (props: Props) { + const message = props.downloaded ? RESTART_MESSAGE : UPDATE_MESSAGE + return ( + + {message} + +

+ 1) After updating your app, we recommend you update your robot version + to ensure the app and robot versions are in sync. +

+ +

+ 2) If you are using more than one computer to operate your robot, please + update the app on those computers as well. +

+
+ ) +} diff --git a/app/src/components/AppSettings/UpdateApp/UpdateAppModal.js b/app/src/components/AppSettings/UpdateApp/UpdateAppModal.js new file mode 100644 index 00000000000..94288799f08 --- /dev/null +++ b/app/src/components/AppSettings/UpdateApp/UpdateAppModal.js @@ -0,0 +1,74 @@ +// @flow +import * as React from 'react' + +import {Portal} from '../../portal' +import {ScrollableAlertModal} from '../../modals' +import UpdateAppMessage from './UpdateAppMessage' +import ReleaseNotes from '../../ReleaseNotes' + +import type {ShellUpdateState} from '../../../shell' +import type {ButtonProps} from '@opentrons/components' + +type Props = { + update: ShellUpdateState, + availableVersion: ?string, + downloadUpdate: () => mixed, + applyUpdate: () => mixed, + closeModal: () => mixed, +} + +type UpdateAppState = { + showReleaseNotes: boolean, +} + +export default class UpdateAppModal extends React.Component< + Props, + UpdateAppState +> { + constructor (props: Props) { + super(props) + this.state = {showReleaseNotes: false} + } + + setShowReleaseNotes = () => { + this.setState({showReleaseNotes: true}) + } + + render () { + const { + downloadUpdate, + closeModal, + availableVersion, + update: {info}, + } = this.props + const {showReleaseNotes} = this.state + + let children: ?React.Node + let button: ?ButtonProps + + if (showReleaseNotes) { + button = { + children: 'download', + onClick: downloadUpdate, + } + children = + } else { + button = { + children: 'View App Update', + onClick: this.setShowReleaseNotes, + } + children = + } + + return ( + + + {children} + + + ) + } +} diff --git a/app/src/components/AppSettings/UpdateApp/index.js b/app/src/components/AppSettings/UpdateApp/index.js new file mode 100644 index 00000000000..cff45606bd2 --- /dev/null +++ b/app/src/components/AppSettings/UpdateApp/index.js @@ -0,0 +1,28 @@ +// @flow +import * as React from 'react' + +import {SpinnerModal} from '@opentrons/components' +import UpdateAppModal from './UpdateAppModal' +import RestartAppModal from './RestartAppModal' + +import type {ShellUpdateState} from '../../../shell' + +type Props = { + update: ShellUpdateState, + availableVersion: ?string, + checkUpdate: () => mixed, + downloadUpdate: () => mixed, + applyUpdate: () => mixed, + closeModal: () => mixed, +} +export default function UpdateApp (props: Props) { + const {downloaded, downloading} = props.update + + if (downloaded) { + return + } else if (downloading) { + return + } else { + return + } +} diff --git a/app/src/components/AppSettings/UpdateApp/styles.css b/app/src/components/AppSettings/UpdateApp/styles.css new file mode 100644 index 00000000000..f8370529467 --- /dev/null +++ b/app/src/components/AppSettings/UpdateApp/styles.css @@ -0,0 +1,7 @@ +@import '@opentrons/components'; + +.update_message { + @apply --font-body-2-dark; + + margin: 1rem; +} diff --git a/app/src/components/ReleaseNotes/styles.css b/app/src/components/ReleaseNotes/styles.css index b0718ce2133..b6b8f0ba26c 100644 --- a/app/src/components/ReleaseNotes/styles.css +++ b/app/src/components/ReleaseNotes/styles.css @@ -2,7 +2,6 @@ .release_notes { max-height: 100%; - padding-bottom: 3rem; /* push the scrollbar out to the right */ padding-right: 1.5rem; diff --git a/app/src/components/RobotSettings/ReachableRobotBanner.js b/app/src/components/RobotSettings/ReachableRobotBanner.js index 3e15b03b35e..53492a96f7b 100644 --- a/app/src/components/RobotSettings/ReachableRobotBanner.js +++ b/app/src/components/RobotSettings/ReachableRobotBanner.js @@ -18,7 +18,7 @@ const LAST_RESORT = ( const RESTARTING_MESSAGE = (
-

Your robot is restarting, and should be back online shortly.

+

Your robot is restarting and should be back online shortly.

{LAST_RESORT}
) diff --git a/app/src/components/RobotSettings/SelectNetwork/styles.css b/app/src/components/RobotSettings/SelectNetwork/styles.css index ffa57c05ce1..f904a574c95 100644 --- a/app/src/components/RobotSettings/SelectNetwork/styles.css +++ b/app/src/components/RobotSettings/SelectNetwork/styles.css @@ -46,7 +46,6 @@ display: table; width: 80%; margin-top: 0.5rem; - padding-bottom: 3rem; & input, & label, diff --git a/app/src/components/RobotSettings/UpdateRobot/RestartRobotModal.js b/app/src/components/RobotSettings/UpdateRobot/RestartRobotModal.js new file mode 100644 index 00000000000..802541e0713 --- /dev/null +++ b/app/src/components/RobotSettings/UpdateRobot/RestartRobotModal.js @@ -0,0 +1,58 @@ +// @flow +import * as React from 'react' +import {connect} from 'react-redux' +import {push} from 'react-router-redux' + +import {restartRobotServer, clearUpdateResponse} from '../../../http-api-client' +import {AlertModal} from '@opentrons/components' + +import type {Dispatch} from '../../../types' +import type {ViewableRobot} from '../../../discovery' + +type OP = {robot: ViewableRobot} + +type DP = {| + restart: () => mixed, + close: () => mixed, +|} + +type Props = {...$Exact, ...DP} + +export default connect( + null, + mapDispatchToProps +)(RestartRobotModal) + +// TODO (ka 2018-11-27): Clarify heading and messaging with UX +const RESTART_HEADING = 'Update installed' + +function RestartRobotModal (props: Props) { + return ( + + Restart your robot to finish the update. It may take several minutes for + your robot to restart. + + ) +} + +function mapDispatchToProps (dispatch: Dispatch, ownProps: OP): DP { + const {robot} = ownProps + + const close = () => dispatch(push(`/robots/${robot.name}`)) + + return { + close, + restart: () => { + dispatch(restartRobotServer(robot)) + .then(() => dispatch(clearUpdateResponse(robot))) + .then(close) + }, + } +} diff --git a/app/src/components/RobotSettings/UpdateRobot/SkipAppUpdateMessage.js b/app/src/components/RobotSettings/UpdateRobot/SkipAppUpdateMessage.js new file mode 100644 index 00000000000..dee7012c913 --- /dev/null +++ b/app/src/components/RobotSettings/UpdateRobot/SkipAppUpdateMessage.js @@ -0,0 +1,23 @@ +// @flow +import * as React from 'react' +import styles from './styles.css' +import type {VersionProps} from './types.js' +type Props = { + ...$Exact, + onClick: () => mixed, +} + +const SKIP_APP_MESSAGE = + 'If you wish to skip this app update and only sync your robot server with your current app version, please ' +export default function SkipAppUpdateMessage (props: Props) { + const {appVersion, robotVersion} = props + if (appVersion === robotVersion) return null + return ( +

+ {SKIP_APP_MESSAGE} + + click here + . +

+ ) +} diff --git a/app/src/components/RobotSettings/UpdateRobot/SyncRobotMessage.js b/app/src/components/RobotSettings/UpdateRobot/SyncRobotMessage.js new file mode 100644 index 00000000000..a541652085f --- /dev/null +++ b/app/src/components/RobotSettings/UpdateRobot/SyncRobotMessage.js @@ -0,0 +1,48 @@ +// @flow +import * as React from 'react' +import styles from './styles.css' +import type {RobotUpdateInfo} from '../../../http-api-client' +type Props = { + updateInfo: RobotUpdateInfo, + appVersion: string, +} + +const notSyncedMessage = ( + + Your robot server version and app version are out of sync.
+
+) + +export default function SyncRobotMessage (props: Props) { + const { + appVersion, + updateInfo: {type}, + } = props + + if (type === 'upgrade') { + return ( +

+ {notSyncedMessage} + For optimal experience, we recommend you upgrade your robot server + version to match the app version. +

+ ) + } + if (type === 'downgrade') { + return ( +

+ {notSyncedMessage} + You may wish to downgrade to robot server version {appVersion} to ensure + compatibility. +

+ ) + } + return null +} + +const REINSTALL_MESSAGE = + "It looks like your robot is already up to date, but if you're experiencing issues you can re-apply the latest update." + +export function ReinstallMessage () { + return

{REINSTALL_MESSAGE}

+} diff --git a/app/src/components/RobotSettings/UpdateRobot/UpdateAppMessage.js b/app/src/components/RobotSettings/UpdateRobot/UpdateAppMessage.js new file mode 100644 index 00000000000..8ff798bb483 --- /dev/null +++ b/app/src/components/RobotSettings/UpdateRobot/UpdateAppMessage.js @@ -0,0 +1,34 @@ +// @flow +import * as React from 'react' +import semver from 'semver' +import styles from './styles.css' +import type {VersionProps} from './types.js' + +const NEWER_VERSION = ( + A newer version of the robot server is available. +) +const RECOMMEND_UPDATE_APP_FIRST = ( + + We recommend you update your app first before updating your robot + server to ensure you have received all the latest improvements. + +) +const UPDATE_APP = ( + + Please update your app to receive all the latest improvements and robot + server update. + +) + +export default function UpdateAppMessage (props: VersionProps) { + const {appVersion, robotVersion} = props + const versionsMatch = semver.eq(appVersion, robotVersion) + + return ( +

+ {NEWER_VERSION} +
+ {!versionsMatch ? RECOMMEND_UPDATE_APP_FIRST : UPDATE_APP} +

+ ) +} diff --git a/app/src/components/RobotSettings/UpdateRobot/UpdateRobotModal.js b/app/src/components/RobotSettings/UpdateRobot/UpdateRobotModal.js new file mode 100644 index 00000000000..9ed9f9b15e8 --- /dev/null +++ b/app/src/components/RobotSettings/UpdateRobot/UpdateRobotModal.js @@ -0,0 +1,192 @@ +// @flow +import * as React from 'react' +import {connect} from 'react-redux' +import {Link} from 'react-router-dom' +import {push} from 'react-router-redux' +import semver from 'semver' + +import { + updateRobotServer, + makeGetRobotUpdateInfo, + setIgnoredUpdate, +} from '../../../http-api-client' + +import {getRobotApiVersion} from '../../../discovery' + +import { + CURRENT_VERSION, + API_RELEASE_NOTES, + getShellUpdateState, +} from '../../../shell' + +import {ScrollableAlertModal} from '../../modals' +import VersionList from './VersionList' +import UpdateAppMessage from './UpdateAppMessage' +import SkipAppUpdateMessage from './SkipAppUpdateMessage' +import SyncRobotMessage, {ReinstallMessage} from './SyncRobotMessage' +import ReleaseNotes from '../../ReleaseNotes' + +import type {State, Dispatch} from '../../../types' +import type {ShellUpdateState} from '../../../shell' +import type {ViewableRobot} from '../../../discovery' +import type {RobotUpdateInfo} from '../../../http-api-client' +import type {ButtonProps} from '@opentrons/components' + +export type VersionProps = { + appVersion: string, + robotVersion: string, + availableUpdate: string, +} + +type OP = {robot: ViewableRobot} + +type SP = {| + appVersion: string, + robotVersion: string, + appUpdate: ShellUpdateState, + robotUpdateInfo: RobotUpdateInfo, +|} + +type DP = {dispatch: Dispatch} + +type Props = { + ...$Exact, + ...SP, + ignoreUpdate: () => mixed, + update: () => mixed, +} + +type UpdateRobotState = { + showReleaseNotes: boolean, +} + +class UpdateRobotModal extends React.Component { + constructor (props) { + super(props) + this.state = {showReleaseNotes: false} + } + + setShowReleaseNotes = () => { + this.setState({showReleaseNotes: true}) + } + + render () { + const { + update, + ignoreUpdate, + appVersion, + robotVersion, + robotUpdateInfo, + appUpdate: {available: appUpdateAvailable, info: appUpdateInfo}, + } = this.props + const {showReleaseNotes} = this.state + const appUpdateVersion = appUpdateInfo && appUpdateInfo.version + const robotUpdateVersion = robotUpdateInfo.version + const availableUpdate = appUpdateVersion || robotUpdateVersion + const versionProps = {appVersion, robotVersion, availableUpdate} + + const heading = !semver.eq(robotVersion, availableUpdate) + ? `Version ${availableUpdate} available` + : 'Robot is up to date' + + let message: ?React.Node + let skipMessage: ?React.Node + let button: ?ButtonProps + + if (showReleaseNotes) { + button = { + children: 'Upgrade Robot', + onClick: update, + } + } else if (appUpdateAvailable) { + message = + skipMessage = ( + console.log('skip and sync')} + {...versionProps} + /> + ) + button = { + Component: Link, + to: '/menu/app/update', + children: 'View App Update', + } + } else if (robotUpdateInfo.type) { + message = ( + + ) + if (robotUpdateInfo.type === 'upgrade') { + button = { + children: 'View Robot Server Update', + onClick: this.setShowReleaseNotes, + } + } else if (robotUpdateInfo.type === 'downgrade') { + button = { + children: 'Downgrade Robot', + onClick: update, + } + } + } else { + message = + button = { + children: 'Reinstall', + onClick: update, + } + } + + return ( + + {showReleaseNotes ? ( + + ) : ( + + {message} + + {skipMessage} + + )} + + ) + } +} + +function makeMapStateToProps (): (State, OP) => SP { + const getRobotUpdateInfo = makeGetRobotUpdateInfo() + + return (state, ownProps) => ({ + appVersion: CURRENT_VERSION, + robotVersion: getRobotApiVersion(ownProps.robot) || 'Unknown', + appUpdate: getShellUpdateState(state), + robotUpdateInfo: getRobotUpdateInfo(state, ownProps.robot), + }) +} + +function mergeProps (stateProps: SP, dispatchProps: DP, ownProps: OP): Props { + const {robot} = ownProps + const {robotUpdateInfo} = stateProps + const {dispatch} = dispatchProps + + const close = () => dispatch(push(`/robots/${robot.name}`)) + let ignoreUpdate = robotUpdateInfo.type + ? () => + dispatch(setIgnoredUpdate(robot, robotUpdateInfo.version)).then(close) + : close + + return { + ...stateProps, + ...ownProps, + ignoreUpdate, + update: () => dispatch(updateRobotServer(robot)), + } +} + +export default connect( + makeMapStateToProps, + null, + mergeProps +)(UpdateRobotModal) diff --git a/app/src/components/RobotSettings/UpdateRobot/VersionList.js b/app/src/components/RobotSettings/UpdateRobot/VersionList.js new file mode 100644 index 00000000000..1aaede85b24 --- /dev/null +++ b/app/src/components/RobotSettings/UpdateRobot/VersionList.js @@ -0,0 +1,14 @@ +// @flow +import * as React from 'react' +import styles from './styles.css' +import type {VersionProps} from './types.js' + +export default function VersionList (props: VersionProps) { + return ( +
    +
  1. Your current app version: {props.appVersion}
  2. +
  3. Your current robot server version: {props.robotVersion}
  4. +
  5. Available update: {props.availableUpdate}
  6. +
+ ) +} diff --git a/app/src/components/RobotSettings/UpdateRobot/index.js b/app/src/components/RobotSettings/UpdateRobot/index.js new file mode 100644 index 00000000000..d1ec3baab3a --- /dev/null +++ b/app/src/components/RobotSettings/UpdateRobot/index.js @@ -0,0 +1,54 @@ +// @flow +import * as React from 'react' +import {connect} from 'react-redux' + +import {makeGetRobotUpdateRequest} from '../../../http-api-client' + +import {SpinnerModal} from '@opentrons/components' +import UpdateRobotModal from './UpdateRobotModal' +import RestartRobotModal from './RestartRobotModal' + +import type {State} from '../../../types' +import type {ViewableRobot} from '../../../discovery' +import type {RobotServerUpdate} from '../../../http-api-client' + +type OP = {robot: ViewableRobot} + +type SP = {| + updateRequest: RobotServerUpdate, +|} + +type Props = { + ...$Exact, + ...SP, +} + +export default connect( + makeMapStateToProps, + null +)(UpdateRobot) + +function UpdateRobot (props: Props) { + const {updateRequest, robot} = props + if (updateRequest.response) { + return + } + if (updateRequest.inProgress) { + // TODO (ka 2018-11-27): Clarify update message with UX + return + } else { + return + } +} + +function makeMapStateToProps (): (State, OP) => Props { + const getRobotUpdateRequest = makeGetRobotUpdateRequest() + + return (state, ownProps) => { + const {robot} = ownProps + return { + robot, + updateRequest: getRobotUpdateRequest(state, ownProps.robot), + } + } +} diff --git a/app/src/components/RobotSettings/UpdateRobot/styles.css b/app/src/components/RobotSettings/UpdateRobot/styles.css new file mode 100644 index 00000000000..8b28190eac1 --- /dev/null +++ b/app/src/components/RobotSettings/UpdateRobot/styles.css @@ -0,0 +1,17 @@ +@import '@opentrons/components'; + +.version_list { + @apply --font-body-1-dark; + + margin: 0 0 1.5rem 2rem; +} + +.sync_link { + color: var(--c-blue); + text-decoration: underline; + cursor: pointer; +} + +.sync_message { + margin-bottom: 1.5rem; +} diff --git a/app/src/components/RobotSettings/UpdateRobot/types.js b/app/src/components/RobotSettings/UpdateRobot/types.js new file mode 100644 index 00000000000..2c205d88c13 --- /dev/null +++ b/app/src/components/RobotSettings/UpdateRobot/types.js @@ -0,0 +1,7 @@ +// @flow + +export type VersionProps = { + appVersion: string, + robotVersion: string, + availableUpdate: string, +} diff --git a/app/src/components/modals/styles.css b/app/src/components/modals/styles.css index c52871116ed..132a5cdc0eb 100644 --- a/app/src/components/modals/styles.css +++ b/app/src/components/modals/styles.css @@ -36,7 +36,9 @@ .bottom_button { margin-left: 1rem; - width: 10rem; + width: auto; + min-width: 10rem; + padding: 0.5rem 1.5rem; } .scrollable_modal { @@ -51,4 +53,5 @@ .scrollable_modal_scroll { max-height: 100%; overflow-y: auto; + padding-bottom: 3rem; } diff --git a/app/src/config/index.js b/app/src/config/index.js index b062ed77486..7dfafa3787a 100644 --- a/app/src/config/index.js +++ b/app/src/config/index.js @@ -56,6 +56,11 @@ export type Config = { discovery: { candidates: string | Array, }, + + // internal development flags + devInternal?: { + newUpdateModal?: boolean, + }, } type UpdateConfigAction = {| diff --git a/app/src/pages/More/AppSettings.js b/app/src/pages/More/AppSettings.js index cdc03249260..95695e64416 100644 --- a/app/src/pages/More/AppSettings.js +++ b/app/src/pages/More/AppSettings.js @@ -2,9 +2,12 @@ // view info about the app and update import * as React from 'react' import {connect} from 'react-redux' +import {getIn} from '@thi.ng/paths' import {Route, Switch, Redirect, type ContextRouter} from 'react-router' import {push} from 'react-router-redux' +import {getConfig} from '../../config' + import { getShellUpdateState, getAvailableShellUpdate, @@ -16,6 +19,7 @@ import { import Page from '../../components/Page' import AppSettings, {AppUpdateModal} from '../../components/AppSettings' +import UpdateApp from '../../components/AppSettings/UpdateApp' import {ErrorModal} from '../../components/modals' import type {State} from '../../types' @@ -26,6 +30,7 @@ type OP = ContextRouter type SP = { update: ShellUpdateState, availableVersion: ?string, + __featureEnabled: boolean, } type DP = { @@ -37,6 +42,8 @@ type DP = { type Props = OP & SP & DP +const __FEATURE_FLAG = 'devInternal.newUpdateModal' + export default connect( mapStateToProps, mapDispatchToProps @@ -49,6 +56,7 @@ function AppSettingsPage (props: Props) { closeModal, update: {available, seen, error}, match: {path}, + __featureEnabled, } = props return ( @@ -64,7 +72,11 @@ function AppSettingsPage (props: Props) { path={`${path}/update`} render={() => !error ? ( - + __featureEnabled ? ( + + ) : ( + + ) ) : ( mixed, } +const __FEATURE_FLAG = 'devInternal.newUpdateModal' + export default withRouter( connect( makeMapStateToProps, @@ -100,7 +106,13 @@ function RobotSettingsPage (props: Props) { } + render={() => { + if (props.__featureEnabled) { + return + } else { + return + } + }} /> SP { homeInProgress: homeRequest && homeRequest.inProgress, homeError: homeRequest && homeRequest.error, showConnectAlert: !connectRequest.inProgress && !!connectRequest.error, + __featureEnabled: !!getIn(getConfig(state), __FEATURE_FLAG), } } } diff --git a/app/src/robot/api-client/client.js b/app/src/robot/api-client/client.js index a60579ff1be..0826736d42a 100755 --- a/app/src/robot/api-client/client.js +++ b/app/src/robot/api-client/client.js @@ -474,7 +474,12 @@ export default function client (dispatch) { const labware = {_id, name, slot, type, isTiprack} if (isTiprack && apiContainer.instruments.length > 0) { - labware.calibratorMount = apiContainer.instruments[0].mount + // if tiprack used by both pipettes, prefer single for calibration + const calibrator = + find(apiContainer.instruments, {channels: 1}) || + apiContainer.instruments[0] + + if (calibrator) labware.calibratorMount = calibrator.mount } update.labwareBySlot[slot] = labware diff --git a/app/src/robot/test/api-client.test.js b/app/src/robot/test/api-client.test.js index 791401bef48..0dd10adb4b5 100755 --- a/app/src/robot/test/api-client.test.js +++ b/app/src/robot/test/api-client.test.js @@ -412,7 +412,10 @@ describe('api client', () => { slot: '1', name: 'a', type: 'tiprack', - instruments: [{mount: 'right'}], + instruments: [ + {mount: 'left', channels: 8}, + {mount: 'right', channels: 1}, + ], }, {_id: 2, slot: '5', name: 'b', type: 'B'}, {_id: 3, slot: '9', name: 'c', type: 'C'}, diff --git a/app/src/shell/index.js b/app/src/shell/index.js index 45249ab041a..0dcb429fed4 100644 --- a/app/src/shell/index.js +++ b/app/src/shell/index.js @@ -26,7 +26,11 @@ const log = createLogger(__filename) export * from './update' export * from './api-update' -export {CURRENT_VERSION, CURRENT_RELEASE_NOTES} +const API_RELEASE_NOTES = CURRENT_RELEASE_NOTES.replace( + /([\S\s]*?)/, + '' +) +export {CURRENT_VERSION, CURRENT_RELEASE_NOTES, API_RELEASE_NOTES} export const shellReducer = combineReducers({ update: updateReducer, diff --git a/appveyor.yml b/appveyor.yml index 9ceabbce130..57a49b82951 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,8 +11,8 @@ environment: MAKE: C:\MinGW\bin\mingw32-make.exe # publish configuration - OT_BUCKET_APP: opentrons-app - OT_FOLDER_APP: builds + OT_APP_DEPLOY_BUCKET: opentrons-app + OT_APP_DEPLOY_FOLDER: builds OT_APP_MIXPANEL_ID: secure: W9ZdkT5jR5zZwQm1PMRzDNSZ1qFizfqGMIYv5hyGXPhpbzOPtyAlbJYfQMJ1Y+H+ @@ -57,7 +57,7 @@ deploy: # TODO(mc, 2018-03-26): use AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY access_key_id: $(AWS_ACCESS_KEY) secret_access_key: $(AWS_SECRET_KEY) - bucket: $(OT_BUCKET_APP) - folder: $(OT_FOLDER_APP) + bucket: $(OT_APP_DEPLOY_BUCKET) + folder: $(OT_APP_DEPLOY_FOLDER) set_public: true artifact: App diff --git a/components/CHANGELOG.md b/components/CHANGELOG.md index 9cfca1fef07..45b5135c5b8 100644 --- a/components/CHANGELOG.md +++ b/components/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + +**Note:** Version bump only for package @opentrons/components + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + +**Note:** Version bump only for package @opentrons/components + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + +**Note:** Version bump only for package @opentrons/components + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/components/package.json b/components/package.json index 7df0ef3a2d1..a4a5ece175b 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "@opentrons/components", - "version": "3.6.0-beta.0", + "version": "3.6.1", "description": "React components library for Opentrons' projects", "main": "src/index.js", "style": "src/index.css", @@ -21,7 +21,7 @@ "peerDependencies": { "classnames": "^2.2.5", "lodash": "^4.17.4", - "react": "^16.2.0", + "react": "^16.6.3", "react-router-dom": "^4.2.2" }, "dependencies": { diff --git a/components/src/__tests__/__snapshots__/lists.test.js.snap b/components/src/__tests__/__snapshots__/lists.test.js.snap index 8e825c41569..9553b70e3d8 100644 --- a/components/src/__tests__/__snapshots__/lists.test.js.snap +++ b/components/src/__tests__/__snapshots__/lists.test.js.snap @@ -111,6 +111,7 @@ exports[`ListItem renders ListItem without icon correctly 1`] = ` exports[`TitledList renders TitledList with children correctly 1`] = `
@@ -137,6 +138,7 @@ exports[`TitledList renders TitledList with children correctly 1`] = ` exports[`TitledList renders TitledList with onMouseEnter & onMouseLeave correctly 1`] = `
@@ -156,6 +158,7 @@ exports[`TitledList renders TitledList with onMouseEnter & onMouseLeave correctl exports[`TitledList renders TitledList with optional icon correctly 1`] = `
@@ -175,6 +178,7 @@ exports[`TitledList renders TitledList with optional icon correctly 1`] = ` exports[`TitledList renders TitledList without icon correctly 1`] = `
@@ -194,6 +198,7 @@ exports[`TitledList renders TitledList without icon correctly 1`] = ` exports[`TitledList renders collapsed TitledList correctly 1`] = `
@@ -233,6 +238,7 @@ exports[`TitledList renders collapsed TitledList correctly 1`] = ` exports[`TitledList renders expanded TitledList correctly 1`] = `
diff --git a/components/src/deck/ContainerNameOverlay.js b/components/src/deck/ContainerNameOverlay.js index 6c2948daf0d..e30d7c7d0f2 100644 --- a/components/src/deck/ContainerNameOverlay.js +++ b/components/src/deck/ContainerNameOverlay.js @@ -1,6 +1,6 @@ // @flow import * as React from 'react' -import {SLOT_HEIGHT_MM} from './constants' +import {SLOT_RENDER_HEIGHT} from '@opentrons/shared-data' import styles from './LabwareContainer.css' type Props = { @@ -22,7 +22,7 @@ export function ContainerNameOverlay (props: Props) { return ( - + { if (slot === TRASH_SLOTNAME) return null - const props = {slot, width: SLOT_WIDTH_MM, height: SLOT_HEIGHT_MM} + const props = {slot, width: SLOT_RENDER_WIDTH, height: SLOT_RENDER_HEIGHT} const transform = `translate(${[ - SLOT_WIDTH_MM * col + SLOT_SPACING_MM * (col + 1), - SLOT_HEIGHT_MM * row + SLOT_SPACING_MM * (row + 1), + SLOT_RENDER_WIDTH * col + SLOT_SPACING_MM * (col + 1), + SLOT_RENDER_HEIGHT * row + SLOT_SPACING_MM * (row + 1), ].join(',')})` return ( diff --git a/components/src/deck/LabwareContainer.js b/components/src/deck/LabwareContainer.js index 79373441598..0b5b06e7a7b 100644 --- a/components/src/deck/LabwareContainer.js +++ b/components/src/deck/LabwareContainer.js @@ -1,6 +1,6 @@ // @flow import * as React from 'react' -import {SLOT_HEIGHT_MM, SLOT_WIDTH_MM} from '@opentrons/shared-data' +import {SLOT_RENDER_HEIGHT, SLOT_RENDER_WIDTH} from '@opentrons/shared-data' import styles from './LabwareContainer.css' const defs = {roundSlotClipPath: 'roundSlotClipPath'} // TODO: import these defs instead of hard-coding in applications? Or should they be passed to children? @@ -16,8 +16,8 @@ type Props = { export default function LabwareContainer (props: Props) { const {x, y, highlighted, children} = props - const height = props.height || SLOT_HEIGHT_MM - const width = props.width || SLOT_WIDTH_MM + const height = props.height || SLOT_RENDER_HEIGHT + const width = props.width || SLOT_RENDER_WIDTH return ( diff --git a/components/src/deck/LabwareOutline.js b/components/src/deck/LabwareOutline.js index b92ff3b8fbf..2d7b9a54a88 100644 --- a/components/src/deck/LabwareOutline.js +++ b/components/src/deck/LabwareOutline.js @@ -1,7 +1,7 @@ // @flow import * as React from 'react' import cx from 'classnames' -import {SLOT_WIDTH_MM, SLOT_HEIGHT_MM} from './constants.js' +import {SLOT_RENDER_WIDTH, SLOT_RENDER_HEIGHT} from '@opentrons/shared-data' import styles from './Labware.css' type Props = {className?: ?string} @@ -13,7 +13,7 @@ export default function LabwareOutline (props: Props) { return } diff --git a/components/src/deck/constants.js b/components/src/deck/constants.js index e2b3c233758..bb03d199117 100644 --- a/components/src/deck/constants.js +++ b/components/src/deck/constants.js @@ -1,7 +1,5 @@ // @flow // ========= OT2 DECK =============== -import {SLOT_WIDTH_MM, SLOT_HEIGHT_MM} from '@opentrons/shared-data' - export const SLOTNAME_MATRIX = [ // used for deckmap ['10', '11', '12'], ['7', '8', '9'], @@ -16,7 +14,3 @@ export const TRASH_SLOTNAME = '12' // Slot dims in mm export const SLOT_SPACING_MM = 5 export const SLOT_OFFSET_MM = 10 -export { - SLOT_WIDTH_MM, - SLOT_HEIGHT_MM, -} diff --git a/components/src/interaction-enhancers/ClickOutside.js b/components/src/interaction-enhancers/ClickOutside.js new file mode 100644 index 00000000000..5c28fbc8c92 --- /dev/null +++ b/components/src/interaction-enhancers/ClickOutside.js @@ -0,0 +1,47 @@ +// @flow +import * as React from 'react' + +type Props = { + onClickOutside: ?(MouseEvent => mixed), + children: ({ref: React.Ref<*>}) => React.Element<*>, +} + +export default class ClickOutside extends React.Component { + wrapperRef: ?Element + + constructor (props: Props) { + super(props) + this.wrapperRef = null + } + + componentDidMount () { + document.addEventListener('mousedown', this.handleClickOutside) + } + componentWillUnmount () { + document.removeEventListener('mousedown', this.handleClickOutside) + } + setWrapperRef = (el: ?Element) => { this.wrapperRef = el } + + handleClickOutside = (event: MouseEvent) => { + const clickedElem = event.target + + if (!(clickedElem instanceof Node)) { + // NOTE: this is some flow type checking funkiness + // TODO Ian 2018-05-24 use assert. + console.warn('expected clicked element to be Node - something went wrong in ClickOutside') + return + } + + if ( + this.props.onClickOutside && + this.wrapperRef && + !this.wrapperRef.contains(clickedElem) + ) { + this.props.onClickOutside(event) + } + } + + render () { + return this.props.children({ref: this.setWrapperRef}) + } +} diff --git a/components/src/interaction-enhancers/ClickOutside.md b/components/src/interaction-enhancers/ClickOutside.md new file mode 100644 index 00000000000..f4578e4e90e --- /dev/null +++ b/components/src/interaction-enhancers/ClickOutside.md @@ -0,0 +1,19 @@ +`ClickOutside` is a "function as children" component that calls its `onClickOutside` whenever a user clicks outside of the child. + +The `ref` parameter in the `children` function must be passed into the wrapped child component. + +```js +initialState = {timesClickedOutside: 0} + +function handleClickOutside () { + setState({timesClickedOutside: state.timesClickedOutside + 1}) +} + + + {({ref}) => +
+ You clicked outside this box {state.timesClickedOutside} times +
+ } +
+``` diff --git a/components/src/interaction-enhancers/ExampleClickOutside.js b/components/src/interaction-enhancers/ExampleClickOutside.js deleted file mode 100644 index c63792fdee9..00000000000 --- a/components/src/interaction-enhancers/ExampleClickOutside.js +++ /dev/null @@ -1,89 +0,0 @@ -// @flow -import * as React from 'react' -import clickOutside from './clickOutside' -import type {ClickOutsideInterface} from './clickOutside' - -type InnerProps = {counter: number} & ClickOutsideInterface - -function WrapMe (props: InnerProps) { - return ( -
-

Click outside of this!

- Outside click count is {props.counter} -

Clicking anywhere inside here does not increment the counter

-
- ) -} - -class WrapMeClass extends React.Component { - render () { - const {passRef, counter} = this.props - return ( -
- Clicked outside {counter} times -
- ) - } -} - -// NOTE: this `BadWrapMe` ensures that flow types on clickOutside work as expected -// TODO Ian 2018-05-25 write flow-typed tests for this??? - -// type BadInnerProps = {counter: number} // NO ClickOutsideInterface -// -// function BadWrapMe (props: BadInnerProps) { -// return ( -//
-//

Click outside of this!

-// Outside click count is {props.counter} -//

Clicking anywhere inside here does not increment the counter

-//
-// ) -// } - -type Props = {} -type State = {counter1: number, counter2: number} - -// NOTE: this is just for react-styleguidist static documentation generator -export default class ExampleClickOutside extends React.Component { - Example: * - ClassExample: * - onClickOutside1: () => void - onClickOutside2: () => void - - constructor (props: Props) { - super(props) - - this.state = {counter1: 0, counter2: 0} - - this.onClickOutside1 = () => { - this.setState({counter1: this.state.counter1 + 1}) - } - - this.onClickOutside2 = () => { - this.setState({counter2: this.state.counter2 + 1}) - } - - this.Example = clickOutside(WrapMe) - this.ClassExample = clickOutside(WrapMeClass) - } - - render () { - // const BadExample = clickOutside(BadWrapMe) - const Example = this.Example - const ClassExample = this.ClassExample - - return ( -
- Functional Component Example - - -
- - Class Component Example - - {/* */} -
- ) - } -} diff --git a/components/src/interaction-enhancers/ExampleClickOutside.md b/components/src/interaction-enhancers/ExampleClickOutside.md deleted file mode 100644 index c0cfb377605..00000000000 --- a/components/src/interaction-enhancers/ExampleClickOutside.md +++ /dev/null @@ -1,12 +0,0 @@ -`clickOutside` is a HOC adds an `onClickOutside` props to a component that will be called whenever a user clicks outside that component. - -This won't work with just any component. The component must implement a prop `passRef` which `clickOutside` can use to get the `ref` of the outermost DOM element. - -A minimal example: `function MyComponent (passRef) {return
}` - -`clickOutside` exposes the type `ClickOutsideInterface` that can be union-typed with your component's Props type to make sure it exposes `passRef`. - -```js -// See ExampleClickOutside.js for the code! - -``` diff --git a/components/src/interaction-enhancers/clickOutside.js b/components/src/interaction-enhancers/clickOutside.js deleted file mode 100644 index bb37008cf80..00000000000 --- a/components/src/interaction-enhancers/clickOutside.js +++ /dev/null @@ -1,108 +0,0 @@ -// @flow -import * as React from 'react' - -type WrapperRefType = ?Element - -export type ClickOutsideInterface = { - passRef: WrapperRefType => mixed, -} - -type HocProps = { - onClickOutside: ?(MouseEvent => mixed), -} - -export default function clickOutside< - WrappedProps: ClickOutsideInterface, - InnerProps: $Diff, - Props: InnerProps & HocProps -> (WrappedComponent: React.ComponentType): React.ComponentType { - return class ClickOutsideWrapper extends React.Component { - wrapperRef: WrapperRefType - - constructor (props: Props) { - super(props) - this.wrapperRef = null - } - - setWrapperRef = (element: WrapperRefType) => { - this.wrapperRef = element - } - - handleClickOutside = (event: MouseEvent) => { - const clickedElem = event.target - - if (!(clickedElem instanceof Node)) { - // NOTE: this is some flow type checking funkiness - // TODO Ian 2018-05-24 use assert. - console.warn('expected clicked element to be Node - something went wrong in ClickOutside') - return - } - - if ( - this.props.onClickOutside && - this.wrapperRef && - !this.wrapperRef.contains(clickedElem) - ) { - this.props.onClickOutside(event) - } - } - - componentDidMount () { - document.addEventListener('mousedown', this.handleClickOutside) - } - - componentWillUnmount () { - document.removeEventListener('mousedown', this.handleClickOutside) - } - - render () { - const {onClickOutside, ...passedProps} = this.props - return - } - } -} - -// TODO: BC 2018-7-25 deprecate HOC version (clickOutside) and move to just ClickOutside FOC -type ClickOutsideProps = { - onClickOutside: ?(MouseEvent => mixed), - children: ({ref: React.Ref<*>}) => React.Element<*>, -} -export class ClickOutside extends React.Component { - wrapperRef: ?Element - - constructor (props: ClickOutsideProps) { - super(props) - this.wrapperRef = null - } - - componentDidMount () { - document.addEventListener('mousedown', this.handleClickOutside) - } - componentWillUnmount () { - document.removeEventListener('mousedown', this.handleClickOutside) - } - setWrapperRef = (el: ?Element) => { this.wrapperRef = el } - - handleClickOutside = (event: MouseEvent) => { - const clickedElem = event.target - - if (!(clickedElem instanceof Node)) { - // NOTE: this is some flow type checking funkiness - // TODO Ian 2018-05-24 use assert. - console.warn('expected clicked element to be Node - something went wrong in ClickOutside') - return - } - - if ( - this.props.onClickOutside && - this.wrapperRef && - !this.wrapperRef.contains(clickedElem) - ) { - this.props.onClickOutside(event) - } - } - - render () { - return this.props.children({ref: this.setWrapperRef}) - } -} diff --git a/components/src/interaction-enhancers/index.js b/components/src/interaction-enhancers/index.js index ba639e548e2..bb821082ac5 100644 --- a/components/src/interaction-enhancers/index.js +++ b/components/src/interaction-enhancers/index.js @@ -1,12 +1,9 @@ // @flow -import clickOutside, {ClickOutside} from './clickOutside' +import ClickOutside from './ClickOutside' import HandleKeypress from './HandleKeypress' import IntervalWrapper from './IntervalWrapper' -export type {ClickOutsideInterface} from './clickOutside' - export { - clickOutside, ClickOutside, HandleKeypress, IntervalWrapper, diff --git a/components/src/lists/TitledList.js b/components/src/lists/TitledList.js index 684eae73568..216c9233eb0 100644 --- a/components/src/lists/TitledList.js +++ b/components/src/lists/TitledList.js @@ -22,6 +22,8 @@ type ListProps = { description?: React.Node, /** optional click action (on title div, not children) */ onClick?: (event: SyntheticMouseEvent<>) => mixed, + /** optional right click action (on wrapping div) */ + onContextMenu?: (event: SyntheticMouseEvent<>) => mixed, /** optional mouseEnter action */ onMouseEnter?: (event: SyntheticMouseEvent<>) => mixed, /** optional mouseLeave action */ @@ -42,7 +44,7 @@ type ListProps = { * An ordered list with optional title, icon, and description. */ export default function TitledList (props: ListProps) { - const {iconName, disabled, onCollapseToggle, iconProps, onMouseEnter, onMouseLeave} = props + const {iconName, disabled, onCollapseToggle, iconProps, onMouseEnter, onMouseLeave, onContextMenu} = props const collapsible = onCollapseToggle != null const onClick = !disabled @@ -74,7 +76,7 @@ export default function TitledList (props: ListProps) { const iconClass = cx(styles.title_bar_icon, styles.icon_left_of_title, iconProps && iconProps.className) return ( -
+
{iconName && ( diff --git a/discovery-client/CHANGELOG.md b/discovery-client/CHANGELOG.md index 428535bfa73..f1fe0e43fa6 100644 --- a/discovery-client/CHANGELOG.md +++ b/discovery-client/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + +**Note:** Version bump only for package @opentrons/discovery-client + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + +**Note:** Version bump only for package @opentrons/discovery-client + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + +**Note:** Version bump only for package @opentrons/discovery-client + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/discovery-client/package.json b/discovery-client/package.json index 47308f1bff1..515d1a2873d 100644 --- a/discovery-client/package.json +++ b/discovery-client/package.json @@ -1,6 +1,6 @@ { "name": "@opentrons/discovery-client", - "version": "3.6.0-beta.0", + "version": "3.6.1", "description": "Node.js client for discovering Opentrons robots on the network", "main": "lib/index.js", "bin": { diff --git a/labware-designer/CHANGELOG.md b/labware-designer/CHANGELOG.md index 6f3617f8daa..746b910c41b 100644 --- a/labware-designer/CHANGELOG.md +++ b/labware-designer/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + +**Note:** Version bump only for package labware-designer + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + +**Note:** Version bump only for package labware-designer + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + +**Note:** Version bump only for package labware-designer + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/labware-designer/README.md b/labware-designer/README.md index 8916b988602..1b32a95c356 100644 --- a/labware-designer/README.md +++ b/labware-designer/README.md @@ -1,15 +1,24 @@ # Overview -This is a simple browser tool which can be used to generate labware definitions for _regular_ labware. -In the coming months, we will be adding more features to the GUI as well as the ability to generate definitions -for _irregular_ labware. +This is a simple browser tool which can be used to generate labware definitions for _regular_ labware (labware that is +laid out on a grid, and where all wells have consistent dimensions), or _irregular_ labware. ### What is a 'regular' labware? -* A labware in which the grid shape is uniform -..* No uneven number of rows or columns -* Spacing between columns and rows remains consistent throughout the labware -* The overall height remains consistent throughout the labware +This is a geometric sense of the word "regular". A labware in which: + +- grid shape is uniform (a single regular grid, where each column and each row has a consistent number of wells) +- spacing between columns and rows remains consistent throughout the labware +- the overall height remains consistent throughout the labware + +### What is an 'irregular' labware? + +Any labware that does not meet the criteria of 'regular'. A labware is irregular if it has: + +- more than one grid defining the x-y position of wells (such as a diamond arrangement) +- differing well dimensions (depth, diameter, shape, etc) +- differing numbers of wells from row to row or column to column +- any other dimensional irregularity ## Launching the Tool @@ -24,149 +33,482 @@ OR 1. Type `make` within the `opentrons/labware-designer` folder 2. Open `labware-designer/dist/index.html` in your browser -Once you have the browser page open, you should be able to go to the browser console. -* Right Click to find the `inspector` or use whichever shortcut you may have associated with this - -When you are in the console, you can use the global variable `sharedData` and use any public functions -which are exported in that project. +- In the browser window, open the console (in Chrome, right click in the middle of the page, select "Inspect" and then select the "Console" tab--other browsers vary but are similar). +- In the console, you can use the global variable `sharedData` and use any public functions which are exported in that project. ## What function do I need to use? -The generator function is called `createRegularLabware()`. You can use it in the browser -by typing `sharedData.createRegularLabware(input)` + +The generator functions are called `createRegularLabware` and `createIrregularLabware`. You can use it in the browser +by typing `sharedData.createRegularLabware(input)` or `sharedData.createIrregularLabware(input)` ### What data is needed? -It takes in an `input` object of the following shape: +To build a *regular* labware, the `input` object should have the following shape: + +``` input = { - metadata, - parameters, - offset, - dimensions, - grid, - spacing, - well, - brand, + "metadata": metadata, + "parameters": parameters, + "offset": offset, + "dimensinos": dimensions, + "grid": grid, + "spacing": spacing, + "well": well, + "brand": brand, } +``` The above inputs are all required except for `brand`. Each individual input has the following shape(s). -Variables in bold signify that they are required, those in italics are optional. +#### Metadata + +``` metadata = { - **name**: string, - **displayCategory**: string, - _displayVolumeUnits_: string, - _displayLengthUnits_: string, - _tags_: array of strings, + "displayName": string, + "displayCategory": string, + "displayVolumeUnits": optional string, + "displayLengthUnits": optional string, + "tags": optional array of strings, } -* Name is what you choose to refer to the container as (i.e.) `96-flat` -* displayCategory is what category the container type falls into. There are currently five options: -..* wellPlate -..* tuberack -..* tiprack -..* trough -..* trash -* Tags are generic words that describe this labware such as shape of bottom, color or other important factors +``` + +"displayName" is the name of the labware in the Opentrons Run App, Protocol Designer, and other client apps (i.e.: "Opentrons 96 PCR plate" or similar) + +"displayCategory" is what category the container type falls into. There are currently five options: + +- "wellPlate" +- "tuberack" +- "tiprack" +- "trough" +- "trash" +"tags" is a list of generic words that describe this labware such as shape of bottom, color or other important factors + +#### Parameters + +``` parameters = { - **format**: string, - **isTiprack**: boolean, - _tipLength_: number, - _loadName_: string, + "format": string, + "isTiprack": boolean, + "tipLength": optional number (required if "isTiprack" is true), } -* Format is used to determine how a multichannel pipette may (or may not) interact with this labware. -There are currently four categories -..* irregular (any type of container a multichannel cannot access -- most tuberacks, irregular labware etc) -..* 96Standard (any container in a 96 format: well plate or tiprack) -..* 384Standard (any container in a 96 format: well plate or tiprack) -..* trough -* loadName is generated by the program as: [brand] _ [num.wells]_ [displayCategory]_ [totalVol]_ [displayVolumeUnits] +``` +Format is used to determine how a multichannel pipette may (or may not) interact with this labware. + +There are currently four categories: + +- irregular (any type of container a multichannel cannot access -- most tuberacks, irregular labware etc) +- 96Standard (any container in a 96 format: well plate or tiprack) +- 384Standard (any container in a 96 format: well plate or tiprack) +- trough + +Note: The parameters schema include a `"loadName"` field, but this should not be set by the user. It is generated by the program as: [brand]_[num.wells]_[displayCategory]_[totalVol]_[displayVolumeUnits] + +#### Well + +``` well = { - **depth**: number, - **shape**: string, - _diameter_: number, - _length_: number, - _width_: number, - _totalLiquidVolume_: number, + "depth": number, + "shape": string, + "diameter": optional number, + "length": optional number, + "width": optional number, + "totalLiquidVolume": optional number, } -* depth is how deep a given well is -* shape is what type of well you are dealing with. Currently there are two options: -..* circular (if of this shape, diameter is required) -..* rectangular (if of this shape, width and length is required) +``` + +"depth" is how deep a given well is. + +"shape" is what type of well you are dealing with. Currently there are two options: + +- "circular" (if of this shape, diameter is required) +- "rectangular" (if of this shape, width and length is required) +"width" corresponds to the Y axis on the deck of the OT2, and "length" corresponds to the X axis + +"totalLiquidVolume" is the actual working volume of the well, in the units specified in "displayLiquidVolume" (default +is uL) + +#### Grid + +``` grid = { - **row**: number, - **column**: number, + "row": number, + "column": number, } -* Grid is the number of rows and columns in a given labware +``` +Grid is the number of rows and columns in a given labware + +#### Spacing + +``` spacing = { - **row**: number, - **column**: number, + "row": number, + "column": number, } -* Spacing is the center to center distance of wells between rows and columns +``` +Spacing is the center to center distance of wells between rows and columns + +#### Offset + +``` offset = { - **x**: number, - **y**: number, - **z**: number, + "x": number, + "y": number, + "z": number, } -* Offset is taken from the top left corner of a container to well `A1`. +``` + +Offset is taken from the **upper left corner of the labware, flush with the deck** to the top-center of well `A1`. + +#### Dimensions -## Output -The output of your data should look something to the affect of this JSON below: ``` -{ - "otId": "mock-id", - "deprecated": false, - "metadata": { - "name": "fake labware", - "displayCategory": "wellPlate", - "displayVolumeUnits": "uL", - "displayLengthUnits": "mm" - }, - "brand": { - "brandId": ["t40u9sernisofsea"], - "brand": "opentrons" - }, - "parameters": { - "format": "96Standard", - "isTiprack": false, - "loadName": ???, +dimensions = { + "overallLength": number, + "overallWidth": number, + "overallHeight": number, +} +``` + +"overallLength" is the outer dimension of the labware in the X axis in mm--usually equal to the length of the slot: 127.76 mm. + +"overallWidth" is the outer dimension of the labware in the Y axis in mm--usually equal to the width of the slot: 85.48 mm. + +"overallHeight" is the outer dimension of the labware in the Z axis in mm--usually the same as the top the well, but can be higher in case of some kind of veritcal protrusion. + +#### Brand + +``` +brand = { + "brand": string, + "brandId": optional string, +} +``` + +"brand" is the name of the manufacturer + +"brandId" is used when a definition accurately reflects several products + +## Example Input-Output + +Given this sequence of commands in the console: + +``` +const arguments = { + metadata: { + displayName: "Opentrons 1.5mL tuberack", + displayCategory: "tuberack", + displayVolumeUnits: "mL" }, - "cornerOffsetFromSlot": { - "x": -77.76, - "y": -35.48, - "z": 0 + parameters: {format: "irregular", isTiprack: false}, + offset: {x: 18.213, y: 10.075, z: 79.85}, + dimensions: { + overallLength: 127.76, + overallWidth: 85.48, + overallHeight: 79.85 }, - "dimensions": { - "overallLength": 50, - "overallWidth": 50, - "overallHeight": 50 + grid: {row: 4, column: 6}, + spacing: {row: 19.278, column: 19.892}, + well: { + depth: 38.58, + shape: "circular", + diameter: 9.9, + totalLiquidVolume: 1.5 }, - "ordering": [["A1"], ["A2"]], - "wells": { - "A1": { - "depth": 40, - "totalLiquidVolume": 100, - "diameter": 30, - "x": 0, - "y": 0, - "z": 0, - "shape": "circular" - }, - "A2": { - "depth": 40, - "totalLiquidVolume": 100, - "diameter": 30, - "x": 10, - "y": 0, - "z": 0, - "shape": "circular" - } - } + brand: {brand: "Opentrons"}, } + +const data = sharedData.createRegularLabware(arguments) +JSON.stringify(data, null, 4) ``` +The output should look like this: -To make the data easier to copy from the browser, simply use the `stringify` function. -It would look something to the effect of: `JSON.stringify(output)` +``` +{ + "ordering": [ + [ + "A1", + "B1", + "C1", + "D1" + ], + [ + "A2", + "B2", + "C2", + "D2" + ], + [ + "A3", + "B3", + "C3", + "D3" + ], + [ + "A4", + "B4", + "C4", + "D4" + ], + [ + "A5", + "B5", + "C5", + "D5" + ], + [ + "A6", + "B6", + "C6", + "D6" + ] + ], + "otId": "b7df6160-e775-11e8-b0a9-079879741b02", + "deprecated": false, + "metadata": { + "displayName": "Opentrons 1.5mL tuberack", + "displayCategory": "tuberack", + "displayVolumeUnits": "mL" + }, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "dimensions": { + "overallLength": 127.76, + "overallWidth": 85.48, + "overallHeight": 79.85 + }, + "parameters": { + "format": "irregular", + "isTiprack": false, + "loadName": "Opentrons_24_tuberack_1.5_mL_Eppendorf" + }, + "wells": { + "D1": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 18.21, + "y": 10.08, + "z": 41.27 + }, + "C1": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 18.21, + "y": 29.35, + "z": 41.27 + }, + "B1": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 18.21, + "y": 48.63, + "z": 41.27 + }, + "A1": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 18.21, + "y": 67.91, + "z": 41.27 + }, + "D2": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 38.11, + "y": 10.08, + "z": 41.27 + }, + "C2": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 38.11, + "y": 29.35, + "z": 41.27 + }, + "B2": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 38.11, + "y": 48.63, + "z": 41.27 + }, + "A2": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 38.11, + "y": 67.91, + "z": 41.27 + }, + "D3": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 58, + "y": 10.08, + "z": 41.27 + }, + "C3": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 58, + "y": 29.35, + "z": 41.27 + }, + "B3": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 58, + "y": 48.63, + "z": 41.27 + }, + "A3": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 58, + "y": 67.91, + "z": 41.27 + }, + "D4": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 77.89, + "y": 10.08, + "z": 41.27 + }, + "C4": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 77.89, + "y": 29.35, + "z": 41.27 + }, + "B4": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 77.89, + "y": 48.63, + "z": 41.27 + }, + "A4": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 77.89, + "y": 67.91, + "z": 41.27 + }, + "D5": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 97.78, + "y": 10.08, + "z": 41.27 + }, + "C5": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 97.78, + "y": 29.35, + "z": 41.27 + }, + "B5": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 97.78, + "y": 48.63, + "z": 41.27 + }, + "A5": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 97.78, + "y": 67.91, + "z": 41.27 + }, + "D6": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 117.67, + "y": 10.08, + "z": 41.27 + }, + "C6": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 117.67, + "y": 29.35, + "z": 41.27 + }, + "B6": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 117.67, + "y": 48.63, + "z": 41.27 + }, + "A6": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 117.67, + "y": 67.91, + "z": 41.27 + } + }, + "brand": { + "brand": "Opentrons" + } +} +``` diff --git a/labware-designer/package.json b/labware-designer/package.json index a82330a8882..3da25c59c73 100644 --- a/labware-designer/package.json +++ b/labware-designer/package.json @@ -10,7 +10,7 @@ "name": "labware-designer", "productName": "Opentrons Labware Designer", "private": true, - "version": "3.6.0-beta.0", + "version": "3.6.1", "description": "Labware Designer", "main": "src/index.js", "bugs": { @@ -19,7 +19,7 @@ "homepage": "https://github.com/Opentrons/opentrons", "license": "Apache-2.0", "dependencies": { - "@opentrons/shared-data": "3.6.0-beta.0" + "@opentrons/shared-data": "3.6.1" }, "devDependencies": { "flow-bin": "^0.82.0", diff --git a/lerna.json b/lerna.json index ef19082bd3e..9c2a1ba96ea 100644 --- a/lerna.json +++ b/lerna.json @@ -12,5 +12,5 @@ }, "npmClient": "yarn", "useWorkspaces": true, - "version": "3.6.0-beta.0" + "version": "3.6.1" } diff --git a/package.json b/package.json index 70e7eb6b5c7..27e5f5db49d 100755 --- a/package.json +++ b/package.json @@ -67,8 +67,8 @@ "postcss-cssnext": "^3.0.2", "postcss-import": "^11.0.0", "postcss-loader": "^3.0.0", - "react": "^16.2.0", - "react-dom": "^16.2.0", + "react": "^16.6.3", + "react-dom": "^16.6.3", "react-styleguidist": "^8.0.1", "react-test-renderer": "^16.2.0", "redux-mock-store": "^1.5.1", diff --git a/protocol-designer/CHANGELOG.md b/protocol-designer/CHANGELOG.md index db59dc418b0..4445a74284d 100644 --- a/protocol-designer/CHANGELOG.md +++ b/protocol-designer/CHANGELOG.md @@ -3,6 +3,67 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + + +### Bug Fixes + +* **protocol-designer:** fix missing disposal volume in new distribute forms ([#2733](https://github.com/Opentrons/opentrons/issues/2733)) ([5657164](https://github.com/Opentrons/opentrons/commit/5657164)), closes [#2705](https://github.com/Opentrons/opentrons/issues/2705) + + +### Features + +* **protocol-designer:** allow user to re-enable dismissed hints ([#2726](https://github.com/Opentrons/opentrons/issues/2726)) ([af52d1e](https://github.com/Opentrons/opentrons/commit/af52d1e)), closes [#2652](https://github.com/Opentrons/opentrons/issues/2652) +* **protocol-designer:** drag and drop step reordering ([#2714](https://github.com/Opentrons/opentrons/issues/2714)) ([13d6fe3](https://github.com/Opentrons/opentrons/commit/13d6fe3)), closes [#2654](https://github.com/Opentrons/opentrons/issues/2654) +* **protocol-designer:** highlight tips per substep ([#2716](https://github.com/Opentrons/opentrons/issues/2716)) ([eb2c2ce](https://github.com/Opentrons/opentrons/commit/eb2c2ce)), closes [#2537](https://github.com/Opentrons/opentrons/issues/2537) +* **protocol-designer:** new protocol modal defaults and visual updates ([#2739](https://github.com/Opentrons/opentrons/issues/2739)) ([333ad5a](https://github.com/Opentrons/opentrons/commit/333ad5a)), closes [#2721](https://github.com/Opentrons/opentrons/issues/2721) +* **protocol-designer:** place tipracks on protocol creation ([#2750](https://github.com/Opentrons/opentrons/issues/2750)) ([a110a8d](https://github.com/Opentrons/opentrons/commit/a110a8d)), closes [#1327](https://github.com/Opentrons/opentrons/issues/1327) +* **protocol-designer:** remove delay from advanced settings of all step types ([#2731](https://github.com/Opentrons/opentrons/issues/2731)) ([b26abdd](https://github.com/Opentrons/opentrons/commit/b26abdd)), closes [#2579](https://github.com/Opentrons/opentrons/issues/2579) +* **protocol-designer:** remove option of tiprack-1000ul-chem from pd ([#2745](https://github.com/Opentrons/opentrons/issues/2745)) ([3d5f276](https://github.com/Opentrons/opentrons/commit/3d5f276)) + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + + +### Features + +* **protocol-designer:** add tooltip to advanced settings icon ([#2727](https://github.com/Opentrons/opentrons/issues/2727)) ([0deb6b7](https://github.com/Opentrons/opentrons/commit/0deb6b7)), closes [#2706](https://github.com/Opentrons/opentrons/issues/2706) +* **protocol-designer:** make multichannel substeps collapsed by default ([#2729](https://github.com/Opentrons/opentrons/issues/2729)) ([b419a72](https://github.com/Opentrons/opentrons/commit/b419a72)), closes [#2678](https://github.com/Opentrons/opentrons/issues/2678) +* **protocol-designer:** remove label from 200ul/300ul tiprack image ([#2722](https://github.com/Opentrons/opentrons/issues/2722)) ([fe5cf6a](https://github.com/Opentrons/opentrons/commit/fe5cf6a)), closes [#2704](https://github.com/Opentrons/opentrons/issues/2704) + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + + +### Bug Fixes + +* **protocol-designer:** de-hydrate disposal and blowout labware in st… ([#2669](https://github.com/Opentrons/opentrons/issues/2669)) ([b6246b2](https://github.com/Opentrons/opentrons/commit/b6246b2)) +* **protocol-designer:** well selection modal refresh on step change ([#2671](https://github.com/Opentrons/opentrons/issues/2671)) ([941916f](https://github.com/Opentrons/opentrons/commit/941916f)) + + +### Features + +* **api:** Add 1.5ml tuberack to old labware definition section ([#2679](https://github.com/Opentrons/opentrons/issues/2679)) ([2739038](https://github.com/Opentrons/opentrons/commit/2739038)) +* **protocol-designer:** allow user to set touch-tip offset ([#2691](https://github.com/Opentrons/opentrons/issues/2691)) ([d5b7d8a](https://github.com/Opentrons/opentrons/commit/d5b7d8a)), closes [#2540](https://github.com/Opentrons/opentrons/issues/2540) +* **protocol-designer:** disambiguate left/right pipette names when they match ([#2698](https://github.com/Opentrons/opentrons/issues/2698)) ([2f43a0e](https://github.com/Opentrons/opentrons/commit/2f43a0e)), closes [#2078](https://github.com/Opentrons/opentrons/issues/2078) +* **protocol-designer:** disconnect well selection modal from hovered step state ([#2662](https://github.com/Opentrons/opentrons/issues/2662)) ([973a8a5](https://github.com/Opentrons/opentrons/commit/973a8a5)), closes [#2558](https://github.com/Opentrons/opentrons/issues/2558) +* **protocol-designer:** liquid placement modal performance boost ([#2661](https://github.com/Opentrons/opentrons/issues/2661)) ([ecc8569](https://github.com/Opentrons/opentrons/commit/ecc8569)), closes [#2557](https://github.com/Opentrons/opentrons/issues/2557) +* **protocol-designer:** make settings tab always active ([#2700](https://github.com/Opentrons/opentrons/issues/2700)) ([036e2ee](https://github.com/Opentrons/opentrons/commit/036e2ee)), closes [#2697](https://github.com/Opentrons/opentrons/issues/2697) +* **protocol-designer:** use tip max vol, not pipette max vol ([#2656](https://github.com/Opentrons/opentrons/issues/2656)) ([418665d](https://github.com/Opentrons/opentrons/commit/418665d)), closes [#2160](https://github.com/Opentrons/opentrons/issues/2160) + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/protocol-designer/package.json b/protocol-designer/package.json index 3c32871c3c1..41cef20d602 100755 --- a/protocol-designer/package.json +++ b/protocol-designer/package.json @@ -10,7 +10,7 @@ "name": "protocol-designer", "productName": "Opentrons Protocol Designer Prototype", "private": true, - "version": "3.6.0-beta.0", + "version": "3.6.1", "description": "Protocol designer app", "main": "src/index.js", "bugs": { @@ -19,13 +19,16 @@ "homepage": "https://github.com/Opentrons/opentrons", "license": "Apache-2.0", "dependencies": { - "@opentrons/components": "3.6.0-beta.0", + "@opentrons/components": "3.6.1", "classnames": "^2.2.5", "formik": "^1.3.1", "i18next": "^11.5.0", "lodash": "^4.17.4", - "react": "^16.2.0", - "react-dom": "^16.2.0", + "moment": "^2.19.1", + "react": "^16.6.3", + "react-dnd": "^6.0.0", + "react-dnd-html5-backend": "^6.0.0", + "react-dom": "^16.6.3", "react-hot-loader": "^3.0.0-beta.7", "react-redux": "^5.0.6", "react-router-dom": "^4.1.1", diff --git a/protocol-designer/src/components/FilePage.js b/protocol-designer/src/components/FilePage.js index 3f46cba0576..21c1c69187a 100644 --- a/protocol-designer/src/components/FilePage.js +++ b/protocol-designer/src/components/FilePage.js @@ -1,5 +1,7 @@ // @flow import * as React from 'react' +import {Formik} from 'formik' +import moment from 'moment' import { Card, FormGroup, @@ -10,62 +12,90 @@ import { } from '@opentrons/components' import cx from 'classnames' import i18n from '../localization' -import type {FormConnector} from '../utils' import {Portal} from './portals/MainPageModalPortal' import styles from './FilePage.css' import EditPipettesModal from './modals/EditPipettesModal' import formStyles from '../components/forms.css' +import type {FileMetadataFields} from '../file-data' export type Props = { - formConnector: FormConnector, - isFormAltered: boolean, + formValues: FileMetadataFields, instruments: React.ElementProps, goToNextPage: () => mixed, - saveFileMetadata: () => mixed, + saveFileMetadata: (FileMetadataFields) => mixed, swapPipettes: () => mixed, } type State = { isEditPipetteModalOpen: boolean } +const DATE_ONLY_FORMAT = 'MMM DD, YYYY' +const DATETIME_FORMAT = 'MMM DD, YYYY | h:mm A' + class FilePage extends React.Component { state = {isEditPipetteModalOpen: false} - handleSubmit = (e: SyntheticEvent<*>) => { - // blur focused field on submit - if (document && document.activeElement) document.activeElement.blur() - this.props.saveFileMetadata() - e.preventDefault() - } - openEditPipetteModal = () => this.setState({isEditPipetteModalOpen: true}) closeEditPipetteModal = () => this.setState({isEditPipetteModalOpen: false}) render () { - const {formConnector, isFormAltered, instruments, goToNextPage, swapPipettes} = this.props + const { + formValues, + instruments, + goToNextPage, + saveFileMetadata, + swapPipettes, + } = this.props return (
-
-
- - - + ( + +
+ + {values.created && moment(values.created).format(DATE_ONLY_FORMAT)} + - - - -
+ + {values['last-modified'] && moment(values['last-modified']).format(DATETIME_FORMAT)} + +
- - - -
- - {isFormAltered ? 'UPDATE' : 'UPDATED'} - -
-
+
+ + + + + + + +
+ + + + +
+ + {dirty ? 'UPDATE' : 'UPDATED'} + +
+ + )} />
diff --git a/protocol-designer/src/components/FileSidebar/ConnectedFileSidebar.js b/protocol-designer/src/components/FileSidebar/ConnectedFileSidebar.js index f24114a8718..a99d425eec7 100644 --- a/protocol-designer/src/components/FileSidebar/ConnectedFileSidebar.js +++ b/protocol-designer/src/components/FileSidebar/ConnectedFileSidebar.js @@ -24,7 +24,7 @@ export default connect(mapStateToProps, null, mergeProps)(FileSidebar) function mapStateToProps (state: BaseState): SP & MP { const protocolName = fileDataSelectors.getFileMetadata(state)['protocol-name'] || 'untitled' const fileData = fileDataSelectors.createFile(state) - const canDownload = selectors.currentPage(state) !== 'file-splash' + const canDownload = selectors.getCurrentPage(state) !== 'file-splash' return { downloadData: (canDownload) @@ -34,8 +34,8 @@ function mapStateToProps (state: BaseState): SP & MP { } : null, // Ignore clicking 'CREATE NEW' button in these cases - _canCreateNew: !selectors.newProtocolModal(state), - _hasUnsavedChanges: loadFileSelectors.hasUnsavedChanges(state), + _canCreateNew: !selectors.getNewProtocolModal(state), + _hasUnsavedChanges: loadFileSelectors.getHasUnsavedChanges(state), } } diff --git a/protocol-designer/src/components/SelectablePlate.css b/protocol-designer/src/components/HighlightableLabware.css similarity index 100% rename from protocol-designer/src/components/SelectablePlate.css rename to protocol-designer/src/components/HighlightableLabware.css diff --git a/protocol-designer/src/components/HighlightableLabware.js b/protocol-designer/src/components/HighlightableLabware.js new file mode 100644 index 00000000000..3bbf045c7da --- /dev/null +++ b/protocol-designer/src/components/HighlightableLabware.js @@ -0,0 +1,72 @@ +// @flow +// Wrap Plate with a SelectionRect. +import * as React from 'react' +import map from 'lodash/map' +import { + getWellDefsForSVG, + getLabware, + getIsTiprack, +} from '@opentrons/shared-data' +import { + Labware, + Well, + Tip, + LabwareOutline, + ingredIdsToColor, +} from '@opentrons/components' + +import type {ContentsByWell} from '../labware-ingred/types' +import styles from './HighlightableLabware.css' + +type LabwareProps = React.ElementProps + +export type Props = { + wellContents: ContentsByWell, + getTipProps?: $PropertyType, + containerType: string, + + // used by container + containerId?: string, +} + +// TODO: BC 2018-10-08 we are only using this component in LabwareOnDeck, +// with no hover or select capabilities, pull out implicit highlighting +// labware into it's own component probably near to View Results' BrowsableLabware +export default function HighlightableLabware (props: Props) { + const {wellContents, getTipProps, containerType} = props + + const allWellDefsByName = getWellDefsForSVG(containerType) + const isTiprack = getIsTiprack(containerType) + const labwareDefinition = getLabware(containerType) + + const tipVolume = labwareDefinition && labwareDefinition.metadata && labwareDefinition.metadata.tipVolume + + return ( + + + {map(wellContents, (well, wellName) => { + if (isTiprack) { + const tipProps = (getTipProps && getTipProps(wellName)) || {} + return ( + + ) + } else { + return ( + + ) + } + })} + + ) +} diff --git a/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/index.js b/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/index.js index 3055e8b7b45..7947ebc13c5 100644 --- a/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/index.js +++ b/protocol-designer/src/components/IngredientsList/LabwareDetailsCard/index.js @@ -17,7 +17,7 @@ type DP = { type SP = $Diff & {_labwareId: ?string} function mapStateToProps (state: BaseState): SP { - const labwareData = labwareIngredSelectors.getSelectedContainer(state) + const labwareData = labwareIngredSelectors.getSelectedLabware(state) assert(labwareData, 'Expected labware data to exist in connected labware details card') const props = (labwareData) diff --git a/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.js b/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.js index 94a8009cf6c..b2d8fb5ee93 100644 --- a/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.js +++ b/protocol-designer/src/components/LabwareSelectionModal/LabwareSelectionModal.js @@ -28,7 +28,6 @@ const hardcodedLabware = { ['tiprack-200ul', '200uL Tip Rack', 'Tiprack-200ul'], ['opentrons-tiprack-300ul', '300µL Tip Rack', 'Tiprack-200ul'], ['tiprack-1000ul', '1000µL Tip Rack', 'Tiprack-200ul'], - ['tiprack-1000ul-chem', '10x10 1000µL Chem-Tip Rack', 'Tiprack-1000ul-chem'], ], 'Aluminum Block': [ ['opentrons-aluminum-block-2ml-eppendorf', 'Aluminum Block - 2mL Eppendorf Tubes'], @@ -37,6 +36,7 @@ const hardcodedLabware = { ['opentrons-aluminum-block-PCR-strips-200ul', 'Aluminum Block - 0.2mL PCR Strips'], ], 'Tube Rack': [ + ['opentrons-tuberack-1.5ml-eppendorf', '1.5mL Tube Rack (4-in-1 Rack)'], ['opentrons-tuberack-2ml-eppendorf', '2mL Eppendorf Tube Rack (4-in-1 Rack)'], ['opentrons-tuberack-2ml-screwcap', '2mL Screw Cap Tube Rack (4-in-1 Rack)'], ['opentrons-tuberack-15ml', '15mL Tube Rack (4-in-1 Rack)'], diff --git a/protocol-designer/src/components/LabwareSelectionModal/index.js b/protocol-designer/src/components/LabwareSelectionModal/index.js index f1b42dfd7e8..edd0261ea2b 100644 --- a/protocol-designer/src/components/LabwareSelectionModal/index.js +++ b/protocol-designer/src/components/LabwareSelectionModal/index.js @@ -18,7 +18,7 @@ type SP = { function mapStateToProps (state: BaseState): SP { return { slot: labwareIngredSelectors.selectedAddLabwareSlot(state) || null, - permittedTipracks: pipetteSelectors.permittedTipracks(state), + permittedTipracks: pipetteSelectors.getPermittedTipracks(state), } } diff --git a/protocol-designer/src/components/LiquidPlacementForm/index.js b/protocol-designer/src/components/LiquidPlacementForm/index.js index 040bc56ca40..b8e867f853e 100644 --- a/protocol-designer/src/components/LiquidPlacementForm/index.js +++ b/protocol-designer/src/components/LiquidPlacementForm/index.js @@ -32,8 +32,8 @@ type SP = $Diff & { function mapStateToProps (state: BaseState): SP { const selectedWells = Object.keys(wellSelectionSelectors.getSelectedWells(state)) - const _labwareId = labwareIngredSelectors.getSelectedContainerId(state) - const liquidLocations = labwareIngredSelectors.getIngredientLocations(state) + const _labwareId = labwareIngredSelectors.getSelectedLabwareId(state) + const liquidLocations = labwareIngredSelectors.getLiquidsByLabwareId(state) const _selectionHasLiquids = Boolean( _labwareId && liquidLocations[_labwareId] && @@ -45,7 +45,7 @@ function mapStateToProps (state: BaseState): SP { commonSelectedVolume: wellContentsSelectors.getSelectedWellsCommonVolume(state), liquidSelectionOptions: labwareIngredSelectors.getLiquidSelectionOptions(state), showForm: selectedWells.length > 0, - selectedWellsMaxVolume: wellContentsSelectors.selectedWellsMaxVolume(state), + selectedWellsMaxVolume: wellContentsSelectors.getSelectedWellsMaxVolume(state), _labwareId, _selectedWells: selectedWells, diff --git a/protocol-designer/src/components/LiquidPlacementModal.js b/protocol-designer/src/components/LiquidPlacementModal.js index a53ddc06e7f..764c37d9a4c 100644 --- a/protocol-designer/src/components/LiquidPlacementModal.js +++ b/protocol-designer/src/components/LiquidPlacementModal.js @@ -1,21 +1,105 @@ // @flow import * as React from 'react' +import {connect} from 'react-redux' +import type {Dispatch} from 'redux' import styles from './LiquidPlacementModal.css' -import SelectablePlate from '../containers/SelectablePlate' +import type {Wells, ContentsByWell} from '../labware-ingred/types' +import {SelectableLabware} from '../components/labware' import LiquidPlacementForm from '../components/LiquidPlacementForm' +import SingleLabwareWrapper from '../components/SingleLabware' import WellSelectionInstructions from './WellSelectionInstructions' -type Props = {} +import {selectors} from '../labware-ingred/reducers' +import * as wellContentsSelectors from '../top-selectors/well-contents' +import wellSelectionSelectors from '../well-selection/selectors' +import { + selectWells, + deselectWells, +} from '../well-selection/actions' -export default function LiquidPlacementModal (props: Props) { - return ( -
- +import type {BaseState} from '../types' +import type {WellIngredientNames} from '../steplist' - - -
- ) +type SP = { + selectedWells: Wells, + wellContents: ContentsByWell, + containerType: string, + liquidNamesById: WellIngredientNames, } +type DP = { + selectWells: (Wells) => mixed, + deselectWells: (Wells) => mixed, +} +type Props = SP & DP + +type State = {highlightedWells: Wells} + +class LiquidPlacementModal extends React.Component { + state = {highlightedWells: {}} + constructor (props) { + super(props) + this.state = {highlightedWells: {}} + } + + updateHighlightedWells = (wells: Wells) => { + this.setState({highlightedWells: wells}) + } + + render () { + return ( +
+ + + + + + + +
+ ) + } +} + +const mapStateToProps = (state: BaseState): SP => { + const containerId = selectors.getSelectedLabwareId(state) + const selectedWells = wellSelectionSelectors.getSelectedWells(state) + if (containerId === null) { + console.error('LiquidPlacementModal: No labware is selected, and no labwareId was given to LiquidPlacementModal') + return { + selectedWells: {}, + wellContents: {}, + containerType: '', + liquidNamesById: {}, + } + } + + const labware = selectors.getLabwareById(state)[containerId] + let wellContents: ContentsByWell = {} + + // selection for deck setup: shows initial state of liquids + wellContents = wellContentsSelectors.getWellContentsAllLabware(state)[containerId] + + return { + selectedWells, + wellContents, + containerType: labware ? labware.type : 'missing labware', + liquidNamesById: selectors.getLiquidNamesById(state), + } +} + +const mapDispatchToProps = (dispatch: Dispatch<*>): DP => ({ + deselectWells: (wells) => dispatch(deselectWells(wells)), + selectWells: (wells) => dispatch(selectWells(wells)), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(LiquidPlacementModal) diff --git a/protocol-designer/src/components/ProtocolEditor.js b/protocol-designer/src/components/ProtocolEditor.js index c9701c633d7..bec0d73991b 100644 --- a/protocol-designer/src/components/ProtocolEditor.js +++ b/protocol-designer/src/components/ProtocolEditor.js @@ -1,6 +1,6 @@ // @flow import * as React from 'react' - +import cx from 'classnames' import ConnectedMoreOptionsModal from '../containers/ConnectedMoreOptionsModal' import ConnectedNav from '../containers/ConnectedNav' import ConnectedSidebar from '../containers/ConnectedSidebar' @@ -11,7 +11,7 @@ import FileUploadErrorModal from './modals/FileUploadErrorModal' import AnalyticsModal from './modals/AnalyticsModal' import {PortalRoot as MainPageModalPortalRoot} from '../components/portals/MainPageModalPortal' import {PortalRoot as TopPortalRoot} from './portals/TopPortal' - +import {SCROLL_ON_SELECT_STEP_CLASSNAME} from '../steplist/actions' import styles from './ProtocolEditor.css' const SelectorDebugger = process.env.NODE_ENV === 'development' @@ -26,7 +26,7 @@ export default function ProtocolEditor () {
-
+
diff --git a/protocol-designer/src/components/SelectablePlate.js b/protocol-designer/src/components/SelectablePlate.js deleted file mode 100644 index f670b93d649..00000000000 --- a/protocol-designer/src/components/SelectablePlate.js +++ /dev/null @@ -1,150 +0,0 @@ -// @flow -// Wrap Plate with a SelectionRect. -import * as React from 'react' -import map from 'lodash/map' -import { - getWellDefsForSVG, - getLabware, - getIsTiprack, -} from '@opentrons/shared-data' -import { - Labware, - Well, - Tip, - LabwareOutline, - LabwareLabels, - ingredIdsToColor, - type Channels, -} from '@opentrons/components' - -import {WELL_LABEL_OFFSET} from '../constants' -import SingleLabware from './SingleLabware' -import SelectionRect from './SelectionRect.js' -import WellTooltip from './labware/WellTooltip' -import type {WellIngredientNames} from '../steplist/types' -import type {ContentsByWell} from '../labware-ingred/types' -import type {RectEvent} from '../collision-types' -import styles from './SelectablePlate.css' - -type LabwareProps = React.ElementProps - -export type Props = { - wellContents: ContentsByWell, - getTipProps?: $PropertyType, - containerType: string, - - selectable?: boolean, - hoverable?: boolean, - makeOnMouseOverWell?: (well: string) => (e: SyntheticMouseEvent<*>) => mixed, - onMouseExitWell?: (e: SyntheticMouseEvent<*>) => mixed, - liquidNamesById: WellIngredientNames, - - onSelectionMove: RectEvent, - onSelectionDone: RectEvent, - - // used by container - containerId: string, - pipetteChannels?: ?Channels, -} - -// TODO: BC 2018-10-08 for disconnect hover and select in the IngredSelectionModal from -// redux, use SelectableLabware or similar component there. Also, where we are using this -// component in LabwareOnDeck, with no hover or select capabilities, pull out implicit highlighting -// labware into it's own component probably near to View Results' BrowsableLabware -export default function SelectablePlate (props: Props) { - const { - wellContents, - getTipProps, - containerType, - onSelectionMove, - onSelectionDone, - selectable = false, - hoverable = true, - makeOnMouseOverWell, - onMouseExitWell, - liquidNamesById, - } = props - - // NOTE: LabwareOnDeck is not selectable or hoverable - if (!hoverable && !selectable) { - const allWellDefsByName = getWellDefsForSVG(containerType) - const isTiprack = getIsTiprack(containerType) - const labwareDefinition = getLabware(containerType) - - const tipVolume = labwareDefinition && labwareDefinition.metadata && labwareDefinition.metadata.tipVolume - - return ( - - - {map(wellContents, (well, wellName) => { - if (isTiprack) { - const tipProps = (getTipProps && getTipProps(wellName)) || {} - return ( - - ) - } else { - return ( - - ) - } - })} - - ) - } else { // NOTE: Currently only selectable and hoverable (bound to redux) in LiquidPlacementModal - // FIXME: SelectionRect is somehow off by one in the x axis, hence the magic number - return ( - - - - {({makeHandleMouseOverWell, handleMouseLeaveWell}) => ( - - { - const well = wellContents[wellName] - return { - onMouseOver: (e: SyntheticMouseEvent<*>) => { - makeOnMouseOverWell && makeOnMouseOverWell(wellName)(e) - if (well.ingreds) { - makeHandleMouseOverWell(wellName, well.ingreds)(e) - } - }, - onMouseLeave: (e: SyntheticMouseEvent<*>) => { - onMouseExitWell && onMouseExitWell(e) - handleMouseLeaveWell(e) - }, - selectable, - wellName, - highlighted: well.highlighted, - selected: well.selected, - error: well.error, - maxVolume: well.maxVolume, - fillColor: ingredIdsToColor(well.groupIds), - } - }} - getTipProps={getTipProps} /> - - - )} - - - - ) - } -} diff --git a/protocol-designer/src/components/SettingsPage/Privacy.js b/protocol-designer/src/components/SettingsPage/SettingsApp.js similarity index 60% rename from protocol-designer/src/components/SettingsPage/Privacy.js rename to protocol-designer/src/components/SettingsPage/SettingsApp.js index 12bdb62dbe9..87d132a7909 100644 --- a/protocol-designer/src/components/SettingsPage/Privacy.js +++ b/protocol-designer/src/components/SettingsPage/SettingsApp.js @@ -2,27 +2,48 @@ import React from 'react' import {connect} from 'react-redux' import i18n from '../../localization' -import {Card, ToggleButton} from '@opentrons/components' +import {Card, OutlineButton, ToggleButton} from '@opentrons/components' import styles from './SettingsPage.css' import { actions as analyticsActions, selectors as analyticsSelectors, } from '../../analytics' +import { + actions as tutorialActions, + selectors as tutorialSelectors, +} from '../../tutorial' import type {BaseState} from '../../types' type Props = { + canClearHintDismissals: boolean, hasOptedIn: boolean | null, + restoreHints: () => mixed, toggleOptedIn: () => mixed, } type SP = { + canClearHintDismissals: $PropertyType, hasOptedIn: $PropertyType, } -function Privacy (props: Props) { - const {hasOptedIn, toggleOptedIn} = props +function SettingsApp (props: Props) { + const {canClearHintDismissals, hasOptedIn, restoreHints, toggleOptedIn} = props return (
+ +
+
+ {i18n.t('card.body.restore_hints')} + + {canClearHintDismissals ? i18n.t('button.restore') : i18n.t('button.restored') } + +
+
+

{i18n.t('card.toggle.share_session')}

@@ -47,6 +68,7 @@ function Privacy (props: Props) { function mapStateToProps (state: BaseState): SP { return { hasOptedIn: analyticsSelectors.getHasOptedIn(state), + canClearHintDismissals: tutorialSelectors.getCanClearHintDismissals(state), } } @@ -60,7 +82,8 @@ function mergeProps (stateProps: SP, dispatchProps: {dispatch: Dispatch<*>}): Pr return { ...stateProps, toggleOptedIn: () => dispatch(_toggleOptedIn()), + restoreHints: () => dispatch(tutorialActions.clearAllHintDismissals()), } } -export default connect(mapStateToProps, null, mergeProps)(Privacy) +export default connect(mapStateToProps, null, mergeProps)(SettingsApp) diff --git a/protocol-designer/src/components/SettingsPage/SettingsPage.css b/protocol-designer/src/components/SettingsPage/SettingsPage.css index 7a0c73f20f0..aa4210dace0 100644 --- a/protocol-designer/src/components/SettingsPage/SettingsPage.css +++ b/protocol-designer/src/components/SettingsPage/SettingsPage.css @@ -60,8 +60,12 @@ } } +.button { + float: right; +} + .body_wrapper { margin: 0.375rem 0 0.625rem; line-height: 1.5; - padding: 1rem; + padding: 2rem 1rem; } diff --git a/protocol-designer/src/components/SettingsPage/SettingsSidebar.js b/protocol-designer/src/components/SettingsPage/SettingsSidebar.js index b17475b68b7..049ea133f6c 100644 --- a/protocol-designer/src/components/SettingsPage/SettingsSidebar.js +++ b/protocol-designer/src/components/SettingsPage/SettingsSidebar.js @@ -16,9 +16,9 @@ const SettingsSidebar = (props: SP & DP) => ( + selected={props.currentPage === 'settings-app'} + onClick={props.makeNavigateToPage('settings-app')} + title={i18n.t('nav.settings.app')}/> {/* ( ) const STP = (state: BaseState): SP => ({ - currentPage: selectors.currentPage(state), + currentPage: selectors.getCurrentPage(state), }) const DTP = (dispatch: ThunkDispatch<*>): DP => ({ diff --git a/protocol-designer/src/components/SettingsPage/index.js b/protocol-designer/src/components/SettingsPage/index.js index d2b428272ce..a2970222ad4 100644 --- a/protocol-designer/src/components/SettingsPage/index.js +++ b/protocol-designer/src/components/SettingsPage/index.js @@ -4,7 +4,7 @@ import {connect} from 'react-redux' import type {BaseState} from '../../types' import {selectors, type Page} from '../../navigation' -import Privacy from './Privacy' +import SettingsApp from './SettingsApp' export {default as SettingsSidebar} from './SettingsSidebar' @@ -16,14 +16,14 @@ const SettingsPage = (props: SP) => { // TODO: BC 2018-09-01 when we have feature flags put them here return
Feature Flags Coming Soon...
} - case 'settings-privacy': + case 'settings-app': default: - return + return } } const STP = (state: BaseState): SP => ({ - currentPage: selectors.currentPage(state), + currentPage: selectors.getCurrentPage(state), }) export default connect(STP)(SettingsPage) diff --git a/protocol-designer/src/components/SingleLabware.js b/protocol-designer/src/components/SingleLabware.js index 9fcffe11eda..cda2f32cb3a 100644 --- a/protocol-designer/src/components/SingleLabware.js +++ b/protocol-designer/src/components/SingleLabware.js @@ -1,7 +1,7 @@ // @flow import * as React from 'react' import cx from 'classnames' -import {SLOT_WIDTH_MM, SLOT_HEIGHT_MM} from '../constants.js' +import {SLOT_RENDER_WIDTH, SLOT_RENDER_HEIGHT} from '@opentrons/shared-data' import styles from './SingleLabware.css' type Props = { @@ -11,13 +11,13 @@ type Props = { } export const LABEL_OFFSET = 8 -/** Simply wraps SVG components like Plate/SelectablePlate with correct dimensions */ +/** Simply wraps SVG components like Plate/SelectableLabware with correct dimensions */ export default function SingleLabware (props: Props) { const {children, className, showLabels = false} = props const minX = showLabels ? -LABEL_OFFSET : 0 const minY = showLabels ? -LABEL_OFFSET : 0 - const width = showLabels ? SLOT_WIDTH_MM + LABEL_OFFSET : SLOT_WIDTH_MM - const height = showLabels ? SLOT_HEIGHT_MM + LABEL_OFFSET : SLOT_HEIGHT_MM + const width = showLabels ? SLOT_RENDER_WIDTH + LABEL_OFFSET : SLOT_RENDER_WIDTH + const height = showLabels ? SLOT_RENDER_HEIGHT + LABEL_OFFSET : SLOT_RENDER_HEIGHT return (
diff --git a/protocol-designer/src/components/StepEditForm/ButtonRow.js b/protocol-designer/src/components/StepEditForm/ButtonRow.js index 8fbf8c3bff8..6f266be07ac 100644 --- a/protocol-designer/src/components/StepEditForm/ButtonRow.js +++ b/protocol-designer/src/components/StepEditForm/ButtonRow.js @@ -29,7 +29,9 @@ const ButtonRow = (props: Props) => { ) } -const STP = (state: BaseState): SP => ({ canSave: selectors.currentFormCanBeSaved(state) }) +const STP = (state: BaseState): SP => ({ + canSave: selectors.getCurrentFormCanBeSaved(state), +}) const DTP = (dispatch: ThunkDispatch<*>): DP => ({ onCancel: () => dispatch(actions.cancelStepForm()), diff --git a/protocol-designer/src/components/StepEditForm/FlowRateField/index.js b/protocol-designer/src/components/StepEditForm/FlowRateField/index.js index 6aeae4b8bc5..143d4d09de9 100644 --- a/protocol-designer/src/components/StepEditForm/FlowRateField/index.js +++ b/protocol-designer/src/components/StepEditForm/FlowRateField/index.js @@ -40,7 +40,7 @@ function mapStateToProps (state: BaseState, ownProps: OP): SP { const formData = steplistSelectors.getUnsavedForm(state) const pipetteId = formData ? formData[pipetteFieldName] : null - const pipette = pipetteId && pipetteSelectors.pipettesById(state)[pipetteId] + const pipette = pipetteId && pipetteSelectors.getPipettesById(state)[pipetteId] const pipetteConfig = pipette && getPipetteNameSpecs(pipette.model) const pipetteDisplayName = pipetteConfig ? pipetteConfig.displayName : 'pipette' diff --git a/protocol-designer/src/components/StepEditForm/FormAlerts.js b/protocol-designer/src/components/StepEditForm/FormAlerts.js index 81debb2f1f0..5315b4b9ee8 100644 --- a/protocol-designer/src/components/StepEditForm/FormAlerts.js +++ b/protocol-designer/src/components/StepEditForm/FormAlerts.js @@ -69,7 +69,7 @@ const mapStateToProps = (state: BaseState, ownProps: OP): SP => { alerts: dismissSelectors.getFormWarningsForSelectedStep(state), }) - const errors = steplistSelectors.formLevelErrors(state) + const errors = steplistSelectors.getFormLevelErrors(state) const filteredErrors = getVisibleAlerts({ focusedField, dirtyFields, diff --git a/protocol-designer/src/components/StepEditForm/FormSection.js b/protocol-designer/src/components/StepEditForm/FormSection.js index 9997a165683..ba2a1cc3ab0 100644 --- a/protocol-designer/src/components/StepEditForm/FormSection.js +++ b/protocol-designer/src/components/StepEditForm/FormSection.js @@ -3,8 +3,9 @@ import * as React from 'react' import {connect} from 'react-redux' import startCase from 'lodash/startCase' import cx from 'classnames' -import {IconButton} from '@opentrons/components' +import {IconButton, HoverTooltip} from '@opentrons/components' +import i18n from '../../localization' import {selectors as steplistSelectors} from '../../steplist' import {collapseFormSection} from '../../steplist/actions' import type {BaseState, ThunkDispatch} from '../../types' @@ -34,19 +35,26 @@ const FormSection = (props: FormSectionProps) => {
{props.collapsed !== undefined && // if doesn't exist in redux -
- -
+ + {(hoverTooltipHandlers) => ( +
+ +
+ )} +
}
) } const FormSectionSTP = (state: BaseState, ownProps: OP) => ({ - collapsed: steplistSelectors.formSectionCollapse(state)[ownProps.sectionName], + collapsed: steplistSelectors.getFormSectionCollapsed(state)[ownProps.sectionName], }) const FormSectionDTP = (dispatch: ThunkDispatch<*>, ownProps: OP) => ({ onCollapseToggle: () => dispatch(collapseFormSection(ownProps.sectionName)), diff --git a/protocol-designer/src/components/StepEditForm/MixForm.js b/protocol-designer/src/components/StepEditForm/MixForm.js index ff722c8869b..b2706cd43ef 100644 --- a/protocol-designer/src/components/StepEditForm/MixForm.js +++ b/protocol-designer/src/components/StepEditForm/MixForm.js @@ -1,13 +1,12 @@ // @flow import * as React from 'react' import cx from 'classnames' -import i18n from '../../localization' import {FormGroup} from '@opentrons/components' import { StepInputField, StepCheckboxRow, - DispenseDelayFields, + BlowoutLocationDropdown, PipetteField, LabwareDropdown, ChangeTipField, @@ -45,21 +44,22 @@ const MixForm = (props: MixFormProps): React.Element => {
- - + + + + -
- +
mixed } +type DP = { updateValue: (?number) => mixed } type OP = { mmFromBottom: number, wellHeightMM: number, isOpen: boolean, closeModal: () => mixed, - prefix: 'aspirate' | 'dispense', + defaultMm: number, + fieldName: TipOffsetFields, } type Props = OP & DP -type State = { value: string } +type State = { value: ?number } -const formatValue = (value: number | string): string => ( - String(round(Number(value), DECIMALS_ALLOWED)) +const roundValue = (value: number | string): number => ( + round(Number(value), DECIMALS_ALLOWED) ) class TipPositionModal extends React.Component { constructor (props: Props) { super(props) - this.state = { value: formatValue(props.mmFromBottom) } + const initialValue = props.mmFromBottom + ? roundValue(props.mmFromBottom) + : roundValue(this.getDefaultMmFromBottom()) + this.state = { value: initialValue } } componentDidUpdate (prevProps) { if (prevProps.wellHeightMM !== this.props.wellHeightMM) { - this.setState({value: formatValue(this.props.mmFromBottom)}) + this.setState({value: roundValue(this.props.mmFromBottom)}) } } applyChanges = () => { - this.props.updateValue(formatValue(this.state.value || 0)) + const {value} = this.state + this.props.updateValue(value == null ? null : roundValue(value)) + this.props.closeModal() + } + getDefaultMmFromBottom = (): number => { + const {fieldName, wellHeightMM} = this.props + return utils.getDefaultMmFromBottom({fieldName, wellHeightMM}) + } + getMinMaxMmFromBottom = (): {maxMmFromBottom: number, minMmFromBottom: number} => { + if (getIsTouchTipField(this.props.fieldName)) { + return { + maxMmFromBottom: roundValue(this.props.wellHeightMM), + minMmFromBottom: roundValue(this.props.wellHeightMM / 2), + } + } + return { + maxMmFromBottom: roundValue(this.props.wellHeightMM * 2), + minMmFromBottom: 0, + } } + handleReset = () => { - // NOTE: when `prefix` isn't set (eg in the Mix form), we'll use - // the value `DEFAULT_MM_FROM_BOTTOM_DISPENSE` (since we gotta pick something :/) - const defaultMm = this.props.prefix === 'aspirate' - ? DEFAULT_MM_FROM_BOTTOM_ASPIRATE - : DEFAULT_MM_FROM_BOTTOM_DISPENSE - this.setState({value: formatValue(defaultMm)}, this.applyChanges) - this.props.closeModal() + this.setState({value: null}, this.applyChanges) } handleCancel = () => { - this.setState({value: formatValue(this.props.mmFromBottom)}, this.applyChanges) - this.props.closeModal() + this.setState({value: roundValue(this.props.mmFromBottom)}, this.props.closeModal) } handleDone = () => { this.applyChanges() - this.props.closeModal() } - handleChange = (e: SyntheticEvent) => { - const {value} = e.currentTarget - const valueFloat = Number(formatValue(value)) - const maximumHeightMM = (this.props.wellHeightMM * 2) - if (!value) { - this.setState({value}) - } else if (valueFloat > maximumHeightMM) { - this.setState({value: formatValue(maximumHeightMM)}) - } else if (valueFloat >= 0) { - const numericValue = value.replace(/[^.0-9]/, '') - this.setState({value: numericValue.replace(/(\d*[.]{1}\d{1})(\d*)/, (match, group1) => group1)}) - } else { - this.setState({value: formatValue(0)}) + handleChange = (newValueRaw: string | number) => { + const {maxMmFromBottom, minMmFromBottom} = this.getMinMaxMmFromBottom() + // if string, strip non-number characters from string and cast to number + const valueFloatUnrounded = (typeof newValueRaw === 'string') + ? Number(newValueRaw + .replace(/[^.0-9]/, '') + .replace(/(\d*[.]{1}\d{1})(\d*)/, (match, group1) => group1)) + : newValueRaw + const valueFloat = roundValue(valueFloatUnrounded) + + if (!Number.isFinite(valueFloat)) { + return } + + this.setState({value: clamp(valueFloat, minMmFromBottom, maxMmFromBottom)}) } - makeHandleIncrement = (step: number) => () => { + handleInputFieldChange = (e: SyntheticEvent) => { + this.handleChange(e.currentTarget.value) + } + handleIncrementDecrement = (delta: number) => { const {value} = this.state - const incrementedValue = parseFloat(value || 0) + step - const maximumHeightMM = (this.props.wellHeightMM * 2) - this.setState({value: formatValue(Math.min(incrementedValue, maximumHeightMM))}) + const prevValue = this.state.value == null + ? this.getDefaultMmFromBottom() + : value + + this.handleChange(prevValue + delta) + } + makeHandleIncrement = (step: number) => () => { + this.handleIncrementDecrement(step) } makeHandleDecrement = (step: number) => () => { - const nextValueFloat = parseFloat(this.state.value || 0) - step - this.setState({value: formatValue(nextValueFloat < 0 ? 0 : nextValueFloat)}) + this.handleIncrementDecrement(step * -1) } render () { if (!this.props.isOpen) return null const {value} = this.state - const {wellHeightMM} = this.props + const {fieldName, wellHeightMM} = this.props + const {maxMmFromBottom, minMmFromBottom} = this.getMinMaxMmFromBottom() return ( @@ -122,33 +145,37 @@ class TipPositionModal extends React.Component { onCloseClick={this.handleCancel}>

{i18n.t('modal.tip_position.title')}

-

{i18n.t('modal.tip_position.body')}

+

{i18n.t(`modal.tip_position.body.${fieldName}`)}

+ value={(value != null) ? String(value) : ''} />
= (wellHeightMM * 2)} + disabled={value != null && value >= maxMmFromBottom} onClick={this.makeHandleIncrement(SMALL_STEP_MM)}>
- +
{/* TODO: xy tip positioning */}
@@ -174,14 +201,9 @@ class TipPositionModal extends React.Component { } const mapDTP = (dispatch: Dispatch, ownProps: OP): DP => { - // NOTE: not interpolating prefix because breaks flow string enum - - let fieldName = 'mmFromBottom' - if (ownProps.prefix === 'aspirate') fieldName = 'aspirate_mmFromBottom' - else if (ownProps.prefix === 'dispense') fieldName = 'dispense_mmFromBottom' return { updateValue: (value) => { - dispatch(actions.changeFormInput({update: {[fieldName]: value}})) + dispatch(actions.changeFormInput({update: {[ownProps.fieldName]: value}})) }, } } diff --git a/protocol-designer/src/components/StepEditForm/TipPositionInput/TipPositionZAxisViz.js b/protocol-designer/src/components/StepEditForm/TipPositionInput/TipPositionZAxisViz.js index 5b8a5d6a30a..2cee5075836 100644 --- a/protocol-designer/src/components/StepEditForm/TipPositionInput/TipPositionZAxisViz.js +++ b/protocol-designer/src/components/StepEditForm/TipPositionInput/TipPositionZAxisViz.js @@ -10,15 +10,15 @@ import styles from './TipPositionInput.css' const WELL_HEIGHT_PIXELS = 48 const PIXEL_DECIMALS = 2 type Props = { - mmFromBottom: string, + mmFromBottom: number, wellHeightMM: number, } const TipPositionZAxisViz = (props: Props) => { - const fractionOfWellHeight = Number(props.mmFromBottom) / props.wellHeightMM + const fractionOfWellHeight = props.mmFromBottom / props.wellHeightMM const pixelsFromBottom = (Number(fractionOfWellHeight) * WELL_HEIGHT_PIXELS) - WELL_HEIGHT_PIXELS - const roundedPixelsFromBottom = String(round(pixelsFromBottom, PIXEL_DECIMALS)) - const bottomPx = props.wellHeightMM ? roundedPixelsFromBottom : (parseFloat(props.mmFromBottom) - WELL_HEIGHT_PIXELS) + const roundedPixelsFromBottom = round(pixelsFromBottom, PIXEL_DECIMALS) + const bottomPx = props.wellHeightMM ? roundedPixelsFromBottom : (props.mmFromBottom - WELL_HEIGHT_PIXELS) return (
{ handleClose = () => { this.setState({isModalOpen: false}) } render () { + const {fieldName, mmFromBottom, wellHeightMM} = this.props + const disabled = !this.props.wellHeightMM + const isTouchTipField = getIsTouchTipField(this.props.fieldName) + + const Wrapper = ({children, hoverTooltipHandlers}) => isTouchTipField + ? {children} + : + {children} + + + let value = '' + if (wellHeightMM != null) { + // show default value for field in parens if no mmFromBottom value is selected + value = (mmFromBottom != null) + ? mmFromBottom + : `Default (${getDefaultMmFromBottom({fieldName, wellHeightMM})})` + } + return ( {(hoverTooltipHandlers) => ( - + - + )} ) } } + const mapSTP = (state: BaseState, ownProps: OP): SP => { const formData = selectors.getUnsavedForm(state) - // NOTE: not interpolating prefix because breaks flow string enum - let fieldName = 'mmFromBottom' - if (ownProps.prefix === 'aspirate') fieldName = 'aspirate_mmFromBottom' - else if (ownProps.prefix === 'dispense') fieldName = 'dispense_mmFromBottom' - - let labwareFieldName = 'labware' - if (ownProps.prefix === 'aspirate') labwareFieldName = 'aspirate_labware' - else if (ownProps.prefix === 'dispense') labwareFieldName = 'dispense_labware' + const {fieldName} = ownProps + const labwareFieldName = getLabwareFieldForPositioningField(ownProps.fieldName) let wellHeightMM = null if (formData && formData[labwareFieldName]) { - const labwareById = labwareIngredsSelectors.getLabware(state) + const labwareById = labwareIngredsSelectors.getLabwareById(state) const labware = labwareById[formData[labwareFieldName]] const labwareDef = labware && labware.type && getLabware(labware.type) if (labwareDef) { @@ -79,6 +110,7 @@ const mapSTP = (state: BaseState, ownProps: OP): SP => { console.warn('the specified source labware definition could not be located') } } + return { wellHeightMM, mmFromBottom: formData && formData[fieldName], diff --git a/protocol-designer/src/components/StepEditForm/TipPositionInput/utils.js b/protocol-designer/src/components/StepEditForm/TipPositionInput/utils.js new file mode 100644 index 00000000000..fd043c64031 --- /dev/null +++ b/protocol-designer/src/components/StepEditForm/TipPositionInput/utils.js @@ -0,0 +1,31 @@ +// @flow +import assert from 'assert' +import { + DEFAULT_MM_FROM_BOTTOM_ASPIRATE, + DEFAULT_MM_FROM_BOTTOM_DISPENSE, + DEFAULT_MM_TOUCH_TIP_OFFSET_FROM_TOP, +} from '../../../constants' + +import {getIsTouchTipField, type TipOffsetFields} from '../../../form-types' + +export function getDefaultMmFromBottom (args: { + fieldName: TipOffsetFields, + wellHeightMM: number, +}): number { + const {fieldName, wellHeightMM} = args + switch (fieldName) { + case 'aspirate_mmFromBottom': + return DEFAULT_MM_FROM_BOTTOM_ASPIRATE + case 'dispense_mmFromBottom': + return DEFAULT_MM_FROM_BOTTOM_DISPENSE + case 'mix_mmFromBottom': + // TODO: Ian 2018-11-131 figure out what offset makes most sense for mix + return DEFAULT_MM_FROM_BOTTOM_DISPENSE + default: + // touch tip fields + assert( + getIsTouchTipField(fieldName), + `getDefaultMmFromBottom fn does not know what to do with field ${fieldName}`) + return DEFAULT_MM_TOUCH_TIP_OFFSET_FROM_TOP + wellHeightMM + } +} diff --git a/protocol-designer/src/components/StepEditForm/TransferLikeForm.js b/protocol-designer/src/components/StepEditForm/TransferLikeForm.js index 53c574342de..0809aac3a61 100644 --- a/protocol-designer/src/components/StepEditForm/TransferLikeForm.js +++ b/protocol-designer/src/components/StepEditForm/TransferLikeForm.js @@ -6,9 +6,8 @@ import i18n from '../../localization' import { StepInputField, StepCheckboxRow, - DispenseDelayFields, PipetteField, - DisposalDestinationDropdown, + BlowoutLocationDropdown, LabwareDropdown, ChangeTipField, } from './formFields' @@ -53,7 +52,9 @@ const TransferLikeForm = (props: TransferLikeFormProps) => {
- + + + @@ -82,7 +83,11 @@ const TransferLikeForm = (props: TransferLikeFormProps) => { {value ?
Blowout
- +
: null } @@ -93,7 +98,7 @@ const TransferLikeForm = (props: TransferLikeFormProps) => {
- +
{stepType !== 'distribute' && } @@ -135,24 +140,27 @@ const TransferLikeForm = (props: TransferLikeFormProps) => {
- + + + - {stepType !== 'distribute' && - - + + }
- +
{stepType !== 'consolidate' && } diff --git a/protocol-designer/src/components/StepEditForm/WellSelectionInput/WellSelectionInput.js b/protocol-designer/src/components/StepEditForm/WellSelectionInput/WellSelectionInput.js index 9fb8f8da0ec..45510f59215 100644 --- a/protocol-designer/src/components/StepEditForm/WellSelectionInput/WellSelectionInput.js +++ b/protocol-designer/src/components/StepEditForm/WellSelectionInput/WellSelectionInput.js @@ -8,9 +8,8 @@ import {selectors as steplistSelectors, actions as steplistActions} from '../../ import styles from '../StepEditForm.css' import type {Dispatch} from 'redux' -import type {StepFieldName} from '../../../steplist/fieldLevel' +import type {StepIdType, StepFieldName} from '../../../form-types' import type {BaseState} from '../../../types' -import type {StepIdType} from '../../../form-types' import type { FocusHandlers } from '../index' type SP = { diff --git a/protocol-designer/src/components/StepEditForm/WellSelectionInput/WellSelectionModal.js b/protocol-designer/src/components/StepEditForm/WellSelectionInput/WellSelectionModal.js index 96ca4cd9ffe..be17954ec62 100644 --- a/protocol-designer/src/components/StepEditForm/WellSelectionInput/WellSelectionModal.js +++ b/protocol-designer/src/components/StepEditForm/WellSelectionInput/WellSelectionModal.js @@ -16,7 +16,7 @@ import type {Wells, ContentsByWell} from '../../../labware-ingred/types' import {selectors as steplistSelectors} from '../../../steplist' import type {WellIngredientNames} from '../../../steplist/types' import {changeFormInput} from '../../../steplist/actions' -import type {StepFieldName} from '../../../steplist/fieldLevel' +import type {StepFieldName} from '../../../form-types' import type {PipetteData} from '../../../step-generation/types' import {SelectableLabware} from '../../labware' @@ -115,13 +115,13 @@ class WellSelectionModal extends React.Component { function mapStateToProps (state: BaseState, ownProps: OP): SP { const {pipetteId, labwareId} = ownProps - const allLabware = selectors.getLabware(state) + const allLabware = selectors.getLabwareById(state) const labware = labwareId && allLabware && allLabware[labwareId] - const allWellContentsForSteps = wellContentsSelectors.allWellContentsForSteps(state) + const allWellContentsForSteps = wellContentsSelectors.getAllWellContentsForSteps(state) - const stepId = steplistSelectors.getActiveItem(state).id + const stepId = steplistSelectors.getSelectedStepId(state) // TODO: Ian 2018-07-31 replace with util function, "findIndexOrNull"? - const orderedSteps = steplistSelectors.orderedSteps(state) + const orderedSteps = steplistSelectors.getOrderedSteps(state) const timelineIdx = orderedSteps.findIndex(id => id === stepId) const allWellContentsForStep = allWellContentsForSteps[timelineIdx] const formData = steplistSelectors.getUnsavedForm(state) @@ -129,7 +129,7 @@ function mapStateToProps (state: BaseState, ownProps: OP): SP { return { initialSelectedWells: formData ? formData[ownProps.name] : [], - pipette: pipetteId ? pipetteSelectors.equippedPipettes(state)[pipetteId] : null, + pipette: pipetteId ? pipetteSelectors.getEquippedPipettes(state)[pipetteId] : null, wellContents: labware && allWellContentsForStep ? allWellContentsForStep[labware.id] : {}, containerType: labware ? labware.type : 'missing labware', ingredNames, diff --git a/protocol-designer/src/components/StepEditForm/WellSelectionInput/index.js b/protocol-designer/src/components/StepEditForm/WellSelectionInput/index.js index 977c218a826..3873bc171ee 100644 --- a/protocol-designer/src/components/StepEditForm/WellSelectionInput/index.js +++ b/protocol-designer/src/components/StepEditForm/WellSelectionInput/index.js @@ -4,9 +4,10 @@ import WellSelectionInput from './WellSelectionInput' import {connect} from 'react-redux' import {selectors as pipetteSelectors} from '../../../pipettes' import {selectors as steplistSelectors} from '../../../steplist' -import {getFieldErrors, type StepFieldName} from '../../../steplist/fieldLevel' -import type {BaseState, ThunkDispatch} from '../../../types' +import {getFieldErrors} from '../../../steplist/fieldLevel' import {showFieldErrors} from '../StepFormField' +import type {BaseState, ThunkDispatch} from '../../../types' +import type {StepFieldName} from '../../../form-types' import type {FocusHandlers} from '../index' type Props = React.ElementProps @@ -33,7 +34,7 @@ const mapStateToProps = (state: BaseState, ownProps: OP): SP => { const formData = steplistSelectors.getUnsavedForm(state) const pipetteId = formData && formData[ownProps.pipetteFieldName] const selectedWells = formData ? formData[ownProps.name] : [] - const pipetteData = pipetteId && pipetteSelectors.pipettesById(state)[pipetteId] + const pipetteData = pipetteId && pipetteSelectors.getPipettesById(state)[pipetteId] const isMulti = pipetteData && (pipetteData.channels > 1) return { diff --git a/protocol-designer/src/components/StepEditForm/formFields.js b/protocol-designer/src/components/StepEditForm/formFields.js index ae473a63dbe..49fd6fba0c0 100644 --- a/protocol-designer/src/components/StepEditForm/formFields.js +++ b/protocol-designer/src/components/StepEditForm/formFields.js @@ -12,13 +12,14 @@ import { import i18n from '../../localization' import {selectors as pipetteSelectors} from '../../pipettes' import {selectors as labwareIngredSelectors} from '../../labware-ingred/reducers' -import {actions} from '../../steplist' import {hydrateField} from '../../steplist/fieldLevel' import type {StepFieldName} from '../../steplist/fieldLevel' -import {DISPOSAL_PERCENTAGE} from '../../steplist/formLevel/warnings' -import {SOURCE_WELL_DISPOSAL_DESTINATION} from '../../steplist/formLevel/stepFormToArgs/transferLikeFormToArgs' +import { + SOURCE_WELL_BLOWOUT_DESTINATION, + DEST_WELL_BLOWOUT_DESTINATION, +} from '../../step-generation/utils' import type {ChangeTipOptions} from '../../step-generation/types' -import type {BaseState, ThunkDispatch} from '../../types' +import type {BaseState} from '../../types' import type {StepType} from '../../form-types' import styles from './StepEditForm.css' import StepField from './StepFormField' @@ -96,40 +97,14 @@ export const StepRadioGroup = (props: StepRadioGroupProps) => { ) } -type DispenseDelayFieldsProps = { - focusHandlers: FocusHandlers, - label?: string, - disabled?: boolean, - tooltipComponent?: React.Node, -} -export function DispenseDelayFields (props: DispenseDelayFieldsProps) { - const {label = 'Delay', focusHandlers, tooltipComponent, disabled} = props - return ( - - - - - ) -} - type PipetteFieldOP = {name: StepFieldName, stepType?: StepType} & FocusHandlers type PipetteFieldSP = {pipetteOptions: Options, getHydratedPipette: (string) => any} // TODO: real hydrated pipette type -type PipetteFieldDP = {updateDisposalVolume: (?mixed) => void} -type PipetteFieldProps = PipetteFieldOP & PipetteFieldSP & PipetteFieldDP +type PipetteFieldProps = PipetteFieldOP & PipetteFieldSP const PipetteFieldSTP = (state: BaseState, ownProps: PipetteFieldOP): PipetteFieldSP => ({ - pipetteOptions: pipetteSelectors.equippedPipetteOptions(state), + pipetteOptions: pipetteSelectors.getEquippedPipetteOptions(state), getHydratedPipette: (value) => hydrateField(state, ownProps.name, value), }) -const PipetteFieldDTP = (dispatch: ThunkDispatch<*>): PipetteFieldDP => ({ - updateDisposalVolume: (disposalVolume: ?mixed) => { - dispatch(actions.changeFormInput({update: {aspirate_disposalVol_volume: disposalVolume}})) - }, -}) -export const PipetteField = connect(PipetteFieldSTP, PipetteFieldDTP)((props: PipetteFieldProps) => ( +export const PipetteField = connect(PipetteFieldSTP)((props: PipetteFieldProps) => ( { props.onFieldFocus(props.name) }} onChange={(e: SyntheticEvent) => { updateValue(e.currentTarget.value) - if (props.stepType === 'distribute') { - const hydratedPipette = props.getHydratedPipette(e.currentTarget.value) - if (hydratedPipette) { - props.updateDisposalVolume(hydratedPipette.maxVolume * DISPOSAL_PERCENTAGE) - } - } }} /> )} /> )) -type DisposalDestinationDropdownOP = {name: StepFieldName, className?: string} & FocusHandlers -type DisposalDestinationDropdownSP = {options: Options} -const DisposalDestinationDropdownSTP = (state: BaseState): DisposalDestinationDropdownSP => ({ - options: labwareIngredSelectors.disposalLabwareOptions(state), -}) -export const DisposalDestinationDropdown = connect(DisposalDestinationDropdownSTP)((props: DisposalDestinationDropdownOP & DisposalDestinationDropdownSP) => { +type BlowoutLocationDropdownOP = { + name: StepFieldName, + className?: string, + includeSourceWell?: ?boolean, + includeDestWell?: ?boolean, +} & FocusHandlers +type BlowoutLocationDropdownSP = {options: Options} +const BlowoutLocationDropdownSTP = (state: BaseState, ownProps: BlowoutLocationDropdownOP): BlowoutLocationDropdownSP => { + let options = labwareIngredSelectors.disposalLabwareOptions(state) + if (ownProps.includeDestWell) { + options = [ + ...options, + {name: 'Destination Well', value: DEST_WELL_BLOWOUT_DESTINATION}, + ] + } + if (ownProps.includeSourceWell) { + options = [ + ...options, + {name: 'Source Well', value: SOURCE_WELL_BLOWOUT_DESTINATION}, + ] + } + return {options} +} +export const BlowoutLocationDropdown = connect(BlowoutLocationDropdownSTP)((props: BlowoutLocationDropdownOP & BlowoutLocationDropdownSP) => { const {options, name, className, focusedField, dirtyFields, onFieldBlur, onFieldFocus} = props return ( ( { onFieldBlur(name) }} onFocus={() => { onFieldFocus(name) }} value={value ? String(value) : null} diff --git a/protocol-designer/src/components/StepEditForm/index.js b/protocol-designer/src/components/StepEditForm/index.js index ec1a82a2482..4c39bc0058e 100644 --- a/protocol-designer/src/components/StepEditForm/index.js +++ b/protocol-designer/src/components/StepEditForm/index.js @@ -6,8 +6,7 @@ import without from 'lodash/without' import cx from 'classnames' import {actions, selectors} from '../../steplist' -import type {StepFieldName} from '../../steplist/fieldLevel' -import type {FormData, StepType} from '../../form-types' +import type {FormData, StepType, StepFieldName, StepIdType} from '../../form-types' import type {BaseState, ThunkDispatch} from '../../types' import formStyles from '../forms.css' import styles from './StepEditForm.css' @@ -38,7 +37,7 @@ type SP = { formData?: ?FormData, isNewStep?: boolean, } -type DP = { deleteStep: () => mixed } +type DP = { deleteStep: (StepIdType) => mixed } type StepEditFormState = { showConfirmDeleteModal: boolean, @@ -102,7 +101,7 @@ class StepEditForm extends React.Component { onCancelClick={this.toggleConfirmDeleteModal} onContinueClick={() => { this.toggleConfirmDeleteModal() - deleteStep() + this.props.formData && deleteStep(this.props.formData.id) }} />}
@@ -123,12 +122,12 @@ class StepEditForm extends React.Component { } const mapStateToProps = (state: BaseState): SP => ({ - formData: selectors.formData(state), - isNewStep: selectors.isNewStepForm(state), + formData: selectors.getUnsavedForm(state), + isNewStep: selectors.getIsNewStepForm(state), }) const mapDispatchToProps = (dispatch: ThunkDispatch<*>): DP => ({ - deleteStep: () => dispatch(actions.deleteStep()), + deleteStep: (stepId: StepIdType) => dispatch(actions.deleteStep(stepId)), }) export default connect(mapStateToProps, mapDispatchToProps)(StepEditForm) diff --git a/protocol-designer/src/components/alerts/TimelineAlerts.js b/protocol-designer/src/components/alerts/TimelineAlerts.js index 521fdec3d4b..b5c5c163c7f 100644 --- a/protocol-designer/src/components/alerts/TimelineAlerts.js +++ b/protocol-designer/src/components/alerts/TimelineAlerts.js @@ -8,6 +8,7 @@ import { import {selectors as steplistSelectors} from '../../steplist' import {selectors as fileDataSelectors} from '../../file-data' import type {BaseState} from '../../types' +import type {StepIdType} from '../../form-types' import type { CommandCreatorError, CommandCreatorWarning, @@ -18,7 +19,7 @@ import type {AlertLevel} from './types' type SP = { errors: Array, warnings: Array, - _stepId: ?number, + _stepId: ?StepIdType, } type MP = { @@ -38,7 +39,7 @@ type MP = { */ function mapStateToProps (state: BaseState): SP { - const timeline = fileDataSelectors.robotStateTimeline(state) + const timeline = fileDataSelectors.getRobotStateTimeline(state) const errors = timeline.errors || [] const warnings = dismissSelectors.getTimelineWarningsForSelectedStep(state) const _stepId = steplistSelectors.getSelectedStepId(state) diff --git a/protocol-designer/src/components/labware/BrowseLabwareModal.js b/protocol-designer/src/components/labware/BrowseLabwareModal.js index bfcade9daa3..3deb3bff918 100644 --- a/protocol-designer/src/components/labware/BrowseLabwareModal.js +++ b/protocol-designer/src/components/labware/BrowseLabwareModal.js @@ -91,9 +91,9 @@ class BrowseLabwareModal extends React.Component { function mapStateToProps (state: BaseState): SP { const labwareId = selectors.getDrillDownLabwareId(state) - const allLabware = selectors.getLabware(state) + const allLabware = selectors.getLabwareById(state) const labware = labwareId && allLabware ? allLabware[labwareId] : null - const allWellContents = wellContentsSelectors.lastValidWellContents(state) + const allWellContents = wellContentsSelectors.getLastValidWellContents(state) const wellContents = labwareId && allWellContents ? allWellContents[labwareId] : {} const ingredNames = selectors.getLiquidNamesById(state) return { diff --git a/protocol-designer/src/components/labware/LabwareOnDeck.js b/protocol-designer/src/components/labware/LabwareOnDeck.js index 8879db70358..082dd5a2ca5 100644 --- a/protocol-designer/src/components/labware/LabwareOnDeck.js +++ b/protocol-designer/src/components/labware/LabwareOnDeck.js @@ -5,18 +5,20 @@ import { LabwareContainer, ContainerNameOverlay, EmptyDeckSlot, - SLOT_WIDTH_MM, - SLOT_HEIGHT_MM, humanizeLabwareType, type DeckSlot, } from '@opentrons/components' +import { + SLOT_RENDER_WIDTH, + SLOT_RENDER_HEIGHT, +} from '@opentrons/shared-data' import styles from './labware.css' import ClickableText from './ClickableText' -import SelectablePlate from '../../containers/SelectablePlate.js' -import NameThisLabwareOverlay from './NameThisLabwareOverlay.js' -import DisabledSelectSlotOverlay from './DisabledSelectSlotOverlay.js' -import BrowseLabwareOverlay from './BrowseLabwareOverlay.js' +import HighlightableLabware from '../../containers/HighlightableLabware' +import NameThisLabwareOverlay from './NameThisLabwareOverlay' +import DisabledSelectSlotOverlay from './DisabledSelectSlotOverlay' +import BrowseLabwareOverlay from './BrowseLabwareOverlay' import {type TerminalItemId, START_TERMINAL_ITEM_ID, END_TERMINAL_ITEM_ID} from '../../steplist' function LabwareDeckSlotOverlay ({ @@ -68,9 +70,9 @@ function SlotWithLabware (props: SlotWithLabwareProps) { {labwareImages[containerType] ? - : + : } diff --git a/protocol-designer/src/components/labware/SelectableLabware.js b/protocol-designer/src/components/labware/SelectableLabware.js index ba445e9d2e6..0c4b71e757b 100644 --- a/protocol-designer/src/components/labware/SelectableLabware.js +++ b/protocol-designer/src/components/labware/SelectableLabware.js @@ -144,7 +144,12 @@ class SelectableLabware extends React.Component { selectable key={wellName} wellName={wellName} - onMouseOver={this.makeHandleMouseOverWell(wellName, makeHandleMouseOverWell(wellName, well.ingreds))} + onMouseOver={ + this.makeHandleMouseOverWell( + wellName, + well.ingreds ? makeHandleMouseOverWell(wellName, well.ingreds) : () => {} + ) + } onMouseLeave={ this.makeHandleMouseExitWell(handleMouseLeaveWell)} highlighted={Object.keys(highlightedWells).includes(wellName)} selected={selectedWellSets.includes(wellName)} diff --git a/protocol-designer/src/components/modals/EditPipettesModal/index.js b/protocol-designer/src/components/modals/EditPipettesModal/index.js index 82a13a10519..8b1d4036eae 100644 --- a/protocol-designer/src/components/modals/EditPipettesModal/index.js +++ b/protocol-designer/src/components/modals/EditPipettesModal/index.js @@ -54,10 +54,9 @@ const pipetteOptionsWithNone = [ // and also auto-select tiprack if there's only one compatible tiprack for a pipette const tiprackOptions = [ {name: '10 μL', value: 'tiprack-10ul'}, + {name: '200 μL', value: 'tiprack-200ul'}, {name: '300 μL', value: 'opentrons-tiprack-300ul'}, {name: '1000 μL', value: 'tiprack-1000ul'}, - {name: '1000 μL Chem', value: 'tiprack-1000ul-chem'}, - // {name: '300 μL', value: 'GEB-tiprack-300ul'} // NOTE this is not supported by Python API yet ] const DEFAULT_SELECTION = {pipetteModel: '', tiprackModel: null} @@ -203,7 +202,7 @@ class EditPipettesModal extends React.Component { } const mapSTP = (state: BaseState): SP => { - const pipetteData = pipetteSelectors.pipettesForEditPipettes(state) + const pipetteData = pipetteSelectors.getPipettesForEditPipettes(state) return { initialLeft: pipetteData.find(i => i.mount === 'left'), initialRight: pipetteData.find(i => i.mount === 'right'), diff --git a/protocol-designer/src/components/modals/NewFileModal/NewFileModal.css b/protocol-designer/src/components/modals/NewFileModal/NewFileModal.css index 25c432b67b3..18fe4343e4a 100644 --- a/protocol-designer/src/components/modals/NewFileModal/NewFileModal.css +++ b/protocol-designer/src/components/modals/NewFileModal/NewFileModal.css @@ -7,6 +7,7 @@ .tiprack_labware { flex: 3; + margin: 0; } .left_pipette, @@ -21,24 +22,43 @@ .new_file_modal { line-height: 1.5; - min-height: 100%; + height: 100%; + padding: 2rem; + min-height: 38rem; /* override default modal top/bottom to allow scroll */ bottom: auto; +} + +.new_file_modal_contents { + position: relative; + border-radius: 0; + margin: 0; + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.new_file_modal_title { + @apply --font-header-dark; - & form > * { - margin-bottom: 1rem; - } + margin-bottom: 1rem; +} + +.beta_restrictions { + @apply --font-body-2-dark; + + margin: 1rem 0; +} - & ol > li { - counter-increment: step-counter; - list-style: none; - margin: 1rem 0; - } +.button_row { + display: flex; + justify-content: flex-end; +} - & ol > li::before { - content: counter(step-counter) ") "; - } +.button { + margin: 0 0 0 1rem; } .mount_fields_row { diff --git a/protocol-designer/src/components/modals/NewFileModal/index.js b/protocol-designer/src/components/modals/NewFileModal/index.js index fa0b54163da..9586e75f44c 100644 --- a/protocol-designer/src/components/modals/NewFileModal/index.js +++ b/protocol-designer/src/components/modals/NewFileModal/index.js @@ -2,14 +2,16 @@ import * as React from 'react' import cx from 'classnames' import { - AlertModal, + Modal, DropdownField, FormGroup, InputField, + OutlineButton, type Mount, } from '@opentrons/components' import startCase from 'lodash/startCase' import isEmpty from 'lodash/isEmpty' +import i18n from '../../../localization' import {pipetteOptions} from '../../../pipettes/pipetteData' import PipetteDiagram from './PipetteDiagram' import TiprackDiagram from './TiprackDiagram' @@ -26,38 +28,25 @@ type Props = { onSave: (NewProtocolFields) => mixed, } -// 'USER_HAS_NOT_SELECTED' state is just a concern of these dropdowns, -// not selected pipette state in general -// It's needed b/c user must select 'None' explicitly, -// they cannot just leave the dropdown blank. -const USER_HAS_NOT_SELECTED = 'USER_HAS_NOT_SELECTED' -// TODO: Ian 2018-06-22 use pristinity instead of this? - const pipetteOptionsWithNone = [ {name: 'None', value: ''}, ...pipetteOptions, ] -const pipetteOptionsWithInvalid = [ - {name: '', value: USER_HAS_NOT_SELECTED}, - ...pipetteOptionsWithNone, -] - // TODO: Ian 2018-06-22 get this programatically from shared-data labware defs // and exclude options that are incompatible with pipette // and also auto-select tiprack if there's only one compatible tiprack for a pipette const tiprackOptions = [ {name: '10 μL', value: 'tiprack-10ul'}, + {name: '200 μL', value: 'tiprack-200ul'}, {name: '300 μL', value: 'opentrons-tiprack-300ul'}, {name: '1000 μL', value: 'tiprack-1000ul'}, - {name: '1000 μL Chem', value: 'tiprack-1000ul-chem'}, - // {name: '300 μL', value: 'GEB-tiprack-300ul'} // NOTE this is not supported by Python API yet ] const initialState = { name: '', - left: {pipetteModel: USER_HAS_NOT_SELECTED, tiprackModel: null}, - right: {pipetteModel: USER_HAS_NOT_SELECTED, tiprackModel: null}, + left: {pipetteModel: '', tiprackModel: null}, + right: {pipetteModel: '', tiprackModel: null}, } // TODO: BC 2018-11-06 there is a lot of copy pasta between this component and the edit pipettes modal, lets consolidate @@ -88,8 +77,6 @@ export default class NewFileModal extends React.Component { const {name, left, right} = this.state const pipetteSelectionIsValid = ( - // neither can be invalid - (left.pipetteModel !== USER_HAS_NOT_SELECTED && right.pipetteModel !== USER_HAS_NOT_SELECTED) && // at least one must not be none (empty string) (left.pipetteModel || right.pipetteModel) ) @@ -103,18 +90,12 @@ export default class NewFileModal extends React.Component { const canSubmit = pipetteSelectionIsValid && tiprackSelectionIsValid return ( - -
{ canSubmit && this.handleSubmit() }}> -

Create New Protocol

- - + + { canSubmit && this.handleSubmit() }}> +

Create New Protocol

+ { value={name} onChange={this.handleNameChange} /> -
@@ -150,7 +130,7 @@ export default class NewFileModal extends React.Component { @@ -178,19 +158,22 @@ export default class NewFileModal extends React.Component {
- +
+ + {i18n.t('button.cancel')} + + + {i18n.t('button.save')} + +
+ ) } } - -const BetaRestrictions = () => ( - -

Beta Pipette Restrictions:

-
    -
  1. - Pipettes can't share tip racks. There needs to be at least 1 tip rack per - pipette on the deck. -
  2. -
-
-) diff --git a/protocol-designer/src/components/steplist/ContextMenu.js b/protocol-designer/src/components/steplist/ContextMenu.js new file mode 100644 index 00000000000..acdf028371b --- /dev/null +++ b/protocol-designer/src/components/steplist/ContextMenu.js @@ -0,0 +1,119 @@ +// @flow +import * as React from 'react' +import {connect} from 'react-redux' +import type {ThunkDispatch} from '../../types' +import i18n from '../../localization' +import {actions as steplistActions} from '../../steplist' +import {Portal} from '../portals/TopPortal' +import type {StepIdType} from '../../form-types' +import styles from './StepItem.css' + +const MENU_OFFSET_PX = 5 + +type DP = { + deleteStep: (StepIdType) => {}, + duplicateStep: (StepIdType) => {}, +} +type Props = { + children: ({makeStepOnContextMenu: (StepIdType) => (event: SyntheticMouseEvent<>) => mixed}) => React.Node, +} & DP +type State = { + visible: boolean, + left: ?number, + top: ?number, + stepId: ?StepIdType, +} + +class ContextMenu extends React.Component { + state = { + visible: false, + left: null, + top: null, + stepId: null, + } + menuRoot: ?HTMLElement + + componentDidMount () { + global.addEventListener('click', this.handleClick) + } + + componentWillUnmount () { + global.removeEventListener('click', this.handleClick) + } + + makeHandleContextMenu = (stepId: StepIdType) => (event) => { + event.preventDefault() + + const clickX = event.clientX + const clickY = event.clientY + + this.setState({visible: true, stepId}, () => { + const screenW = window.innerWidth + const screenH = window.innerHeight + const rootW = this.menuRoot ? this.menuRoot.offsetWidth : 0 + const rootH = this.menuRoot ? this.menuRoot.offsetHeight : 0 + + const left = (screenW - clickX) > rootW ? clickX + MENU_OFFSET_PX : clickX - rootW - MENU_OFFSET_PX + const top = (screenH - clickY) > rootH ? clickY + MENU_OFFSET_PX : clickY - rootH - MENU_OFFSET_PX + this.setState({left, top}) + }) + } + + handleClick = (event: SyntheticMouseEvent<*>) => { + const { visible } = this.state + + const wasOutside = !(this.menuRoot && event.target instanceof Node && this.menuRoot.contains(event.target)) + + if (wasOutside && visible) this.setState({visible: false, left: null, top: null}) + } + + handleDuplicate = () => { + if (this.state.stepId != null) { + this.props.duplicateStep(this.state.stepId) + this.setState({stepId: null, visible: false}) + } + } + + handleDelete = () => { + if (this.state.stepId != null && confirm(i18n.t('alert.window.confirm_delete_step'))) { + this.props.deleteStep(this.state.stepId) + this.setState({stepId: null, visible: false}) + } + } + + render () { + return ( +
+ {this.props.children({makeStepOnContextMenu: this.makeHandleContextMenu})} + {this.state.visible && + + +
{ this.menuRoot = ref }} + style={{left: this.state.left, top: this.state.top}} + className={styles.context_menu}> +
+ {i18n.t('context_menu.step.duplicate')} +
+
+ {i18n.t('context_menu.step.delete')} +
+
+
+
+ } +
+ ) + } +} + +const mapDispatchToProps = (dispatch: ThunkDispatch<*>) => ({ + deleteStep: (stepId: StepIdType) => dispatch(steplistActions.deleteStep(stepId)), + duplicateStep: (stepId: StepIdType) => dispatch(steplistActions.duplicateStep(stepId)), +}) + +export default connect(null, mapDispatchToProps)(ContextMenu) diff --git a/protocol-designer/src/components/steplist/DraggableStepItems.js b/protocol-designer/src/components/steplist/DraggableStepItems.js new file mode 100644 index 00000000000..b3bf7d86700 --- /dev/null +++ b/protocol-designer/src/components/steplist/DraggableStepItems.js @@ -0,0 +1,138 @@ +// @flow +import * as React from 'react' +import { DragSource, DropTarget } from 'react-dnd' +import isEqual from 'lodash/isEqual' + +import StepItem from '../../containers/ConnectedStepItem' +import type {StepIdType} from '../../form-types' +import ContextMenu from './ContextMenu' + +const DND_TYPES: {STEP_ITEM: "STEP_ITEM"} = { + STEP_ITEM: 'STEP_ITEM', +} + +type DragDropStepItemProps = React.ElementProps & { + connectDragSource: mixed => React.Element, + connectDropTarget: mixed => React.Element, + stepId: StepIdType, + findStepIndex: (StepIdType) => number, + onDrag: () => void, + moveStep: (StepIdType, number) => void, +} +const DragSourceStepItem = (props: DragDropStepItemProps) => ( + props.connectDragSource( + props.connectDropTarget( +
+ +
+ ) + ) +) + +const stepItemSource = { + beginDrag: (props) => { + props.onDrag() + return {stepId: props.stepId} + }, +} +const collectStepSource = (connect, monitor) => ({ + connectDragSource: connect.dragSource(), + isDragging: monitor.isDragging(), +}) +const DraggableStepItem = DragSource(DND_TYPES.STEP_ITEM, stepItemSource, collectStepSource)(DragSourceStepItem) + +const stepItemTarget = { + canDrop: () => { return false }, + hover: (props: DragDropStepItemProps, monitor) => { + const { stepId: draggedId } = monitor.getItem() + const { stepId: overId } = props + + if (draggedId !== overId) { + const overIndex = props.findStepIndex(overId) + props.moveStep(draggedId, overIndex) + } + }, +} +const collectStepTarget = (connect) => ({ + connectDropTarget: connect.dropTarget(), +}) +const DragDropStepItem = DropTarget(DND_TYPES.STEP_ITEM, stepItemTarget, collectStepTarget)(DraggableStepItem) + +type StepItemsProps = { + orderedSteps: Array, + reorderSteps: (Array) => mixed, + isOver: boolean, + connectDropTarget: mixed => React.Element, +} +type StepItemsState = {stepIds: Array} +class StepItems extends React.Component { + constructor (props) { + super(props) + this.state = {stepIds: this.props.orderedSteps} + } + + onDrag = () => { + this.setState({stepIds: this.props.orderedSteps}) + } + + submitReordering = () => { + if (confirm('Are you sure you want to reorder these steps, it may cause errors?')) { + this.props.reorderSteps(this.state.stepIds) + } + } + + // TODO: BC 2018-11-27 make util function for reordering and use it in hotkey implementation too + moveStep = (stepId: StepIdType, targetIndex: number) => { + const {stepIds} = this.state + const currentIndex = this.findStepIndex(stepId) + const currentRemoved = [ + ...stepIds.slice(0, currentIndex), + ...stepIds.slice(currentIndex + 1, stepIds.length), + ] + const currentReinserted = [ + ...currentRemoved.slice(0, targetIndex), + stepId, + ...currentRemoved.slice(targetIndex, currentRemoved.length), + ] + this.setState({stepIds: currentReinserted}) + } + + findStepIndex = stepId => ( + this.state.stepIds.findIndex(id => stepId === id) + ) + + render () { + const currentIds = this.props.isOver ? this.state.stepIds : this.props.orderedSteps + return this.props.connectDropTarget( +
+ + {({makeStepOnContextMenu}) => ( + currentIds.map((stepId: StepIdType) => ( + + )) + )} + +
+ ) + } +} + +const listTarget = { + drop: (props, monitor, component) => { + if (!isEqual(props.orderedSteps, component.state.stepIds)) { + component.submitReordering() + } + }, +} +const collectListTarget = (connect, monitor) => ({ + isOver: monitor.isOver(), + connectDropTarget: connect.dropTarget(), +}) + +export default DropTarget(DND_TYPES.STEP_ITEM, listTarget, collectListTarget)(StepItems) diff --git a/protocol-designer/src/components/steplist/MultiChannelSubstep.js b/protocol-designer/src/components/steplist/MultiChannelSubstep.js index 306e205c442..7e5858143fe 100644 --- a/protocol-designer/src/components/steplist/MultiChannelSubstep.js +++ b/protocol-designer/src/components/steplist/MultiChannelSubstep.js @@ -57,11 +57,11 @@ export default class MultiChannelSubstep extends React.Component{`${formatVolume(rowGroup[0].volume)} μL`} {firstChannelDest ? destWellRange : ''} - + - {collapsed && rowGroup.map((row, rowKey) => { + {!collapsed && rowGroup.map((row, rowKey) => { // Channel rows (1 for each channel in multi-channel pipette return ( ?Labware, handleSubstepHover: SubstepIdentifier => mixed, onStepClick?: (event?: SyntheticEvent<>) => mixed, + onStepContextMenu?: (event?: SyntheticEvent<>) => mixed, onStepItemCollapseToggle?: (event?: SyntheticEvent<>) => mixed, onStepHover?: (event?: SyntheticEvent<>) => mixed, onStepMouseLeave?: (event?: SyntheticEvent<>) => mixed, } -export default function StepItem (props: StepItemProps) { +function StepItem (props: StepItemProps) { const { step, @@ -47,6 +49,7 @@ export default function StepItem (props: StepItemProps) { onStepMouseLeave, onStepClick, + onStepContextMenu, onStepItemCollapseToggle, onStepHover, } = props @@ -62,6 +65,7 @@ export default function StepItem (props: StepItemProps) { iconProps={{className: error ? styles.error_icon : ''}} title={title || ''} onClick={onStepClick} + onContextMenu={onStepContextMenu} onMouseEnter={onStepHover} onMouseLeave={onStepMouseLeave} onCollapseToggle={onStepItemCollapseToggle} @@ -147,3 +151,5 @@ function getStepItemContents (stepItemProps: StepItemProps) { return result } + +export default StepItem diff --git a/protocol-designer/src/components/steplist/StepList.js b/protocol-designer/src/components/steplist/StepList.js index 01d1d81b9dc..0c8c65b8214 100644 --- a/protocol-designer/src/components/steplist/StepList.js +++ b/protocol-designer/src/components/steplist/StepList.js @@ -3,7 +3,6 @@ import * as React from 'react' import {SidePanel} from '@opentrons/components' import StartingDeckStateTerminalItem from './StartingDeckStateTerminalItem' -import StepItem from '../../containers/ConnectedStepItem' import StepCreationButton from '../../containers/StepCreationButton' import TerminalItem from './TerminalItem' import {END_TERMINAL_TITLE} from '../../constants' @@ -11,10 +10,12 @@ import {END_TERMINAL_ITEM_ID} from '../../steplist' import type {StepIdType} from '../../form-types' import {PortalRoot} from './TooltipPortal' +import DraggableStepItems from './DraggableStepItems' type Props = { orderedSteps: Array, reorderSelectedStep: (delta: number) => mixed, + reorderSteps: (Array) => mixed, } export default class StepList extends React.Component { @@ -24,11 +25,14 @@ export default class StepList extends React.Component { const altIsPressed = e.getModifierState('Alt') if (altIsPressed) { + let delta = 0 if (key === 'ArrowUp') { - reorderSelectedStep(-1) + delta = -1 } else if (key === 'ArrowDown') { - reorderSelectedStep(1) + delta = 1 } + if (!delta) return + reorderSelectedStep(delta) } } @@ -41,17 +45,14 @@ export default class StepList extends React.Component { } render () { - const {orderedSteps} = this.props - - const stepItems = orderedSteps.map((stepId: StepIdType) => - ) - return ( - {stepItems} + diff --git a/protocol-designer/src/constants.js b/protocol-designer/src/constants.js index 233d1aef22a..2852cc196d1 100644 --- a/protocol-designer/src/constants.js +++ b/protocol-designer/src/constants.js @@ -3,13 +3,12 @@ import reduce from 'lodash/reduce' import * as componentLib from '@opentrons/components' import {getLabware} from '@opentrons/shared-data' import type {JsonWellData, WellVolumes} from './types' +// TODO Ian 2018-11-27: import these from components lib, not from this contants file export const { // OT2 DECK CONSTANTS SLOTNAME_MATRIX, sortedSlotnames, TRASH_SLOTNAME, - SLOT_WIDTH_MM, - SLOT_HEIGHT_MM, SLOT_SPACING_MM, // STYLE CONSTANTS swatchColors, diff --git a/protocol-designer/src/containers/Alerts.js b/protocol-designer/src/containers/Alerts.js index 1538e167e94..6ffcefb18bc 100644 --- a/protocol-designer/src/containers/Alerts.js +++ b/protocol-designer/src/containers/Alerts.js @@ -64,7 +64,7 @@ function Alerts (props: Props) { } function mapStateToProps (state: BaseState): SP { - const timeline = fileDataSelectors.robotStateTimeline(state) + const timeline = fileDataSelectors.getRobotStateTimeline(state) const errors = timeline.errors || [] const warnings = dismissSelectors.getTimelineWarningsForSelectedStep(state) const _stepId = steplistSelectors.getSelectedStepId(state) diff --git a/protocol-designer/src/containers/ConnectedDeckSetup.js b/protocol-designer/src/containers/ConnectedDeckSetup.js index 95301d5c54a..45ffd3b8bf0 100644 --- a/protocol-designer/src/containers/ConnectedDeckSetup.js +++ b/protocol-designer/src/containers/ConnectedDeckSetup.js @@ -21,8 +21,6 @@ import {selectors as steplistSelectors, START_TERMINAL_ITEM_ID, type TerminalIte import type {BaseState, ThunkDispatch} from '../types' -const ingredSelModIsVisible = activeModals => activeModals.ingredientSelection && activeModals.ingredientSelection.slot - type StateProps = { selectedTerminalItemId: ?TerminalItemId, ingredSelectionMode: boolean, @@ -42,10 +40,9 @@ type Props = { const mapStateToProps = (state: BaseState): StateProps => ({ selectedTerminalItemId: steplistSelectors.getSelectedTerminalItemId(state), - // TODO SOON remove all uses of the `activeModals` selector - ingredSelectionMode: !!ingredSelModIsVisible(selectors.activeModals(state)), + ingredSelectionMode: Boolean(selectors.getSelectedLabware(state)), drilledDown: !!selectors.getDrillDownLabwareId(state), - _moveLabwareMode: !!selectors.slotToMoveFrom(state), + _moveLabwareMode: !!selectors.getSlotToMoveFrom(state), }) const mapDispatchToProps = (dispatch: ThunkDispatch<*>): DispatchProps => ({ diff --git a/protocol-designer/src/containers/ConnectedFilePage.js b/protocol-designer/src/containers/ConnectedFilePage.js index 62af0282102..b876587573c 100644 --- a/protocol-designer/src/containers/ConnectedFilePage.js +++ b/protocol-designer/src/containers/ConnectedFilePage.js @@ -1,32 +1,26 @@ // @flow import {connect} from 'react-redux' +import * as React from 'react' import type {BaseState} from '../types' import FilePage from '../components/FilePage' -import type {Props as FilePageProps} from '../components/FilePage' import {actions, selectors as fileSelectors} from '../file-data' import {actions as pipetteActions, selectors as pipetteSelectors} from '../pipettes' -import type {FileMetadataFields, FileMetadataFieldAccessors} from '../file-data' +import type {FileMetadataFields} from '../file-data' import {actions as navActions} from '../navigation' -import {formConnectorFactory, type FormConnector} from '../utils' + +type Props = React.ElementProps type SP = { - instruments: $PropertyType, - isFormAltered: $PropertyType, - _values: {[accessor: FileMetadataFieldAccessors]: any}, + instruments: $PropertyType, + formValues: $PropertyType, } -type DP = { - _updateFileMetadataFields: typeof actions.updateFileMetadataFields, - _saveFileMetadata: ({[accessor: FileMetadataFieldAccessors]: mixed}) => mixed, - goToNextPage: $PropertyType, - swapPipettes: $PropertyType, -} +type DP = $Diff const mapStateToProps = (state: BaseState): SP => { - const pipetteData = pipetteSelectors.pipettesForInstrumentGroup(state) + const pipetteData = pipetteSelectors.getPipettesForInstrumentGroup(state) return { - _values: fileSelectors.fileFormValues(state), - isFormAltered: fileSelectors.isUnsavedMetadatFormAltered(state), + formValues: fileSelectors.getFileMetadata(state), instruments: { left: pipetteData.find(i => i.mount === 'left'), right: pipetteData.find(i => i.mount === 'right'), @@ -34,35 +28,11 @@ const mapStateToProps = (state: BaseState): SP => { } } -const mapDispatchToProps: DP = { - _updateFileMetadataFields: actions.updateFileMetadataFields, - _saveFileMetadata: actions.saveFileMetadata, - goToNextPage: () => navActions.navigateToPage('liquids'), - swapPipettes: pipetteActions.swapPipettes, -} - -const mergeProps = ( - {instruments, isFormAltered, _values}: SP, - {_updateFileMetadataFields, _saveFileMetadata, goToNextPage, swapPipettes}: DP -): FilePageProps => { - const onChange = (accessor) => (e: SyntheticInputEvent<*>) => { - if (accessor === 'protocol-name' || accessor === 'description' || accessor === 'author') { - _updateFileMetadataFields({[accessor]: e.target.value}) - } else { - console.warn('Invalid accessor in ConnectedFilePage:', accessor) - } - } - - const formConnector: FormConnector = formConnectorFactory(onChange, _values) - - return { - formConnector, - isFormAltered, - instruments, - goToNextPage, - saveFileMetadata: () => _saveFileMetadata(_values), - swapPipettes, - } -} +const mapDispatchToProps = (dispatch: Dispatch<*>): DP => ({ + goToNextPage: () => dispatch(navActions.navigateToPage('liquids')), + saveFileMetadata: (nextFormValues: FileMetadataFields) => + dispatch(actions.saveFileMetadata(nextFormValues)), + swapPipettes: () => dispatch(pipetteActions.swapPipettes), +}) -export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(FilePage) +export default connect(mapStateToProps, mapDispatchToProps)(FilePage) diff --git a/protocol-designer/src/containers/ConnectedMainPanel.js b/protocol-designer/src/containers/ConnectedMainPanel.js index a1adc5bdf2c..7c862f90cd2 100644 --- a/protocol-designer/src/containers/ConnectedMainPanel.js +++ b/protocol-designer/src/containers/ConnectedMainPanel.js @@ -24,7 +24,7 @@ function MainPanel (props: Props) { return case 'liquids': return - case 'settings-privacy': + case 'settings-app': return default: return @@ -33,6 +33,6 @@ function MainPanel (props: Props) { function mapStateToProps (state: BaseState): Props { return { - page: selectors.currentPage(state), + page: selectors.getCurrentPage(state), } } diff --git a/protocol-designer/src/containers/ConnectedMoreOptionsModal.js b/protocol-designer/src/containers/ConnectedMoreOptionsModal.js index b3cfd3011b8..9fd5b4c2745 100644 --- a/protocol-designer/src/containers/ConnectedMoreOptionsModal.js +++ b/protocol-designer/src/containers/ConnectedMoreOptionsModal.js @@ -14,7 +14,7 @@ import { import type {BaseState, ThunkDispatch} from '../types' function mapStateToProps (state: BaseState) { - const formModalData = selectors.formModalData(state) + const formModalData = selectors.getFormModalData(state) return { hideModal: formModalData === null, formData: formModalData, diff --git a/protocol-designer/src/containers/ConnectedNav.js b/protocol-designer/src/containers/ConnectedNav.js index a9e5a40850c..1e1b864c7f0 100644 --- a/protocol-designer/src/containers/ConnectedNav.js +++ b/protocol-designer/src/containers/ConnectedNav.js @@ -7,13 +7,16 @@ import {KNOWLEDGEBASE_ROOT_URL} from '../components/KnowledgeBaseLink' import {NavTab, TabbedNavBar, OutsideLinkTab} from '@opentrons/components' import i18n from '../localization' import {type Page, actions, selectors} from '../navigation' +import {selectors as fileSelectors} from '../file-data' type Props = { currentPage: Page, + currentProtocolExists: boolean, handleClick: Page => (e: ?SyntheticEvent<>) => void, } function Nav (props: Props) { + const noCurrentProtocol = !props.currentProtocolExists return ( @@ -46,9 +49,8 @@ function Nav (props: Props) { + selected={props.currentPage === 'settings-app'} + onClick={props.handleClick('settings-app')} /> } /> @@ -57,7 +59,8 @@ function Nav (props: Props) { function mapStateToProps (state: BaseState) { return { - currentPage: selectors.currentPage(state), + currentPage: selectors.getCurrentPage(state), + currentProtocolExists: fileSelectors.getCurrentProtocolExists(state), } } diff --git a/protocol-designer/src/containers/ConnectedNewFileModal.js b/protocol-designer/src/containers/ConnectedNewFileModal.js index 5737202eaa8..5330e652b94 100644 --- a/protocol-designer/src/containers/ConnectedNewFileModal.js +++ b/protocol-designer/src/containers/ConnectedNewFileModal.js @@ -25,8 +25,8 @@ type DP = { function mapStateToProps (state: BaseState): SP { return { - hideModal: !selectors.newProtocolModal(state), - _hasUnsavedChanges: loadFileSelectors.hasUnsavedChanges(state), + hideModal: !selectors.getNewProtocolModal(state), + _hasUnsavedChanges: loadFileSelectors.getHasUnsavedChanges(state), } } diff --git a/protocol-designer/src/containers/ConnectedSidebar.js b/protocol-designer/src/containers/ConnectedSidebar.js index 2ce921cc322..c81523c5d87 100644 --- a/protocol-designer/src/containers/ConnectedSidebar.js +++ b/protocol-designer/src/containers/ConnectedSidebar.js @@ -28,15 +28,15 @@ function Sidebar (props: Props) { case 'file-detail': return case 'settings-features': - case 'settings-privacy': + case 'settings-app': return } return null } function mapStateToProps (state: BaseState): Props { - const page = selectors.currentPage(state) - const liquidPlacementMode = !!labwareIngredSelectors.getSelectedContainer(state) + const page = selectors.getCurrentPage(state) + const liquidPlacementMode = !!labwareIngredSelectors.getSelectedLabware(state) return { page, diff --git a/protocol-designer/src/containers/ConnectedStepItem.js b/protocol-designer/src/containers/ConnectedStepItem.js index b0332967704..e18581a3865 100644 --- a/protocol-designer/src/containers/ConnectedStepItem.js +++ b/protocol-designer/src/containers/ConnectedStepItem.js @@ -35,7 +35,7 @@ type DP = $Diff<$Diff, OP> function mapStateToProps (state: BaseState, ownProps: OP): SP { const {stepId} = ownProps - const allSteps = steplistSelectors.allSteps(state) + const allSteps = steplistSelectors.getAllSteps(state) const hoveredSubstep = steplistSelectors.getHoveredSubstep(state) const hoveredStep = steplistSelectors.getHoveredStepId(state) @@ -62,7 +62,7 @@ function mapStateToProps (state: BaseState, ownProps: OP): SP { // user is not hovering on substep. hovered: (hoveredStep === stepId) && !hoveredSubstep, - getLabware: (labwareId: ?string) => labwareId ? labwareIngredSelectors.getLabware(state)[labwareId] : null, + getLabware: (labwareId: ?string) => labwareId ? labwareIngredSelectors.getLabwareById(state)[labwareId] : null, ingredNames: labwareIngredSelectors.getLiquidNamesById(state), } } diff --git a/protocol-designer/src/containers/ConnectedStepList.js b/protocol-designer/src/containers/ConnectedStepList.js index d12eccabdf0..8750b55cc0f 100644 --- a/protocol-designer/src/containers/ConnectedStepList.js +++ b/protocol-designer/src/containers/ConnectedStepList.js @@ -1,7 +1,10 @@ // @flow import * as React from 'react' +import HTML5Backend from 'react-dnd-html5-backend' import {connect} from 'react-redux' +import { DragDropContext } from 'react-dnd' import type {BaseState, ThunkDispatch} from '../types' +import type {StepIdType} from '../form-types' import { actions as steplistActions, @@ -19,15 +22,19 @@ type DP = $Diff function mapStateToProps (state: BaseState): SP { return { - orderedSteps: steplistSelectors.orderedSteps(state), + orderedSteps: steplistSelectors.getOrderedSteps(state), } } function mapDispatchToProps (dispatch: ThunkDispatch<*>): DP { return { - reorderSelectedStep: (delta: number) => - dispatch(steplistActions.reorderSelectedStep(delta)), + reorderSelectedStep: (delta: number) => { + dispatch(steplistActions.reorderSelectedStep(delta)) + }, + reorderSteps: (stepIds: Array) => { + dispatch(steplistActions.reorderSteps(stepIds)) + }, } } -export default connect(mapStateToProps, mapDispatchToProps)(StepList) +export default DragDropContext(HTML5Backend)(connect(mapStateToProps, mapDispatchToProps)(StepList)) diff --git a/protocol-designer/src/containers/ConnectedTitleBar.js b/protocol-designer/src/containers/ConnectedTitleBar.js index 8d1cc50a680..0e6991ea937 100644 --- a/protocol-designer/src/containers/ConnectedTitleBar.js +++ b/protocol-designer/src/containers/ConnectedTitleBar.js @@ -46,15 +46,15 @@ function TitleWithIcon (props: TitleWithIconProps) { } function mapStateToProps (state: BaseState): SP { - const _page = selectors.currentPage(state) + const _page = selectors.getCurrentPage(state) const fileName = fileDataSelectors.protocolName(state) const selectedStep = steplistSelectors.getSelectedStep(state) const selectedTerminalId = steplistSelectors.getSelectedTerminalItemId(state) - const labware = labwareIngredSelectors.getSelectedContainer(state) + const labware = labwareIngredSelectors.getSelectedLabware(state) const labwareNames = labwareIngredSelectors.getLabwareNames(state) const labwareNickname = labware && labware.id && labwareNames[labware.id] const drilledDownLabwareId = labwareIngredSelectors.getDrillDownLabwareId(state) - const liquidPlacementMode = !!labwareIngredSelectors.getSelectedContainer(state) + const liquidPlacementMode = !!labwareIngredSelectors.getSelectedLabware(state) const wellSelectionLabwareKey = steplistSelectors.getWellSelectionLabwareKey(state) switch (_page) { @@ -62,7 +62,7 @@ function mapStateToProps (state: BaseState): SP { case 'file-splash': case 'file-detail': case 'settings-features': - case 'settings-privacy': + case 'settings-app': return { _page, title: i18n.t([`nav.title.${_page}`, fileName]), @@ -90,7 +90,7 @@ function mapStateToProps (state: BaseState): SP { subtitle = END_TERMINAL_TITLE if (drilledDownLabwareId) { backButtonLabel = 'Deck' - const drilledDownLabware = labwareIngredSelectors.getLabware(state)[drilledDownLabwareId] + const drilledDownLabware = labwareIngredSelectors.getLabwareById(state)[drilledDownLabwareId] title = drilledDownLabware && drilledDownLabware.name subtitle = drilledDownLabware && humanizeLabwareType(drilledDownLabware.type) } diff --git a/protocol-designer/src/containers/HighlightableLabware.js b/protocol-designer/src/containers/HighlightableLabware.js new file mode 100644 index 00000000000..396cb7c42e7 --- /dev/null +++ b/protocol-designer/src/containers/HighlightableLabware.js @@ -0,0 +1,119 @@ +// @flow +import * as React from 'react' +import {connect} from 'react-redux' +import mapValues from 'lodash/mapValues' +import noop from 'lodash/noop' + +import HighlightableLabware from '../components/HighlightableLabware' + +import {selectors} from '../labware-ingred/reducers' +import { + selectors as steplistSelectors, + START_TERMINAL_ITEM_ID, + END_TERMINAL_ITEM_ID, +} from '../steplist' +import * as highlightSelectors from '../top-selectors/substep-highlight' +import * as wellContentsSelectors from '../top-selectors/well-contents' +import * as tipContentsSelectors from '../top-selectors/tip-contents' +import wellSelectionSelectors from '../well-selection/selectors' + +import type {WellContents, ContentsByWell} from '../labware-ingred/types' +import type {BaseState} from '../types' + +type Props = React.ElementProps + +type OP = { + containerId?: string, +} + +type SP = $Diff + +function mapStateToProps (state: BaseState, ownProps: OP): SP { + const selectedContainerId = selectors.getSelectedLabwareId(state) + const containerId = ownProps.containerId || selectedContainerId + + if (containerId === null) { + console.error('HighlightableLabware: No container is selected, and no containerId was given to Connected HighlightableLabware') + return { + containerId: '', + wellContents: {}, + containerType: '', + } + } + + const labware = selectors.getLabwareById(state)[containerId] + const allWellContentsForSteps = wellContentsSelectors.getAllWellContentsForSteps(state) + const wellSelectionModeForLabware = selectedContainerId === containerId + let wellContents: ContentsByWell = {} + + const activeItem = steplistSelectors.getActiveItem(state) + if ( + !activeItem.isStep && activeItem.id === START_TERMINAL_ITEM_ID + ) { + // selection for deck setup: shows initial state of liquids + wellContents = wellContentsSelectors.getWellContentsAllLabware(state)[containerId] + } else if ( + !activeItem.isStep && activeItem.id === END_TERMINAL_ITEM_ID + ) { + // "end" terminal + wellContents = wellContentsSelectors.getLastValidWellContents(state)[containerId] + } else if (!activeItem.isStep) { + console.warn(`HighlightableLabware got unhandled terminal id: "${activeItem.id}"`) + } else { + const stepId = activeItem.id + // TODO: Ian 2018-07-31 replace with util function, "findIndexOrNull"? + const orderedSteps = steplistSelectors.getOrderedSteps(state) + const timelineIdx = orderedSteps.includes(stepId) + ? orderedSteps.findIndex(id => id === stepId) + : null + + // shows liquids the current step in timeline + const selectedWells = wellSelectionSelectors.getSelectedWells(state) + let wellContentsWithoutHighlight = null + let highlightedWells + + if ((timelineIdx != null)) { + wellContentsWithoutHighlight = (allWellContentsForSteps[timelineIdx]) + // Valid non-end step + ? allWellContentsForSteps[timelineIdx][containerId] + // Erroring step: show last valid well contents in timeline + : wellContentsSelectors.getLastValidWellContents(state)[containerId] + } + + if (wellSelectionModeForLabware) { + // we're in the well selection modal, highlight hovered/selected wells + highlightedWells = wellSelectionSelectors.getHighlightedWells(state) + } else { + // wells are highlighted for steps / substep hover + + // TODO Ian 2018-05-02: Should wellHighlightsForSteps return well highlights + // even when prev step isn't processed (due to encountering an upstream error + // in the timeline reduce op) + const highlightedWellsByLabware = highlightSelectors.wellHighlightsByLabwareId(state) + highlightedWells = highlightedWellsByLabware[containerId] || {} + } + + // TODO: Ian 2018-07-31 some sets of wells are {[wellName]: true}, + // others {[wellName]: wellName}. Use Set instead! + // TODO: Ian 2018-08-16 pass getWellProps instead of wellContents, + // and make getWellProps a plain old selector (move that logic out of this STP) + wellContents = (mapValues( + wellContentsWithoutHighlight, + (wellContentsForWell: WellContents, well: string): WellContents => ({ + ...wellContentsForWell, + highlighted: Boolean(highlightedWells[well]), + selected: Boolean(selectedWells[well]), + }) + ): ContentsByWell) + } + + const getTipProps = tipContentsSelectors.getTipsForCurrentStep(state, {labwareId: containerId}) + + return { + wellContents, + getTipProps: getTipProps || noop, + containerType: labware ? labware.type : 'missing labware', + } +} + +export default connect(mapStateToProps)(HighlightableLabware) diff --git a/protocol-designer/src/containers/IngredientsList.js b/protocol-designer/src/containers/IngredientsList.js index b3255d5ed8d..8e7b32c7e0c 100644 --- a/protocol-designer/src/containers/IngredientsList.js +++ b/protocol-designer/src/containers/IngredientsList.js @@ -18,12 +18,12 @@ type DP = { type SP = $Diff & {_labwareId: ?string} function mapStateToProps (state: BaseState): SP { - const container = selectors.getSelectedContainer(state) + const container = selectors.getSelectedLabware(state) const _labwareId = container && container.id return { liquidGroupsById: selectors.getLiquidGroupsById(state), - labwareWellContents: (container && selectors.getIngredientLocations(state)[container.id]) || {}, + labwareWellContents: (container && selectors.getLiquidsByLabwareId(state)[container.id]) || {}, selectedIngredientGroupId: wellSelectionSelectors.getSelectedWellsCommonIngredId(state), selected: false, _labwareId, diff --git a/protocol-designer/src/containers/LabwareContainer.js b/protocol-designer/src/containers/LabwareContainer.js index 6270712fcd2..ea829271487 100644 --- a/protocol-designer/src/containers/LabwareContainer.js +++ b/protocol-designer/src/containers/LabwareContainer.js @@ -58,7 +58,7 @@ function mapStateToProps (state: BaseState, ownProps: OP): SP { const containerId = container && container.id const containerName = containerId && labwareNames[containerId] - const selectedContainer = selectors.getSelectedContainer(state) + const selectedContainer = selectors.getSelectedLabware(state) const isSelectedSlot = !!(selectedContainer && selectedContainer.slot === slot) const selectedTerminalItem = steplistSelectors.getSelectedTerminalItemId(state) @@ -66,11 +66,10 @@ function mapStateToProps (state: BaseState, ownProps: OP): SP { const isTiprack = getIsTiprack(containerType) const showNameOverlay = container && !isTiprack && !labwareHasName - const slotToMoveFrom = selectors.slotToMoveFrom(state) - const activeModals = selectors.activeModals(state) + const slotToMoveFrom = selectors.getSlotToMoveFrom(state) const slotHasLabware = !!containerType - const addLabwareMode = activeModals.labwareSelection + const addLabwareMode = selectors.getLabwareSelectionMode(state) const moveLabwareMode = Boolean(slotToMoveFrom) const setDefaultLabwareName = () => renameLabware({ @@ -102,7 +101,7 @@ function mapStateToProps (state: BaseState, ownProps: OP): SP { // or when targeted by an open "Add Labware" modal ? (isSelectedSlot || selectors.selectedAddLabwareSlot(state) === slot) // outside of deckSetupMode, labware is highlighted when step/substep is hovered - : steplistSelectors.hoveredStepLabware(state).includes(containerId), + : steplistSelectors.getHoveredStepLabware(state).includes(containerId), selectedTerminalItem, slot, diff --git a/protocol-designer/src/containers/SelectablePlate.js b/protocol-designer/src/containers/SelectablePlate.js deleted file mode 100644 index cdf5cb013bc..00000000000 --- a/protocol-designer/src/containers/SelectablePlate.js +++ /dev/null @@ -1,218 +0,0 @@ -// @flow -import * as React from 'react' -import {connect} from 'react-redux' -import type {Dispatch} from 'redux' -import mapValues from 'lodash/mapValues' -import noop from 'lodash/noop' - -import SelectablePlate from '../components/SelectablePlate.js' - -import {getCollidingWells} from '../utils' -import {getWellSetForMultichannel} from '../well-selection/utils' -import {selectors} from '../labware-ingred/reducers' -import { - selectors as steplistSelectors, - START_TERMINAL_ITEM_ID, - END_TERMINAL_ITEM_ID, -} from '../steplist' -import * as highlightSelectors from '../top-selectors/substep-highlight' -import * as wellContentsSelectors from '../top-selectors/well-contents' -import * as tipContentsSelectors from '../top-selectors/tip-contents' -import { - highlightWells, - selectWells, - deselectWells, -} from '../well-selection/actions' -import wellSelectionSelectors from '../well-selection/selectors' - -import {SELECTABLE_WELL_CLASS} from '../constants' -import type {GenericRect} from '../collision-types' - -import type {WellContents, Wells, ContentsByWell} from '../labware-ingred/types' -import type {BaseState} from '../types' - -type Props = React.ElementProps - -type OP = { - containerId?: string, - pipetteChannels?: $PropertyType, - selectable?: $PropertyType, - cssFillParent?: boolean, -} - -type DP = { - dispatch: Dispatch<*>, -} - -type MP = { - onSelectionMove: $PropertyType, - onSelectionDone: $PropertyType, - makeOnMouseOverWell: $PropertyType, - onMouseExitWell: $PropertyType, -} - -type SP = $Diff - -function mapStateToProps (state: BaseState, ownProps: OP): SP { - const {selectable} = ownProps - const selectedContainerId = selectors.getSelectedContainerId(state) - const containerId = ownProps.containerId || selectedContainerId - - if (containerId === null) { - console.error('SelectablePlate: No container is selected, and no containerId was given to Connected SelectablePlate') - return { - containerId: '', - wellContents: {}, - containerType: '', - selectable: selectable, - liquidNamesById: {}, - } - } - - const labware = selectors.getLabware(state)[containerId] - const allWellContentsForSteps = wellContentsSelectors.allWellContentsForSteps(state) - const wellSelectionModeForLabware = selectedContainerId === containerId - let wellContents: ContentsByWell = {} - - const activeItem = steplistSelectors.getActiveItem(state) - if ( - !activeItem.isStep && activeItem.id === START_TERMINAL_ITEM_ID - ) { - // selection for deck setup: shows initial state of liquids - wellContents = wellContentsSelectors.wellContentsAllLabware(state)[containerId] - } else if ( - !activeItem.isStep && activeItem.id === END_TERMINAL_ITEM_ID - ) { - // "end" terminal - wellContents = wellContentsSelectors.lastValidWellContents(state)[containerId] - } else if (!activeItem.isStep) { - console.warn(`SelectablePlate got unhandled terminal id: "${activeItem.id}"`) - } else { - const stepId = activeItem.id - // TODO: Ian 2018-07-31 replace with util function, "findIndexOrNull"? - const orderedSteps = steplistSelectors.orderedSteps(state) - const timelineIdx = orderedSteps.includes(stepId) - ? orderedSteps.findIndex(id => id === stepId) - : null - - // shows liquids the current step in timeline - const selectedWells = wellSelectionSelectors.getSelectedWells(state) - let wellContentsWithoutHighlight = null - let highlightedWells - - if ((timelineIdx != null)) { - wellContentsWithoutHighlight = (allWellContentsForSteps[timelineIdx]) - // Valid non-end step - ? allWellContentsForSteps[timelineIdx][containerId] - // Erroring step: show last valid well contents in timeline - : wellContentsSelectors.lastValidWellContents(state)[containerId] - } - - if (wellSelectionModeForLabware) { - // we're in the well selection modal, highlight hovered/selected wells - highlightedWells = wellSelectionSelectors.getHighlightedWells(state) - } else { - // wells are highlighted for steps / substep hover - - // TODO Ian 2018-05-02: Should wellHighlightsForSteps return well highlights - // even when prev step isn't processed (due to encountering an upstream error - // in the timeline reduce op) - const highlightedWellsByLabware = highlightSelectors.wellHighlightsByLabwareId(state) - highlightedWells = highlightedWellsByLabware[containerId] || {} - } - - // TODO: Ian 2018-07-31 some sets of wells are {[wellName]: true}, - // others {[wellName]: wellName}. Use Set instead! - // TODO: Ian 2018-08-16 pass getWellProps instead of wellContents, - // and make getWellProps a plain old selector (move that logic out of this STP) - wellContents = (mapValues( - wellContentsWithoutHighlight, - (wellContentsForWell: WellContents, well: string): WellContents => ({ - ...wellContentsForWell, - highlighted: Boolean(highlightedWells[well]), - selected: Boolean(selectedWells[well]), - }) - ): ContentsByWell) - } - - const getTipProps = tipContentsSelectors.getTipsForCurrentStep(state, {labwareId: containerId}) - - return { - containerId, - wellContents, - getTipProps: getTipProps || noop, - containerType: labware ? labware.type : 'missing labware', - selectable, - liquidNamesById: selectors.getLiquidNamesById(state), - } -} - -function mergeProps (stateProps: SP, dispatchProps: DP, ownProps: OP): Props { - const {dispatch} = dispatchProps - const {pipetteChannels} = ownProps - - const _wellsFromSelected = (selectedWells: Wells): Wells => { - // Returns PRIMARY WELLS from the selection. - if (pipetteChannels === 8) { - // for the wells that have been highlighted, - // get all 8-well well sets and merge them - const primaryWells: Wells = Object.keys(selectedWells).reduce((acc: Wells, well: string): Wells => { - const wellSet = getWellSetForMultichannel(stateProps.containerType, well) - if (!wellSet) { - return acc - } - - const primaryWell = wellSet[0] - - return { - ...acc, - [primaryWell]: primaryWell, - } - }, - {}) - - return primaryWells - } - - // single-channel or ingred selection mode - return selectedWells - } - - const _getWellsFromRect = (rect: GenericRect): * => { - const selectedWells = getCollidingWells(rect, SELECTABLE_WELL_CLASS) - return _wellsFromSelected(selectedWells) - } - - return { - ...stateProps, - ...ownProps, - - onSelectionMove: (e, rect) => { - const wells = _getWellsFromRect(rect) - if (!e.shiftKey) { - dispatch(highlightWells(wells)) - } - }, - - onSelectionDone: (e, rect) => { - const wells = _getWellsFromRect(rect) - if (e.shiftKey) { - dispatch(deselectWells(wells)) - } else { - dispatch(selectWells(wells)) - } - }, - - makeOnMouseOverWell: (well: string) => (e: SyntheticMouseEvent<*>) => { - if (!e.shiftKey) { - const hoveredWell = {[well]: well} - dispatch(highlightWells(_wellsFromSelected(hoveredWell))) - } - }, - onMouseExitWell: () => dispatch( - highlightWells(_wellsFromSelected({})) // TODO more convenient way to de-highlight - ), - } -} - -export default connect(mapStateToProps, null, mergeProps)(SelectablePlate) diff --git a/protocol-designer/src/containers/StepCreationButton.js b/protocol-designer/src/containers/StepCreationButton.js index 37c96e99fad..9c50f5adb2a 100644 --- a/protocol-designer/src/containers/StepCreationButton.js +++ b/protocol-designer/src/containers/StepCreationButton.js @@ -18,7 +18,7 @@ type DispatchProps = $Diff function mapStateToProps (state: BaseState): StateProps { return ({ - expanded: selectors.stepCreationButtonExpanded(state), + expanded: selectors.getStepCreationButtonExpanded(state), }) } diff --git a/protocol-designer/src/dismiss/actions.js b/protocol-designer/src/dismiss/actions.js index 9a3895fd9b8..66edbfefaa4 100644 --- a/protocol-designer/src/dismiss/actions.js +++ b/protocol-designer/src/dismiss/actions.js @@ -1,12 +1,13 @@ // @flow import type {CommandCreatorWarning} from '../step-generation' import type {FormWarning} from '../steplist' +import type {StepIdType} from '../form-types' export type DismissAction = { type: ActionType, payload: { warning: WarningType, - stepId: ?number, + stepId: ?StepIdType, }, } diff --git a/protocol-designer/src/dismiss/reducers.js b/protocol-designer/src/dismiss/reducers.js index d24de53efa7..d70b4da78eb 100644 --- a/protocol-designer/src/dismiss/reducers.js +++ b/protocol-designer/src/dismiss/reducers.js @@ -12,8 +12,9 @@ import type {LoadFileAction} from '../load-file' import type {CommandCreatorWarning} from '../step-generation' import type {FormWarning} from '../steplist' import type {DeleteStepAction} from '../steplist/actions' +import type {StepIdType} from '../form-types' -export type DismissedWarningsAllSteps = {[stepId: number]: ?Array} +export type DismissedWarningsAllSteps = {[stepId: StepIdType]: ?Array} export type DismissedWarningState = { form: DismissedWarningsAllSteps, timeline: DismissedWarningsAllSteps, @@ -62,7 +63,7 @@ const dismissedWarnings = handleActions({ }, DELETE_STEP: (state: DismissedWarningState, action: DeleteStepAction): DismissedWarningState => { // remove key for deleted step - const stepId = action.payload.toString(10) + const stepId = action.payload return { form: omit(state.form, stepId), timeline: omit(state.timeline, stepId), diff --git a/protocol-designer/src/dismiss/selectors.js b/protocol-designer/src/dismiss/selectors.js index 057dcbaccdd..6d2890d5220 100644 --- a/protocol-designer/src/dismiss/selectors.js +++ b/protocol-designer/src/dismiss/selectors.js @@ -30,7 +30,7 @@ export const getDismissedTimelineWarnings: Selector> = createSelector( getDismissedTimelineWarnings, timelineWarningsPerStep, - steplistSelectors.orderedSteps, + steplistSelectors.getOrderedSteps, (dismissedWarnings, warningsPerStep, orderedSteps) => { return orderedSteps.reduce( (stepAcc: DismissedWarningsAllSteps, stepId) => { @@ -57,18 +57,19 @@ export const getTimelineWarningsForSelectedStep: Selector - (typeof stepId === 'number' && warningsPerStep[stepId]) || [] + (stepId && warningsPerStep[stepId]) || [] ) export const getDismissedFormWarningsForSelectedStep: Selector> = createSelector( getDismissedFormWarnings, steplistSelectors.getSelectedStepId, - (dismissedWarnings, stepId) => (typeof stepId === 'number' && dismissedWarnings[stepId]) || [] + (dismissedWarnings, stepId) => + (stepId && dismissedWarnings[stepId]) || [] ) /** Non-dismissed form-level warnings for selected step */ export const getFormWarningsForSelectedStep: Selector> = createSelector( - steplistSelectors.formLevelWarnings, + steplistSelectors.getFormLevelWarnings, getDismissedFormWarningsForSelectedStep, (warnings, dismissedWarnings) => { const dismissedTypesForStep = dismissedWarnings.map(dw => dw.type) diff --git a/protocol-designer/src/file-data/actions.js b/protocol-designer/src/file-data/actions.js index 620aa1cb604..941c0768ec7 100644 --- a/protocol-designer/src/file-data/actions.js +++ b/protocol-designer/src/file-data/actions.js @@ -1,12 +1,7 @@ // @flow -import type {FileMetadataFieldAccessors} from './types' +import type {FileMetadataFields} from './types' -export const updateFileMetadataFields = (payload: {[accessor: FileMetadataFieldAccessors]: mixed}) => ({ - type: 'UPDATE_FILE_METADATA_FIELDS', - payload, -}) - -export const saveFileMetadata = (payload: {[accessor: FileMetadataFieldAccessors]: mixed}) => ({ +export const saveFileMetadata = (payload: FileMetadataFields) => ({ type: 'SAVE_FILE_METADATA', payload, }) diff --git a/protocol-designer/src/file-data/reducers/index.js b/protocol-designer/src/file-data/reducers/index.js index 36030716f91..9c29aee33e6 100644 --- a/protocol-designer/src/file-data/reducers/index.js +++ b/protocol-designer/src/file-data/reducers/index.js @@ -2,10 +2,7 @@ import {combineReducers} from 'redux' import {handleActions, type ActionType} from 'redux-actions' -import { - saveFileMetadata, - updateFileMetadataFields, -} from '../actions' +import {saveFileMetadata} from '../actions' import type {FileMetadataFields} from '../types' import type {LoadFileAction, NewProtocolFields} from '../../load-file' @@ -23,6 +20,12 @@ const updateMetadataFields = ( return metadata } +// track if a protocol has been created or loaded +const currentProtocolExists = handleActions({ + LOAD_FILE: () => true, + CREATE_NEW_PROTOCOL: () => true, +}, false) + function newProtocolMetadata ( state: FileMetadataFields, action: {payload: NewProtocolFields} @@ -34,19 +37,6 @@ function newProtocolMetadata ( } } -const unsavedMetadataForm = handleActions({ - LOAD_FILE: updateMetadataFields, - CREATE_NEW_PROTOCOL: newProtocolMetadata, - UPDATE_FILE_METADATA_FIELDS: (state: FileMetadataFields, action: ActionType): FileMetadataFields => ({ - ...state, - ...action.payload, - }), - SAVE_FILE_METADATA: (state: FileMetadataFields, action: ActionType): FileMetadataFields => ({ - ...state, - ...action.payload, - }), -}, defaultFields) - const fileMetadata = handleActions({ LOAD_FILE: updateMetadataFields, CREATE_NEW_PROTOCOL: newProtocolMetadata, @@ -61,12 +51,12 @@ const fileMetadata = handleActions({ }, defaultFields) export type RootState = { - unsavedMetadataForm: FileMetadataFields, + currentProtocolExists: boolean, fileMetadata: FileMetadataFields, } const _allReducers = { - unsavedMetadataForm, + currentProtocolExists, fileMetadata, } diff --git a/protocol-designer/src/file-data/selectors/commands.js b/protocol-designer/src/file-data/selectors/commands.js index a309b4f9219..ee39e8ada2d 100644 --- a/protocol-designer/src/file-data/selectors/commands.js +++ b/protocol-designer/src/file-data/selectors/commands.js @@ -13,6 +13,7 @@ import {selectors as steplistSelectors} from '../../steplist' import {selectors as pipetteSelectors} from '../../pipettes' import {selectors as labwareIngredSelectors} from '../../labware-ingred/reducers' import type {Labware} from '../../labware-ingred/types' +import type {StepIdType} from '../../form-types' const all96Tips = reduce( StepGeneration.tiprackWellNamesFlat, @@ -22,8 +23,8 @@ const all96Tips = reduce( // NOTE this just adds missing well keys to the labware-ingred 'deck setup' liquid state export const getLabwareLiquidState: Selector = createSelector( - labwareIngredSelectors.getIngredientLocations, - labwareIngredSelectors.getLabware, + labwareIngredSelectors.getLiquidsByLabwareId, + labwareIngredSelectors.getLabwareById, (ingredLocations, allLabware) => { const allLabwareIds: Array = Object.keys(allLabware) return allLabwareIds.reduce(( @@ -58,8 +59,8 @@ function labwareConverter (labwareAppState: {[labwareId: string]: ?Labware}): {[ } export const getInitialRobotState: BaseState => StepGeneration.RobotState = createSelector( - pipetteSelectors.equippedPipettes, - labwareIngredSelectors.getLabware, + pipetteSelectors.getEquippedPipettes, + labwareIngredSelectors.getLabwareById, getLabwareLiquidState, (pipettes, labwareAppState, labwareLiquidState) => { type TipState = $PropertyType @@ -132,9 +133,9 @@ function compoundCommandCreatorFromStepArgs (stepArgs: StepGeneration.CommandCre } // exposes errors and last valid robotState -export const robotStateTimeline: Selector = createSelector( +export const getRobotStateTimeline: Selector = createSelector( steplistSelectors.getArgsAndErrorsByStepId, - steplistSelectors.orderedSteps, + steplistSelectors.getOrderedSteps, getInitialRobotState, (allStepArgsAndErrors, orderedSteps, initialRobotState) => { const allStepArgs: Array = orderedSteps.map(stepId => { @@ -197,8 +198,8 @@ export const robotStateTimeline: Selector = createSelec type WarningsPerStep = {[stepId: number | string]: ?Array} export const timelineWarningsPerStep: Selector = createSelector( - steplistSelectors.orderedSteps, - robotStateTimeline, + steplistSelectors.getOrderedSteps, + getRobotStateTimeline, (orderedSteps, timeline) => timeline.timeline.reduce((acc: WarningsPerStep, frame, timelineIndex) => { const stepId = orderedSteps[timelineIndex] @@ -210,9 +211,9 @@ export const timelineWarningsPerStep: Selector = createSelector }, {}) ) -export const getErrorStepId: Selector = createSelector( - steplistSelectors.orderedSteps, - robotStateTimeline, +export const getErrorStepId: Selector = createSelector( + steplistSelectors.getOrderedSteps, + getRobotStateTimeline, (orderedSteps, timeline) => { const hasErrors = timeline.errors && timeline.errors.length > 0 if (hasErrors) { @@ -226,7 +227,7 @@ export const getErrorStepId: Selector = createSelector( ) export const lastValidRobotState: Selector = createSelector( - robotStateTimeline, + getRobotStateTimeline, getInitialRobotState, (timeline, initialRobotState) => { const lastTimelineFrame = last(timeline.timeline) diff --git a/protocol-designer/src/file-data/selectors/fileCreator.js b/protocol-designer/src/file-data/selectors/fileCreator.js index 8fab818552f..9d839c24e00 100644 --- a/protocol-designer/src/file-data/selectors/fileCreator.js +++ b/protocol-designer/src/file-data/selectors/fileCreator.js @@ -3,10 +3,11 @@ import {createSelector} from 'reselect' import mapValues from 'lodash/mapValues' import {getPropertyAllPipettes} from '@opentrons/shared-data' import {getFileMetadata} from './fileFields' -import {getInitialRobotState, robotStateTimeline} from './commands' +import {getInitialRobotState, getRobotStateTimeline} from './commands' import {selectors as dismissSelectors} from '../../dismiss' import {selectors as ingredSelectors} from '../../labware-ingred/reducers' import {selectors as steplistSelectors} from '../../steplist' +import {selectors as pipetteSelectors} from '../../pipettes' import { DEFAULT_MM_FROM_BOTTOM_ASPIRATE, DEFAULT_MM_FROM_BOTTOM_DISPENSE, @@ -36,21 +37,23 @@ const executionDefaults = { export const createFile: BaseState => ProtocolFile = createSelector( getFileMetadata, getInitialRobotState, - robotStateTimeline, + getRobotStateTimeline, dismissSelectors.getAllDismissedWarnings, ingredSelectors.getLiquidGroupsById, - ingredSelectors.getIngredientLocations, + ingredSelectors.getLiquidsByLabwareId, steplistSelectors.getSavedForms, - steplistSelectors.orderedSteps, + steplistSelectors.getOrderedSteps, + pipetteSelectors.getEquippedPipettes, ( fileMetadata, initialRobotState, - _robotStateTimeline, + robotStateTimeline, dismissedWarnings, ingredients, ingredLocations, savedStepForms, - orderedSteps + orderedSteps, + equippedPipettes, ) => { const {author, description, created} = fileMetadata const name = fileMetadata['protocol-name'] || 'untitled' @@ -106,7 +109,7 @@ export const createFile: BaseState => ProtocolFile = createSelector( _internalAppBuildDate, data: { pipetteTiprackAssignments: mapValues( - initialRobotState.instruments, + equippedPipettes, (p: PipetteData): ?string => p.tiprackModel ), dismissedWarnings, @@ -124,7 +127,7 @@ export const createFile: BaseState => ProtocolFile = createSelector( pipettes: instruments, labware, - procedure: _robotStateTimeline.timeline.map((timelineItem, i) => ({ + procedure: robotStateTimeline.timeline.map((timelineItem, i) => ({ annotation: { name: `TODO Name ${i}`, description: 'todo description', diff --git a/protocol-designer/src/file-data/selectors/fileFields.js b/protocol-designer/src/file-data/selectors/fileFields.js index 544ae5fa7d9..80fd52fffea 100644 --- a/protocol-designer/src/file-data/selectors/fileFields.js +++ b/protocol-designer/src/file-data/selectors/fileFields.js @@ -1,19 +1,13 @@ // @flow -import isEqual from 'lodash/isEqual' import {createSelector} from 'reselect' import type {BaseState} from '../../types' import type {RootState} from '../reducers' export const rootSelector = (state: BaseState): RootState => state.fileData -export const fileFormValues = createSelector( +export const getCurrentProtocolExists = createSelector( rootSelector, - state => state.unsavedMetadataForm -) - -export const isUnsavedMetadatFormAltered = createSelector( - rootSelector, - state => !isEqual(state.unsavedMetadataForm, state.fileMetadata) + (rootState) => rootState.currentProtocolExists ) export const protocolName = createSelector(rootSelector, state => state.fileMetadata['protocol-name']) diff --git a/protocol-designer/src/form-types.js b/protocol-designer/src/form-types.js index 751196c93d8..18e22093534 100644 --- a/protocol-designer/src/form-types.js +++ b/protocol-designer/src/form-types.js @@ -1,9 +1,56 @@ // @flow import type {IconName} from '@opentrons/components' import type {ChangeTipOptions} from './step-generation' -import type {StepFieldName} from './steplist/fieldLevel' -export type StepIdType = number // TODO Ian 2018-05-10 change to string +export type StepIdType = string + +export type StepFieldName = + | 'aspirate_airGap_checkbox' + | 'aspirate_airGap_volume' + | 'aspirate_changeTip' + | 'aspirate_disposalVol_checkbox' + | 'aspirate_disposalVol_volume' + | 'aspirate_flowRate' + | 'aspirate_labware' + | 'aspirate_mix_checkbox' + | 'aspirate_mix_times' + | 'aspirate_mix_volume' + | 'aspirate_preWetTip' + | 'aspirate_touchTip' + | 'aspirate_touchTipMmFromBottom' + | 'aspirate_mmFromBottom' + | 'aspirate_wellOrder_first' + | 'aspirate_wellOrder_second' + | 'aspirate_wells' + | 'changeTip' + | 'dispense_blowout_checkbox' + | 'dispense_blowout_location' + | 'dispense_flowRate' + | 'dispense_labware' + | 'dispense_touchTip' + | 'dispense_mix_checkbox' + | 'dispense_mix_times' + | 'dispense_mix_volume' + | 'dispense_touchTipMmFromBottom' + | 'dispense_mmFromBottom' + | 'dispense_wellOrder_first' + | 'dispense_wellOrder_second' + | 'dispense_wells' + | 'labware' + | 'pauseForAmountOfTime' + | 'pauseHour' + | 'pauseMessage' + | 'pauseMinute' + | 'pauseSecond' + | 'pipette' + | 'stepDetails' + | 'stepName' + | 'times' + | 'mix_mmFromBottom' + | 'mix_touchTipMmFromBottom' + | 'touchTip' + | 'volume' + | 'wells' // TODO Ian 2018-01-16 factor out to some constants.js ? export const stepIconsByType: {[string]: IconName} = { @@ -23,33 +70,21 @@ export type FormModalFields = {| 'step-details': string, |} -export type DelayFields = {| - 'dispense_delay_checkbox'?: boolean, - 'dispense_delayMinutes'?: string, - 'dispense_delaySeconds'?: string, -|} - export type BlowoutFields = {| 'dispense_blowout_checkbox'?: boolean, - 'dispense_blowout_labware'?: string, + 'dispense_blowout_location'?: string, |} export type ChangeTipFields = {| 'aspirate_changeTip'?: ChangeTipOptions, |} -export type TouchTipFields = {| - 'aspirate_touchTip'?: boolean, -|} - export type TransferLikeStepType = 'transfer' | 'consolidate' | 'distribute' export type TransferLikeForm = {| ...FormModalFields, ...BlowoutFields, ...ChangeTipFields, - ...DelayFields, - ...TouchTipFields, stepType: TransferLikeStepType, id: StepIdType, @@ -79,8 +114,6 @@ export type MixForm = {| ...FormModalFields, ...BlowoutFields, ...ChangeTipFields, - ...DelayFields, - ...TouchTipFields, stepType: 'mix', id: StepIdType, @@ -121,3 +154,20 @@ export type BlankForm = { stepType: StepType, id: StepIdType, } + +// fields used in TipPositionInput +export type TipOffsetFields = 'aspirate_mmFromBottom' + | 'dispense_mmFromBottom' + | 'mix_mmFromBottom' + | 'aspirate_touchTipMmFromBottom' + | 'dispense_touchTipMmFromBottom' + | 'mix_touchTipMmFromBottom' + +export function getIsTouchTipField (fieldName: string): boolean { + const touchTipFields = [ + 'aspirate_touchTipMmFromBottom', + 'dispense_touchTipMmFromBottom', + 'mix_touchTipMmFromBottom', + ] + return touchTipFields.includes(fieldName) +} diff --git a/protocol-designer/src/images/labware/Tiprack-200ul.png b/protocol-designer/src/images/labware/Tiprack-200ul.png index c0f73d1026dc8e283dd9c07f64df1a50d3f853b3..c3f3bfed1856437a44ef7e5f1bafe06d7d6e67cf 100644 GIT binary patch literal 171582 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%0D>o zvw4qZZ%KwgLlc{k7Ovf}fs%qb-QOEF&H2Oecn-*9$yypLrE+|u=NIaWSKZuG=r&Y4 zr%QtOtrk21KoX~H$A3coLO=rRc(Cjq7_cY3s zWD7Fg_dwD{=zOG)2A6|(BRuByx$SZRDwHtE1RpT0gWo%hELrPo=j{B49|YK4CHccQ zhsqZmf$Khe&bsPz)1#Ud7Mcc@4tvE+x`p3)d&}RLJ$a=nn!cA4+x!1_W*+FL>zXw;DEl~? zx|beupai2ts8d*3ms$x)EcZ%Zyl7!6fo)X3e))s!z#cKHTvY`W3PQzgrDc3e0LQEY zHw=a+_E@pcRBVzA3m7>x0J$KbAd8w?T58aR^1IMX9Z>&t$NE;&%a`#a2x5#t>``zc zUCaB<)Z5@3V=aGrsBw#_DFNZiJiaT{9x14+(}?StVCVn?CHiOSIwBjPi)SA6W^Aq! zT>(!*N?NHA-PfKyc&Yxmx}y1=SYxI8-1Nsg>SfHKXG}+o5R|^WZ~@$0JWfXe-Bv!0 z){-TGd~}m5*I7D<2Ti}o0@4o9jzg0)a}#JvegY_)4Eg@~voP}RChXy(fF-1nGpMuU zcJN7})yx5Q&{wLS*N_mSU5QOhWD3=d;2-tNoJlBtHJ_I9r}wQr7u*VaB6{Xe18kyY zvETWT9R!T2eM9-gTjh(01d1kMGq$UcdS7sG95G^tLtRA8F4mQ^W1JbGP>Bsd0U+O4 zgm7jVG%=6UMn3^U>;`khjy|B!C>sEdzkmMVTZ3$odHFa8EtOq`Xff)kfDs6A6f2og zincDH}<#hSD^>*+;5!OJeCr_&aO>Kp05z_|@pijvd+KA~}h% ztv7GpJXtmONq3YQ)D777vOUUV0d`~>G+21zK%YubcbjKjnJRQ&rmBrg_d)R)MI%CXz zMWTZvDmDs#C_b7X#J(SDYMLoA4iz6lfW_;_C7FpVRy5$QIbK_PufzRyH1OfDfPirP z=S)_Y(8hy=r#Xxh3$|adU@OlX@)mp*D=GejvVn(4g(?fes6UxQKru$qP|k7Z_#868 zEu;Xw1f(n_?bp^2^!jfH_ z_@Rx=@1xh|Bf2}gf25^nZW^XvtnTD*2sWwRyEE-45*c4Aw=pRgnsxg0FIbSn9Z^(G zNiDg&@WDb}B7+{#_h==BwtK5$X#qXo0&t0O<7(sHMYntMRMlnKz92ns4PXP60Bs$H zoFaS5%gPv-M@J2&i*wZ!M^_?l&+grI_-Fih3IuVj(c!Zgrp9ugGY;y4sM+1DkB0vV zvy-Bu{4@4CDi6a4+Hm6mnA?bJqXlp?Lk~HW_hqTJGKw*9cIHkr$BaP{vFux_LkL7e zQefwypLa+}wo}UjRhxG$=m^$eg_xWiv%`S8XsMBKRkMu+!)`xH2c+OOvKW;?sS!`#l~Di)7dSqEm$HZ&b=?OE2= zC$qBlo2xd`mNzyEgJ3>BSPbBrVDbC4&6)X`>Dk#Y3k%UjWTd8s?%A`Bq{8$hr9C$r zO%_$S%*_@>E)aF@i*t+KVAHCjlSgpFE2}6<^491X2+pM46jir2qAB51>R8ymz z*m18KBHudD1##P&7iX9>5!7d^#JxE?lowz=^R!xsHfg;GLf;!20BOyb748`pl6cJa z_KO!+SfM;^8tYlUQ}>_&AVOKHU1V;4-@dWjJN5viPdLrjCk6v46ZB|(QD0K>qp|`~ z<%7%z@g1~>Wy2};w>fL@$NVenj*C!596J7!fe(z!_=~)ULyP~874;o!BNp6<2|lr( zpQ=B|v^r~!QM5$%Lfve+qT*@i=V#IoZ(tmcc9I;pTzxU2^6Qr`N5GtwmDjCZJ7Zd? zx`1+2or4kdU{IYV50nGb({hG<*2{$7A*>@YI6v>=G3;Znms3xzV@`hXV4=;2r$x&~ zY=*6YkmU-0`uK6SpZy%q{8QR@0xZQH^JWf?IMtn2J9F1jKEA4UuUZ0ftkTOjZ>CQ> z|78iqUOy@hWE3>7SnccG+^j)88g=k9`9|;M-v*zMYauC8z(HiI7`bADC{;@CDQ6@TV7aMqJ~i{|6rDln-lS%_4AVH)7OkR)4J%^#t~*J#2MbFp&6P4 zyb&081(lhm7R`yHhW5G}v@9p+gk8`Lzs%IL*dWpCf)_C+NASPtT`%iBz{?ZJf_Dz1 zYTa!l9b1ijx4qY|`=JdVKD%6zLIC~jUQ0C^IqDwJtyOusf(0*nZ1;{ozi4L}t(K`J z?hEU8nCO&~D`iNF4tzwOO*O8cn;cxr-Y?G zUOq83YRZynP=Z4ujLdSi!QeTSs;X6#3tnsoI5nVFrWBeQ8r_eT@4fS$euOnL zXa6lCc#!<>u(H5iMMbFNCr+H0vHDuvtvPiMb(;Fu@68?;Gium~5fg6Qy-Ztoy_#t~ zD~HVBM35J$^v^`d~kTX&40OzS^lM*PzrNTbK<(Mf@1 zJ^0^5!14Z?ZSUr34a_M}ELa*kd-E^Uvq;G%Q`e9TK@u#!i&;q{ArB3mLNF%E%SN&o zB*gdF|42ZwV6x{gk|xiQ`vO$LbQ^>%lEn2iMMz#q0OT^_6ZsFYOF;CSoBIr&KvC5% zTrgKeRQjl-=JTAuhmt4NLCu7B z;nSn7io;JWHg~);% zo6lam*2YCAxC>5uK&&fPOf;TkN)87;5LRwp_tqRb6h~cV(1e|_A57p6I7@zjeDKaF zwz-Xd=LSlK=DQduaeTZ;`m{D6P~#xR2Pf0D&3^45zGO%6#G@&4g(nU-qx>`-)~I&} z-9(Ch_MtJ-;;Fh$R&eNYXMyuNIub50d5*A;Xvn}e1Eo@FDN_A2iqHITZ++JDaDH2s z@^3N`J!i+8Oqbi+i;{Y^8K*-=d^Xkgc(l12PROWBBB7wNAieVu{e=60%Kdlo|TIXusZuX*yL!C zgp;8)iKeL?5#%I|G1zyiyD!_!1Q^t`_dS1aZ@E2I{kv~xvMs8K$j)38$Pa2a{XsO> zo2_QhtIvL$*Y=er^vE;aswbK&cicXI)Ng-u^hPF$!QTRpFKQ&}L14WsFTV$l1RD(q zt(*AsE!_+HDb_&1%TeX<%Jo(v_YFiogmdYxLLw{Tw1nvR{%{y2+?-ptCb6lLb3iFK zF7Zw|V{Ig5egIq#7w_(oqW3?rsrf?y(i%u*e2J~)bpzJMDJUyZKDm9!al;Nxi@BXhH~$KSg*m|Tscu$UM}@fS-kE*$;cjJ>tow3sk=E` z+AA~x+$W%xf5s%`PJzf=3k%O`p5g29Ry z-C`EJOxd@2o*dqV)pgxr9&q*^6RjjV&E2z{W((OtJixdrWh2U1c>TOJFKkBZ zdfrpsRTy%^Kz(_JV&Jsn`RdM*fiw%JC|(dn^Tdcb zFJ8Y!%wyS8=uKIi!N7jQ+ZzWRCT{iQm4P;rq5w=r3>)@Lkomka#15O=SXs#zhn#m~ zD^%@c<+_RAs;ZKSQH**(JmYCVRnO8{)F=cbq5|>?!he+YG8)$AUNAA{YSEy4!r}*J z?VyDDlgw5C1Jc#}8?hq9-=I}X7VN$k5%aluTmk(1!7IqB6rA+=!0sFd{)8|%-*FoV zNm!Zr`7@Lacc20^mo@^wxYANR6f%sH&YcUwh`>q0KZc-6SfKo+0^uM)IjGmOh=Vob z+AwIN|2xO>`c04LNG2e*Lm!2sA9bv7pO}edp&0(O*RIWXb{5)25+U_@w+g8hO-nG` zn$I{1n!M0_ftK4lSVGsg2&c=$G2&AzLSuZSwMW@%4tT>JwLMm2oiAI@olCrki@q`I z|4*goK<+yYZTbF?Z_7}}Hh+IiHnyRkwaQ^+tC1K-EC);Gp(=_7*uImdw2p9?=%YwXD8G5{s%XcRSh=ZY$+W=6>fGle*rp{vW{=|ucNYwW4 zN0m_6{MvQdRYl9QrDoxbs4eC-zI!)z%$S*rm;J1!c)-&NlF2f~9!QJ(lzCi|kj1B) z@!9G!uog6K#^gCBL$GrWaF7)~KZ1mCOSKh4ZqQP}ff9F^Qe=tc9xEm%;#NdsSH|h0nL9eo*=k_#@zObn~`FZEgtw$<=d{`>bQ5pzu=*%w7h!(KY-Uc=-+Z2s&sdsKGX z*blRkGKTebUK>+!E&Qd$`dL$@X6~sC=*x#@DV?A*w@OufK9&W{L{Ef);G1qw|8_l! zPaQ=U{PQo1k8YnIv{4{f^IfPKIT?Tm{1>oLv*!NbwRrB*RnT(1`)Af>Si25b4BJDr ztw03SPk3m~$||U#p#dW1YH}I@!3m|ANueGFOvj7^RR_Qzm*ZN?AFCpdO4-a>M$OE7 zU>kWtp*Sh%`0?e)PY}3AL|C&mkC>mo4rB-y$zoiW4<5XVH`U#{?z0>>pkERWCy`?8 zSllVHE?h{yewfw}Ne{IS#TJj!YiB7!8^Z3kZ8#@(nRT@@KJQ6K;1NpPCu>a5)uo}t z(W>>!`P@(HyI9@Dkv)Cvm<7`-?2w`F(ADi%0rwKk%sFNX|5p1UNIEjd9?@$3$B#}- z>34Rp(f%gE)?u}qS?Ixo7_Tis28Qk$TT2R;KZdVJ4`;RzdCbkt8Eaya1cBC}1>3uX zZA?hBSQI4O2gt}ngV$~z>mw_3Q_*(Of2Zyq0Q#!+P7L?d*6iD-KnoZh_&U*K%LiOS zm?x{Ol%CYbgV9nf53wsqKX+~j;6Uj5rO<3(xX^5ch13xW%`C!xLx|+HvTw|fkl)l@ z|M)wdw+?3LO)v(Vs8J|jA>_CtZD7WszR#dBi*r_!VOoxq#fOj$t}>8GT~8H7=`ij? z7Q?E%9a5p*jH%A!#s@5j{b}z>L5C zAO_~#*RPk>!!my?wK93n+gsnnL}^(X5GwnKxbG0u*8XfKdq{h<`CA3WJ-bGpy?SM{ zs)oGCD^8<7PD}GXXHjWI@0p0P;Z0+pI5eM^`-pHw81p4`-Y^$NHq*R;e@RC0zVJEdbC~XWpV-8O1jHIU8=PCqMr5-=>NcKi|Gt z7b9##Tx8sE36~crm|u}G0l_L7x<~i!)qeRhU2`p| zUtdQj3R#@Iywq|?xyj84WTB=k1eVXm6M_`a2udskW6YN4M}Sp<`Yz%v)4JKv1xeOTm<6*1dl9YW&2B2*PM^WIfD@_58t>Z*O}oiW|j- zU49OU{=(tS2w(tR&YWpLIwg}T#yux5ah(CFg2eg1jJ*n452SRH6KbeA;Wc6Rh#aC) zm;szecms_7G)oR6pTi7>Iyp@}cTOZUpE8n0jOp6G9k&5l3Bk;?W8B`&KoxI7I%4eL zP}Iqc6eeP{2J$HXHoO`aaYCnUFP^{)=FO}4XV3MAPZg&pQzyNci^KH9cwf!!Y;44z3pYjtb4zs=gEzvqP{#3(Q2Zud78e`1>n47qWKPzi zVW7jKAC?IR1A;n*%gPVOga^h(#G-!U3?FevnY!uwgXi6)R+wOX%w~?bBMG;(Pv6-Q zpUT71J~ZOB$~B=5v#LoHQmyV^MtDgFe1vVet2z^lr3dOvt*8}%BC}u;7C6_ghzPCu zmn8nor}!F$RPgNCZri5P=3cmXQ5i$;KNA!&zyfy%#YwK7#0FS+Sm>ZSXN#boNa9}Je3#cs(D(LYPv&*2Di%$*>|48 za_ra>^|#^PV6w3WrFOZ$FD9{^5=8yx?1-1IUcpr}nJ;ep1?YqFKxlJD=)MLrkDc4^ zsh#U>15!E<4=9FhLd@9-=+pfw!%CfIpWZG%4eZUMW?3rne~>@bCrY+wDa!3D1Ol#qdGadPwvl5QEma6 zQE}BwqZYM(urs~r6Um1fR`{O*bvz&bJuuEgZZD;c0!vu5|ZVZyj!na;Be-vGM-a#=G0CGV$Fw%IVOoKL=dlibnM9LYS|SHHC1U zc}G-#sy@aQ?6w$ZVj_&Gzbop`+&kuH^atD_a@>o$QY8wfD+orRT;QOD_y$4WSA^_-}&bPOuo=>n0Bj zpcdVIp6Yl*LlWCi+hxT&c&z+8hk4S{;m=Ak#e+#Y9#ORtYzZy#dCyBgI4F#3^2xE5 zkv;;CNckUh7A|>SqpykFmhXm9x4fHfL=^d?!GS*i^%GqV9rWc-a~|(qVi9<+*yca_ zCmMD8Z!*`tDhM=B65#3uLq#I7qT(t>t`{trzUhi8Hu%gNE#&SkSYQmR9e(H0B-;nN z?8$RxRWuN*lCFv~&;}r3B&f;s>6w==OSJDr`gC7qP#W-)kDt6n77#F9dzXp z*391m5@!ExF|IGK`uQAwFasV8N*NEZ5o5+Y%3j?WC;hsohYY`3689wxZzfU5Jn1 z`xgU!oTe#^UlbVSsA%MH8tq_;wf^H(npm{bp9w>P8U_AYV zKAYm1+0Wf^Z}22QOf)pw8f`txkJh-U$G#$?={U^(x%CbqK9xydK7-B6XjxyATl}4C z*S0XQR5ML*{5>;owzIQs>`Z2`LCy1KPDHxMOA$09AKc=Y4iF|_w9F`+1xZ+ny}qKl zOm`%StwfKiFeD>IXjj}1gqrt!C_3T_xP1H{+?0^11D%1Rck-%6#i9Gm>%G(^<%2VUB0K|iX^8vOf++d3Gt@pCZ z0U25%wIYA3XV~FWlIeD3{R(0w4WrFfgU%ai7YJJ$o<+TG?^e=C(BVuQ#gOQjF?|*mhmWFpB2ZJf!yQ!Rhh_$r#c3b-7GeB$ zw3@>56Dqb@;%(`DEbl2xhd;SuhDFB|V}(wsEp1K5>9K>&vDiY}>sCPfUds(2-VDL# zoo?8DLW_@Uy4l?g^Ti*j&bW8fh{6PU6g>iSBinuP9$;n$qJjV;s&pZ+tCLhiltw%e zF#&Xi6whCv{1K4?Hlfq|i$C7?1G20jI)1$D-MhXoC03)8Cmau+ur{0Jik6`|3Jq|K zLeqdT`7}=Q0$gn987KoM>r-K}lov47=G54FAafEn#wXTUUXOa?56a8s0R-JdSA3k; z3&I5cr#c9QEfPFLX>U-{Rz1$n%GyLwXO0RcX6PUaMHDD(G|9SpHGEQ^5mg}F{AGYh zb#{DG%|AUdBuMAP6P4y1X#`}iWVg%oT97Y(M>QzT?ODH#NuuF*Xwi{%N_Fc7vE0YL zqlXc1qIY^GfEWB^#q~|2VUnr2Yjn5T%1>t+gOKbnFZ|nWagDId%>5Is?PbqMTsHfe zw=6CH#n^j%D%7_$K0yEU$aNy089yC`PY_%U}&p zhftIr2``Gtih)2!`7>MVz zAn%0B$Gua;;1h#Aq;UZL?JtL(#tcqFW971C1<1)u-v}lhRI5ZK>R9`=ow%5Fm*7U> znx^a##4PZsQ}x)wK^=*VcB?g4mn9v*O+Yu`*s@x~%f(_pC=6N!hXI4+e)NebZne8? zWR5mC(=;IBlwMV^tBkqQoQT3xK~e4h74SrB zp2y=&{r%(e9*Ss~+SK(g504+BvtWz(wm~%!k&)5sUxQJbrG>5d|3>DQ5VX)0o14z8 z<158}n1sOt4eYyBduMc-k(qh2oITQGP#?9fWrCocq8@<~NN`F)EUFTqGV1pA71^R{ zML-ZjR(Ci*$3uSLu0l?_4^lSDJk?ulPT0VV89faRm!+jdtNM|{hp%**wLCT%lF`vs zJucL>dzkz7wd-W(-RpFy(=4jMo06 z4U$Vg{l2%Q-Q<(;!$af7z1^Dnv;B0!lP!O@xfdV$UE8rGcggqtqXCBab>`mZnR8t6 z=N=>dZXIC(=sfwk`S$Jt#B>Z1;aup^ZFZ-~}j?j%g5k|l$s4Conzo4&yi11w$ zb!f-EFOt?1gaN%BX2T&0N`nW#xw-XfeEdA**+7VSfyTYPQ4IsG0Hhb#eIMeUZkHsT z_Q2zfL_oWNLNaq2wi&$<>2;2vFRu3eAQ3a_&P9U(ZW@QJ)uD#j%|<+6YQHYrWt&*{ zM!Z2tB1k2JdNqdDWP4R4c^K>o4N>v5$mU383zxZA(oaNgk7VwA~#<63&hq z@87nYas=`!Ysd#zFJBh6!lK7xu}4zmW*x0)tn%qwo0>p9dthOA{=`o&QR8p+*EUvL zK^k&rSaQw~#zWgP82vECfD-yYmZ-marI>SaAv7q zPLttGR?{9a_JO|Eys;WRqMPcGTmV71BhpFL&+Wm|lA&!QZvj0n4^FrWn|RJM?BYDF zo7qy{@;lp7Y5R+##^?72N=xeJ<2ROd-A~y;fBy>`8LO@&he_WA ziZ=>9E0Tf?o;3_QZxNZD>0ObsR#qWyqU!o~5#%^BXTvot$8BU8W?}UY5)9v)F#K@^ zt!3pc6g12+GMx7RF!df_J^$_de<`UXsi;ULMaZa(Qj~qtVXps?-godOtGNPe0 z?937h(IgEj+&)P(Rb~@K>i2m0{J+QXcYKfg{@yg+@7MeJyvBK*=XsSs*m<-lVv39* z)bHIeqCmkrCmW2bx)a?s0qb|nifEi}T)6_k#Rk6ns5#*nFzuvrgk(V@%wkpu4}>&JD39V z*BnQ#FY1P1i?h^b;HDck2!3ByR&1P!o#48Jk{C38mZ{j0nZQqiHzQesX)#Q22+FXh zPlbmM56vTFQHcphIVp*bxePdcOZuNDTTckIa!X6wl+9hX7zf3Wu+bcDe0F*QPliH* z&xp*=!G@>o1u{p@A(>(+o7hC@3fp<>ZK>8+P$^cE*TeckiY5qu(qW2~7_Tl~rGqel z=IPhQgAAvU9yL9^kl6MgG|5*3 z17|Uur)DNG`>Ai6XS=q39(SwHdGUaCDk5{=ED7nilODV7@_gVW?A@NO5;1Tpj7tx{ zn&rZ-Mk$Rg;K#7gSG2>g*mVLP-vcK&wfTAq)I>2|zJ>OG(X- z)aQqzshdU1IB61Y->PTlM|2OM50DRDgtsPW_ z|DhCpize&wmevA`(Xc!@B?Zpj*ZApy?Fl{4JJY8?SH+1qqVgW;}>LRLRdZ)7_xudIMV?zQ(TwOmD<=;S5^5vUd#38(`Eek)ZrH079?F# zSc>s(HV$E<1`@&zLro0(loAjI*!Y288yakxIT6`5r+-ED(x1i$Cvx=CRNl~52=3ev zl#m}kF0--8nx6Xrp)dQXA?{#s$)ECane7n}5PkRs%*W$)e-+{Ea6gGIc6T>MBA=x3 zN_5kbN9`e4#gRETU%d!O1|K~FOAv(B`uY&j@d-fwFp3G?w{NR$Y@nGXb1+URwAZOX3@lYqmSJuJY?$!y;VLt;jOWh*`k@14 ztp1&2&LKjPP+s>uxXd?J{eOdF4*fH2VBEf0<$B68?t?e5sJ6gEPUi5aEh27<*G{`&qaZIY zNY+2U9)06vh|jjmi#`z~-~ss_7_!IfD^M}fBqS)v6D7TwnaGzr*_|@;UIp!DhwVed znsmDd_8T`AI{Wn&qx8gOt8=^GnwhItdkch~osC_76PrCv)Q)!hNsz1smKQ=Lbr(SC zA3rO6oQHqR9z^N8(s7!bIP@4GcnVI_;$ek3YfV;(`i`1?3`E(hLU!%#)mW_#$(8Uk zqbKqUl)x{}(%(R5^bDp+@FIUP+=Qmd(1ghG{?|Jm2LL3)5I!kb9q~xa=m{Ci@76hq&bbmwv6JezsUC~d_c!ic8-v|IcXO^f%|E2V$SJ!g<{F8i zuMw1^2&u-8S3FiV^th$Ts|ak}5`6$u)kP?&AZZQhryV&UxM1OZlWr zj77UkGe+`0#EHHT!(nwHz>$`=O0?XM=|yTcRgH}HzmABvF-r-5}e^>Rf=15GF9gtBqyjnPb z5=K8LIfCXpH&lerUg;#AMN`MbNH{c53E1~N_2CcVBEB&+^7LeaX~Syc!Ua#oJ<6#j z>0$KNKW|4loXSKJn-8ivx`#p>NV8^7DP9n9_4#|5hs*mNJ2Nq?OIxwt29JhS3$&ZU z&s@koYN09Eb5aRFq+%S;cY36-G6UKvAtBWAJU8M+_n2c6m(v_;lcPo}wg;yItms?r zx_jr&wDQM@nb?RY+Rgq6zehi##1Z||%|g-S83^cI*&0@KB_|uiwPKu7TC|e_Sgh9{KKJZ|M$OREVou=gHNe5d9hGkG<&~vtl z4+(>|MYz!#HcXH^5S~mo9N-qnDU@!dnV6v=N0kPBtK;XPf1vCMIvJ`dG+E~HPS2yE zoz2paD|K989?#wuq$R$Fapdpl$!kV0`adp!kvon1c$m8}eTevM)@03sPe)6@oC{WG zCgX7M5|f0$Ti3S|HRwDj&mo?Ln8#yf5Bk%w(i36icCR*?I58|d zd?}1OaAis;RD8Tn21vorrmc{3G_!4?5+f4g8=@ZxX@MS; zw-^`nx;y_^UM(k^%}GtrBRDnP-?z8-Y%u97d4GD}@Q|My2KQQf&}446{G12sl}{oK zob@}?F#PFUJ$_)HhPSr{#bLZaK@Hmjn2Uct4L3zf>fZhP@0of41-s0Aa)Mw}*CFzc ziLw_8-6mJp-+(#<2p*1f0GUy# zUq8BmDoozKnW^lDu4ba<0|+OmFY{{oBK=5MOuq%E+~#)vb#osuAIdDw99|aC-xunf z1WM%x@-l$i1VLC@TJ#FRkChrR<<_k^xX5<>F-~lv`1$LPF`w)lc0?>Q_~=oz|Nf7^=6$cMtYlKHq-*O&uHl1%K;9g{ZjSB_dN%mwh`pnqjs zu6A(0+@JI=8hA3OyCSWmTijxQj9+uQdegg-S}YCPc~z7RbRC>IvMUjgs)qlcKTOe2 zx7}1LJijK(_?zUI$F3cIGtZ$V-BNa&vFjSXnX#&&s@1Gn&XC!_Zm4wWlmygwK!1xU z{@X&c89z0AT)H7>N6rK5fXhM~j${p(i}b>0VxigZSDn_RN&h~5dKufhY186iuUS|) z@FRgfkX7(Y=s~y!6v-_=e+ITYE;v_$c?n$;u1X^m^BMlr<0iU6n`H-?cl+D28?9Ix}wTPEt$H?-5XR*KGz8_~bpX6_(W;xC0;C6$f zBYu*s4g;!4QvY9Wy{WTFnRJrBye|j_`KaB8xJk_sC+wpY43!V4V>8&mfTD8JE%$lx zp0_nr>f7S1b%;ZZT6yVT=*DV1$sCoB6T0_b8CqbMztCC1cgW(4f{^J^vF9j}8xy@1 zjx#@{;?|FZNq^hp>vC`DfYzF z2;O&mULqaPqjo>@8@Y|8}?$HX~t_s`8N)}p0$i=u{IL5q9+`X>B7DYl8dDmf}T zigQSikedO^;E`|JraxY21d1*mTw`kFJW?}5YAs6l5wF~e1fqPCMgam?NJOhG>GXdi(dt1X( za~>k0BTUn;1IB^0+r|XH4CU$b12|HYv`q16$q$HfEXXSy0@sZj;nK8HTpEp(pvYsm z0ho`c5sR4hYvo{m^1{Et7zJHIdqrr2q$xTH-~Aa{@_Z^d=P(4gL1LAw6Ajr6dI;x= zzoC(%mFT(I{RLo(VBpLvJ7en8l{;}kyGlc2jW=fqP1-!l8wBSLST z#9q&RS0yf+8A@ax0l9;;1fnpXj@8I0vPMbNka-ooBw-h~zal_;pI0(#?7QX<+mQ3F zuu!+NJ1HflTgkhI5-DNP22vX1X&Si#<#cv|QOEtKRI! z(P4xxvzZUAn$8wN(er`=w#}}3w8toQ`5WqXT$(RlzHGSe$zdukr<;TQ%s2=u(>(PI z4FwN(MQLF}T4it6+ZB=%s51Dm!ZW=kV~PL&(4p(FQ$>S|?gnpwYq?F)|V;msM1K@RG1vpU+tO(W`o~?l~A#O8b&_!K>Mhz-CtEzFxFw-lJpT~cL5Ze5g7l;2Z?e~@N3mG#8!nVFY^IPcAh0kKDNVc0QBzE zRDLhRJ-+_N@;e6u3$M-=3ow^LdvM$3I3giLq_wSO{Uj||_RMx62ZvflJX9F*6+xNy zPaX7|8fi>|zVD)-6cxheds+Fd^`kqYhN@2KQXkVR*xqNV$OReSj(#|!#|3>haM-== z!Y4zu>w#k|4E!2EuXx5_65MzWd3#$Kgmw&lCQY6^NAtM-&B0F9`U?mD^ogV^1&1QY z!%8nGFIRQYk`6$)VGR;GX;KB=WC7-DCbjUCL70F+I0ThP*Xs_5ijMBY)`_2v<*r9I z{`$C5U{*^X1Wqm%qrHCfX0?9(njymR<1ydy$bO&hqpqa%^FPKS6FfgH}g?fb?$e@aQd!aEfOE3p#9F1;{o9`E) zX$*Iq=VN1QOaJt-s!CLUn|vr#(wjFcH~`kxiI8NahJTmrhZh^&JOzkb`D}f&vAS%N z6Kzh7jbA#7H6ep$E$F9J-PKpy$Gxq6S4e7W7#*|>^WouKJL z{KRfNxI6jn2xO2PAz5M;%6T8x*9BKPq;P0R*}4Z$a+W`6B*+{7WJ5yp2#)qDYP%`6 zsNwNQBz?!t<0s_+q99nOXylmd3O>9*vC>ikm1tTL77gq9v?ho8tL1Cq8pQnRudn^T@Z4=fn!kUCRmXw~ zm^aoNW3W*s0K9rNUQ@H0Wwj1!#T6AkAO>WAl-p)TB}^{p@m3N*B>WSuU;lGK-ii7g z9YBf8b~q$gu6**Dawb+$!$_^&!mK$>G{SfiT?XA&ND4&a%*9u_?gjm((<~_T_FC`m zga}z9L0{F>AO8*Kr^_~M*%H{Y2HY^tCZVRA#~E;A3)A(64w<232`c^)F6F+_A3znqCyfhYkV zRRF-F-)g0s{9zdxrd)_{!o=t;(fTn0jT>daAz-R|Jg*k|mVq6}sw?IU(EpjMSoi~- zaT?TBRXZ6@*~-FHxrHnA@#B77GMMuTmub?ZbcC}7qCi!Ya1aoSPpQyR!+M8|)mfF@ ztL`ef61bdca%IG<@kp+z!st!Xc6=UCAnMco=O;WdIm!LF>{~<;f3XIepr;4#bXd-c zVZDS-G9jV4rDfkk55Yjm)4ONeH9_!Ox6W+fktfY&{;OoAPO9#Fuevit&2&rPIFniB z@#D=Lznv4;YmBa6vQkofE&3*s6g6tytkXY+3%0nBFNLj4{7M;_+FVyI1a&<)GE)c` z*@^$k8mtHKeNGBSYl7)j(#EM-A@o{8s}E$+IndI|>Kio3)U8988jvAB!p_DxGe2P>krz>8iaF7|kdO*JY+=2@(*fO-xME@EB~6=qI@! zx-;2@g^jHjK=g_5AnWeef-cOW3@JG~gML7F#Y91T_iN(H@86-OVtO@NHW1Wp-J{bd zPMBY?F;$<4TC? z)rmv$r|Dr#Mr`^ zDN*X!WUMD#)7_97L7n`^+>{b)Z58XD;LbkU{c|qt8zpUk!kNuJOh9a<0|8eFhiU*oyF$lvmf`qr1{eMxzF=< z_w1a#EU2|G=%=+pVr64=Y>=_=q!QNRboecGdP4u0dDaQ97-Ojn9LSgxoVIE0$Pn5G zti#(VdzivWbLxKV7L};0@8wZ$L|E4|F)3UacwB{OOq{E;88`CONG&a>{vz5B&ZrT- zySlu?DkgK0C?O%Nlv~LcpLe#}P4`alps+GgY=JUM6`FWBl{bN@fcsT%5uJrS3Y=4E z74;qS6+zq8hGCxebXygZHbv=x6eacq1$7Jt!vLh_=M*n~FXC&yf~15~!{*@zQntxX z*iWK8VG6`4?;NB%lEq;=yIQA@?RvI&$#{PssgipRZa;H7shQEnDJg=}uQ29gkrR{Yv5S?&TjvTh z+xW3+`y}PG9jBhJsV@zgbKzEJHH8PuAOll%pWa90CLc^F|L}TP@%x|;`hIz>O>1ou z7L7cW-}3mpO@fJTw0XS7am%n!az02>uSYeKQwPYFe=kt`j(a&#luv`OMx65>{|H1> zqVe6^l9C~;PXD^TXhCl{c0beaWD=M1R?`$q8(NvA3_}XO~;u zqD%D8Ok6Y^^b6BH>w!Vzic3qO89votJO6?WBkR=pD>1WY0?N360ik0mb2lWAMQG=jSPeZ{6&n7~&o4IR04vSF3`~oh*gZY(j?(Be*l61f)`;ZtAq% z-CB3#`0*0>I{3JviYQo6s3zfLE@J#Gx`c&eB`(Fg%fu-4wr}6g96}ehcgK|zCtlD; ztxogIJoSv)SctcmFORbWXJowxE;3?$C+iD4-$tH-%Jgi{Y`SusDc%OKp_;v9-dNpV zct#Xrym@Fv6v>L@w)UeOah2}*L|!fF_r^xn&Z)AF5$3NQTapG399Zpff@YKAiKM0b zwt<~PTzR+OANE8L?o^U zZH7COHf+b5hRG=OHrpfDK540s8jsc@&m3+91NfCgiUF*>mDpWT^-4A~R@JyjWo*X! zK}%az1D7q9xS!CxNjYbEm6Y_6nTJ9`m`OvOvNZL2O$6fJ+jjCD_Wjrh2%iL zNVAOhBF+QGt`=19%a-NotDhbW4h3dts~hI%o6B(9!lIUvd*w6XKV8O`m6ROscyV&X zKa3-QHFyH?gJ_0u+aGq^Qg={{LU0cK6Ju1j{!fnv2kT9m1pcE=wJ8Jd1yr9RA3SaXh?71zUIE!|pwm|#e)OgO%Ib8OBEJW<#od;h_M?)I9#VPcqc9y@+q zXt)CHf#j^tm5{kh*NCvY4rwYaRf zW*zvTOcB5$5lR}WEgh)}ax?ukt?F9}&IemCku@AYo`(N6;w+DjXKh4y_Al@epP8~d z?46L{IDyn^9(_(Jm!@oqg#tWdMo;5S-Xue2)aLOB@)57+l-To*fJOiU;8kZ{AMkAK zzAIM*jU>SzRK=&EINr|MGqX}m)nMQShcG@s#-^WFnVoSHL#?p#JuvX(Et;#xz7##sWQB~7T=MlKt& z5UMK3Xn9cg9cl?cboxoQ;H0jZeN|z9V7x}-0)^A;;8_edF}~o0(}8V;tu5zIIO4OV znRvz|=BZ8tnT`m(f?m1z`zjOh5ZB=qH<-~t{OX9o41+^?y* zZ_>LMJLzA~=Syy87R#(?*|P)nzZM-6$ua#`1c7?kkge)oVvA%X;C1xqjJkTm7EnpB zG5Jf)B|`go{=2{m&n1+1=ua0eEP+Vfp7(CcrcKz5K0sRuX^@@Y-{*cT&(0V}8ny=H z?CVy>W|h6ehvOHee?XKhK$DSE(~RZb*s+aVa^0(zx&7qiV0t1OhWE4zcPaYQh=Nhf z(jbu3Q4~5kg|SBp9@FZ8i)YWG5{V2C$K{z5$SOmDsxX#;yNJiSI+>L2gKy-{x(O<^fYRA11N_1`a#?&=cuqP2{@p*rs)C6@0)qGo9k(A?7ZA{~iF0 zK^?^k?;ArkK0MeSD}bDEBK?-u1M_B(1f-H!+F!u}7l1D?8@~lH^8y$mlwinsxW*$j zT*WTzJj^(bh(a#9hIT^MxpEhA*7qL{BW zHTZwmS5=j~dgTBGYSgH?@z(Tk7`9`5rFOKas0cP641{_YYt+(|;Mv*J>7Cu&Shj0U ziexav?*)JWL+!+j>eQ+KG4_JB!%hj&$4M+@ojqqx+3oc#N%|%*Mbu4YbywQj!fgjl zabxus6+Go3n;isq%98OwV1SAp>c$s%)8cid2v{hV?}a;(UN_zek8 zAfBbiyjmc=S8I^h2Vu|rrcI;&EYO(vPt8C5PB?m=nq>5pBk%r2XHv}Osj}N6_wWnK z%A|Fw81Oe2D{nsAN=1arGRGQjd(+tJwziM|06wFHJYlKjo#vw)k(Xm}Bz4q?5dqz% zz}L*Kx}P_Kc&tNHHBfN#VlIb+(x4_rN85w$8iyyLL1u+8G#T3FgB!sp@=5o=|`4BK%)0W%LxAzZ6@AeH$05_ z2By;FYXGXxEE-{EMI?qA2`Q6`5uZ68VrxrFoabNe6D%_3d(6_NYaR!2wA8wF_3ELS z=ZHhFM0_CIB0ylP-M$-z!sMDCDP)eNOF@&Vq9kk$2Of!G`!&`pICWAv5ApgcGHS^+ znzcyENw$43spT-xxB!9ySHtY(2!@kirdM>Hx9G|DlJPZKC}&*vx;0?KQy)!@KSb&(7%)U@rQm)IndxYft#pXc-Z` zLHlFX=6x~oeqXDR`F5h{xb0yx%%Z~wrmmbTDnRQ<*e1lGKGc;6RNHH%H8?%@6^)&%;%7~Q6i5TJ-X+dYS;}QNlET| z9%p1!f%qNji=1#J;ADCm;=rMEST*49~N}1 z-pqvE#DQ>h)Gl^mSN3;+XjON&;evA(RojP-qtbq6XyLFphiwJyO#Q_BnZI_^Mm3T1 z<-Fv3+s1s{eWwRS71i+8wC31`O!05~l7AnOJM@prz&3LeTeHqBr{`mCVA?W5;Skq$ z@YFq}Ow~j`L|wW^gzFoq{O<5v*-@^;}bWZK0WNK{Vs_BbE+r){4t9H4WirOk7;q8mObDb zS!)%9KXz-jwGNOFQHceiSDoV32C>dpp?h7u(N@tD&Aub&H9Xhedvl3M(AgUB(rG5% zO+U^8_39R!98#BR5L9nA*5GlKTTQ_AVug*v#?yS@Bc`sRLI-i$c;^_?ivVkk@5zCX zO<2%cdBc6&INiun^}{3)f@`<2)Hev2-LmO_ehdn>z^r1@xN*>IMT^ep_LCGx+D75} zmpk>AGC@W4mR;D^D#aVobE$hJu8#~_wNw~rd}&S=J9|ZD`b@btwZ&~&#>IDBhUxI} z;7UReEWhKr6qGb}^>2bSBs%&%s%pwbsoh`4jr$Uj5qpHvj@Du$&Wls$`};*Yplv6g zQ)7-q5>r@s4GyQeEATh)AA?*Zo@V}u>Jy5j@;ztvN_nn5U3pOT`r%--E+=~S^H4KA zHRnS_WA3(e=yBO4Tb->w;J6qN(Zyibz*|Re;>0H_Hoq_GOV@q)FkL+oHf{p|l)CGG z0`k5n&IsYs($xkpB_y0)7%&mzaltSn>;imr|Lcwjuwxc>DD=eO(I${_Ah31>hhuNc z@drGDlm&&0Kk9}>Qh^K#i_M`s?7Qlq1!?YAoN-RRD5LZDNq&PhKz08#5nZy}or2Ivz+-T%e!|HH``du7Oy`-W*o;o{D4?pZp`6XquKZ75EcFE1-Dc0(Np$vN#!CnFCK8V`>jbRaB`J~9)V zj0pw?Y^~^1G$Ra57TYLtIbtbGEv9z1&;gNl@a<_|cRh7z;lT5Bz;A%TSXBiTn=RjL zGA(}!7??7P!pRzWWX$m=o zJt1MIP7znJLA9@9XaN&AZFCwYg&bB)^!d$_;``=Yp#Gpo$9RA|+G6h}?{A?=_WN90 zyPdHl!f5!L+||~NFyZx>?iw5KCR9+G(0jvCFm=0YY6`ao@ddw%gLm@SF<A z(D)-syuR|@i3P6Y4jL;8Cnm9g{iY6(?9ye)K$LbRZj-wv+&p6*zcSTr8e3#}rJMtj zHsAzWbb4k=4{{SSC%${-8!DZ5cQ-}B%HiVzs6gS5Zr}>UiqWH2tysakW-YnL=JX#x zZV=xIYg7q*5h5m5p3%{lxU`Yd85!UbNwSO^gy!i1dwFrPXY2)rP65wXCfY()#mN<8 z>L9$3U?40FW!*}}J@-opM=7bFDADJ@EuuY3MLq}3Mi9(wBpS<0iUTo$*>iT73hel_ zh>sn55!{3SmKWAtyrKc8k}`=B1yRL3v}g>w5f~kM41jnzB!s2P+;rZd`-D6yK~Pwv zVN0<=0nY+<$jG9@q(kTbSc~)vwe*dRUD8xulypq3p5){(5FNL3Y@IX|LqHnHR6YFM z;2hkTDjO<7@4>0Kk>-)pT~H#@ec)ROhp=VInnEjC`8hdQIO?CzXUB@UOlJ|i4wJEm z-b!5N*`p|7mRk2Csp+Nsph1UnYZmG(Vk-+Fn3pkWV`*hgjXQSV+|f)b44J<3Vvc2` zn?V~wi$>*sol0%-VqtT34?m6J!zYa&zX;tQn`U5q;6Oik@^%-hTO=~BBp8&3WI zv^l{cA$UuT96g%vI*h;3w(>Xs``;b*fHCf6YE0REo&N#}p%Vn(<`w`R(<8A%vovWP zmkyl3dO!>sdmseO=Yi|PM&&vo(x;iAlEiKS%pBy)3S+IIL#NN5 zzX`aNR+fAXUdpKu#-4?d!bVPlp!yUq@fkgDUb+Mya{||cL01>`3q=(K8c1=B13<;u z2?q6V{l<-|$W2fID=SOR(1^9r#N7ynbj-|iJ3KtbthhT5xvY!I3S8u1c)fh-pIwEw zCOR!3$T;23aO%<_z#PMe*QZo?GhQZV)^vPU4>12)nv~6FTv4HZG&k0G=W~|als1u#9V3h#M5R!W%1PoB_=UbjuEp7l&lqD~32b3DEWYZ!C7x+20HC@-JY z)bqb#HGIuM7)WUzC%7_GW&@YV=2o6BYp_L^ou*t4L2f579Q^6ENim24L^Q7lExbN z2+kdRX-F%(QF?-&clEtETpJD&8eaq-g@qgGKA^qzDvFc>0^#czn{3^=Go6L7q|HC- zS~64EN!d_$pmNw^0QPz4t6U_X_16Fl56XsJ|DyZ+_3M4A_Y;lUht!YN%zX|uCF3eqz%3sv{;;PZl}He4x8mpL*ME?d%_JI|fMfI0Jqm_XsK^AN3I**ITvFj~K!LG)T(I z3JWhDe9|HGKziXxl!BL~ruz2E7Pz$Q*W+)+I-YqFH}|6R64pC2Q4pLkCQQHt(_eYx z=FRW#xH9$$OHK7;qGLRKHi;ACccwF3VltVTrlB#&o^*g6XP<7UiFt|td^Z9c@<(`bg{^s%M9Ajc*yQzpks8A4iUwam5P!B{yuq1-vUpw4= z)livgp9}JI`>CJq=NG3*Nz;vTMG8#=<+oy3>G*UUDKtRY_)_d9I+mpg`U+<#+JIkS zeP9O%0){Ywu>>)h=9&=?&-rga@6JGP{jDN>thTmrJJi*Sl0u%5)X|>LxgfzIjsD*Y zuvk%Af8Gd`p{8-8<%9XSLFp|tw*o|cIY4#p5oc$ z`!11L0_rGEJuuu>8Dr`inE4l}=D^en%{SKI=F>0O!d^M|{Atp_Y)ebFIW*#h^)7D$_h;`gTY}B)^O2=hGIgNN4r=Rp#;y?vnnfq(w||y-K7)5rS~L%hF4DQc%#_@X4Dyu1f7s?Nn(wq00(2C36xgvC2UvA^c`)a$*x7FfDNJ zJ+41{Yl26`cJ^5{>cCW^m{GP=o-g-Hc#Q7+gB+yT8dHX{ub?=ekF9)VHL zHZxj54ieH!A@f+(fN7fb82{jO8hue2hF;b>{1zRFB-?A@;Yz3G@G~8hwo`NHvPx}x zgIvy|2Hp;JC?(~W7yAKHkZ~ia+TQSRO~Z&9$@{CX zmuIz$ezM{(_(?HGyksDP zhZOQ!p>L3p`I72BY|ta{-X^AN=yVdywW-#Qa7?Kt}mxVvY zEvN1s<6c(lE|Uc#M@HPz-0U|skG#T0JwDZ>MOiH5p?fZR{=9Bv8HaNfUM(>(&$k)4 z0ld?=@rPd%BtbeMAyJO{K<{dJ*?x+k3h5uBCBc&iSj*F7F9}q0%3EGJRbv;$r>R?v zf|6J6V6S|`YM*tbD={(8OY7s$Y6?t~jxDZ0cr|6Q)1JG$Xu0eG3McvCS%pX>_4M+B zCNB9)?4WRQVgK;CY00mr_zS($yT44Kk0g(@j(|tW$T6(@qykjCk})qH)^>J9dnWwd zWfJ`Mel~B`o7#x>wlExi4s|*w5awOnAhaudYglOL?(d)axBd@Mg?T=KeB0t56yPse zir!F^cv~u{)ofCbnFed!A*A7tki91XV{03m7IFraTX7%iHK@3dS{TXRimv56Qi9P? zZI2@4HKKD&bz6h2ckBOPb|F#OT+zJv>XN-kC!pP3ecr67*ubL)FHRX-$MvQLy}W3oyJ9!zg6zg0xz+_w$OuqYezi9bZPm6f z$eiv@kE*2ax=e(=fYZ74K@(hwywV^C+aFbKdljg^O0fz*RU9@WPFFd@V11IL&M?bMq$Qk_xr zhAqfHkx!DQ+2$oNJ^?*+|J`}Mo})%XM8zX)cw+!y9N!a>nR*XSoD=J?&EuOibbYg{ zm;*CUSMj#GV8d@&sH50sRVD&Mk$#YTSQrlO1CrQx)_q%D4|pKEctU5PjCy)T1ZL^l zSLyC3$L^i}1VZal3BLVrXTO~7QP~#&*4beDULaE$c730>0BEALRC&up>NMLiD5tJC$Vu&+lgOg+O6Cwk;in6TT$N`R$VwssJC~5y z)_+>P(PAeSKoxF^0VbEautTwRY=H8=jI+#~T`09pOk_4)R5(BjA#Z*+`o z94vT%>>HE2h(F6iVAv$Sm0^w#Jke}j&rUeljZgIF_1w7pNxEYE^muD9_=ur@l^LycR%^cvy~67%^cPgl6>v+S(^l&xk=hIW_qC$>V7sR!aa}=#yzOXa}Vlh z)8-Z+Db|+8ATVJ@FTjRdhSUaI@#A>7pt5wvZ4WRWnL1`xc7NRuE*evfJ{q*#+gnPA z>*}bFghhj zQ8$Opu;O6RSn=;GRX~(jw*_`Eu2q6fJNK?%KN7eyi00rRnm5HG@Lf3Yl~s=!Qxo%| zjNFH{YI9n^r#36SXPk_N9tMz3u;{oiasvjSLKoBm^eS|_?T5p0P$APi;blPVGc=62 zP~5IHlVnThN}9c@HJLGrn#c8^?yvuoMg%XeH=|cz_K}K$#Se7w52T4@5juk;hVBhJ z|J(+K05q;@_9Q|wAe*{EpO5+a@;gG}W}b`m$i!4{H~N{)LP(+^0i?{yvAFRKR*hW0 ze#B%Z7ox3;$(B^0Xjl)AilWepn&27+rrN3v{gqX+!0($^mHuUYPa}rb&84;GB2$a4 zRN1(GJ%9v@03D4M5F@DjHY>$ML>MBP1f;2(3&G=hLIOTYbsqlB=*{rG=;4>KClA;K z3F?Ru!K3^^*g@y`PEV7Vjw?uVKwA1XwiDf|X2zI`(~Qut@u_xkxUkWoxImY_YUN65 zaBei7d_Ok*nNaohnpj}A-qWP%|2os6)s%SM$QcDA7kefsHh^wLgLnC;@u^FRXAypI z8KWmny>ibvj_MR1J1_;{&~Qs7BjS;dtibQVo+<7_;o=5uU0s=@xs-`XCT1)UC69&# z1t||69N^-{@yE3YHv+j}XW0A2aJi4>1|lSmbpTtD4#X;RUiJtF^oTDHBeKmSeIG7Cw+lg$FlBjw{$e zF(^UE23t<_osg&bLcoW|`iq~ud2^3yZsf>=j+^x6LiGZDfmvy>##>p31%2teS|ytD zXti>|eCN&k!t9F}Cos*i_}X2*Zzu{Y|3<5dtNlg1YKAk-Z~nRrxysF#v(`sb{t43v z#?q9~%*HA&_0&Bw^8wWrg%~4P&~e+TM%>M=p7yzC3RZ%P-%$b>iKKOHolPpsIR#O`bb=rW1jX%mLX6>^eBp zKBCuu`*x{b8;j$ow^hq%yn6i_Q($(hzJK=Y$OjRs+XDwAKxi2m=|IP}V9bGAy};{2 zZWJaat7d}YJL=4tXExAvS(t}+2#mHZTZ(Sw%r`R=Mle8W)Om7qU!r%$P@0$h_}gGy z`N`Lm*o1PwwQ_!D&!AWj?<)QvoY0zG&zhK8wx zD2Ot2-}Q!mXk=+R#RV!k}-B`Kj47F&{&Shds8Jl9)JNhuwDBM1kxW%6oJ7SyvOP;3lGIJN@ceLj#dA2`4n zrrwl`$?k{Nk6(_rI9s!T4B=zrY8&({E{@5yCSS`nKb8|i4g!FtmnGj5>--g`lC>Z_ z{^YDX=26Pi;4s?%$HYcTzOz648ci%TO1t3 zSI_^@*a-5%h8&K0-xoJ7v+aV4ozM*J=Hb>F3Cq?QjOpRmKl1txVbBF3v&Nu!MqONd zFa+#VaDMFRaDrNamZ!gh0z-2C^l1JHmXN+Km!Z}XrZetulcf%fA}9f@V1Xfwl+j~1 zDU6*JZ;iJLZ8q2xb@JLbuf8mu38^VCN2_j_MDd`wwMnIRqZePieft#*3_(7akN{4k zd(>u#`LIxGhWT3Z#LLsik7qhVBbKO}rMGbKPA(dyh0qxmDc30gr%;aZd}`bbk>7y8 zQsf@78$4*xZU_e$N)zHXIXQ7ec!4FJQ7SUOi>@m09hrE8g1g1_rmz;m#;7+#*IYnC0y*sE8Z6kkA9%hKJ7h1=kEX-xGxFTQz$#AeRdBi|0a}zxo zAT;|mft!RS&D0r>Rw$gB^Q@={AiDyGF+>C;L~sMcPcIwsdwuXZZJ=13sFVO%4KE=eu)Z;(6$(x9v?r$;*_e_^OH zE^&pOcDr|~_5EHpRd&ylu)X0ET=(BPs{PwW>*TCiA^+sY2fWHVeO*&KINx%}oPv)o z?juLbhU&f<_~5K=-V%=!dncuv)_wo21V^ZEAsQBZ{w zr|h?5LLubeW!oU)QdH3U!L4K@rlF-}VRf5_Ma`@#i}`}&?u{b0i^7_`ckvLnO}=uB zcPNPYxg1D-$y#@llRq~!*soj1Q^nUljKXEW05x^>`no#ru1=%lS4DWfYNp;_a0JGX zjM4^X489|%JQ+CjAGHMRhA=?iigzSFGXW9MOQUHdU=u*{tY^VPP>|cUZRVQCnKg1c z5OguYV5A2Mi67Z8&$Tu9mIA0s}$PX)!>&?brYQNzZbJD+<_(S16NI z3MgvIe6V#oKWYjqwbkLWkfB|2G=fE*6lIRrl}bURgjb zx_HqEIO6zXV>K9$%mtCL_wGG+@7^hx&j<{Zh=^mytPw9!CLBH5SHgeDtqr;CvBdG8 znE{<8+Hdf~&TTdPPtb3=4px4yupVp6_hW>|!=tR{T4tlXmNX9ib6XVfSdc)Bj} zl1LPIq8t@ivNV)MPoL@#jYf{V&v1oE`u)cbrpHW2`YpRt!yY&jyaHTxVeBv)iO5y@q`Mq{@w%5GR&6WPPVw4#_;Y zFZ&uNLbtwsTg&|sE6{E;^uz09{`{{*;o3IuHae{7@bA9oQFp)#Gt=Nr z0UER39xoWDA0LLPO_}oNuiw-ADHA6A4~Uzc;F+0Fbnu%6|zf)Iwfd+3{*`rzz?ss}TQ*TlBgu$Z>4?X}? zTiyF7KbB&8*szQI&u#A$2E;?K<&z?EF>RCk5;rT2wu)8=z6$&(FdcGCf|jU=Vz0$L zmI?b0-s}iPRs~yDv(zip0WeLmv66!^{msyU^x+T!o~{hb66l2{c1NW8Tl zCd}xpz$M~a`WdOiBR~H2}3KrFqNI6>)$6wJvsn`k^DzH?jYD>?L{lw#723a3w=Z?cQ3yZ@Vlug5nco_PRL!+(Q$7KMJl6MIKn+H zB_r+z@iKuUBjh#BjLTyBHG`X1IE>P})IKia2JX(RI zu#iKCgy&BQv^L3ol7y&;uKC;@M~o?VHg5cK^jSQa2AkRRcXQbD1(~_?e?{%j5_qk| zB%(v@Myo$P(v5bkUAvDS%BJ_r=H26gx#69Rxb>lTx)D93l247|n{!6YCdDTi4ci5j1kZbc>DvLcBQ(@rJY z^VxE7?o;A&;vrjgiR8e`VOAMz13!VPMZ6BmbrYwD_s$%l>i_^;+ zM>;@%FY;!S9Ii}(JKrGlsP_y#`$%B)y72`WRN_ktoC)+A)AyyFsY45pI)Z{FK z;K6}}FfOO%daLf!Iqmt78I@5OJ^XBK{atg^v}tc8jp72Uf3TxE!p#9CK`Zz5-GiUB zt}Bbz+%grzh=TXsnQJ;*Y!Su-f463{QQTq67CW|o)zy_jWuY#|+=g#vF`f0u*&-P~ zQx=8icj^$Ls7!b@)vMpbe}SyZsF(;$ zR>hr-Pj2p*Jy657+n$sg1tylZw3&e~H*?5FBi zo8rZ8J!Zk_ym=nh-Mb$4_GXI~k#yU_?Yx`Y+61eEsYv)P@)DpmacT_=TB%;CMTG|5 z@;n6x*PfTa*lYS8v!*}fbC`2Oaf0G8F%z_#y#0houmzm0{sRWEi6Y+mGE-max_dGd zPau-~)#yfv%btWWo+%%EQDI@*j~~M>ZBR#hCMj9UDTUh`l4&2ep_hGvf7V`6)-8Pb z{F(iNtd>pV{s3O{l2B;F3L$yXUU3Qk7HSFjyHm!J-7_wFIdfg{5=u;QIiMg_og70gZz3=q?3 z4s&8P0^JcyM!;mrh)AEPkeMNK2?T>wKn2<`EqQn`7&Nqh&)noL& z#XrRl?IcH%pT_Cfwd)=pE8DlD!k(me#+AO8atj4L6)AjwdJ3dNysG~i^l&;0O-(51 zuELp^TR;WWFBIrckl@gS5lEWf+0y27(%2v)%%Gr_5r)Xd&CPU;?{4;e6fqrm07Ih_ zCv1qiBfzi@bF8V9Bjzc)U1{}Tbocy zGft-lU-f8@pn~NwDHgiVhF8Ned*YM!B|M+EgE5(>rzb!?Cd8qwo*4Aw0zh_8N=#%% z%SUECZh=TfU;p1yo%lb3XSd3_@7O^N9Q}0zZ2+HLOw4Gi96RqjocvpV;rM^}ootN++yRfHV;jF>9zzc5MsyEE+qL5ⅅe4+FDxJ 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 literal 143011 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

25>D2TzK2VoM3~5Dw$z6jn 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 (dispatch: Dispatch, getState: GetState) => { const state = getState() - const fromSlot = selectors.slotToMoveFrom(state) + const fromSlot = selectors.getSlotToMoveFrom(state) if (fromSlot) { return dispatch({ type: 'MOVE_LABWARE', diff --git a/protocol-designer/src/labware-ingred/reducers/index.js b/protocol-designer/src/labware-ingred/reducers/index.js index 673c5084f1f..28454a4538a 100644 --- a/protocol-designer/src/labware-ingred/reducers/index.js +++ b/protocol-designer/src/labware-ingred/reducers/index.js @@ -9,7 +9,6 @@ import mapValues from 'lodash/mapValues' import max from 'lodash/max' import pickBy from 'lodash/pickBy' import reduce from 'lodash/reduce' -import isEmpty from 'lodash/isEmpty' import {sortedSlotnames, FIXED_TRASH_ID} from '../../constants.js' import {uuid} from '../../utils' @@ -32,7 +31,7 @@ import type { import * as actions from '../actions' import {getPDMetadata} from '../../file-types' import type {BaseState, Options} from '../../types' -import type {LoadFileAction} from '../../load-file' +import type {LoadFileAction, NewProtocolFields} from '../../load-file' import type { RemoveWellsContents, DeleteLiquidGroup, @@ -195,6 +194,27 @@ export const containers = handleActions({ } }, {}) }, + CREATE_NEW_PROTOCOL: ( + state: ContainersState, + action: {payload: NewProtocolFields} + ): ContainersState => { + const initialTipracks = [action.payload.left, action.payload.right].reduce((acc, mount) => { + if (mount.tiprackModel) { + const id = `${uuid()}:${String(mount.tiprackModel)}` + return { + ...acc, + [id]: { + slot: nextEmptySlot(_loadedContainersBySlot(acc || {})), + type: mount.tiprackModel, + disambiguationNumber: getNextDisambiguationNumber(acc || {}, String(mount.tiprackModel)), + id, + name: null, // create with null name, so we force explicit naming. + }, + } + } + }, state) + return initialTipracks || {} + }, }, initialLabwareState) type SavedLabwareState = {[labwareId: string]: boolean} @@ -264,6 +284,11 @@ export const ingredLocations = handleActions({ mapValues(labwareContents, well => omit(well, liquidGroupId))) }, + DELETE_CONTAINER: ( + state: LocationsState, + action: ActionType + ): LocationsState => + omit(state, action.payload.containerId), LOAD_FILE: (state: LocationsState, action: LoadFileAction): LocationsState => getPDMetadata(action.payload).ingredLocations, }, {}) @@ -298,33 +323,33 @@ type Selector = (RootSlice) => T // SELECTORS const rootSelector = (state: RootSlice): RootState => state.labwareIngred -const getLabware: Selector<{[labwareId: string]: ?Labware}> = createSelector( +const getLabwareById: Selector<{[labwareId: string]: ?Labware}> = createSelector( rootSelector, rootState => rootState.containers ) const getLabwareNames: Selector<{[labwareId: string]: string}> = createSelector( - getLabware, - (_labware) => mapValues( - _labware, + getLabwareById, + (labwareById) => mapValues( + labwareById, labwareToDisplayName, ) ) const getLabwareTypes: Selector = createSelector( - getLabware, - (_labware) => mapValues( - _labware, - (l: Labware) => l.type + getLabwareById, + (labwareById) => mapValues( + labwareById, + (labware: Labware) => labware.type ) ) const getLiquidGroupsById = (state: RootSlice) => rootSelector(state).ingredients -const getIngredientLocations = (state: RootSlice) => rootSelector(state).ingredLocations +const getLiquidsByLabwareId = (state: RootSlice) => rootSelector(state).ingredLocations const getNextLiquidGroupId: Selector = createSelector( getLiquidGroupsById, - (_ingredGroups) => ((max(Object.keys(_ingredGroups).map(id => parseInt(id))) + 1) || 0).toString() + (ingredGroups) => ((max(Object.keys(ingredGroups).map(id => parseInt(id))) + 1) || 0).toString() ) const getLiquidNamesById: Selector<{[ingredId: string]: string}> = createSelector( @@ -352,15 +377,15 @@ const _loadedContainersBySlot = (containers: ContainersState) => , {}) const loadedContainersBySlot = createSelector( - getLabware, + getLabwareById, containers => _loadedContainersBySlot(containers) ) /** Returns options for dropdowns, excluding tiprack labware */ const labwareOptions: Selector = createSelector( - getLabware, + getLabwareById, getLabwareNames, - (_labware, names) => reduce(_labware, (acc: Options, labware: Labware, labwareId): Options => { + (labwareById, names) => reduce(labwareById, (acc: Options, labware: Labware, labwareId): Options => { const isTiprack = getIsTiprack(labware.type) if (!labware.type || isTiprack) { return acc @@ -378,9 +403,9 @@ const labwareOptions: Selector = createSelector( const DISPOSAL_LABWARE_TYPES = ['trash-box', 'fixed-trash'] /** Returns options for disposal (e.g. fixed trash and trash box) */ const disposalLabwareOptions: Selector = createSelector( - getLabware, + getLabwareById, getLabwareNames, - (_labware, names) => reduce(_labware, (acc: Options, labware: Labware, labwareId): Options => { + (labwareById, names) => reduce(labwareById, (acc: Options, labware: Labware, labwareId): Options => { if (!labware.type || !DISPOSAL_LABWARE_TYPES.includes(labware.type)) { return acc } @@ -399,7 +424,7 @@ const selectedAddLabwareSlot = (state: BaseState) => rootSelector(state).modeLab const getSavedLabware = (state: BaseState) => rootSelector(state).savedLabware -const getSelectedContainerId: Selector = createSelector( +const getSelectedLabwareId: Selector = createSelector( rootSelector, rootState => rootState.selectedContainerId ) @@ -409,10 +434,11 @@ const getSelectedLiquidGroupState: Selector = createSe rootState => rootState.selectedLiquidGroup ) -const getSelectedContainer: Selector = createSelector( - getSelectedContainerId, - getLabware, - (_selectedId, _labware) => (_selectedId && _labware[_selectedId]) || null +const getSelectedLabware: Selector = createSelector( + getSelectedLabwareId, + getLabwareById, + (selectedLabwareId, labware) => + (selectedLabwareId && labware[selectedLabwareId]) || null ) const getDrillDownLabwareId: Selector = createSelector( @@ -423,7 +449,7 @@ const getDrillDownLabwareId: Selector = createSelector( type ContainersBySlot = { [DeckSlot]: {...Labware, containerId: string} } const containersBySlot: Selector = createSelector( - getLabware, + getLabwareById, containers => reduce( containers, (acc: ContainersBySlot, containerObj: Labware, containerId: string) => ({ @@ -457,38 +483,17 @@ const allIngredientNamesIds: BaseState => OrderedLiquids = createSelector( ({ingredientId: ingredId, name: ingreds[ingredId].name})) ) -// TODO: just use the individual selectors separately, no need to combine it into 'activeModals' -// -- so you'd have to refactor the props of the containers that use this selector too -type ActiveModals = { - labwareSelection: boolean, - ingredientSelection: ?{ - slot: ?DeckSlot, - containerName: ?string, - }, -} - -const activeModals: Selector = createSelector( +const getLabwareSelectionMode: Selector = createSelector( rootSelector, - getLabware, - getSelectedContainerId, - (state, _allLabware, _selectedContainerId) => { - const selectedContainer = _selectedContainerId && _allLabware[_selectedContainerId] - return ({ - labwareSelection: state.modeLabwareSelection !== false, - ingredientSelection: { - slot: selectedContainer ? selectedContainer.slot : null, - containerName: selectedContainer && selectedContainer.type, - }, - }) + (rootState) => { + return rootState.modeLabwareSelection !== false } ) -const slotToMoveFrom = (state: BaseState) => rootSelector(state).moveLabwareMode - -const hasLiquid = (state: BaseState) => !isEmpty(getLiquidGroupsById(state)) +const getSlotToMoveFrom = (state: BaseState) => rootSelector(state).moveLabwareMode const getLiquidGroupsOnDeck: Selector> = createSelector( - getIngredientLocations, + getLiquidsByLabwareId, (ingredLocationsByLabware) => { let liquidGroups: Set = new Set() forEach(ingredLocationsByLabware, (byWell: $Values) => @@ -504,28 +509,32 @@ const getLiquidGroupsOnDeck: Selector> = createSelector( } ) +const getDeckHasLiquid: Selector = createSelector( + getLiquidGroupsOnDeck, + (liquidGroups) => liquidGroups.length > 0 +) + // TODO: prune selectors export const selectors = { rootSelector, getLiquidGroupsById, - getIngredientLocations, + getLiquidsByLabwareId, getLiquidNamesById, - getLabware, + getLabwareById, getLabwareNames, + getLabwareSelectionMode, getLabwareTypes, getLiquidSelectionOptions, getLiquidGroupsOnDeck, getNextLiquidGroupId, getSavedLabware, - getSelectedContainer, - getSelectedContainerId, + getSelectedLabware, + getSelectedLabwareId, getSelectedLiquidGroupState, getDrillDownLabwareId, - activeModals, - - slotToMoveFrom, + getSlotToMoveFrom, allIngredientGroupFields, allIngredientNamesIds, @@ -534,7 +543,7 @@ export const selectors = { selectedAddLabwareSlot, disposalLabwareOptions, labwareOptions, - hasLiquid, + getDeckHasLiquid, } export default rootReducer diff --git a/protocol-designer/src/labware-ingred/types.js b/protocol-designer/src/labware-ingred/types.js index 2204a621b5e..d8800b04754 100644 --- a/protocol-designer/src/labware-ingred/types.js +++ b/protocol-designer/src/labware-ingred/types.js @@ -20,7 +20,7 @@ export type Wells = { [wellName: string]: string, // eg A1: 'A1'. } -export type WellContents = {| // non-ingredient well state, for SelectablePlate +export type WellContents = {| // non-ingredient well state, for SelectableLabware highlighted: boolean, selected: boolean, error: boolean, diff --git a/protocol-designer/src/load-file/selectors.js b/protocol-designer/src/load-file/selectors.js index 435ec3c0636..b29dd478e67 100644 --- a/protocol-designer/src/load-file/selectors.js +++ b/protocol-designer/src/load-file/selectors.js @@ -10,7 +10,7 @@ export const getFileLoadErrors: Selector<$PropertyType> s => s.fileErrors ) -export const hasUnsavedChanges: Selector<$PropertyType> = createSelector( +export const getHasUnsavedChanges: Selector<$PropertyType> = createSelector( rootSelector, s => s.unsavedChanges ) diff --git a/protocol-designer/src/localization/en/alert.json b/protocol-designer/src/localization/en/alert.json index 824e7bcc7e6..d74a8af1d22 100644 --- a/protocol-designer/src/localization/en/alert.json +++ b/protocol-designer/src/localization/en/alert.json @@ -34,6 +34,7 @@ }, "window": { "confirm_create_new": "Are you sure you want to create a new file? Any unsaved changes will be discarded.", + "confirm_delete_step": "Are you sure you want to delete this step?", "confirm_import": "Are you sure you want to import this file? You will lose any current unsaved changes.", "confirm_leave": "Are you sure you want to leave? You will lose any unsaved changes." } diff --git a/protocol-designer/src/localization/en/button.json b/protocol-designer/src/localization/en/button.json index d1948312e39..9d543920413 100644 --- a/protocol-designer/src/localization/en/button.json +++ b/protocol-designer/src/localization/en/button.json @@ -11,6 +11,8 @@ "no": "no", "ok": "ok", "reset": "reset", + "restore": "restore", + "restored": "restored", "save": "save", "swap": "swap", "yes": "yes" diff --git a/protocol-designer/src/localization/en/card.json b/protocol-designer/src/localization/en/card.json index e979f5445ff..2b5a9d2cb5b 100644 --- a/protocol-designer/src/localization/en/card.json +++ b/protocol-designer/src/localization/en/card.json @@ -3,13 +3,14 @@ "data_collected_is_internal": "We never share sessions outside of Opentrons", "data_only_from_pd": "We don’t record or store anything happening outside of your open Protocol Designer tab", "opt_out_of_data_collection": "You can choose to opt in or out in Settings > Privacy", - "reason_for_collecting_data": "We’re working to improve Protocol Designer. Part of the process involves watching real user sessions to understand which parts of the interface are working and which could use improvement." - + "reason_for_collecting_data": "We’re working to improve Protocol Designer. Part of the process involves watching real user sessions to understand which parts of the interface are working and which could use improvement.", + "restore_hints": "Restore all hints and tips notifications" }, "title": { - "privacy": "Privacy" + "privacy": "Privacy", + "hints": "Hints" }, "toggle": { "share_session": "Share sessions with the Opentrons Product Team" } -} \ No newline at end of file +} diff --git a/protocol-designer/src/localization/en/context_menu.json b/protocol-designer/src/localization/en/context_menu.json new file mode 100644 index 00000000000..e78b8340482 --- /dev/null +++ b/protocol-designer/src/localization/en/context_menu.json @@ -0,0 +1,6 @@ +{ + "step": { + "duplicate": "Duplicate Step", + "delete": "Delete Step" + } +} \ No newline at end of file diff --git a/protocol-designer/src/localization/en/index.js b/protocol-designer/src/localization/en/index.js index 22235ff6b04..f97ff3ad6d9 100644 --- a/protocol-designer/src/localization/en/index.js +++ b/protocol-designer/src/localization/en/index.js @@ -3,6 +3,7 @@ import alert from './alert.json' import button from './button.json' import card from './card.json' +import context_menu from './context_menu.json' import deck from './deck.json' import form from './form.json' import modal from './modal.json' @@ -15,6 +16,7 @@ export default { alert, button, card, + context_menu, deck, form, modal, diff --git a/protocol-designer/src/localization/en/modal.json b/protocol-designer/src/localization/en/modal.json index 64fc56d6ef4..240ca12d4f5 100644 --- a/protocol-designer/src/localization/en/modal.json +++ b/protocol-designer/src/localization/en/modal.json @@ -4,7 +4,14 @@ }, "tip_position": { "title": "Tip Positioning", - "body": "Change from where in the well the robot aspirates", + "body": { + "aspirate_mmFromBottom": "Change from where in the well the robot aspirates", + "dispense_mmFromBottom": "Change from where in the well the robot dispenses", + "mix_mmFromBottom": "Change from where in the well the robot aspirates and dispenses during the mix", + "aspirate_touchTipMmFromBottom": "Change from where in the well the robot performs touch tip", + "dispense_touchTipMmFromBottom": "Change from where in the well the robot performs touch tip", + "mix_touchTipMmFromBottom": "Change from where in the well the robot performs touch tip" + }, "field_label": "Distance from bottom of well" }, "well_order": { @@ -36,4 +43,4 @@ } } } -} \ No newline at end of file +} diff --git a/protocol-designer/src/localization/en/nav.json b/protocol-designer/src/localization/en/nav.json index 9c09aa13e92..c75c9ae3dd5 100644 --- a/protocol-designer/src/localization/en/nav.json +++ b/protocol-designer/src/localization/en/nav.json @@ -1,5 +1,6 @@ { "settings": { + "app": "APP", "privacy": "PRIVACY", "feature_flags": "Feature Flags" }, @@ -8,7 +9,7 @@ "file": "FILE", "help": "HELP", "liquids": "LIQUIDS", - "settings": "SETTINGS" + "settings": "Settings" }, "terminal_item": { "__initial_setup__": "Starting Deck State", @@ -16,12 +17,12 @@ }, "title": { "settings-features": "Opentrons Beta", - "settings-privacy": "Opentrons Beta", + "settings-app": "Opentrons Beta", "file-splash": "Opentrons Beta" }, "subtitle": { "file-detail": "File Details", - "settings-privacy": "Privacy", + "settings-app": "App Settings", "liquids": "Liquids" } } diff --git a/protocol-designer/src/localization/en/tooltip.json b/protocol-designer/src/localization/en/tooltip.json index 6e61146ce5a..b17fbba6373 100644 --- a/protocol-designer/src/localization/en/tooltip.json +++ b/protocol-designer/src/localization/en/tooltip.json @@ -1,5 +1,6 @@ { "not_in_beta": "ⓘ Coming Soon", + "advanced_settings": "Advanced Settings", "step_description": { "transfer": "Move liquid from wells to an equal number of wells", @@ -19,7 +20,7 @@ "dispense_tipPosition": "Where in the well the pipette dispenses to", "blowout_checkbox": "Where to dispose of remaining volume in tip", - "disposalVol_checkbox": "Aspirate extra volume that is disposed of after a distribute is complete. 20% of tip capacity recommended.", + "disposalVol_checkbox": "Aspirate extra volume that is disposed of after a distribute is complete. We recommend a disposal volume of at least the pipette's minimum.", "changeTip": "Choose when the robot picks up fresh tips", "preWetTip": "Pre-wet pipette tip by aspirating and dispensing 2/3 of the tip's max volume", diff --git a/protocol-designer/src/navigation/selectors.js b/protocol-designer/src/navigation/selectors.js index d42b2f2dcb2..fe644d072dd 100644 --- a/protocol-designer/src/navigation/selectors.js +++ b/protocol-designer/src/navigation/selectors.js @@ -4,10 +4,10 @@ import {rootSelector as navigationRootSelector} from './reducers' import type {Page} from './types' -export const newProtocolModal = (state: BaseState) => +export const getNewProtocolModal = (state: BaseState) => navigationRootSelector(state).newProtocolModal -export const currentPage: Selector = (state: BaseState) => { +export const getCurrentPage: Selector = (state: BaseState) => { let page = navigationRootSelector(state).page return page diff --git a/protocol-designer/src/navigation/types.js b/protocol-designer/src/navigation/types.js index 6834a1b55d3..8bf3013288b 100644 --- a/protocol-designer/src/navigation/types.js +++ b/protocol-designer/src/navigation/types.js @@ -4,5 +4,5 @@ export type Page = 'file-detail' | 'liquids' | 'steplist' | - 'settings-privacy' | + 'settings-app' | 'settings-features' diff --git a/protocol-designer/src/pipettes/selectors.js b/protocol-designer/src/pipettes/selectors.js index 6afa6bf59f6..afb8c55b2d8 100644 --- a/protocol-designer/src/pipettes/selectors.js +++ b/protocol-designer/src/pipettes/selectors.js @@ -1,8 +1,10 @@ // @flow import {createSelector} from 'reselect' +import startCase from 'lodash/startCase' import reduce from 'lodash/reduce' import get from 'lodash/get' import mapValues from 'lodash/mapValues' +import uniq from 'lodash/uniq' import {getAllPipetteNames, getPipetteNameSpecs, getLabware} from '@opentrons/shared-data' import type {DropdownOption} from '@opentrons/components' @@ -17,17 +19,17 @@ type Selector = (RootSlice) => T export const rootSelector = (state: {pipettes: RootState}) => state.pipettes -export const pipettesById: Selector = createSelector( +export const getPipettesById: Selector = createSelector( rootSelector, pipettes => pipettes.byId ) -export const pipetteIdsByMount: Selector<*> = createSelector( +export const getPipetteIdsByMount: Selector<*> = createSelector( rootSelector, pipettes => pipettes.byMount ) -export const pipettesByMount: Selector<*> = createSelector( +export const getPipettesByMount: Selector<*> = createSelector( rootSelector, pipettes => mapValues(pipettes.byMount, id => pipettes.byId[id]) ) @@ -48,28 +50,8 @@ function _getPipetteName (pipetteData): string { return pipette ? pipette.displayName : '???' } -export const equippedPipetteOptions: Selector> = createSelector( - rootSelector, - pipettes => { - const byId = pipettes.byId - - const pipetteIds: Array = [pipettes.byMount.left, pipettes.byMount.right] - return pipetteIds.reduce((acc: Array, pipetteId: ?string): Array => - (pipetteId && byId[pipetteId]) - ? [ - ...acc, - { - name: _getPipetteName(byId[pipetteId]), - value: pipetteId, - }, - ] - : acc, - []) - } -) - // Shows equipped (left & right) pipettes by ID, not mount -export const equippedPipettes: Selector = createSelector( +export const getEquippedPipettes: Selector = createSelector( rootSelector, pipettes => reduce(pipettes.byMount, (acc: PipettesById, pipetteId: string): PipettesById => { const pipetteData = pipettes.byId[pipetteId] @@ -81,8 +63,43 @@ export const equippedPipettes: Selector = createSelector( }, {}) ) +export const getEquippedPipetteOptions: Selector> = createSelector( + getEquippedPipettes, + (pipettesById: PipettesById) => { + const pipetteIds = Object.keys(pipettesById) + const pipetteNamesById = pipetteIds.reduce((acc: {[string]: string}, pipetteId: string) => { + const pipetteData = pipettesById[pipetteId] + if (!pipetteData) return acc + return { + ...acc, + [pipetteId]: _getPipetteName(pipetteData), + } + }, {}) + + const namesAreAmbiguous = ( + uniq(Object.values(pipetteNamesById)).length !== + Object.values(pipetteNamesById).length) + + return pipetteIds.reduce((acc: Array, pipetteId: string): Array => { + const pipetteData = pipettesById[pipetteId] + if (!pipetteData) return acc + const pipetteName = pipetteNamesById[pipetteId] + + return [ + ...acc, + { + name: (namesAreAmbiguous) + ? `${pipetteName} (${startCase(pipetteData.mount)})` + : pipetteName, + value: pipetteId, + }, + ] + }, []) + } +) + // Formats pipette data specifically for edit pipette -export const pipettesForInstrumentGroup: Selector<*> = createSelector( +export const getPipettesForInstrumentGroup: Selector<*> = createSelector( rootSelector, pipettes => [pipettes.byMount.left, pipettes.byMount.right].reduce((acc, pipetteId) => { if (!pipetteId) return acc @@ -106,7 +123,7 @@ export const pipettesForInstrumentGroup: Selector<*> = createSelector( ) // Formats pipette data specifically for edit pipette -export const pipettesForEditPipettes: Selector> = createSelector( +export const getPipettesForEditPipettes: Selector> = createSelector( rootSelector, pipettes => [pipettes.byMount.left, pipettes.byMount.right].reduce((acc, pipetteId) => { if (!pipetteId) return acc @@ -129,10 +146,10 @@ export const pipettesForEditPipettes: Selector> = create }, []) ) -export const permittedTipracks: Selector> = createSelector( - equippedPipettes, - (_equippedPipettes) => - reduce(_equippedPipettes, (acc: Array, pipette: PipetteData) => { +export const getPermittedTipracks: Selector> = createSelector( + getEquippedPipettes, + (equippedPipettes) => + reduce(equippedPipettes, (acc: Array, pipette: PipetteData) => { return (pipette.tiprackModel) ? [...acc, pipette.tiprackModel] : acc diff --git a/protocol-designer/src/pipettes/thunks.js b/protocol-designer/src/pipettes/thunks.js index 34e8e81392f..fc0f6814174 100644 --- a/protocol-designer/src/pipettes/thunks.js +++ b/protocol-designer/src/pipettes/thunks.js @@ -23,7 +23,7 @@ import {createPipette} from './utils' export const editPipettes = (payload: EditPipettesFields) => (dispatch: ThunkDispatch<*>, getState: GetState) => { const state = getState() - const prevPipettesByMount = pipetteSelectors.pipettesByMount(state) + const prevPipettesByMount = pipetteSelectors.getPipettesByMount(state) const savedForms = steplistSelectors.getSavedForms(state) const nextPipettesByMount: PipettesByMount = Object.keys(payload).reduce( diff --git a/protocol-designer/src/step-generation/aspirateUpdateLiquidState.js b/protocol-designer/src/step-generation/aspirateUpdateLiquidState.js index 9c54925630b..8a13364e03a 100644 --- a/protocol-designer/src/step-generation/aspirateUpdateLiquidState.js +++ b/protocol-designer/src/step-generation/aspirateUpdateLiquidState.js @@ -66,6 +66,7 @@ export default function updateLiquidState ( // Remove liquid from source well(s) const labwareLiquidState: SingleLabwareLiquidState = { ...prevLiquidState.labware[labwareId], + // $FlowFixMe: flow is having a hard time with this reduce for some reason ...wellsForTips.reduce((acc: SingleLabwareLiquidState, well) => ({ ...acc, [well]: splitLiquid( diff --git a/protocol-designer/src/step-generation/aspirate.js b/protocol-designer/src/step-generation/commandCreators/atomic/aspirate.js similarity index 60% rename from protocol-designer/src/step-generation/aspirate.js rename to protocol-designer/src/step-generation/commandCreators/atomic/aspirate.js index 4347a616d59..7de156d320f 100644 --- a/protocol-designer/src/step-generation/aspirate.js +++ b/protocol-designer/src/step-generation/commandCreators/atomic/aspirate.js @@ -1,11 +1,13 @@ // @flow -import updateLiquidState from './aspirateUpdateLiquidState' -import * as errorCreators from './errorCreators' -import type {RobotState, CommandCreator, CommandCreatorError, AspirateDispenseArgs} from './' +import getNextRobotStateAndWarnings from '../../getNextRobotStateAndWarnings' +import * as errorCreators from '../../errorCreators' +import {getPipetteWithTipMaxVol} from '../../robotStateSelectors' +import type {RobotState, CommandCreator, CommandCreatorError, AspirateDispenseArgs} from '../../types' /** Aspirate with given args. Requires tip. */ const aspirate = (args: AspirateDispenseArgs): CommandCreator => (prevRobotState: RobotState) => { const {pipette, volume, labware, well, offsetFromBottomMm} = args + const flowRateUlSec = args['flow-rate'] const actionName = 'aspirate' let errors: Array = [] @@ -16,14 +18,19 @@ const aspirate = (args: AspirateDispenseArgs): CommandCreator => (prevRobotState errors.push(errorCreators.pipetteDoesNotExist({actionName, pipette})) } - if (prevRobotState.tipState.pipettes[pipette] === false) { + if (!prevRobotState.tipState.pipettes[pipette]) { errors.push(errorCreators.noTipOnPipette({actionName, pipette, volume, labware, well})) } - if (pipetteData && pipetteData.maxVolume < volume) { + if (pipetteData && pipetteData.maxVolume < volume && errors.length === 0) { errors.push(errorCreators.pipetteVolumeExceeded({actionName, volume, maxVolume: pipetteData.maxVolume})) } + const tipMaxVolume = getPipetteWithTipMaxVol(pipette, prevRobotState) + if (tipMaxVolume < volume && errors.length === 0) { + errors.push(errorCreators.tipVolumeExceeded({actionName, volume, maxVolume: tipMaxVolume})) + } + if (!labware || !prevRobotState.labware[labware]) { errors.push(errorCreators.labwareDoesNotExist({actionName, labware})) } @@ -42,29 +49,15 @@ const aspirate = (args: AspirateDispenseArgs): CommandCreator => (prevRobotState offsetFromBottomMm: offsetFromBottomMm == null ? undefined : offsetFromBottomMm, + 'flow-rate': flowRateUlSec == null + ? undefined + : flowRateUlSec, }, }] - const liquidStateAndWarnings = updateLiquidState({ - pipetteId: pipette, - pipetteData: prevRobotState.instruments[pipette], - labwareId: labware, - labwareType: prevRobotState.labware[labware].type, - volume, - well, - }, prevRobotState.liquidState) - - const {liquidState, warnings: liquidUpdateWarnings} = liquidStateAndWarnings - - const robotState = { - ...prevRobotState, - liquidState, - } - return { commands, - robotState, - warnings: liquidUpdateWarnings, + ...getNextRobotStateAndWarnings(commands[0], prevRobotState), } } diff --git a/protocol-designer/src/step-generation/blowout.js b/protocol-designer/src/step-generation/commandCreators/atomic/blowout.js similarity index 87% rename from protocol-designer/src/step-generation/blowout.js rename to protocol-designer/src/step-generation/commandCreators/atomic/blowout.js index 7e535b309bf..a69cf40d5e6 100644 --- a/protocol-designer/src/step-generation/blowout.js +++ b/protocol-designer/src/step-generation/commandCreators/atomic/blowout.js @@ -1,8 +1,8 @@ // @flow -import * as errorCreators from './errorCreators' -import type {RobotState, CommandCreator, CommandCreatorError, PipetteLabwareFields} from './' +import * as errorCreators from '../../errorCreators' +import type {RobotState, CommandCreator, CommandCreatorError, PipetteLabwareFields} from '../../types' -import updateLiquidState from './dispenseUpdateLiquidState' +import updateLiquidState from '../../dispenseUpdateLiquidState' const blowout = (args: PipetteLabwareFields): CommandCreator => (prevRobotState: RobotState) => { /** Blowout with given args. Requires tip. */ @@ -20,7 +20,7 @@ const blowout = (args: PipetteLabwareFields): CommandCreator => (prevRobotState: errors.push(errorCreators.pipetteDoesNotExist({actionName, pipette})) } - if (prevRobotState.tipState.pipettes[pipette] === false) { + if (!prevRobotState.tipState.pipettes[pipette]) { errors.push(errorCreators.noTipOnPipette({actionName, pipette, labware, well})) } diff --git a/protocol-designer/src/step-generation/delay.js b/protocol-designer/src/step-generation/commandCreators/atomic/delay.js similarity index 80% rename from protocol-designer/src/step-generation/delay.js rename to protocol-designer/src/step-generation/commandCreators/atomic/delay.js index ac357550515..c0408070c1f 100644 --- a/protocol-designer/src/step-generation/delay.js +++ b/protocol-designer/src/step-generation/commandCreators/atomic/delay.js @@ -1,5 +1,5 @@ // @flow -import type {PauseFormData, RobotState, CommandCreator} from './' +import type {PauseFormData, RobotState, CommandCreator} from '../../types' const pause = (data: PauseFormData): CommandCreator => (prevRobotState: RobotState) => { return { diff --git a/protocol-designer/src/step-generation/dispense.js b/protocol-designer/src/step-generation/commandCreators/atomic/dispense.js similarity index 78% rename from protocol-designer/src/step-generation/dispense.js rename to protocol-designer/src/step-generation/commandCreators/atomic/dispense.js index 67134db835c..1f753e18ce7 100644 --- a/protocol-designer/src/step-generation/dispense.js +++ b/protocol-designer/src/step-generation/commandCreators/atomic/dispense.js @@ -1,16 +1,17 @@ // @flow -import * as errorCreators from './errorCreators' -import updateLiquidState from './dispenseUpdateLiquidState' -import type {RobotState, CommandCreator, CommandCreatorError, AspirateDispenseArgs} from './' +import * as errorCreators from '../../errorCreators' +import updateLiquidState from '../../dispenseUpdateLiquidState' +import type {RobotState, CommandCreator, CommandCreatorError, AspirateDispenseArgs} from '../../types' /** Dispense with given args. Requires tip. */ const dispense = (args: AspirateDispenseArgs): CommandCreator => (prevRobotState: RobotState) => { const {pipette, volume, labware, well, offsetFromBottomMm} = args + const flowRateUlSec = args['flow-rate'] const actionName = 'dispense' let errors: Array = [] - if (prevRobotState.tipState.pipettes[pipette] === false) { + if (!prevRobotState.tipState.pipettes[pipette]) { errors.push(errorCreators.noTipOnPipette({actionName, pipette, labware, well})) } @@ -32,6 +33,9 @@ const dispense = (args: AspirateDispenseArgs): CommandCreator => (prevRobotState offsetFromBottomMm: offsetFromBottomMm == null ? undefined : offsetFromBottomMm, + 'flow-rate': flowRateUlSec == null + ? undefined + : flowRateUlSec, }, }] diff --git a/protocol-designer/src/step-generation/dropAllTips.js b/protocol-designer/src/step-generation/commandCreators/atomic/dropAllTips.js similarity index 80% rename from protocol-designer/src/step-generation/dropAllTips.js rename to protocol-designer/src/step-generation/commandCreators/atomic/dropAllTips.js index 72bb6a7b401..9985444790c 100644 --- a/protocol-designer/src/step-generation/dropAllTips.js +++ b/protocol-designer/src/step-generation/commandCreators/atomic/dropAllTips.js @@ -1,6 +1,6 @@ // @flow -import type {CommandCreator, RobotState} from './' -import {reduceCommandCreators} from './utils' +import type {CommandCreator, RobotState} from '../../types' +import {reduceCommandCreators} from '../../utils' import dropTip from './dropTip' /** Drop all tips from equipped pipettes. diff --git a/protocol-designer/src/step-generation/dropTip.js b/protocol-designer/src/step-generation/commandCreators/atomic/dropTip.js similarity index 81% rename from protocol-designer/src/step-generation/dropTip.js rename to protocol-designer/src/step-generation/commandCreators/atomic/dropTip.js index dfdd825171b..f6f28f0d6dc 100644 --- a/protocol-designer/src/step-generation/dropTip.js +++ b/protocol-designer/src/step-generation/commandCreators/atomic/dropTip.js @@ -1,12 +1,12 @@ // @flow -import type {CommandCreator, RobotState} from './' -import {FIXED_TRASH_ID} from '../constants' +import type {CommandCreator, RobotState} from '../../types' +import {FIXED_TRASH_ID} from '../../../constants' import cloneDeep from 'lodash/cloneDeep' -import updateLiquidState from './dispenseUpdateLiquidState' +import updateLiquidState from '../../dispenseUpdateLiquidState' const dropTip = (pipetteId: string): CommandCreator => (prevRobotState: RobotState) => { // No-op if there is no tip - if (prevRobotState.tipState.pipettes[pipetteId] === false) { + if (!prevRobotState.tipState.pipettes[pipetteId]) { return { robotState: prevRobotState, commands: [], diff --git a/protocol-designer/src/step-generation/commandCreators/atomic/index.js b/protocol-designer/src/step-generation/commandCreators/atomic/index.js new file mode 100644 index 00000000000..70af25804d1 --- /dev/null +++ b/protocol-designer/src/step-generation/commandCreators/atomic/index.js @@ -0,0 +1,20 @@ +// @flow +import aspirate from './aspirate' +import blowout from './blowout' +import delay from './delay' +import dispense from './dispense' +import dropAllTips from './dropAllTips' +import dropTip from './dropTip' +import replaceTip from './replaceTip' +import touchTip from './touchTip' + +export { + aspirate, + blowout, + delay, + dispense, + dropAllTips, + dropTip, + replaceTip, + touchTip, +} diff --git a/protocol-designer/src/step-generation/replaceTip.js b/protocol-designer/src/step-generation/commandCreators/atomic/replaceTip.js similarity index 85% rename from protocol-designer/src/step-generation/replaceTip.js rename to protocol-designer/src/step-generation/commandCreators/atomic/replaceTip.js index 4a4c9145804..c86e86b9c77 100644 --- a/protocol-designer/src/step-generation/replaceTip.js +++ b/protocol-designer/src/step-generation/commandCreators/atomic/replaceTip.js @@ -1,8 +1,10 @@ // @flow import cloneDeep from 'lodash/cloneDeep' -import {dropTip, getNextTiprack, tiprackWellNamesByCol} from './' -import {insufficientTips} from './errorCreators' -import type {RobotState, CommandCreator} from './types' +import {getNextTiprack} from '../../robotStateSelectors' +import {tiprackWellNamesByCol} from '../../data' +import {insufficientTips} from '../../errorCreators' +import type {RobotState, CommandCreator} from '../../types' +import dropTip from './dropTip' const replaceTip = (pipetteId: string): CommandCreator => (prevRobotState: RobotState) => { /** @@ -47,12 +49,6 @@ const replaceTip = (pipetteId: string): CommandCreator => (prevRobotState: Robot // pipette now has tip robotState.tipState.pipettes[pipetteId] = true - // update tiprack-to-pipette assignment - robotState.tiprackAssignment = { - ...robotState.tiprackAssignment, - [nextTiprack.tiprackId]: pipetteId, - } - // remove tips from tiprack if (pipetteData.channels === 1 && nextTiprack.well) { robotState.tipState.tipracks[nextTiprack.tiprackId][nextTiprack.well] = false diff --git a/protocol-designer/src/step-generation/touchTip.js b/protocol-designer/src/step-generation/commandCreators/atomic/touchTip.js similarity index 86% rename from protocol-designer/src/step-generation/touchTip.js rename to protocol-designer/src/step-generation/commandCreators/atomic/touchTip.js index 2b7131e99a0..2861ce49baa 100644 --- a/protocol-designer/src/step-generation/touchTip.js +++ b/protocol-designer/src/step-generation/commandCreators/atomic/touchTip.js @@ -1,7 +1,7 @@ // @flow // import cloneDeep from 'lodash/cloneDeep' -import {noTipOnPipette, pipetteDoesNotExist} from './errorCreators' -import type {RobotState, CommandCreator, CommandCreatorError, TouchTipArgs} from './' +import {noTipOnPipette, pipetteDoesNotExist} from '../../errorCreators' +import type {RobotState, CommandCreator, CommandCreatorError, TouchTipArgs} from '../../types' const touchTip = (args: TouchTipArgs): CommandCreator => (prevRobotState: RobotState) => { /** touchTip with given args. Requires tip. */ @@ -16,7 +16,7 @@ const touchTip = (args: TouchTipArgs): CommandCreator => (prevRobotState: RobotS errors.push(pipetteDoesNotExist({actionName, pipette})) } - if (prevRobotState.tipState.pipettes[pipette] === false) { + if (!prevRobotState.tipState.pipettes[pipette]) { errors.push(noTipOnPipette({actionName, pipette, labware, well})) } diff --git a/protocol-designer/src/step-generation/consolidate.js b/protocol-designer/src/step-generation/commandCreators/compound/consolidate.js similarity index 67% rename from protocol-designer/src/step-generation/consolidate.js rename to protocol-designer/src/step-generation/commandCreators/compound/consolidate.js index 2e8bde070c2..bb245718c58 100644 --- a/protocol-designer/src/step-generation/consolidate.js +++ b/protocol-designer/src/step-generation/commandCreators/compound/consolidate.js @@ -1,11 +1,12 @@ // @flow import chunk from 'lodash/chunk' import flatMap from 'lodash/flatMap' -import {FIXED_TRASH_ID} from '../constants' -import {aspirate, dispense, blowout, replaceTip, touchTip} from './' +import * as errorCreators from '../../errorCreators' +import {getPipetteWithTipMaxVol} from '../../robotStateSelectors' +import type {ConsolidateFormData, RobotState, CommandCreator, CompoundCommandCreator} from '../../types' +import {blowoutUtil} from '../../utils' +import {aspirate, dispense, replaceTip, touchTip} from '../atomic' import {mixUtil} from './mix' -import * as errorCreators from './errorCreators' -import type {ConsolidateFormData, RobotState, CommandCreator, CompoundCommandCreator} from './' const consolidate = (data: ConsolidateFormData): CompoundCommandCreator => (prevRobotState: RobotState) => { /** @@ -35,17 +36,14 @@ const consolidate = (data: ConsolidateFormData): CompoundCommandCreator => (prev } const { + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, aspirateOffsetFromBottomMm, dispenseOffsetFromBottomMm, } = data - // TODO error on negative data.disposalVolume? - const disposalVolume = (data.disposalVolume && data.disposalVolume > 0) - ? data.disposalVolume - : 0 - const maxWellsPerChunk = Math.floor( - (pipetteData.maxVolume - disposalVolume) / data.volume + getPipetteWithTipMaxVol(data.pipette, prevRobotState) / data.volume ) const commandCreators = flatMap( @@ -53,22 +51,22 @@ const consolidate = (data: ConsolidateFormData): CompoundCommandCreator => (prev (sourceWellChunk: Array, chunkIndex: number): Array => { // Aspirate commands for all source wells in the chunk const aspirateCommands = flatMap(sourceWellChunk, (sourceWell: string, wellIndex: number): Array => { - const isFirstWellInChunk = wellIndex === 0 - const touchTipAfterAspirateCommand = data.touchTipAfterAspirate ? [touchTip({ pipette: data.pipette, labware: data.sourceLabware, well: sourceWell, + offsetFromBottomMm: data.touchTipAfterAspirateOffsetMmFromBottom, })] : [] return [ aspirate({ pipette: data.pipette, - volume: data.volume + (isFirstWellInChunk ? disposalVolume : 0), + volume: data.volume, labware: data.sourceLabware, well: sourceWell, + 'flow-rate': aspirateFlowRateUlSec, offsetFromBottomMm: aspirateOffsetFromBottomMm, }), ...touchTipAfterAspirateCommand, @@ -89,65 +87,59 @@ const consolidate = (data: ConsolidateFormData): CompoundCommandCreator => (prev pipette: data.pipette, labware: data.destLabware, well: data.destWell, + offsetFromBottomMm: data.touchTipAfterDispenseOffsetMmFromBottom, })] : [] - const trashTheDisposalVol = disposalVolume - ? [ - blowout({ - pipette: data.pipette, - labware: FIXED_TRASH_ID, - well: 'A1', - }), - ] - : [] - const mixBeforeCommands = (data.mixFirstAspirate) - ? mixUtil( - data.pipette, - data.sourceLabware, - sourceWellChunk[0], - data.mixFirstAspirate.volume, - data.mixFirstAspirate.times, + ? mixUtil({ + pipette: data.pipette, + labware: data.sourceLabware, + well: sourceWellChunk[0], + volume: data.mixFirstAspirate.volume, + times: data.mixFirstAspirate.times, aspirateOffsetFromBottomMm, - dispenseOffsetFromBottomMm - ) + dispenseOffsetFromBottomMm, + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, + }) : [] const preWetTipCommands = (data.preWetTip) // Pre-wet tip is equivalent to a single mix, with volume equal to the consolidate volume. - ? mixUtil( - data.pipette, - data.sourceLabware, - sourceWellChunk[0], - data.volume, - 1, + ? mixUtil({ + pipette: data.pipette, + labware: data.sourceLabware, + well: sourceWellChunk[0], + volume: data.volume, + times: 1, aspirateOffsetFromBottomMm, - dispenseOffsetFromBottomMm - ) + dispenseOffsetFromBottomMm, + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, + }) : [] const mixAfterCommands = (data.mixInDestination) - ? mixUtil( - data.pipette, - data.destLabware, - data.destWell, - data.mixInDestination.volume, - data.mixInDestination.times, + ? mixUtil({ + pipette: data.pipette, + labware: data.destLabware, + well: data.destWell, + volume: data.mixInDestination.volume, + times: data.mixInDestination.times, aspirateOffsetFromBottomMm, - dispenseOffsetFromBottomMm - ) + dispenseOffsetFromBottomMm, + }) : [] - const blowoutCommand = (data.blowout) - ? [ - blowout({ - pipette: data.pipette, - labware: data.blowout, // TODO Ian 2018-05-04 more explicit test for non-trash blowout destination - well: 'A1', // TODO LATER: should user be able to specify the blowout well? - }), - ] - : [] + const blowoutCommand = blowoutUtil( + data.pipette, + data.sourceLabware, + sourceWellChunk[0], + data.destLabware, + data.destWell, + data.blowoutLocation, + ) return [ ...tipCommands, @@ -159,10 +151,10 @@ const consolidate = (data: ConsolidateFormData): CompoundCommandCreator => (prev volume: data.volume * sourceWellChunk.length, labware: data.destLabware, well: data.destWell, + 'flow-rate': dispenseFlowRateUlSec, offsetFromBottomMm: dispenseOffsetFromBottomMm, }), ...touchTipAfterDispenseCommands, - ...trashTheDisposalVol, ...mixAfterCommands, ...blowoutCommand, ] diff --git a/protocol-designer/src/step-generation/distribute.js b/protocol-designer/src/step-generation/commandCreators/compound/distribute.js similarity index 77% rename from protocol-designer/src/step-generation/distribute.js rename to protocol-designer/src/step-generation/commandCreators/compound/distribute.js index eab4b2d4fdd..38d3e6c1c67 100644 --- a/protocol-designer/src/step-generation/distribute.js +++ b/protocol-designer/src/step-generation/commandCreators/compound/distribute.js @@ -4,11 +4,12 @@ import chunk from 'lodash/chunk' import flatMap from 'lodash/flatMap' import flatten from 'lodash/flatten' // import {FIXED_TRASH_ID} from '../constants' -import {aspirate, dispense, blowout, replaceTip, touchTip} from './' +import * as errorCreators from '../../errorCreators' +import {getPipetteWithTipMaxVol} from '../../robotStateSelectors' +import type {DistributeFormData, RobotState, CommandCreator, CompoundCommandCreator, TransferLikeFormDataFields, TransferFormData} from '../../types' +import {aspirate, dispense, blowout, replaceTip, touchTip} from '../atomic' import transfer from './transfer' import {mixUtil} from './mix' -import * as errorCreators from './errorCreators' -import type {DistributeFormData, RobotState, CommandCreator, CompoundCommandCreator, TransferLikeFormDataFields, TransferFormData} from './' const distribute = (data: DistributeFormData): CompoundCommandCreator => (prevRobotState: RobotState) => { /** @@ -39,6 +40,8 @@ const distribute = (data: DistributeFormData): CompoundCommandCreator => (prevRo } const { + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, aspirateOffsetFromBottomMm, dispenseOffsetFromBottomMm, } = data @@ -49,22 +52,29 @@ const distribute = (data: DistributeFormData): CompoundCommandCreator => (prevRo : 0 const maxWellsPerChunk = Math.floor( - (pipetteData.maxVolume - disposalVolume) / data.volume + (getPipetteWithTipMaxVol(data.pipette, prevRobotState) - disposalVolume) / data.volume ) const {pipette} = data if (maxWellsPerChunk === 0) { // distribute vol exceeds pipette vol, break up into 1 transfer per dest well - const transferCommands = data.destWells.map((destWell) => { + const transferCommands = data.destWells.map((destWell, wellIndex) => { + let changeTip = data.changeTip + // 'once' means 'once per all inner transfers' + // so it should only apply to the first inner transfer + if (data.changeTip === 'once') { + changeTip = (wellIndex === 0) ? 'once' : 'never' + } const transferData: TransferFormData = { ...(data: TransferLikeFormDataFields), + changeTip, stepType: 'transfer', sourceWells: [data.sourceWell], destWells: [destWell], mixBeforeAspirate: data.mixBeforeAspirate, mixInDestination: null, - blowout: null, + blowoutLocation: null, } return transfer(transferData) }) @@ -84,6 +94,7 @@ const distribute = (data: DistributeFormData): CompoundCommandCreator => (prevRo pipette, labware: data.destLabware, well: destWell, + offsetFromBottomMm: data.touchTipAfterDispenseOffsetMmFromBottom, }), ] : [] @@ -94,6 +105,7 @@ const distribute = (data: DistributeFormData): CompoundCommandCreator => (prevRo volume: data.volume, labware: data.destLabware, well: destWell, + 'flow-rate': dispenseFlowRateUlSec, offsetFromBottomMm: dispenseOffsetFromBottomMm, }), ...touchTipAfterDispenseCommand, @@ -110,6 +122,7 @@ const distribute = (data: DistributeFormData): CompoundCommandCreator => (prevRo tipCommands = [replaceTip(data.pipette)] } + // TODO: BC 2018-11-29 instead of disposalLabware and disposalWell use blowoutLocation let blowoutCommands = [] if (data.disposalVolume && data.disposalLabware && data.disposalWell) { blowoutCommands = [blowout({ @@ -125,20 +138,23 @@ const distribute = (data: DistributeFormData): CompoundCommandCreator => (prevRo pipette: data.pipette, labware: data.sourceLabware, well: data.sourceWell, + offsetFromBottomMm: data.touchTipAfterDispenseOffsetMmFromBottom, }), ] : [] const mixBeforeAspirateCommands = (data.mixBeforeAspirate) - ? mixUtil( - data.pipette, - data.sourceLabware, - data.sourceWell, - data.mixBeforeAspirate.volume, - data.mixBeforeAspirate.times, + ? mixUtil({ + pipette: data.pipette, + labware: data.sourceLabware, + well: data.sourceWell, + volume: data.mixBeforeAspirate.volume, + times: data.mixBeforeAspirate.times, aspirateOffsetFromBottomMm, - dispenseOffsetFromBottomMm - ) + dispenseOffsetFromBottomMm, + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, + }) : [] return [ @@ -149,6 +165,7 @@ const distribute = (data: DistributeFormData): CompoundCommandCreator => (prevRo volume: data.volume * destWellChunk.length + disposalVolume, labware: data.sourceLabware, well: data.sourceWell, + 'flow-rate': aspirateFlowRateUlSec, offsetFromBottomMm: aspirateOffsetFromBottomMm, }), ...touchTipAfterAspirateCommand, diff --git a/protocol-designer/src/step-generation/commandCreators/compound/index.js b/protocol-designer/src/step-generation/commandCreators/compound/index.js new file mode 100644 index 00000000000..e2d87915c52 --- /dev/null +++ b/protocol-designer/src/step-generation/commandCreators/compound/index.js @@ -0,0 +1,12 @@ +// @flow +import consolidate from './consolidate' +import distribute from './distribute' +import mix from './mix' +import transfer from './transfer' + +export { + consolidate, + distribute, + mix, + transfer, +} diff --git a/protocol-designer/src/step-generation/mix.js b/protocol-designer/src/step-generation/commandCreators/compound/mix.js similarity index 63% rename from protocol-designer/src/step-generation/mix.js rename to protocol-designer/src/step-generation/commandCreators/compound/mix.js index f80ef9c0265..0bb9602210d 100644 --- a/protocol-designer/src/step-generation/mix.js +++ b/protocol-designer/src/step-generation/commandCreators/compound/mix.js @@ -1,27 +1,36 @@ // @flow import flatMap from 'lodash/flatMap' -import aspirate from './aspirate' -import blowout from './blowout' -import dispense from './dispense' -import replaceTip from './replaceTip' -import touchTip from './touchTip' -import {repeatArray} from './utils' -import * as errorCreators from './errorCreators' -import type {MixFormData, RobotState, CommandCreator, CompoundCommandCreator} from './' +import {repeatArray, blowoutUtil} from '../../utils' +import * as errorCreators from '../../errorCreators' +import type {MixFormData, RobotState, CommandCreator, CompoundCommandCreator} from '../../types' +import {aspirate, dispense, replaceTip, touchTip} from '../atomic' /** Helper fn to make mix command creators w/ minimal arguments */ -export function mixUtil ( +export function mixUtil (args: { pipette: string, labware: string, well: string, volume: number, times: number, aspirateOffsetFromBottomMm?: ?number, - dispenseOffsetFromBottomMm?: ?number -): Array { + dispenseOffsetFromBottomMm?: ?number, + aspirateFlowRateUlSec?: ?number, + dispenseFlowRateUlSec?: ?number, +}): Array { + const { + pipette, + labware, + well, + volume, + times, + aspirateOffsetFromBottomMm, + dispenseOffsetFromBottomMm, + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, + } = args return repeatArray([ - aspirate({pipette, volume, labware, well, offsetFromBottomMm: aspirateOffsetFromBottomMm}), - dispense({pipette, volume, labware, well, offsetFromBottomMm: dispenseOffsetFromBottomMm}), + aspirate({pipette, volume, labware, well, offsetFromBottomMm: aspirateOffsetFromBottomMm, 'flow-rate': aspirateFlowRateUlSec}), + dispense({pipette, volume, labware, well, offsetFromBottomMm: dispenseOffsetFromBottomMm, 'flow-rate': dispenseFlowRateUlSec}), ], times) } @@ -47,6 +56,8 @@ const mix = (data: MixFormData): CompoundCommandCreator => (prevRobotState: Robo changeTip, aspirateOffsetFromBottomMm, dispenseOffsetFromBottomMm, + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, } = data // Errors @@ -77,31 +88,41 @@ const mix = (data: MixFormData): CompoundCommandCreator => (prevRobotState: Robo } const touchTipCommands = data.touchTip - ? [touchTip({pipette, labware, well})] + ? [ + touchTip({ + pipette, + labware, + well, + offsetFromBottomMm: data.touchTipMmFromBottom, + }), + ] : [] - const blowoutCommands = data.blowout - ? [blowout({ - pipette, - labware: data.blowout, - well: 'A1', - })] - : [] + const blowoutCommand = blowoutUtil( + data.pipette, + data.labware, + well, + data.labware, + well, + data.blowoutLocation, + ) - const mixCommands = mixUtil( + const mixCommands = mixUtil({ pipette, labware, well, volume, times, aspirateOffsetFromBottomMm, - dispenseOffsetFromBottomMm - ) + dispenseOffsetFromBottomMm, + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, + }) return [ ...tipCommands, ...mixCommands, - ...blowoutCommands, + ...blowoutCommand, ...touchTipCommands, ] } diff --git a/protocol-designer/src/step-generation/transfer.js b/protocol-designer/src/step-generation/commandCreators/compound/transfer.js similarity index 68% rename from protocol-designer/src/step-generation/transfer.js rename to protocol-designer/src/step-generation/commandCreators/compound/transfer.js index 4fddb8e6f5b..129358c3f29 100644 --- a/protocol-designer/src/step-generation/transfer.js +++ b/protocol-designer/src/step-generation/commandCreators/compound/transfer.js @@ -1,13 +1,12 @@ // @flow import flatMap from 'lodash/flatMap' import zip from 'lodash/zip' -import aspirate from './aspirate' -import dispense from './dispense' +import * as errorCreators from '../../errorCreators' +import {getPipetteWithTipMaxVol} from '../../robotStateSelectors' +import type {TransferFormData, RobotState, CommandCreator, CompoundCommandCreator} from '../../types' +import {blowoutUtil} from '../../utils' +import {aspirate, dispense, replaceTip, touchTip} from '../atomic' import {mixUtil} from './mix' -import replaceTip from './replaceTip' -import touchTip from './touchTip' -import * as errorCreators from './errorCreators' -import type {TransferFormData, RobotState, CommandCreator, CompoundCommandCreator} from './' const transfer = (data: TransferFormData): CompoundCommandCreator => (prevRobotState: RobotState) => { /** @@ -41,16 +40,13 @@ const transfer = (data: TransferFormData): CompoundCommandCreator => (prevRobotS } const { + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, aspirateOffsetFromBottomMm, dispenseOffsetFromBottomMm, } = data - // TODO error on negative data.disposalVolume? - const disposalVolume = (data.disposalVolume && data.disposalVolume > 0) - ? data.disposalVolume - : 0 - - const effectiveTransferVol = pipetteData.maxVolume - disposalVolume + const effectiveTransferVol = getPipetteWithTipMaxVol(data.pipette, prevRobotState) const chunksPerSubTransfer = Math.ceil( data.volume / effectiveTransferVol @@ -71,7 +67,6 @@ const transfer = (data: TransferFormData): CompoundCommandCreator => (prevRobotS return flatMap( subTransferVolumes, (subTransferVol: number, chunkIdx: number): Array => { - // TODO IMMEDIATELY disposal vol ^^^ const tipCommands: Array = ( (data.changeTip === 'once' && pairIdx === 0 && chunkIdx === 0) || data.changeTip === 'always') @@ -79,27 +74,31 @@ const transfer = (data: TransferFormData): CompoundCommandCreator => (prevRobotS : [] const preWetTipCommands = (data.preWetTip && chunkIdx === 0) - ? mixUtil( - data.pipette, - data.sourceLabware, - sourceWell, - Math.max(subTransferVol), - 1, + ? mixUtil({ + pipette: data.pipette, + labware: data.sourceLabware, + well: sourceWell, + volume: Math.max(subTransferVol), + times: 1, aspirateOffsetFromBottomMm, - dispenseOffsetFromBottomMm - ) + dispenseOffsetFromBottomMm, + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, + }) : [] const mixBeforeAspirateCommands = (data.mixBeforeAspirate) - ? mixUtil( - data.pipette, - data.sourceLabware, - sourceWell, - data.mixBeforeAspirate.volume, - data.mixBeforeAspirate.times, + ? mixUtil({ + pipette: data.pipette, + labware: data.sourceLabware, + well: sourceWell, + volume: data.mixBeforeAspirate.volume, + times: data.mixBeforeAspirate.times, aspirateOffsetFromBottomMm, - dispenseOffsetFromBottomMm - ) + dispenseOffsetFromBottomMm, + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, + }) : [] const touchTipAfterAspirateCommands = (data.touchTipAfterAspirate) @@ -107,6 +106,7 @@ const transfer = (data: TransferFormData): CompoundCommandCreator => (prevRobotS pipette: data.pipette, labware: data.sourceLabware, well: sourceWell, + offsetFromBottomMm: data.touchTipAfterAspirateOffsetMmFromBottom, })] : [] @@ -115,21 +115,33 @@ const transfer = (data: TransferFormData): CompoundCommandCreator => (prevRobotS pipette: data.pipette, labware: data.destLabware, well: destWell, + offsetFromBottomMm: data.touchTipAfterDispenseOffsetMmFromBottom, })] : [] const mixInDestinationCommands = (data.mixInDestination) - ? mixUtil( - data.pipette, - data.destLabware, - destWell, - data.mixInDestination.volume, - data.mixInDestination.times, + ? mixUtil({ + pipette: data.pipette, + labware: data.destLabware, + well: destWell, + volume: data.mixInDestination.volume, + times: data.mixInDestination.times, aspirateOffsetFromBottomMm, - dispenseOffsetFromBottomMm - ) + dispenseOffsetFromBottomMm, + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, + }) : [] + const blowoutCommand = blowoutUtil( + data.pipette, + data.sourceLabware, + sourceWell, + data.destLabware, + destWell, + data.blowoutLocation, + ) + return [ ...tipCommands, ...preWetTipCommands, @@ -139,6 +151,7 @@ const transfer = (data: TransferFormData): CompoundCommandCreator => (prevRobotS volume: subTransferVol, labware: data.sourceLabware, well: sourceWell, + 'flow-rate': aspirateFlowRateUlSec, offsetFromBottomMm: aspirateOffsetFromBottomMm, }), ...touchTipAfterAspirateCommands, @@ -147,10 +160,12 @@ const transfer = (data: TransferFormData): CompoundCommandCreator => (prevRobotS volume: subTransferVol, labware: data.destLabware, well: destWell, + 'flow-rate': dispenseFlowRateUlSec, offsetFromBottomMm: dispenseOffsetFromBottomMm, }), ...touchTipAfterDispenseCommands, ...mixInDestinationCommands, + ...blowoutCommand, ] } ) diff --git a/protocol-designer/src/step-generation/commandCreators/index.js b/protocol-designer/src/step-generation/commandCreators/index.js new file mode 100644 index 00000000000..aa161bf5028 --- /dev/null +++ b/protocol-designer/src/step-generation/commandCreators/index.js @@ -0,0 +1,19 @@ +// @flow + +export { + transfer, + mix, + consolidate, + distribute, +} from './compound' + +export { + aspirate, + blowout, + delay, + dispense, + dropAllTips, + dropTip, + replaceTip, + touchTip, +} from './atomic' diff --git a/protocol-designer/src/step-generation/errorCreators.js b/protocol-designer/src/step-generation/errorCreators.js index 027c8af91a1..2fb82642632 100644 --- a/protocol-designer/src/step-generation/errorCreators.js +++ b/protocol-designer/src/step-generation/errorCreators.js @@ -39,6 +39,18 @@ export function labwareDoesNotExist (args: {actionName: string, labware: string} } } +export function tipVolumeExceeded (args: { + actionName: string, + volume: string | number, + maxVolume: string | number, +}): CommandCreatorError { + const {actionName, volume, maxVolume} = args + return { + message: `Attempted to ${actionName} volume greater than tip max volume (${volume} > ${maxVolume})`, + type: 'TIP_VOLUME_EXCEEDED', + } +} + export function pipetteVolumeExceeded (args: { actionName: string, volume: string | number, diff --git a/protocol-designer/src/step-generation/getNextRobotStateAndWarnings/forAspirateDispense.js b/protocol-designer/src/step-generation/getNextRobotStateAndWarnings/forAspirateDispense.js new file mode 100644 index 00000000000..1fd8555c156 --- /dev/null +++ b/protocol-designer/src/step-generation/getNextRobotStateAndWarnings/forAspirateDispense.js @@ -0,0 +1,93 @@ +// @flow +import range from 'lodash/range' +import isEmpty from 'lodash/isEmpty' +import {mergeLiquid, splitLiquid, getWellsForTips, totalVolume} from '../utils' +import * as warningCreators from '../warningCreators' +import type { + RobotState, + SingleLabwareLiquidState, + CommandCreatorWarning, + AspirateDispenseArgs, + RobotStateAndWarnings, +} from '../types' + +export default function getNextRobotStateAndWarningsForAspDisp ( + args: AspirateDispenseArgs, + prevRobotState: RobotState +): RobotStateAndWarnings { + const {pipette: pipetteId, volume, labware: labwareId, well} = args + + const {liquidState: prevLiquidState} = prevRobotState + const pipetteData = prevRobotState.instruments[pipetteId] + const labwareType = prevRobotState.labware[labwareId].type + + const {wellsForTips} = getWellsForTips(pipetteData.channels, labwareType, well) + + // Blend tip's liquid contents (if any) with liquid of the source + // to update liquid state in all pipette tips + type PipetteLiquidStateAcc = { + pipetteLiquidState: SingleLabwareLiquidState, + pipetteWarnings: Array, + } + const {pipetteLiquidState, pipetteWarnings} = range(pipetteData.channels).reduce( + (acc: PipetteLiquidStateAcc, tipIndex) => { + const prevTipLiquidState = prevLiquidState.pipettes[pipetteId][tipIndex.toString()] + const prevSourceLiquidState = prevLiquidState.labware[labwareId][wellsForTips[tipIndex]] + + const newLiquidFromWell = splitLiquid( + volume, + prevSourceLiquidState + ).dest + + let nextWarnings = [] + if (isEmpty(prevSourceLiquidState)) { + nextWarnings = [...nextWarnings, warningCreators.aspirateFromPristineWell()] + } else if (volume > totalVolume(prevSourceLiquidState)) { + nextWarnings = [...nextWarnings, warningCreators.aspirateMoreThanWellContents()] + } + + return { + pipetteLiquidState: { + ...acc.pipetteLiquidState, + [tipIndex]: mergeLiquid( + prevTipLiquidState, + newLiquidFromWell + ), + }, + pipetteWarnings: [...acc.pipetteWarnings, ...nextWarnings], + } + }, {pipetteLiquidState: {}, pipetteWarnings: []}) + + // Remove liquid from source well(s) + const labwareLiquidState: SingleLabwareLiquidState = { + ...prevLiquidState.labware[labwareId], + ...wellsForTips.reduce((acc: SingleLabwareLiquidState, well) => ({ + ...acc, + [well]: splitLiquid( + volume, + // When multiple tips aspirate from 1 well, + // that volume is sequentially removed, tip by tip + acc[well] || prevLiquidState.labware[labwareId][well] + ).source, + }), {}), + } + + const nextLiquidState = { + pipettes: { + ...prevLiquidState.pipettes, + [pipetteId]: pipetteLiquidState, + }, + labware: { + ...prevLiquidState.labware, + [labwareId]: labwareLiquidState, + }, + } + + return { + robotState: { + ...prevRobotState, + liquidState: nextLiquidState, + }, + warnings: pipetteWarnings, + } +} diff --git a/protocol-designer/src/step-generation/getNextRobotStateAndWarnings/index.js b/protocol-designer/src/step-generation/getNextRobotStateAndWarnings/index.js new file mode 100644 index 00000000000..cb5c68ffabd --- /dev/null +++ b/protocol-designer/src/step-generation/getNextRobotStateAndWarnings/index.js @@ -0,0 +1,35 @@ +// @flow +import assert from 'assert' +import type { + RobotState, + Command, + RobotStateAndWarnings, +} from '../types' +import forAspirateDispense from './forAspirateDispense' + +export default function getNextRobotStateAndWarnings (command: Command, prevRobotState: RobotState): RobotStateAndWarnings { + assert(command, 'undefined command passed to getNextRobotStateAndWarning') + switch (command.command) { + case 'dispense': + case 'aspirate': + // TODO: BC 2018-11-29 handle dispense + return forAspirateDispense(command.params, prevRobotState) + case 'blowout': + case 'drop-tip': + case 'pick-up-tip': + // TODO: BC 2018-11-29 handle PipetteLabwareArgs + return {robotState: prevRobotState, warnings: []} + case 'touch-tip': + // TODO: BC 2018-11-29 handle touch-tip + return {robotState: prevRobotState, warnings: []} + case 'delay': + // TODO: BC 2018-11-29 handle delay + return {robotState: prevRobotState, warnings: []} + case 'air-gap': + // TODO: BC 2018-11-29 handle air-gap + return {robotState: prevRobotState, warnings: []} + default: + assert(false, `unknown command: ${command.command} passed to getNextRobotStateAndWarning`) + return {robotState: prevRobotState, warnings: []} + } +} diff --git a/protocol-designer/src/step-generation/index.js b/protocol-designer/src/step-generation/index.js index b82ea5233ab..85fd0187e92 100644 --- a/protocol-designer/src/step-generation/index.js +++ b/protocol-designer/src/step-generation/index.js @@ -1,21 +1,4 @@ // @flow -import aspirate from './aspirate' -import blowout from './blowout' -import consolidate from './consolidate' -import distribute from './distribute' -import delay from './delay' -import dispense from './dispense' -import dropAllTips from './dropAllTips' -import dropTip from './dropTip' -import mix from './mix' -import replaceTip from './replaceTip' -import touchTip from './touchTip' -import transfer from './transfer' -export * from './robotStateSelectors' -export * from './types' -export * from './data' -export * from './utils' - export { aspirate, blowout, @@ -29,4 +12,9 @@ export { replaceTip, touchTip, transfer, -} +} from './commandCreators' + +export * from './robotStateSelectors' +export * from './types' +export * from './data' +export * from './utils' diff --git a/protocol-designer/src/step-generation/robotStateSelectors.js b/protocol-designer/src/step-generation/robotStateSelectors.js index 45ffd075c22..2526dfb8274 100644 --- a/protocol-designer/src/step-generation/robotStateSelectors.js +++ b/protocol-designer/src/step-generation/robotStateSelectors.js @@ -1,8 +1,11 @@ // @flow -import {tiprackWellNamesByCol, tiprackWellNamesFlat} from './' -import type {Channels} from '@opentrons/components' -import type {RobotState, PipetteData, LabwareData} from './' +import assert from 'assert' +import min from 'lodash/min' import sortBy from 'lodash/sortBy' +import type {Channels} from '@opentrons/components' +import {getLabware} from '@opentrons/shared-data' +import {tiprackWellNamesByCol, tiprackWellNamesFlat} from './' +import type {RobotState, PipetteData} from './' // SELECTOR UTILITIES @@ -16,8 +19,7 @@ export function getPipetteChannels (pipetteId: string, robotState: RobotState): const pipette = robotState.instruments[pipetteId] if (!pipette) { - // TODO Ian 2018-06-04 use assert - console.warn(`no pipette id: "${pipetteId}"`) + assert(false, `no pipette with ID {pipetteId} found in robot state`) return null } @@ -29,8 +31,7 @@ export function getLabwareType (labwareId: string, robotState: RobotState): ?str const labware = robotState.labware[labwareId] if (!labware) { - // TODO Ian 2018-06-04 use assert - console.warn(`no labware id: "${labwareId}"`) + assert(false, `no labware id: "${labwareId}"`) return null } @@ -58,28 +59,6 @@ export function _getNextTip ( return fullColumn ? fullColumn[0] : null } -/** Tipracks are "available" if they match the assignment type, - * and are not assigned to another pipette. */ -export function tiprackIsAvailableToPipette ( - pipette: PipetteData, - tiprackData: LabwareData, - assignedPipetteId: ?string -): boolean { - const matchingTiprackModel = (pipette.tiprackModel) - ? pipette.tiprackModel === tiprackData.type - : true // with no tiprack assigned, pipette can use anything - - // robotState.tiprackAssignment key may not exist, - // or tiprack id may not be in tiprackAssignment - // both these indicate that the tiprack is unassigned - const tiprackAssignmentOk = ( - assignedPipetteId == null || - assignedPipetteId === pipette.id - ) - - return matchingTiprackModel && tiprackAssignmentOk -} - type NextTiprack = {|tiprackId: string, well: string|} | null export function getNextTiprack (pipette: PipetteData, robotState: RobotState): NextTiprack { /** Returns the next tiprack that has tips. @@ -90,11 +69,7 @@ export function getNextTiprack (pipette: PipetteData, robotState: RobotState): N const sortedTipracksIds = sortLabwareBySlot(robotState).filter(labwareId => // assume if labwareId is not in tipState.tipracks, it's not a tiprack robotState.tipState.tipracks[labwareId] && - tiprackIsAvailableToPipette( - pipette, - robotState.labware[labwareId], - robotState.tiprackAssignment && robotState.tiprackAssignment[labwareId] - ) + (pipette.tiprackModel === robotState.labware[labwareId].type) ) const firstAvailableTiprack = sortedTipracksIds.find(tiprackId => @@ -114,3 +89,19 @@ export function getNextTiprack (pipette: PipetteData, robotState: RobotState): N // No available tipracks (for given pipette channels) return null } + +export function getPipetteWithTipMaxVol (pipetteId: string, robotState: RobotState): number { + // NOTE: this fn assumes each pipette is assigned to exactly one tiprack type, + // across the entire timeline + const pipetteData = robotState.instruments[pipetteId] + const pipetteMaxVol = pipetteData && pipetteData.maxVolume + + const tiprackData = pipetteData && pipetteData.tiprackModel && getLabware(pipetteData.tiprackModel) + const tiprackTipVol = tiprackData && tiprackData.metadata.tipVolume + + if (!pipetteMaxVol || !tiprackTipVol) { + console.warn('getPipetteEffectiveMaxVol expected tiprackMaxVol and pipette maxVolume to be > 0, got', {pipetteMaxVol, tiprackTipVol}) + return NaN + } + return min([tiprackTipVol, pipetteMaxVol]) +} diff --git a/protocol-designer/src/step-generation/test-with-flow/aspirate.test.js b/protocol-designer/src/step-generation/test-with-flow/aspirate.test.js index 5a136f45549..01639e09008 100644 --- a/protocol-designer/src/step-generation/test-with-flow/aspirate.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/aspirate.test.js @@ -1,27 +1,27 @@ // @flow -import _aspirate from '../aspirate' +import {expectTimelineError} from './testMatchers' +import _aspirate from '../commandCreators/atomic/aspirate' import { - createRobotStateFixture, createRobotState, commandCreatorHasErrors, commandCreatorNoErrors, } from './fixtures' -import updateLiquidState from '../aspirateUpdateLiquidState' +import getNextRobotStateAndWarnings from '../getNextRobotStateAndWarnings' -jest.mock('../aspirateUpdateLiquidState') +jest.mock('../getNextRobotStateAndWarnings') const aspirate = commandCreatorNoErrors(_aspirate) const aspirateWithErrors = commandCreatorHasErrors(_aspirate) -const mockLiquidReturnValue = { +const mockRobotStateAndWarningsReturnValue = { // using strings instead of properly-shaped objects for easier assertions - liquidState: 'expected liquid state', + robotState: 'expected robot state', warnings: 'expected warnings', } beforeEach(() => { // $FlowFixMe - updateLiquidState.mockReturnValue(mockLiquidReturnValue) + getNextRobotStateAndWarnings.mockReturnValue(mockRobotStateAndWarningsReturnValue) }) describe('aspirate', () => { @@ -34,51 +34,87 @@ describe('aspirate', () => { destPlateType: '96-flat', fillPipetteTips: false, fillTiprackTips: true, - tipracks: [200, 200], + tipracks: [300, 300], }) robotStateWithTip = createRobotState({ sourcePlateType: 'trough-12row', destPlateType: '96-flat', fillPipetteTips: true, fillTiprackTips: true, - tipracks: [200, 200], + tipracks: [300, 300], }) }) - // Fixtures without liquidState key, for use with `toMatchObject` - const robotStateWithTipNoLiquidState = createRobotStateFixture({ - sourcePlateType: 'trough-12row', - destPlateType: '96-flat', - fillPipetteTips: true, - fillTiprackTips: true, - tipracks: [200, 200], + describe('aspirate normally (with tip)', () => { + const optionalArgsCases = [ + { + description: 'no optional args', + expectInParams: false, + args: {}, + }, + { + description: 'null optional args', + expectInParams: false, + args: { + offsetFromBottomMm: null, + 'flow-rate': null, + }, + }, + { + description: 'all optional args', + expectInParams: true, + args: { + offsetFromBottomMm: 5, + 'flow-rate': 6, + }, + }, + ] + + optionalArgsCases.forEach(testCase => { + test(testCase.description, () => { + const result = aspirate({ + pipette: 'p300SingleId', + volume: 50, + labware: 'sourcePlateId', + well: 'A1', + ...testCase.args, + })(robotStateWithTip) + + expect(result.commands).toEqual([{ + command: 'aspirate', + params: { + pipette: 'p300SingleId', + volume: 50, + labware: 'sourcePlateId', + well: 'A1', + ...(testCase.expectInParams ? testCase.args : {}), + }, + }]) + }) + }) }) - test('aspirate with tip', () => { - const result = aspirate({ + test('aspirate with volume > tip max volume should throw error', () => { + robotStateWithTip.instruments['p300SingleId'].tiprackModel = 'tiprack-200ul' + const result = aspirateWithErrors({ pipette: 'p300SingleId', - volume: 50, + volume: 201, labware: 'sourcePlateId', well: 'A1', })(robotStateWithTip) - expect(result.commands).toEqual([{ - command: 'aspirate', - params: { - pipette: 'p300SingleId', - volume: 50, - labware: 'sourcePlateId', - well: 'A1', - }, - }]) - - expect(result.robotState).toMatchObject(robotStateWithTipNoLiquidState) + expect(result.errors).toHaveLength(1) + expect(result.errors[0]).toMatchObject({ + type: 'TIP_VOLUME_EXCEEDED', + }) }) - test('aspirate with volume > pipette max vol should throw error', () => { + test('aspirate with volume > pipette max volume should throw error', () => { + // NOTE: assigning p300 to a 1000uL tiprack is nonsense, just for this test + robotStateWithTip.instruments['p300SingleId'].tiprackModel = 'tiprack-1000ul' const result = aspirateWithErrors({ pipette: 'p300SingleId', - volume: 10000, + volume: 301, labware: 'sourcePlateId', well: 'A1', })(robotStateWithTip) @@ -89,7 +125,7 @@ describe('aspirate', () => { }) }) - test('aspirate with invalid pipette ID should throw error', () => { + test('aspirate with invalid pipette ID should return error', () => { const result = aspirateWithErrors({ pipette: 'badPipette', volume: 50, @@ -97,10 +133,7 @@ describe('aspirate', () => { well: 'A1', })(robotStateWithTip) - expect(result.errors).toHaveLength(1) - expect(result.errors[0]).toMatchObject({ - type: 'PIPETTE_DOES_NOT_EXIST', - }) + expectTimelineError(result.errors, 'PIPETTE_DOES_NOT_EXIST') }) test('aspirate with no tip should return error', () => { @@ -132,28 +165,18 @@ describe('aspirate', () => { }) describe('liquid tracking', () => { - test('aspirate calls aspirateUpdateLiquidState with correct args and puts result into robotState.liquidState', () => { - const result = aspirate({ + test('aspirate calls getNextRobotStateAndWarnings with correct args and puts result into robotState', () => { + const args = { pipette: 'p300SingleId', labware: 'sourcePlateId', well: 'A1', volume: 152, - })(robotStateWithTip) - - expect(updateLiquidState).toHaveBeenCalledWith( - { - pipetteId: 'p300SingleId', - labwareId: 'sourcePlateId', - volume: 152, - well: 'A1', - labwareType: 'trough-12row', - pipetteData: robotStateWithTip.instruments.p300SingleId, - }, - robotStateWithTip.liquidState - ) + } + const result = aspirate(args)(robotStateWithTip) - expect(result.robotState.liquidState).toBe(mockLiquidReturnValue.liquidState) - expect(result.warnings).toBe(mockLiquidReturnValue.warnings) + expect(getNextRobotStateAndWarnings).toHaveBeenCalledWith(result.commands[0], robotStateWithTip) + expect(result.robotState).toBe(mockRobotStateAndWarningsReturnValue.robotState) + expect(result.warnings).toBe(mockRobotStateAndWarningsReturnValue.warnings) }) }) }) diff --git a/protocol-designer/src/step-generation/test-with-flow/blowout.test.js b/protocol-designer/src/step-generation/test-with-flow/blowout.test.js index 8bc8958003d..04acae7dda5 100644 --- a/protocol-designer/src/step-generation/test-with-flow/blowout.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/blowout.test.js @@ -1,5 +1,6 @@ // @flow -import _blowout from '../blowout' +import {expectTimelineError} from './testMatchers' +import _blowout from '../commandCreators/atomic/blowout' import {createRobotState, commandCreatorNoErrors, commandCreatorHasErrors} from './fixtures' import updateLiquidState from '../dispenseUpdateLiquidState' @@ -19,7 +20,7 @@ describe('blowout', () => { destPlateType: '96-flat', fillTiprackTips: true, fillPipetteTips: false, - tipracks: [200, 200], + tipracks: [300, 300], }) robotStateWithTip = { @@ -65,10 +66,7 @@ describe('blowout', () => { well: 'A1', })(robotStateWithTip) - expect(result.errors).toHaveLength(1) - expect(result.errors[0]).toMatchObject({ - type: 'PIPETTE_DOES_NOT_EXIST', - }) + expectTimelineError(result.errors, 'PIPETTE_DOES_NOT_EXIST') }) test('blowout with invalid labware ID should throw error', () => { diff --git a/protocol-designer/src/step-generation/test-with-flow/blowoutUtil.test.js b/protocol-designer/src/step-generation/test-with-flow/blowoutUtil.test.js new file mode 100644 index 00000000000..ae3c7ca7781 --- /dev/null +++ b/protocol-designer/src/step-generation/test-with-flow/blowoutUtil.test.js @@ -0,0 +1,65 @@ +// @flow +import _blowout from '../commandCreators/atomic/blowout' +import { + blowoutUtil, + SOURCE_WELL_BLOWOUT_DESTINATION, + DEST_WELL_BLOWOUT_DESTINATION, +} from '../utils' + +jest.mock('../commandCreators/atomic/blowout') + +const pipetteId = 'p300SingleId' +const sourceLabwareId = 'sourcePlateId' +const sourceWell = 'A1' +const destLabwareId = 'destPlateId' +const destWell = 'A2' + +const blowoutArgs = [ + pipetteId, + sourceLabwareId, + sourceWell, + destLabwareId, + destWell, +] + +describe('blowoutUtil', () => { + beforeEach(() => { + // $FlowFixMe + _blowout.mockClear() + // $FlowFixMe + _blowout.mockReturnValue('return value from blowout') + }) + + test('blowoutUtil calls blowout with source well params', () => { + blowoutUtil( + ...blowoutArgs, + + SOURCE_WELL_BLOWOUT_DESTINATION, + ) + + expect(_blowout).toHaveBeenCalledWith({ + pipette: pipetteId, + labware: sourceLabwareId, + well: sourceWell, + }) + }) + + test('blowoutUtil calls blowout with dest plate params', () => { + blowoutUtil( + ...blowoutArgs, + DEST_WELL_BLOWOUT_DESTINATION, + ) + + expect(_blowout).toHaveBeenCalledWith({ + pipette: pipetteId, + labware: destLabwareId, + well: destWell, + }) + }) + + test('blowoutUtil returns an empty array if not given a blowoutLocation', () => { + const result = blowoutUtil(...blowoutArgs, null) + expect(_blowout).not.toHaveBeenCalled() + expect(result).toEqual([]) + }) +}) diff --git a/protocol-designer/src/step-generation/test-with-flow/consolidate.test.js b/protocol-designer/src/step-generation/test-with-flow/consolidate.test.js index c08d1097761..c89d7ead890 100644 --- a/protocol-designer/src/step-generation/test-with-flow/consolidate.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/consolidate.test.js @@ -9,7 +9,7 @@ import { compoundCommandCreatorHasErrors, commandFixtures as cmd, } from './fixtures' -import _consolidate from '../consolidate' +import _consolidate from '../commandCreators/compound/consolidate' const consolidate = compoundCommandCreatorNoErrors(_consolidate) const consolidateWithErrors = compoundCommandCreatorHasErrors(_consolidate) @@ -35,7 +35,7 @@ const robotInitialStateNoLiquidState = createRobotStateFixture({ destPlateType: '96-flat', fillTiprackTips: true, fillPipetteTips: false, - tipracks: [200, 200], + tipracks: [300, 300], }) const emptyLiquidState = createEmptyLiquidState({ @@ -94,13 +94,11 @@ describe('consolidate single-channel', () => { preWetTip: false, touchTipAfterAspirate: false, - disposalVolume: null, mixFirstAspirate: null, touchTipAfterDispense: false, mixInDestination: null, - delayAfterDispense: null, - blowout: null, + blowoutLocation: null, } test('Minimal single-channel: A1 A2 to B1, 50uL with p300', () => { @@ -229,31 +227,6 @@ describe('consolidate single-channel', () => { expect(result.robotState).toMatchObject(robotStatePickedUpOneTipNoLiquidState) }) - test('disposal vol should be taken from first well', () => { - const data = { - ...baseData, - volume: 100, - changeTip: 'once', - disposalVolume: 50, - } - - const result = consolidate(data)(robotInitialState) - - expect(result.commands).toEqual([ - cmd.pickUpTip('A1'), - cmd.aspirate('A1', 150), // disposalVolume included - cmd.aspirate('A2', 100), - dispense('B1', 200), - cmd.blowout(), // Trash the disposal volume - - cmd.aspirate('A3', 150), // disposalVolume included - cmd.aspirate('A4', 100), - dispense('B1', 200), - cmd.blowout(), // Trash the disposal volume - ]) - expect(result.robotState).toMatchObject(robotStatePickedUpOneTipNoLiquidState) - }) - test('mix on aspirate should mix before aspirate in first well of chunk only', () => { const data = { ...baseData, @@ -282,11 +255,10 @@ describe('consolidate single-channel', () => { expect(result.robotState).toMatchObject(robotStatePickedUpOneTipNoLiquidState) }) - test('mix on aspirate with disposal vol', () => { + test('mix on aspirate', () => { const data = { ...baseData, volume: 125, - disposalVolume: 30, changeTip: 'once', mixFirstAspirate: {times: 3, volume: 50}, } @@ -303,13 +275,10 @@ describe('consolidate single-channel', () => { cmd.aspirate('A1', 50), cmd.dispense('A1', 50), // sourceLabwareId // done mix - cmd.aspirate('A1', 155), // with disposal vol + cmd.aspirate('A1', 125), cmd.aspirate('A2', 125), dispense('B1', 250), - // Trash the disposal volume - cmd.blowout(), - // Start mix cmd.aspirate('A3', 50), cmd.dispense('A3', 50), // sourceLabwareId @@ -319,11 +288,9 @@ describe('consolidate single-channel', () => { cmd.dispense('A3', 50), // sourceLabwareId // done mix - cmd.aspirate('A3', 155), // with disposal volume + cmd.aspirate('A3', 125), cmd.aspirate('A4', 125), dispense('B1', 250), - // Trash the disposal volume - cmd.blowout(), ]) expect(result.robotState).toMatchObject(robotStatePickedUpOneTipNoLiquidState) }) @@ -361,7 +328,7 @@ describe('consolidate single-channel', () => { volume: 100, changeTip: 'once', mixInDestination: {times: 3, volume: 54}, - blowout: 'trashId', + blowoutLocation: 'trashId', } const result = consolidate(data)(robotInitialState) @@ -385,40 +352,6 @@ describe('consolidate single-channel', () => { expect(result.robotState).toMatchObject(robotStatePickedUpOneTipNoLiquidState) }) - test('mix after dispense with disposal volume: dispose, then mix (?)', () => { - // TODO Ian 2018-02-13 should the mixing happen after disposing? Or should this behavior be different? - const data = { - ...baseData, - volume: 100, - changeTip: 'once', - disposalVolume: 30, - mixInDestination: {times: 3, volume: 52}, - } - - const result = consolidate(data)(robotInitialState) - expect(result.commands).toEqual([ - cmd.pickUpTip('A1'), - cmd.aspirate('A1', 130), // includes disposal volume - cmd.aspirate('A2', 100), - dispense('B1', 200), - // Trash the disposal volume - cmd.blowout(), - - // Mix in the dest well - ...tripleMix('B1', 52, 'destPlateId'), - - cmd.aspirate('A3', 130), // includes disposal volume - cmd.aspirate('A4', 100), - dispense('B1', 200), - // Trash the disposal volume - cmd.blowout(), - - // Mix in the dest well - ...tripleMix('B1', 52, 'destPlateId'), - ]) - expect(result.robotState).toMatchObject(robotStatePickedUpOneTipNoLiquidState) - }) - test('"pre-wet tip" should aspirate and dispense consolidate volume from first well of each chunk', () => { // TODO LATER Ian 2018-02-13 Should it be 2/3 max volume instead? const data = { @@ -531,7 +464,6 @@ describe('consolidate single-channel', () => { expect(result.errors[0].type).toEqual('PIPETTE_DOES_NOT_EXIST') }) - test('delay after dispense') // TODO Ian 2018-04-05 support delay in consolidate test('air gap') // TODO Ian 2018-04-05 determine air gap behavior }) @@ -559,13 +491,11 @@ describe('consolidate multi-channel', () => { preWetTip: false, touchTipAfterAspirate: false, - disposalVolume: null, mixFirstAspirate: null, touchTipAfterDispense: false, mixInDestination: null, - delayAfterDispense: null, - blowout: null, + blowoutLocation: null, } test('simple multi-channel: cols A1 A2 A3 A4 to col A12', () => { diff --git a/protocol-designer/src/step-generation/test-with-flow/delay.test.js b/protocol-designer/src/step-generation/test-with-flow/delay.test.js index 0db90d6c624..824f5c1a44f 100644 --- a/protocol-designer/src/step-generation/test-with-flow/delay.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/delay.test.js @@ -1,5 +1,5 @@ // @flow -import _delay from '../delay' +import _delay from '../commandCreators/atomic/delay' import {commandCreatorNoErrors} from './fixtures' const delay = commandCreatorNoErrors(_delay) diff --git a/protocol-designer/src/step-generation/test-with-flow/dispense.test.js b/protocol-designer/src/step-generation/test-with-flow/dispense.test.js index 1188da1ec91..eeec8fd4e20 100644 --- a/protocol-designer/src/step-generation/test-with-flow/dispense.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/dispense.test.js @@ -4,7 +4,7 @@ import { commandCreatorNoErrors, commandCreatorHasErrors, } from './fixtures' -import _dispense from '../dispense' +import _dispense from '../commandCreators/atomic/dispense' import updateLiquidState from '../dispenseUpdateLiquidState' @@ -22,7 +22,7 @@ describe('dispense', () => { destPlateType: '96-flat', fillTiprackTips: true, fillPipetteTips: false, - tipracks: [200, 200], + tipracks: [300, 300], }) robotStateWithTip = { @@ -43,22 +43,69 @@ describe('dispense', () => { }) describe('tip tracking & commands:', () => { - test('dispense with tip', () => { - const result = dispense({ + describe('dispense normally (with tip)', () => { + const optionalArgsCases = [ + { + description: 'no optional args', + expectInParams: false, + args: {}, + }, + { + description: 'null optional args', + expectInParams: false, + args: { + offsetFromBottomMm: null, + 'flow-rate': null, + }, + }, + { + description: 'all optional args', + expectInParams: true, + args: { + offsetFromBottomMm: 5, + 'flow-rate': 6, + }, + }, + ] + optionalArgsCases.forEach(testCase => { + test(testCase.description, () => { + const result = dispense({ + pipette: 'p300SingleId', + volume: 50, + labware: 'sourcePlateId', + well: 'A1', + ...testCase.args, + })(robotStateWithTip) + + expect(result.commands).toEqual([{ + command: 'dispense', + params: { + pipette: 'p300SingleId', + volume: 50, + labware: 'sourcePlateId', + well: 'A1', + ...(testCase.expectInParams ? testCase.args : {}), + }, + }]) + }) + }) + }) + + test('dispense normally (with tip) and optional args', () => { + const args = { pipette: 'p300SingleId', volume: 50, labware: 'sourcePlateId', well: 'A1', - })(robotStateWithTip) + offsetFromBottomMm: 5, + 'flow-rate': 6, + } + + const result = dispense(args)(robotStateWithTip) expect(result.commands).toEqual([{ command: 'dispense', - params: { - pipette: 'p300SingleId', - volume: 50, - labware: 'sourcePlateId', - well: 'A1', - }, + params: args, }]) }) diff --git a/protocol-designer/src/step-generation/test-with-flow/distribute.test.js b/protocol-designer/src/step-generation/test-with-flow/distribute.test.js index 6e502fa47c4..53c59ea547d 100644 --- a/protocol-designer/src/step-generation/test-with-flow/distribute.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/distribute.test.js @@ -1,5 +1,5 @@ // @flow -import _distribute from '../distribute' +import _distribute from '../commandCreators/compound/distribute' // import merge from 'lodash/merge' import { createRobotState, @@ -39,13 +39,12 @@ beforeEach(() => { mixBeforeAspirate: null, touchTipAfterDispense: false, - delayAfterDispense: null, } robotInitialState = createRobotState({ sourcePlateType: '96-flat', destPlateType: '96-flat', - tipracks: [200], + tipracks: [300], fillPipetteTips: true, fillTiprackTips: true, }) @@ -53,7 +52,7 @@ beforeEach(() => { robotInitialStatePipettesLackTips = createRobotState({ sourcePlateType: '96-flat', destPlateType: '96-flat', - tipracks: [200], + tipracks: [300], fillPipetteTips: true, fillTiprackTips: false, }) @@ -491,9 +490,6 @@ describe('distribute volume exceeds pipette max volume', () => { dispense('A2', 50), // A2 done, move to A3 - cmd.dropTip('A1'), - cmd.pickUpTip('B1'), - cmd.aspirate('A1', 300), dispense('A3', 300), cmd.aspirate('A1', 50), diff --git a/protocol-designer/src/step-generation/test-with-flow/dropAllTips.test.js b/protocol-designer/src/step-generation/test-with-flow/dropAllTips.test.js index 3c5b8d624ca..70ca79bf6d1 100644 --- a/protocol-designer/src/step-generation/test-with-flow/dropAllTips.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/dropAllTips.test.js @@ -1,7 +1,7 @@ // @flow import type {RobotState} from '../types' import {createRobotState, commandCreatorNoErrors} from './fixtures' -import _dropAllTips from '../dropAllTips' +import _dropAllTips from '../commandCreators/atomic/dropAllTips' const dropAllTips = commandCreatorNoErrors(_dropAllTips) @@ -16,7 +16,7 @@ beforeEach(() => { destPlateType: '96-flat', fillTiprackTips: true, fillPipetteTips: false, - tipracks: [200, 200], + tipracks: [300, 300], }) }) diff --git a/protocol-designer/src/step-generation/test-with-flow/dropTip.test.js b/protocol-designer/src/step-generation/test-with-flow/dropTip.test.js index 8d49dc14f12..9c34d0cf0bb 100644 --- a/protocol-designer/src/step-generation/test-with-flow/dropTip.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/dropTip.test.js @@ -1,7 +1,7 @@ // @flow import merge from 'lodash/merge' import {createRobotState, commandCreatorNoErrors} from './fixtures' -import _dropTip from '../dropTip' +import _dropTip from '../commandCreators/atomic/dropTip' import updateLiquidState from '../dispenseUpdateLiquidState' @@ -19,7 +19,7 @@ describe('dropTip', () => { destPlateType: '96-flat', fillTiprackTips: true, fillPipetteTips: false, - tipracks: [200, 200], + tipracks: [300, 300], }) robotStateWithTip = { @@ -45,7 +45,7 @@ describe('dropTip', () => { createRobotState({ sourcePlateType: 'trough-12row', destPlateType: '96-flat', - tipracks: [200, 200], + tipracks: [300, 300], fillPipetteTips: false, fillTiprackTips: true, }), diff --git a/protocol-designer/src/step-generation/test-with-flow/fixtureGeneration.test.js b/protocol-designer/src/step-generation/test-with-flow/fixtureGeneration.test.js index 8e46aafe34c..d32ef0e806c 100644 --- a/protocol-designer/src/step-generation/test-with-flow/fixtureGeneration.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/fixtureGeneration.test.js @@ -49,7 +49,7 @@ describe('createRobotState fixture generator', () => { destPlateType: '96-flat', fillPipetteTips: false, fillTiprackTips, - tipracks: [200, 200], + tipracks: [300, 300], }) const tiprackIds = ['tiprack1Id', 'tiprack2Id'] @@ -70,7 +70,7 @@ describe('createRobotState fixture generator', () => { destPlateType: '96-flat', fillPipetteTips, fillTiprackTips: true, - tipracks: [200, 200], + tipracks: [300, 300], }) const pipetteIds = ['p300SingleId', 'p300MultiId'] diff --git a/protocol-designer/src/step-generation/test-with-flow/fixtures/commandFixtures.js b/protocol-designer/src/step-generation/test-with-flow/fixtures/commandFixtures.js index 31a4a64d66b..52dac99c863 100644 --- a/protocol-designer/src/step-generation/test-with-flow/fixtures/commandFixtures.js +++ b/protocol-designer/src/step-generation/test-with-flow/fixtures/commandFixtures.js @@ -1,6 +1,6 @@ // @flow import {tiprackWellNamesFlat} from '../../data' -import type {Command} from '../../types' +import type {AspirateDispenseArgs, Command} from '../../types' export const replaceTipCommands = (tip: number | string): Array => [ dropTip('A1'), @@ -8,14 +8,14 @@ export const replaceTipCommands = (tip: number | string): Array => [ ] export const dropTip = ( - tip: number | string, // TODO IMMEDIATELY should this be well?: string & default to A1? + well: string, params?: {| pipette?: string, labware?: string |} ): Command => ({ command: 'drop-tip', params: { pipette: 'p300SingleId', labware: 'trashId', - well: (typeof tip === 'string') ? tip : tiprackWellNamesFlat[tip], + well: (typeof well === 'string') ? well : tiprackWellNamesFlat[well], ...params, }, }) @@ -49,10 +49,7 @@ export const touchTip = ( export const aspirate = ( well: string, volume: number, - params?: {| - pipette?: string, - labware?: string, - |} + params?: $Shape ): Command => ({ command: 'aspirate', params: { @@ -67,10 +64,7 @@ export const aspirate = ( export const dispense = ( well: string, volume: number, - params?: {| - pipette?: string, - labware?: string, - |} + params?: $Shape ): Command => ({ command: 'dispense', params: { diff --git a/protocol-designer/src/step-generation/test-with-flow/fixtures/fixtures.js b/protocol-designer/src/step-generation/test-with-flow/fixtures/fixtures.js index 4e90150df70..1977d46d180 100644 --- a/protocol-designer/src/step-generation/test-with-flow/fixtures/fixtures.js +++ b/protocol-designer/src/step-generation/test-with-flow/fixtures/fixtures.js @@ -83,6 +83,7 @@ export const p300Single = { id: 'p300SingleId', mount: 'right', model: 'p300_single_v1', + tiprackModel: 'opentrons-tiprack-300ul', maxVolume: 300, channels: 1, } @@ -91,6 +92,7 @@ export const p300Multi = { id: 'p300MultiId', mount: 'left', model: 'p300_multi_v1', + tiprackModel: 'opentrons-tiprack-300ul', maxVolume: 300, channels: 8, } @@ -144,8 +146,8 @@ type RobotStateNoLiquidState = $Diff type CreateRobotArgs = { sourcePlateType: string, destPlateType?: string, - tipracks: Array<10 | 200 | 1000>, - fillPipetteTips?: boolean, + tipracks: Array<10 | 200 | 300 | 1000>, + fillPipetteTips: boolean, fillTiprackTips?: boolean, } /** RobotState with empty liquid state */ @@ -163,6 +165,20 @@ export function createRobotState (args: CreateRobotArgs): RobotState { } } +function getTiprackType (volume: number): string { + const tiprackMap = { + '1000': 'tiprack-1000ul', + '300': 'opentrons-tiprack-300ul', + '200': 'tiprack-200ul', + '10': 'tiprack-10ul', + } + const result = tiprackMap[volume] + if (!result) { + throw new Error(`No tiprack in getTiprackType for tiprack volume: ${volume}`) + } + return result +} + /** RobotState without liquidState key, for use with jest's `toMatchObject` */ export function createRobotStateFixture (args: CreateRobotArgs): RobotStateNoLiquidState { function _getTiprackSlot (tiprackIndex: number, occupiedSlots: Array): string { @@ -204,14 +220,16 @@ export function createRobotStateFixture (args: CreateRobotArgs): RobotStateNoLiq const occupiedSlots = map(baseLabware, (labwareData: LabwareData, labwareId) => labwareData.slot) - const tiprackLabware = args.tipracks.reduce((acc, tiprackVolume, tiprackIndex) => ({ - ...acc, - [`tiprack${tiprackIndex + 1}Id`]: { - slot: _getTiprackSlot(tiprackIndex, occupiedSlots), - type: `tiprack-${tiprackVolume}ul`, - name: `Tip rack ${tiprackIndex + 1}`, - }, - }), {}) + const tiprackLabware = args.tipracks.reduce((acc, tiprackVolume, tiprackIndex) => { + return { + ...acc, + [`tiprack${tiprackIndex + 1}Id`]: { + slot: _getTiprackSlot(tiprackIndex, occupiedSlots), + type: getTiprackType(tiprackVolume), + name: `Tip rack ${tiprackIndex + 1}`, + }, + } + }, {}) return { instruments, @@ -227,8 +245,8 @@ export function createRobotStateFixture (args: CreateRobotArgs): RobotStateNoLiq [tiprackId]: getTiprackTipstate(args.fillTiprackTips), }), {}), pipettes: { - p300SingleId: !!args.fillPipetteTips, - p300MultiId: !!args.fillPipetteTips, + p300SingleId: args.fillPipetteTips, + p300MultiId: args.fillPipetteTips, }, }, } diff --git a/protocol-designer/src/step-generation/test-with-flow/getNextRobotStateAndWarnings.test.js b/protocol-designer/src/step-generation/test-with-flow/getNextRobotStateAndWarnings.test.js new file mode 100644 index 00000000000..a767e7c2453 --- /dev/null +++ b/protocol-designer/src/step-generation/test-with-flow/getNextRobotStateAndWarnings.test.js @@ -0,0 +1,35 @@ +// @flow +import getNextRobotStateAndWarnings from '../getNextRobotStateAndWarnings' +import forAspirateDispense from '../getNextRobotStateAndWarnings/forAspirateDispense' +import { + createRobotState, + commandCreatorNoErrors, +} from './fixtures' + +import _aspirate from '../commandCreators/atomic/aspirate' + +const aspirate = commandCreatorNoErrors(_aspirate) + +jest.mock('../getNextRobotStateAndWarnings/forAspirateDispense') + +describe('Aspirate Command', () => { + test('aspirate from single-ingredient well', () => { + const prevRobotState = createRobotState({ + sourcePlateType: 'trough-12row', + destPlateType: '96-flat', + fillTiprackTips: true, + fillPipetteTips: true, + tipracks: [300, 300], + }) + const args = { + pipette: 'p300SingleId', + labware: 'sourcePlateId', + well: 'A1', + volume: 152, + } + const command = aspirate(args)(prevRobotState).commands[0] + getNextRobotStateAndWarnings(command, prevRobotState) + + expect(forAspirateDispense).toHaveBeenCalledWith(command.params, prevRobotState) + }) +}) diff --git a/protocol-designer/src/step-generation/test-with-flow/aspirateUpdateLiquidState.test.js b/protocol-designer/src/step-generation/test-with-flow/getNextRobotStateAndWarningsForAspDisp.test.js similarity index 75% rename from protocol-designer/src/step-generation/test-with-flow/aspirateUpdateLiquidState.test.js rename to protocol-designer/src/step-generation/test-with-flow/getNextRobotStateAndWarningsForAspDisp.test.js index f8d0c0b2d3b..cfbfe701e18 100644 --- a/protocol-designer/src/step-generation/test-with-flow/aspirateUpdateLiquidState.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/getNextRobotStateAndWarningsForAspDisp.test.js @@ -1,13 +1,14 @@ // @flow import {AIR} from '../utils' import { + createRobotState, createEmptyLiquidState, createTipLiquidState, p300Single, p300Multi, } from './fixtures' -import updateLiquidState from '../aspirateUpdateLiquidState' +import forAspirateDispense from '../getNextRobotStateAndWarnings/forAspirateDispense' function getBlankLiquidState (sourcePlateType: ?string) { return createEmptyLiquidState({ @@ -25,13 +26,20 @@ function getBlankLiquidState (sourcePlateType: ?string) { describe('...single-channel pipette', () => { let aspirateSingleCh50FromA1Args + let initialRobotState beforeEach(() => { + initialRobotState = createRobotState({ + sourcePlateType: 'trough-12row', + destPlateType: '96-flat', + fillPipetteTips: false, + fillTiprackTips: true, + tipracks: [300, 300], + }) + aspirateSingleCh50FromA1Args = { - labwareId: 'sourcePlateId', - labwareType: '96-flat', - pipetteId: 'p300SingleId', - pipetteData: p300Single, + labware: 'sourcePlateId', + pipette: 'p300SingleId', volume: 50, well: 'A1', } @@ -45,12 +53,12 @@ describe('...single-channel pipette', () => { }, } - const result = updateLiquidState( + const result = forAspirateDispense( aspirateSingleCh50FromA1Args, - initialLiquidState + {...initialRobotState, liquidState: initialLiquidState}, ) - expect(result.liquidState).toMatchObject({ + expect(result.robotState.liquidState).toMatchObject({ pipettes: { p300SingleId: { '0': {ingred1: {volume: 50}}, @@ -80,12 +88,12 @@ describe('...single-channel pipette', () => { volume: 300, } - const result = updateLiquidState( + const result = forAspirateDispense( args, - initialLiquidState + {...initialRobotState, liquidState: initialLiquidState}, ) - expect(result.liquidState).toMatchObject({ + expect(result.robotState.liquidState).toMatchObject({ pipettes: { p300SingleId: { '0': {ingred1: {volume: 200}, [AIR]: {volume: 100}}, @@ -113,9 +121,12 @@ describe('...single-channel pipette', () => { volume: 60, } - const result = updateLiquidState(args, initialLiquidState) + const result = forAspirateDispense( + args, + {...initialRobotState, liquidState: initialLiquidState}, + ) - expect(result.liquidState).toMatchObject({ + expect(result.robotState.liquidState).toMatchObject({ pipettes: { p300SingleId: { '0': {ingred1: {volume: 40}, ingred2: {volume: 20}}, @@ -141,9 +152,12 @@ describe('...single-channel pipette', () => { volume: 150, } - const result = updateLiquidState(args, initialLiquidState) + const result = forAspirateDispense( + args, + {...initialRobotState, liquidState: initialLiquidState}, + ) - expect(result.liquidState).toMatchObject({ + expect(result.robotState.liquidState).toMatchObject({ pipettes: { p300SingleId: { '0': {ingred1: {volume: 60}, ingred2: {volume: 70}, [AIR]: {volume: 20}}, @@ -168,9 +182,12 @@ describe('...single-channel pipette', () => { ingred1: {volume: 30}, } - const result = updateLiquidState(aspirateSingleCh50FromA1Args, initialLiquidState) + const result = forAspirateDispense( + aspirateSingleCh50FromA1Args, + {...initialRobotState, liquidState: initialLiquidState}, + ) - expect(result.liquidState).toMatchObject({ + expect(result.robotState.liquidState).toMatchObject({ pipettes: { p300SingleId: { '0': {ingred1: {volume: 30 + 50}}, @@ -188,13 +205,16 @@ describe('...single-channel pipette', () => { describe('...8-channel pipette', () => { let aspirate8Ch50FromA1Args + let initialRobotState beforeEach(() => { + initialRobotState = createRobotState({ + sourcePlateType: '96-flat', + tipracks: [300, 300], + }) aspirate8Ch50FromA1Args = { - labwareId: 'sourcePlateId', - labwareType: '96-flat', - pipetteId: 'p300MultiId', - pipetteData: p300Multi, + labware: 'sourcePlateId', + pipette: 'p300MultiId', volume: 50, well: 'A1', } @@ -215,9 +235,11 @@ describe('...8-channel pipette', () => { {ingred1: {volume: 30}} ) - const result = updateLiquidState(aspirate8Ch50FromA1Args, initialLiquidState) - - expect(result.liquidState).toMatchObject({ + const result = forAspirateDispense( + aspirate8Ch50FromA1Args, + {...initialRobotState, liquidState: initialLiquidState}, + ) + expect(result.robotState.liquidState).toMatchObject({ pipettes: { p300MultiId: { ...createTipLiquidState(8, {[AIR]: {volume: 50}, ingred1: {volume: 30}}), @@ -249,9 +271,12 @@ describe('...8-channel pipette', () => { volume: 250, } - const result = updateLiquidState(args, initialLiquidState) + const result = forAspirateDispense( + args, + {...initialRobotState, liquidState: initialLiquidState}, + ) - expect(result.liquidState).toMatchObject({ + expect(result.robotState.liquidState).toMatchObject({ pipettes: { p300MultiId: { ...createTipLiquidState(8, {[AIR]: {volume: 250}}), @@ -271,6 +296,10 @@ describe('...8-channel pipette', () => { test('aspirate from single-ingredient common well (trough-12row)', () => { let initialLiquidState = getBlankLiquidState('trough-12row') + const initialTroughRobotState = createRobotState({ + sourcePlateType: 'trough-12row', + tipracks: [300, 300], + }) const initialSourceVolume = 300 const aspirateVolume = 20 @@ -281,13 +310,14 @@ describe('...8-channel pipette', () => { const args = { ...aspirate8Ch50FromA1Args, - labwareType: 'trough-12row', volume: aspirateVolume, } - const result = updateLiquidState(args, initialLiquidState) - - expect(result.liquidState).toMatchObject({ + const result = forAspirateDispense( + args, + {...initialTroughRobotState, liquidState: initialLiquidState}, + ) + expect(result.robotState.liquidState).toMatchObject({ pipettes: { p300MultiId: { // aspirate volume divided among the 8 tips diff --git a/protocol-designer/src/step-generation/test-with-flow/mix.test.js b/protocol-designer/src/step-generation/test-with-flow/mix.test.js index 0c8c008b535..2e124b7a682 100644 --- a/protocol-designer/src/step-generation/test-with-flow/mix.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/mix.test.js @@ -1,5 +1,5 @@ // @flow -import _mix from '../mix' +import _mix from '../commandCreators/compound/mix' import { createRobotState, compoundCommandCreatorNoErrors, @@ -17,7 +17,7 @@ beforeEach(() => { robotInitialState = createRobotState({ sourcePlateType: '96-flat', destPlateType: '96-flat', - tipracks: [200], + tipracks: [300], fillPipetteTips: true, fillTiprackTips: true, }) @@ -30,7 +30,7 @@ beforeEach(() => { pipette: 'p300SingleId', labware: 'sourcePlateId', - delay: null, + blowoutLocation: null, touchTip: false, } }) @@ -130,6 +130,43 @@ describe('mix: advanced options', () => { const times = 2 const blowoutLabwareId = 'destPlateId' + test('flow rate', () => { + const ASPIRATE_OFFSET = 11 + const DISPENSE_OFFSET = 12 + const ASPIRATE_FLOW_RATE = 3 + const DISPENSE_FLOW_RATE = 6 + const args: MixFormData = { + ...mixinArgs, + volume, + times, + wells: ['A1'], + changeTip: 'once', + aspirateOffsetFromBottomMm: ASPIRATE_OFFSET, + dispenseOffsetFromBottomMm: DISPENSE_OFFSET, + aspirateFlowRateUlSec: ASPIRATE_FLOW_RATE, + dispenseFlowRateUlSec: DISPENSE_FLOW_RATE, + } + + const aspirateParams = { + 'flow-rate': ASPIRATE_FLOW_RATE, + offsetFromBottomMm: ASPIRATE_OFFSET, + } + const dispenseParams = { + 'flow-rate': DISPENSE_FLOW_RATE, + offsetFromBottomMm: DISPENSE_OFFSET, + } + + const result = mix(args)(robotInitialState) + expect(result.commands).toEqual([ + ...cmd.replaceTipCommands(0), + {...cmd.aspirate('A1', volume, aspirateParams)}, + {...cmd.dispense('A1', volume, dispenseParams)}, + + {...cmd.aspirate('A1', volume, aspirateParams)}, + {...cmd.dispense('A1', volume, dispenseParams)}, + ]) + }) + test('touch tip (after each dispense)', () => { const args: MixFormData = { ...mixinArgs, @@ -138,6 +175,10 @@ describe('mix: advanced options', () => { changeTip: 'always', touchTip: true, wells: ['A1', 'B1', 'C1'], + aspirateOffsetFromBottomMm: null, + dispenseOffsetFromBottomMm: null, + aspirateFlowRateUlSec: null, + dispenseFlowRateUlSec: null, } const result = mix(args)(robotInitialState) @@ -175,7 +216,7 @@ describe('mix: advanced options', () => { volume, times, changeTip: 'always', - blowout: blowoutLabwareId, + blowoutLocation: blowoutLabwareId, wells: ['A1', 'B1', 'C1'], } @@ -214,8 +255,8 @@ describe('mix: advanced options', () => { volume, times, changeTip: 'always', + blowoutLocation: blowoutLabwareId, touchTip: true, - blowout: blowoutLabwareId, wells: ['A1', 'B1', 'C1'], } @@ -250,8 +291,6 @@ describe('mix: advanced options', () => { cmd.touchTip('C1'), ]) }) - - test.skip('delay') // TODO Ian 2018-05-08 implement when behavior is decided }) describe('mix: errors', () => { diff --git a/protocol-designer/src/step-generation/test-with-flow/replaceTip.test.js b/protocol-designer/src/step-generation/test-with-flow/replaceTip.test.js index 24ae67f58ac..0a2125cdb37 100644 --- a/protocol-designer/src/step-generation/test-with-flow/replaceTip.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/replaceTip.test.js @@ -7,7 +7,7 @@ import { commandCreatorNoErrors, commandFixtures as cmd, } from './fixtures' -import _replaceTip from '../replaceTip' +import _replaceTip from '../commandCreators/atomic/replaceTip' import updateLiquidState from '../dispenseUpdateLiquidState' @@ -33,7 +33,7 @@ describe('replaceTip', () => { ...labwareTypes1, fillTiprackTips: true, fillPipetteTips: false, - tipracks: [200, 200], + tipracks: [300, 300], }) // $FlowFixMe: mock methods @@ -335,80 +335,4 @@ describe('replaceTip', () => { )) }) }) - - describe('tip assignment', () => { - let firstTiprackAssignedState - let twoTipracksAssignedState - - beforeEach(() => { - firstTiprackAssignedState = { - [tiprack1Id]: p300MultiId, - } - - twoTipracksAssignedState = { - [tiprack1Id]: p300MultiId, - [tiprack2Id]: p300MultiId, - } - }) - - test('initial assignment (no tiprackAssignment key)', () => { - const result = replaceTip(p300MultiId)(robotInitialState) - - expect(result.robotState.tiprackAssignment).toEqual(firstTiprackAssignedState) - - expect(result.commands[0].params).toEqual({ - labware: tiprack1Id, - pipette: p300MultiId, - well: 'A1', - }) - }) - - test('use same non-empty tiprack that was already assigned to selected pipette', () => { - robotInitialState.tiprackAssignment = {...firstTiprackAssignedState} - - const result = replaceTip(p300MultiId)(robotInitialState) - - expect(result.robotState.tiprackAssignment).toEqual({...firstTiprackAssignedState}) - - expect(result.commands[0].params).toEqual({ - labware: tiprack1Id, - pipette: p300MultiId, - well: 'A1', - }) - }) - - test('get next unassigned tiprack when assigned is empty', () => { - // first tiprack was previously assigned to our pipette (p300Multi) - robotInitialState.tiprackAssignment = {...firstTiprackAssignedState} - // but it's empty - robotInitialState.tipState.tipracks[tiprack1Id] = getTiprackTipstate(false) - - const result = replaceTip(p300MultiId)(robotInitialState) - - expect(result.robotState.tiprackAssignment).toEqual({...twoTipracksAssignedState}) - - expect(result.commands[0].params).toEqual({ - labware: tiprack2Id, - pipette: p300MultiId, - well: 'A1', - }) - }) - - test('skip full tiprack when it is assigned to a different pipette', () => { - robotInitialState.tiprackAssignment = {...firstTiprackAssignedState} - - const result = replaceTip(p300SingleId)(robotInitialState) - - expect(result.robotState.tiprackAssignment).toEqual({ - ...firstTiprackAssignedState, - [tiprack2Id]: p300SingleId, - }) - - expect(result.commands[0].params).toEqual({ - labware: tiprack2Id, - pipette: p300SingleId, - well: 'A1', - }) - }) - }) }) diff --git a/protocol-designer/src/step-generation/test-with-flow/robotStateSelectors.test.js b/protocol-designer/src/step-generation/test-with-flow/robotStateSelectors.test.js index aa3b35525fd..25d0f7b9966 100644 --- a/protocol-designer/src/step-generation/test-with-flow/robotStateSelectors.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/robotStateSelectors.test.js @@ -1,6 +1,6 @@ // @flow import {p300Single, p300Multi, createEmptyLiquidState, getTiprackTipstate, getTipColumn} from './fixtures' -import {sortLabwareBySlot, getNextTiprack, tiprackIsAvailableToPipette, _getNextTip} from '../' +import {sortLabwareBySlot, getNextTiprack, _getNextTip} from '../' // just a blank liquidState to appease flow const basicLiquidState = { @@ -26,12 +26,12 @@ describe('sortLabwareBySlot', () => { }, one: { slot: '1', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack', }, eleven: { slot: '11', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack', }, two: { @@ -127,7 +127,7 @@ describe('getNextTiprack - single-channel', () => { labware: { tiprack2Id: { slot: '2', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 2', }, sourcePlateId: { @@ -212,12 +212,12 @@ describe('getNextTiprack - single-channel', () => { labware: { tiprack2Id: { slot: '2', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 2', }, tiprack11Id: { slot: '11', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 11', }, sourcePlateId: { @@ -267,12 +267,12 @@ describe('getNextTiprack - single-channel', () => { labware: { tiprack2Id: { slot: '2', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 2', }, tiprack11Id: { slot: '11', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 11', }, sourcePlateId: { @@ -324,12 +324,12 @@ describe('getNextTiprack - single-channel', () => { labware: { tiprack2Id: { slot: '2', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 2', }, tiprack11Id: { slot: '11', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 11', }, sourcePlateId: { @@ -380,7 +380,7 @@ describe('getNextTiprack - 8-channel', () => { labware: { tiprack2Id: { slot: '2', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 2', }, sourcePlateId: { @@ -425,7 +425,7 @@ describe('getNextTiprack - 8-channel', () => { labware: { tiprack2Id: { slot: '2', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 2', }, sourcePlateId: { @@ -511,7 +511,7 @@ describe('getNextTiprack - 8-channel', () => { labware: { tiprack2Id: { slot: '2', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 2', }, sourcePlateId: { @@ -569,17 +569,17 @@ describe('getNextTiprack - 8-channel', () => { labware: { tiprack2Id: { slot: '2', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 2', }, tiprack3Id: { slot: '3', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 3', }, tiprack10Id: { slot: '10', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 10', }, sourcePlateId: { @@ -632,17 +632,17 @@ describe('getNextTiprack - 8-channel', () => { labware: { tiprack2Id: { slot: '2', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 2', }, tiprack3Id: { slot: '3', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 3', }, tiprack10Id: { slot: '10', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 10', }, sourcePlateId: { @@ -665,7 +665,7 @@ describe('getNextTiprack - 8-channel', () => { tipracks: { tiprack2Id: { ...getTiprackTipstate(true), - // empty diagona, 8-channel cannot use + // empty diagonal, 8-channel cannot use F1: false, B2: false, C3: false, @@ -722,17 +722,17 @@ describe('getNextTiprack - 8-channel', () => { labware: { tiprack2Id: { slot: '2', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 2', }, tiprack3Id: { slot: '3', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 3', }, tiprack10Id: { slot: '10', - type: 'tiprack-200uL', + type: 'opentrons-tiprack-300ul', name: 'Tip rack 10', }, sourcePlateId: { @@ -811,55 +811,3 @@ describe('getNextTiprack - 8-channel', () => { expect(result).toEqual(null) }) }) - -describe('tiprackIsAvailableToPipette', () => { - let pipette - let tiprack - const tiprackModel = 'tiprack-200uL' - const pipetteId = 'pipetteId' - - beforeEach(() => { - pipette = { - channels: 1, - id: pipetteId, - maxVolume: 300, - model: 'some-model', - mount: 'left', - tiprackModel, - } - - tiprack = { - name: 'Tiprack', - type: tiprackModel, - slot: '1', - } - }) - test('tiprack unassigned, can use', () => { - const unassignedValues = [undefined, null] - - unassignedValues.forEach(tiprackAssignment => { - expect( - tiprackIsAvailableToPipette(pipette, tiprack, tiprackAssignment) - ).toBe(true) - }) - }) - - test('tiprack already assigned to current pipette, can use', () => { - expect( - tiprackIsAvailableToPipette(pipette, tiprack, pipetteId) - ).toBe(true) - }) - - test('tiprack assigned to different pipette, cannot use', () => { - expect( - tiprackIsAvailableToPipette(pipette, tiprack, 'differentPipetteId') - ).toBe(false) - }) - - test('tiprack unassigned but of wrong type, cannot use', () => { - pipette.tiprackModel = 'tiprack-wrong-type' - expect( - tiprackIsAvailableToPipette(pipette, tiprack, pipetteId) - ).toBe(false) - }) -}) diff --git a/protocol-designer/src/step-generation/test-with-flow/testMatchers.js b/protocol-designer/src/step-generation/test-with-flow/testMatchers.js new file mode 100644 index 00000000000..3fb31e6f973 --- /dev/null +++ b/protocol-designer/src/step-generation/test-with-flow/testMatchers.js @@ -0,0 +1,10 @@ +// error of type exists somewhere in timeline errors +export function expectTimelineError (errors, errorType) { + expect(errors).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + type: errorType, + }), + ]) + ) +} diff --git a/protocol-designer/src/step-generation/test-with-flow/touchTip.test.js b/protocol-designer/src/step-generation/test-with-flow/touchTip.test.js index c66fb2dc483..59d5323494c 100644 --- a/protocol-designer/src/step-generation/test-with-flow/touchTip.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/touchTip.test.js @@ -1,5 +1,6 @@ // @flow -import _touchTip from '../touchTip' +import {expectTimelineError} from './testMatchers' +import _touchTip from '../commandCreators/atomic/touchTip' import { createRobotState, commandCreatorNoErrors, @@ -15,7 +16,7 @@ describe('touchTip', () => { destPlateType: '96-flat', fillTiprackTips: true, fillPipetteTips: false, - tipracks: [200, 200], + tipracks: [300, 300], } const initialRobotState = createRobotState(_robotFixtureArgs) const robotStateWithTip = createRobotState({..._robotFixtureArgs, fillPipetteTips: true}) @@ -67,10 +68,7 @@ describe('touchTip', () => { well: 'A1', })(robotStateWithTip) - expect(result.errors).toEqual([{ - message: 'Attempted to touchTip with pipette id "badPipette", this pipette was not found under "instruments"', - type: 'PIPETTE_DOES_NOT_EXIST', - }]) + expectTimelineError(result.errors, 'PIPETTE_DOES_NOT_EXIST') }) test('touchTip with no tip should throw error', () => { diff --git a/protocol-designer/src/step-generation/test-with-flow/transfer.test.js b/protocol-designer/src/step-generation/test-with-flow/transfer.test.js index f479e9aaf33..f4d22bb3de1 100644 --- a/protocol-designer/src/step-generation/test-with-flow/transfer.test.js +++ b/protocol-designer/src/step-generation/test-with-flow/transfer.test.js @@ -6,7 +6,7 @@ import { compoundCommandCreatorHasErrors, commandFixtures as cmd, } from './fixtures' -import _transfer from '../transfer' +import _transfer from '../commandCreators/compound/transfer' const transfer = compoundCommandCreatorNoErrors(_transfer) const transferWithErrors = compoundCommandCreatorHasErrors(_transfer) @@ -26,19 +26,17 @@ beforeEach(() => { preWetTip: false, touchTipAfterAspirate: false, - disposalVolume: null, mixBeforeAspirate: null, touchTipAfterDispense: false, mixInDestination: null, - delayAfterDispense: null, - blowout: null, + blowoutLocation: null, } robotInitialState = createRobotState({ sourcePlateType: '96-flat', destPlateType: '96-flat', - tipracks: [200], + tipracks: [300], fillPipetteTips: true, fillTiprackTips: true, }) @@ -405,7 +403,6 @@ describe('advanced options', () => { ]) }) test('air gap => ???') // TODO determine behavior - test('disposal volume => ???') // TODO determine behavior }) describe('...dispense options', () => { @@ -441,57 +438,6 @@ describe('advanced options', () => { ]) }) - test.skip('delay after dispense', () => { // TODO Ian 2018-04-05 support delay in transfer. REMOVE SKIP - transferArgs = { - ...transferArgs, - volume: 350, - delayAfterDispense: 100, - } - - const result = transfer(transferArgs)(robotInitialState) - - const delayCommand = { - command: 'delay', - params: { - wait: 100, - message: null, - }, - } - - expect(result.commands).toEqual([ - { - command: 'aspirate', - labware: 'sourcePlateId', - pipette: 'p300SingleId', - volume: 300, - well: 'A1', - }, - { - command: 'dispense', - labware: 'destPlateId', - pipette: 'p300SingleId', - volume: 300, - well: 'B1', - }, - delayCommand, - - { - command: 'aspirate', - labware: 'sourcePlateId', - pipette: 'p300SingleId', - volume: 50, - well: 'A1', - }, - { - command: 'dispense', - labware: 'destPlateId', - pipette: 'p300SingleId', - volume: 50, - well: 'B1', - }, - delayCommand, - ]) - }) test('blowout should blowout in specified labware after each dispense') // TODO }) }) diff --git a/protocol-designer/src/step-generation/types.js b/protocol-designer/src/step-generation/types.js index f14187f73f4..2844d7caec1 100644 --- a/protocol-designer/src/step-generation/types.js +++ b/protocol-designer/src/step-generation/types.js @@ -34,18 +34,22 @@ export type TransferLikeFormDataFields = { preWetTip: boolean, /** Touch tip after every aspirate */ touchTipAfterAspirate: boolean, + /** Optional offset for touch tip after aspirate (if null, use PD default) */ + touchTipAfterAspirateOffsetMmFromBottom?: ?number, /** changeTip is interpreted differently by different Step types */ changeTip: ChangeTipOptions, - /** Disposal volume is added to the volume of the first aspirate of each asp-asp-disp cycle */ - disposalVolume: ?number, + /** Flow rate in uL/sec for all aspirates */ + aspirateFlowRateUlSec?: ?number, /** offset from bottom of well in mm */ aspirateOffsetFromBottomMm?: ?number, // ===== DISPENSE SETTINGS ===== /** Touch tip in destination well after dispense */ touchTipAfterDispense: boolean, - /** Number of seconds to delay at the very end of the step (TODO: or after each dispense ?) */ - delayAfterDispense: ?number, + /** Optional offset for touch tip after dispense (if null, use PD default) */ + touchTipAfterDispenseOffsetMmFromBottom?: ?number, + /** Flow rate in uL/sec for all dispenses */ + dispenseFlowRateUlSec?: ?number, /** offset from bottom of well in mm */ dispenseOffsetFromBottomMm?: ?number, } @@ -56,8 +60,9 @@ export type ConsolidateFormData = { sourceWells: Array, destWell: string, - /** If given, blow out in the specified labware after dispense at the end of each asp-asp-dispense cycle */ - blowout: ?string, // TODO LATER LabwareId export type here instead of string? + /** If given, blow out in the specified destination after dispense at the end of each asp-asp-dispense cycle */ + blowoutLocation: ?string, + /** Mix in first well in chunk */ mixFirstAspirate: ?MixArgs, /** Mix in destination well after dispense */ @@ -70,8 +75,9 @@ export type TransferFormData = { sourceWells: Array, destWells: Array, - /** If given, blow out in the specified labware after dispense at the end of each asp-asp-dispense cycle */ - blowout: ?string, // TODO LATER LabwareId export type here instead of string? + /** If given, blow out in the specified destination after dispense at the end of each asp-dispense cycle */ + blowoutLocation: ?string, + /** Mix in first well in chunk */ mixBeforeAspirate: ?MixArgs, /** Mix in destination well after dispense */ @@ -84,6 +90,8 @@ export type DistributeFormData = { sourceWell: string, destWells: Array, + /** Disposal volume is added to the volume of the first aspirate of each asp-asp-disp cycle */ + disposalVolume: ?number, /** Disposal labware and well for final blowout destination of disposalVolume contents (e.g. trash, source well, etc.) */ disposalLabware: ?string, disposalWell: ?string, @@ -104,15 +112,19 @@ export type MixFormData = { times: number, /** Touch tip after mixing */ touchTip: boolean, - /** Delay in seconds */ - delay: ?number, + touchTipMmFromBottom?: ?number, /** change tip: see comments in step-generation/mix.js */ changeTip: ChangeTipOptions, - /** If given, blow out in the specified labware after mixing each well */ - blowout?: string, + + /** If given, blow out in the specified destination after mixing each well */ + blowoutLocation: ?string, + /** offset from bottom of well in mm */ aspirateOffsetFromBottomMm?: ?number, dispenseOffsetFromBottomMm?: ?number, + /** flow rates in uL/sec */ + aspirateFlowRateUlSec?: ?number, + dispenseFlowRateUlSec?: ?number, } export type PauseFormData = {| @@ -140,7 +152,7 @@ export type PipetteData = {| // TODO refactor all 'pipette fields', split Pipett model: string, // TODO Ian 2018-11-05 rename 'model' to 'name' when breaking change is made in JSON protocols maxVolume: number, channels: Channels, - tiprackModel?: string, // NOTE: this will go away when tiprack sharing is implemented + tiprackModel: string, // NOTE: this will go away when tiprack choice-per-step and/or tiprack sharing is implemented |} export type LabwareData = {| @@ -170,12 +182,6 @@ export type RobotState = {| labware: { [labwareId: string]: LabwareData, }, - // tiprackAssignment: maps tiprackLabwareId to its assigned PipetteId. - // Each tiprack is either unassigned, or assigned to one pipette. - // `tiprackAssignment` will go away when tiprack sharing is implemented - tiprackAssignment?: ?{ - [tiprackLabwareId: string]: ?string, - }, tipState: { tipracks: { [labwareId: string]: { @@ -183,7 +189,7 @@ export type RobotState = {| }, }, pipettes: { - [pipetteId: string]: boolean, // true if tip is on pipette + [pipetteId: string]: boolean, // true if pipette has tip(s) }, }, liquidState: { @@ -216,6 +222,7 @@ export type AspirateDispenseArgs = {| ...PipetteLabwareFields, volume: number, offsetFromBottomMm?: ?number, + 'flow-rate'?: ?number, |} export type Command = {| @@ -253,6 +260,7 @@ export type ErrorType = | 'PIPETTE_DOES_NOT_EXIST' | 'NO_TIP_ON_PIPETTE' | 'PIPETTE_VOLUME_EXCEEDED' + | 'TIP_VOLUME_EXCEEDED' export type CommandCreatorError = {| message: string, @@ -286,3 +294,8 @@ export type Timeline = {| timeline: Array, // TODO: Ian 2018-06-14 avoid timeline.timeline shape, better names errors?: ?Array, |} + +export type RobotStateAndWarnings = { + robotState: RobotState, + warnings: Array, +} diff --git a/protocol-designer/src/step-generation/utils.js b/protocol-designer/src/step-generation/utils.js index 977d10642d8..d21cce4ce2f 100644 --- a/protocol-designer/src/step-generation/utils.js +++ b/protocol-designer/src/step-generation/utils.js @@ -12,11 +12,16 @@ import type { RobotState, SourceAndDest, Timeline, + PipetteLabwareFields, } from './types' +import blowout from './commandCreators/atomic/blowout' import {AIR} from '@opentrons/components' export {AIR} +export const SOURCE_WELL_BLOWOUT_DESTINATION: 'source_well' = 'source_well' +export const DEST_WELL_BLOWOUT_DESTINATION: 'dest_well' = 'dest_well' + export function repeatArray (array: Array, repeats: number): Array { return flatMap(range(repeats), (i: number): Array => array) } @@ -109,12 +114,7 @@ export function getLocationTotalVolume (loc: LocationLiquidState): number { export function splitLiquid (volume: number, sourceLiquidState: LocationLiquidState): SourceAndDest { const totalSourceVolume = getLocationTotalVolume(sourceLiquidState) - if (AIR in sourceLiquidState) { - console.warn('Splitting liquid with air present', sourceLiquidState) - } - if (totalSourceVolume === 0) { - console.warn('splitting with zero source volume') // Splitting from empty source return { source: sourceLiquidState, @@ -123,7 +123,6 @@ export function splitLiquid (volume: number, sourceLiquidState: LocationLiquidSt } if (volume > totalSourceVolume) { - console.warn('volume to split exceeds total source volume, adding air', sourceLiquidState, volume, totalSourceVolume) // Take all of source, plus air return { source: mapValues(sourceLiquidState, () => ({volume: 0})), @@ -212,3 +211,26 @@ export function totalVolume (location: LocationLiquidState): number { : acc }, 0) } + +export const blowoutUtil = ( + pipette: $PropertyType, + sourceLabware: $PropertyType, + sourceWell: $PropertyType, + destLabware: $PropertyType, + destWell: $PropertyType, + blowoutLocation: ?string, +): Array => { + if (!blowoutLocation) return [] + let labware = blowoutLocation + let well = 'A1' + + // TODO Ian 2018-05-04 more explicit test for non-trash blowout destination + if (blowoutLocation === SOURCE_WELL_BLOWOUT_DESTINATION) { + labware = sourceLabware + well = sourceWell + } else if (blowoutLocation === DEST_WELL_BLOWOUT_DESTINATION) { + labware = destLabware + well = destWell + } + return [blowout({pipette: pipette, labware, well})] +} diff --git a/protocol-designer/src/steplist/actions/actions.js b/protocol-designer/src/steplist/actions/actions.js index d101c24edf6..e2c9a58255e 100644 --- a/protocol-designer/src/steplist/actions/actions.js +++ b/protocol-designer/src/steplist/actions/actions.js @@ -25,9 +25,10 @@ export type ChangeFormInputAction = { export const changeFormInput = (payload: ChangeFormPayload) => (dispatch: ThunkDispatch, getState: GetState) => { + const unsavedForm = selectors.getUnsavedForm(getState()) dispatch({ type: 'CHANGE_FORM_INPUT', - payload: handleFormChange(payload, getState), + payload: handleFormChange(payload, unsavedForm, getState), }) } @@ -53,12 +54,10 @@ export type DeleteStepAction = { payload: StepIdType, } -export const deleteStep = () => (dispatch: Dispatch<*>, getState: GetState) => { - dispatch({ - type: 'DELETE_STEP', - payload: selectors.getSelectedStepId(getState()), - }) -} +export const deleteStep = (stepId: StepIdType) => ({ + type: 'DELETE_STEP', + payload: stepId, +}) type ExpandAddStepButtonAction = { type: 'EXPAND_ADD_STEP_BUTTON', @@ -123,10 +122,10 @@ export const saveStepForm = () => (dispatch: Dispatch<*>, getState: GetState) => { const state = getState() - if (selectors.currentFormCanBeSaved(state)) { + if (selectors.getCurrentFormCanBeSaved(state)) { dispatch({ type: 'SAVE_STEP_FORM', - payload: selectors.formData(state), + payload: selectors.getUnsavedForm(state), }) } } @@ -157,7 +156,7 @@ export type OpenMoreOptionsModal = { export const openMoreOptionsModal = () => (dispatch: Dispatch<*>, getState: GetState) => { dispatch({ type: 'OPEN_MORE_OPTIONS_MODAL', - payload: selectors.formData(getState()), // TODO only pull in relevant fields? + payload: selectors.getUnsavedForm(getState()), // TODO only pull in relevant fields? }) } @@ -184,7 +183,7 @@ export type SaveMoreOptionsModal = { export const saveMoreOptionsModal = () => (dispatch: Dispatch<*>, getState: GetState) => { dispatch({ type: 'SAVE_MORE_OPTIONS_MODAL', - payload: selectors.formModalData(getState()), + payload: selectors.getFormModalData(getState()), }) } @@ -197,3 +196,15 @@ export const clearWellSelectionLabwareKey = (): * => ({ type: 'CLEAR_WELL_SELECTION_LABWARE_KEY', payload: null, }) + +export type ReorderStepsAction = { + type: 'REORDER_STEPS', + payload: { + stepIds: Array, + }, +} + +export const reorderSteps = (stepIds: Array): ReorderStepsAction => ({ + type: 'REORDER_STEPS', + payload: {stepIds}, +}) diff --git a/protocol-designer/src/steplist/actions/handleFormChange.js b/protocol-designer/src/steplist/actions/handleFormChange.js index 75a47caa1af..55cdd609037 100644 --- a/protocol-designer/src/steplist/actions/handleFormChange.js +++ b/protocol-designer/src/steplist/actions/handleFormChange.js @@ -1,17 +1,14 @@ // @flow import uniq from 'lodash/uniq' +import {getPipetteNameSpecs} from '@opentrons/shared-data' import {getWellSetForMultichannel} from '../../well-selection/utils' -import {selectors} from '../index' import {selectors as pipetteSelectors} from '../../pipettes' -import { - DEFAULT_MM_FROM_BOTTOM_ASPIRATE, - DEFAULT_MM_FROM_BOTTOM_DISPENSE, -} from '../../constants' import {selectors as labwareIngredSelectors} from '../../labware-ingred/reducers' + import type {PipetteChannels} from '@opentrons/shared-data' import type {BaseState, GetState} from '../../types' import type {FormData} from '../../form-types' - +import type {StepFieldName} from '../fieldLevel' import type {ChangeFormPayload} from './types' function _getAllWells ( @@ -38,7 +35,7 @@ function _getAllWells ( // maybe remove channels from pipette state and use shared-data? // or if not, make this its own selector in pipettes/ atom const getChannels = (pipetteId: string, state: BaseState): PipetteChannels => { - const pipettes = pipetteSelectors.pipettesById(state) + const pipettes = pipetteSelectors.getPipettesById(state) const pipette = pipettes[pipetteId] if (!pipette) { console.error(`${pipetteId} not found in pipettes, cannot handleFormChange properly`) @@ -51,65 +48,86 @@ const getChannels = (pipetteId: string, state: BaseState): PipetteChannels => { // Eventually we gotta allow arbitrary actions like DELETE_LABWARE // (or more speculatively, CHANGE_PIPETTE etc), which affect saved forms from // 'outside', to cause changes that run thru all the logic in this block -function handleFormChange (payload: ChangeFormPayload, getState: GetState): ChangeFormPayload { +function handleFormChange ( + payload: ChangeFormPayload, + baseForm: ?FormData, + getState: GetState, +): ChangeFormPayload { // Use state to handle form changes const baseState = getState() - const unsavedForm = selectors.formData(baseState) - let updateOverrides = {} - if (unsavedForm == null) { - // pass thru, unchanged - return payload + // pass thru, unchanged + if (baseForm == null) { return payload } + + let updateOverrides = getChangeLabwareEffects(payload.update) + + if (baseForm.pipette && payload.update.pipette) { + if (typeof payload.update.pipette !== 'string') { + // this should not happen! + console.error('no next pipette, could not handleFormChange') + return payload + } + const nextChannels = getChannels(payload.update.pipette, baseState) + updateOverrides = { + ...updateOverrides, + ...reconcileFormPipette(baseForm, baseState, payload.update.pipette, nextChannels), + } + } + + if (baseForm.stepType === 'distribute') { + if (typeof payload.update.pipette === 'string') { + const pipetteData = pipetteSelectors.getPipettesById(baseState)[payload.update.pipette] + const pipetteSpecs = getPipetteNameSpecs(pipetteData.model) + const disposalVol = pipetteSpecs + ? pipetteSpecs.minVolume + : null + + updateOverrides = { + ...updateOverrides, + 'aspirate_disposalVol_checkbox': true, + 'aspirate_disposalVol_volume': disposalVol, + } + } + } + + return { + update: { + ...payload.update, + ...updateOverrides, + }, } +} +export const getChangeLabwareEffects = (updateFormData: {[StepFieldName]: ?mixed}) => { + let updateOverrides = {} // Changing labware clears wells selection: source labware - if ('aspirate_labware' in payload.update) { + if ('aspirate_labware' in updateFormData) { updateOverrides = { ...updateOverrides, 'aspirate_wells': null, - 'aspirate_mmFromBottom': DEFAULT_MM_FROM_BOTTOM_ASPIRATE, + 'aspirate_mmFromBottom': null, + 'aspirate_touchTipMmFromBottom': null, } } - // Changing labware clears wells selection: dest labware - if ('dispense_labware' in payload.update) { + if ('dispense_labware' in updateFormData) { updateOverrides = { ...updateOverrides, 'dispense_wells': null, - 'dispense_mmFromBottom': DEFAULT_MM_FROM_BOTTOM_DISPENSE, + 'dispense_mmFromBottom': null, + 'dispense_touchTipMmFromBottom': null, } } - // Changing labware clears wells selection: labware (eg, mix) - if ('labware' in payload.update) { + if ('labware' in updateFormData) { updateOverrides = { ...updateOverrides, 'wells': null, - // TODO: Ian 2018-09-03 should we have both asp/disp for Mix? - // if not, is dispense the right choice vs aspirate? - 'dispense_mmFromBottom': DEFAULT_MM_FROM_BOTTOM_DISPENSE, - } - } - - if (unsavedForm.pipette && payload.update.pipette) { - if (typeof payload.update.pipette !== 'string') { - // this should not happen! - console.error('no next pipette, could not handleFormChange') - return payload - } - const nextChannels = getChannels(payload.update.pipette, baseState) - updateOverrides = { - ...updateOverrides, - ...reconcileFormPipette(unsavedForm, baseState, payload.update.pipette, nextChannels), + 'mix_mmFromBottom': null, + 'mix_touchTipMmFromBottom': null, } } - - return { - update: { - ...payload.update, - ...updateOverrides, - }, - } + return updateOverrides } export const reconcileFormPipette = (formData: FormData, baseState: BaseState, nextPipetteId: ?mixed, nextChannels: ?number) => { @@ -156,7 +174,7 @@ export const reconcileFormPipette = (formData: FormData, baseState: BaseState, n } else if (multiToSingle) { // multi-channel to single-channel: convert primary wells to all wells const labwareId = formData.labware - const labware = labwareId && labwareIngredSelectors.getLabware(baseState)[labwareId] + const labware = labwareId && labwareIngredSelectors.getLabwareById(baseState)[labwareId] const labwareType = labware && labware.type updateOverrides = { @@ -173,9 +191,9 @@ export const reconcileFormPipette = (formData: FormData, baseState: BaseState, n const sourceLabwareId = formData['aspirate_labware'] const destLabwareId = formData['dispense_labware'] - const sourceLabware = sourceLabwareId && labwareIngredSelectors.getLabware(baseState)[sourceLabwareId] + const sourceLabware = sourceLabwareId && labwareIngredSelectors.getLabwareById(baseState)[sourceLabwareId] const sourceLabwareType = sourceLabware && sourceLabware.type - const destLabware = destLabwareId && labwareIngredSelectors.getLabware(baseState)[destLabwareId] + const destLabware = destLabwareId && labwareIngredSelectors.getLabwareById(baseState)[destLabwareId] const destLabwareType = destLabware && destLabware.type updateOverrides = { @@ -185,6 +203,7 @@ export const reconcileFormPipette = (formData: FormData, baseState: BaseState, n } } } + return updateOverrides } diff --git a/protocol-designer/src/steplist/actions/thunks.js b/protocol-designer/src/steplist/actions/thunks.js index ca864cf2e50..3e23de07b63 100644 --- a/protocol-designer/src/steplist/actions/thunks.js +++ b/protocol-designer/src/steplist/actions/thunks.js @@ -1,14 +1,17 @@ // @flow -import {selectors} from '../index' - +import forEach from 'lodash/forEach' +import handleFormChange from './handleFormChange' +import {uuid} from '../../utils' import {selectors as labwareIngredsSelectors} from '../../labware-ingred/reducers' import * as pipetteSelectors from '../../pipettes/selectors' +import {selectors as steplistSelectors} from '../../steplist' import {actions as tutorialActions} from '../../tutorial' import {getNextDefaultPipetteId, generateNewForm} from '../formLevel' - import type {StepType, StepIdType, FormData} from '../../form-types' import type {BaseState, GetState, ThunkAction, ThunkDispatch} from '../../types' +export const SCROLL_ON_SELECT_STEP_CLASSNAME = 'scroll_on_select_step' + export type SelectStepAction = { type: 'SELECT_STEP', payload: StepIdType, @@ -16,23 +19,17 @@ export type SelectStepAction = { // get new or existing step for given stepId function getStepFormData (state: BaseState, stepId: StepIdType, newStepType?: StepType): ?FormData { - const existingStep = selectors.getSavedForms(state)[stepId] + const existingStep = steplistSelectors.getSavedForms(state)[stepId] if (existingStep) { return existingStep } - const defaultNextPipette = getNextDefaultPipetteId( - selectors.getSavedForms(state), - selectors.orderedSteps(state), - pipetteSelectors.pipetteIdsByMount(state) - ) - // TODO: Ian 2018-09-19 sunset 'steps' reducer. Right now, it's needed here to get stepType // for any step that was created but never saved (never clicked Save button). // Instead, new steps should have their stepType immediately added // to 'savedStepForms' upon creation. - const steps = selectors.getSteps(state) + const steps = steplistSelectors.getSteps(state) const stepTypeFromStepReducer = steps[stepId] && steps[stepId].stepType const stepType = newStepType || stepTypeFromStepReducer @@ -44,7 +41,6 @@ function getStepFormData (state: BaseState, stepId: StepIdType, newStepType?: St return generateNewForm({ stepId, stepType: stepType, - defaultNextPipette, }) } @@ -58,18 +54,52 @@ export const selectStep = (stepId: StepIdType, newStepType?: StepType): ThunkAct dispatch(selectStepAction) - const formData = getStepFormData(getState(), stepId, newStepType) + const state = getState() + let formData = getStepFormData(state, stepId, newStepType) + + const defaultPipetteId = getNextDefaultPipetteId( + steplistSelectors.getSavedForms(state), + steplistSelectors.getOrderedSteps(state), + pipetteSelectors.getEquippedPipettes(state), + ) + + // For a pristine step, if there is a `pipette` field in the form + // (added by upstream `getDefaultsForStepType` fn), + // then set `pipette` field of new steps to the next default pipette id. + // + // In order to trigger dependent field changes (eg default disposal volume), + // update the form thru handleFormChange. + const formHasPipetteField = formData && 'pipette' in formData + if (newStepType && formHasPipetteField && defaultPipetteId) { + const updatePayload = {update: {pipette: defaultPipetteId}} + const updatedFields = handleFormChange( + updatePayload, + formData, + getState).update + + formData = { + ...formData, + ...updatedFields, + } + } + dispatch({ type: 'POPULATE_FORM', payload: formData, }) + + // scroll to top of all elements with the special class + forEach( + global.document.getElementsByClassName(SCROLL_ON_SELECT_STEP_CLASSNAME), + elem => { elem.scrollTop = 0 } + ) } // addStep thunk adds an incremental integer ID for Step reducers. export const addStep = (payload: {stepType: StepType}) => (dispatch: ThunkDispatch<*>, getState: GetState) => { const state = getState() - const stepId = selectors.nextStepId(state) + const stepId = uuid() const {stepType} = payload dispatch({ type: 'ADD_STEP', @@ -78,7 +108,7 @@ export const addStep = (payload: {stepType: StepType}) => id: stepId, }, }) - const deckHasLiquid = labwareIngredsSelectors.hasLiquid(state) + const deckHasLiquid = labwareIngredsSelectors.getDeckHasLiquid(state) const stepNeedsLiquid = ['transfer', 'distribute', 'consolidate', 'mix'].includes(payload.stepType) if (stepNeedsLiquid && !deckHasLiquid) { dispatch(tutorialActions.addHint('add_liquids_and_labware')) @@ -96,7 +126,7 @@ export type ReorderSelectedStepAction = { export const reorderSelectedStep = (delta: number) => (dispatch: ThunkDispatch, getState: GetState) => { - const stepId = selectors.getSelectedStepId(getState()) + const stepId = steplistSelectors.getSelectedStepId(getState()) if (stepId != null) { dispatch({ @@ -108,3 +138,23 @@ export const reorderSelectedStep = (delta: number) => }) } } + +export type DuplicateStepAction = { + type: 'DUPLICATE_STEP', + payload: { + stepId: StepIdType, + duplicateStepId: StepIdType, + }, +} + +export const duplicateStep = (stepId: StepIdType) => + (dispatch: ThunkDispatch, getState: GetState) => { + const duplicateStepId = uuid() + + if (stepId != null) { + dispatch({ + type: 'DUPLICATE_STEP', + payload: {stepId, duplicateStepId}, + }) + } + } diff --git a/protocol-designer/src/steplist/actions/types.js b/protocol-designer/src/steplist/actions/types.js index 80087bcde54..ac2584d7084 100644 --- a/protocol-designer/src/steplist/actions/types.js +++ b/protocol-designer/src/steplist/actions/types.js @@ -1,4 +1,5 @@ // @flow +import type {StepFieldName} from '../fieldLevel' // Update Form input (onChange on inputs) export type ChangeFormPayload = { @@ -6,13 +7,13 @@ export type ChangeFormPayload = { // Accessor strings and values depend on StepType stepType?: string, update: { - [accessor: string]: ?mixed, // string | boolean | Array | null, + [StepFieldName]: ?mixed, // string | boolean | Array | null, }, } export type ChangeSavedFormPayload = { - stepId?: number, + stepId?: string, update: { - [accessor: string]: ?mixed, // string | boolean | Array | null, + [StepFieldName]: ?mixed, // string | boolean | Array | null, }, } diff --git a/protocol-designer/src/steplist/fieldLevel/index.js b/protocol-designer/src/steplist/fieldLevel/index.js index 071193a2252..874765e070b 100644 --- a/protocol-designer/src/steplist/fieldLevel/index.js +++ b/protocol-designer/src/steplist/fieldLevel/index.js @@ -16,7 +16,7 @@ import { composeProcessors, type ValueProcessor, } from './processing' -import type {StepFieldName} from './types' +import type {StepFieldName} from '../../form-types' import type {StepFormContextualState} from '../types' export type { @@ -24,10 +24,10 @@ export type { } const hydrateLabware = (state: StepFormContextualState, id: string) => ( - labwareIngredSelectors.getLabware(state)[id] + labwareIngredSelectors.getLabwareById(state)[id] ) const hydratePipette = (state: StepFormContextualState, id: string) => ( - pipetteSelectors.pipettesById(state)[id] + pipetteSelectors.getPipettesById(state)[id] ) type StepFieldHelpers = { @@ -46,12 +46,6 @@ const stepFieldHelperMap: {[StepFieldName]: StepFieldHelpers} = { getErrors: composeErrors(requiredField, minimumWellCount(1)), processValue: defaultTo([]), }, - 'dispense_delayMinutes': { - processValue: composeProcessors(castToNumber, defaultTo(0)), - }, - 'dispense_delaySeconds': { - processValue: composeProcessors(castToNumber, defaultTo(0)), - }, 'dispense_labware': { getErrors: composeErrors(requiredField), hydrate: hydrateLabware, diff --git a/protocol-designer/src/steplist/fieldLevel/types.js b/protocol-designer/src/steplist/fieldLevel/types.js deleted file mode 100644 index 791f8269f62..00000000000 --- a/protocol-designer/src/steplist/fieldLevel/types.js +++ /dev/null @@ -1,50 +0,0 @@ -// @flow - -export type StepFieldName = - | 'aspirate_airGap_checkbox' - | 'aspirate_airGap_volume' - | 'aspirate_changeTip' - | 'aspirate_disposalVol_checkbox' - | 'aspirate_disposalVol_destination' - | 'aspirate_disposalVol_volume' - | 'aspirate_flowRate' - | 'aspirate_labware' - | 'aspirate_mix_checkbox' - | 'aspirate_mix_times' - | 'aspirate_mix_volume' - | 'aspirate_preWetTip' - | 'aspirate_touchTip' - | 'aspirate_mmFromBottom' - | 'aspirate_wellOrder_first' - | 'aspirate_wellOrder_second' - | 'aspirate_wells' - | 'changeTip' - | 'dispense_blowout_checkbox' - | 'dispense_blowout_labware' - | 'dispense_delay_checkbox' - | 'dispense_delayMinutes' - | 'dispense_delaySeconds' - | 'dispense_flowRate' - | 'dispense_labware' - | 'dispense_touchTip' - | 'dispense_mix_checkbox' - | 'dispense_mix_times' - | 'dispense_mix_volume' - | 'dispense_mmFromBottom' - | 'dispense_wellOrder_first' - | 'dispense_wellOrder_second' - | 'dispense_wells' - | 'labware' - | 'pauseForAmountOfTime' - | 'pauseHour' - | 'pauseMessage' - | 'pauseMinute' - | 'pauseSecond' - | 'pipette' - | 'stepDetails' - | 'stepName' - | 'times' - | 'mmFromBottom' - | 'touchTip' - | 'volume' - | 'wells' diff --git a/protocol-designer/src/steplist/formLevel/errors.js b/protocol-designer/src/steplist/formLevel/errors.js index 85f77937a41..c5d69dbee08 100644 --- a/protocol-designer/src/steplist/formLevel/errors.js +++ b/protocol-designer/src/steplist/formLevel/errors.js @@ -1,7 +1,7 @@ // @flow import * as React from 'react' import {canPipetteUseLabware} from '@opentrons/shared-data' -import type {StepFieldName} from '../fieldLevel' +import type {StepFieldName} from '../../form-types' /******************* ** Error Messages ** diff --git a/protocol-designer/src/steplist/formLevel/generateNewForm.js b/protocol-designer/src/steplist/formLevel/generateNewForm.js index 13c44973205..98d1a7a3086 100644 --- a/protocol-designer/src/steplist/formLevel/generateNewForm.js +++ b/protocol-designer/src/steplist/formLevel/generateNewForm.js @@ -8,17 +8,14 @@ import type { FormData, } from '../../form-types' -const FORMS_WITH_PIPETTE = ['transfer', 'mix', 'distribute', 'consolidate'] - type NewFormArgs = { stepId: StepIdType, stepType: StepType, - defaultNextPipette: string, } // Add default values to a new step form export default function generateNewForm (args: NewFormArgs): FormData { - const {stepId, stepType, defaultNextPipette} = args + const {stepId, stepType} = args const baseForm: BlankForm = { id: stepId, stepType: stepType, @@ -28,10 +25,6 @@ export default function generateNewForm (args: NewFormArgs): FormData { let additionalFields = {} - if (FORMS_WITH_PIPETTE.includes(stepType)) { - additionalFields.pipette = defaultNextPipette - } - return { ...baseForm, ...getDefaultsForStepType(stepType), diff --git a/protocol-designer/src/steplist/formLevel/getDefaultsForStepType.js b/protocol-designer/src/steplist/formLevel/getDefaultsForStepType.js index 7c89e25f802..a4fa07d1125 100644 --- a/protocol-designer/src/steplist/formLevel/getDefaultsForStepType.js +++ b/protocol-designer/src/steplist/formLevel/getDefaultsForStepType.js @@ -23,7 +23,10 @@ export default function getDefaultsForStepType (stepType: StepType) { 'dispense_wellOrder_first': DEFAULT_WELL_ORDER_FIRST_OPTION, 'dispense_wellOrder_second': DEFAULT_WELL_ORDER_SECOND_OPTION, 'dispense_mmFromBottom': DEFAULT_MM_FROM_BOTTOM_DISPENSE, + 'dispense_blowout_checkbox': false, + 'dispense_blowout_location': FIXED_TRASH_ID, 'dispense_wells': [], + 'pipette': null, 'volume': undefined, } case 'consolidate': @@ -36,7 +39,10 @@ export default function getDefaultsForStepType (stepType: StepType) { 'aspirate_wells': [], 'dispense_labware': null, 'dispense_mmFromBottom': DEFAULT_MM_FROM_BOTTOM_DISPENSE, + 'dispense_blowout_checkbox': false, + 'dispense_blowout_location': FIXED_TRASH_ID, 'dispense_wells': [], + 'pipette': null, 'volume': undefined, } case 'mix': @@ -45,15 +51,18 @@ export default function getDefaultsForStepType (stepType: StepType) { 'labware': null, 'aspirate_wellOrder_first': DEFAULT_WELL_ORDER_FIRST_OPTION, 'aspirate_wellOrder_second': DEFAULT_WELL_ORDER_SECOND_OPTION, - 'wells': [], - 'mmFromBottom': DEFAULT_MM_FROM_BOTTOM_DISPENSE, // NOTE: mix uses dispense for both asp + disp, for now + 'dispense_blowout_checkbox': false, + 'dispense_blowout_location': FIXED_TRASH_ID, + 'mix_mmFromBottom': DEFAULT_MM_FROM_BOTTOM_DISPENSE, // NOTE: mix uses dispense for both asp + disp, for now + 'pipette': null, 'volume': undefined, + 'wells': [], } case 'distribute': return { 'aspirate_changeTip': DEFAULT_CHANGE_TIP_OPTION, 'aspirate_disposalVol_checkbox': true, - 'aspirate_disposalVol_destination': FIXED_TRASH_ID, + 'dispense_blowout_location': FIXED_TRASH_ID, // only blowout location for disposalVol 'aspirate_labware': null, 'aspirate_mmFromBottom': DEFAULT_MM_FROM_BOTTOM_ASPIRATE, 'aspirate_wells': [], @@ -62,6 +71,7 @@ export default function getDefaultsForStepType (stepType: StepType) { 'dispense_wellOrder_second': DEFAULT_WELL_ORDER_SECOND_OPTION, 'dispense_mmFromBottom': DEFAULT_MM_FROM_BOTTOM_DISPENSE, 'dispense_wells': [], + 'pipette': null, 'volume': undefined, } default: diff --git a/protocol-designer/src/steplist/formLevel/getNextDefaultPipetteId/index.js b/protocol-designer/src/steplist/formLevel/getNextDefaultPipetteId/index.js index e3529d1f925..0aca04bb82b 100644 --- a/protocol-designer/src/steplist/formLevel/getNextDefaultPipetteId/index.js +++ b/protocol-designer/src/steplist/formLevel/getNextDefaultPipetteId/index.js @@ -1,5 +1,7 @@ // @flow +import findKey from 'lodash/findKey' import last from 'lodash/last' +import type {PipetteData} from '../../../step-generation' import type {StepIdType, FormData} from '../../../form-types' // TODO: Ian 2018-09-18 once we support switching pipettes mid-protocol, @@ -11,7 +13,7 @@ import type {StepIdType, FormData} from '../../../form-types' export default function getNextDefaultPipetteId ( savedForms: {[StepIdType]: FormData}, orderedSteps: Array, - pipetteIdsByMount: {left?: ?string, right?: ?string} + equippedPipettesById: {[string]: PipetteData} ): string { const prevPipetteSteps = orderedSteps .map(stepId => savedForms[stepId]) @@ -19,10 +21,11 @@ export default function getNextDefaultPipetteId ( const lastPipetteStep = last(prevPipetteSteps) - const nextDefaultPipette = ( + // NOTE: order of findKey not guaranteed, expecting at most one pipette on each mount + const nextDefaultPipette: ?string = ( (lastPipetteStep && lastPipetteStep.pipette) || - pipetteIdsByMount['left'] || - pipetteIdsByMount['right'] + findKey(equippedPipettesById, p => p.mount === 'left') || + findKey(equippedPipettesById, p => p.mount === 'right') ) if (!nextDefaultPipette) { diff --git a/protocol-designer/src/steplist/formLevel/getNextDefaultPipetteId/test/getNextDefaultPipetteId.test.js b/protocol-designer/src/steplist/formLevel/getNextDefaultPipetteId/test/getNextDefaultPipetteId.test.js index 195c11cc859..c2329b997dc 100644 --- a/protocol-designer/src/steplist/formLevel/getNextDefaultPipetteId/test/getNextDefaultPipetteId.test.js +++ b/protocol-designer/src/steplist/formLevel/getNextDefaultPipetteId/test/getNextDefaultPipetteId.test.js @@ -6,17 +6,20 @@ describe('getNextDefaultPipetteId', () => { const testCases = [ { testMsg: 'both pipettes present: use left pipette', - equippedPipettes: {'left': 'leftId', 'right': 'rightId'}, + equippedPipettesById: { + 'leftId': {id: 'leftId', mount: 'left'}, + 'rightId': {id: 'rightId', mount: 'right'}, + }, expected: 'leftId', }, { testMsg: 'right only: use right', - equippedPipettes: {'right': 'rightId'}, + equippedPipettesById: {'rightId': {id: 'rightId', mount: 'right'}}, expected: 'rightId', }, ] - testCases.forEach(({testMsg, equippedPipettes, expected}) => { + testCases.forEach(({testMsg, equippedPipettesById, expected}) => { test(testMsg, () => { const savedForms = {} const orderedSteps = [] @@ -24,7 +27,7 @@ describe('getNextDefaultPipetteId', () => { const result = getNextDefaultPipetteId( savedForms, orderedSteps, - equippedPipettes) + equippedPipettesById) expect(result).toBe(expected) }) @@ -41,7 +44,7 @@ describe('getNextDefaultPipetteId', () => { { testMsg: 'no previous forms use pipettes', orderedSteps: ['x', 'x', 'x'], - expected: 'default', + expected: 'defaultId', }, { testMsg: 'mix of steps with and without pipettes', @@ -56,7 +59,7 @@ describe('getNextDefaultPipetteId', () => { { testMsg: 'only missing steps', orderedSteps: ['missingStep', 'missingStep'], - expected: 'default', + expected: 'defaultId', }, ] @@ -68,12 +71,12 @@ describe('getNextDefaultPipetteId', () => { x: {}, // no 'pipette' key, eg a Pause step } - const equippedPipettes = {left: 'default'} + const equippedPipettesById = {'defaultId': {id: 'defaultId', mount: 'left'}} const result = getNextDefaultPipetteId( savedForms, orderedSteps, - equippedPipettes) + equippedPipettesById) expect(result).toBe(expected) }) diff --git a/protocol-designer/src/steplist/formLevel/stepFormToArgs/mixFormToArgs.js b/protocol-designer/src/steplist/formLevel/stepFormToArgs/mixFormToArgs.js index 1d2329a6fe5..214d17bb124 100644 --- a/protocol-designer/src/steplist/formLevel/stepFormToArgs/mixFormToArgs.js +++ b/protocol-designer/src/steplist/formLevel/stepFormToArgs/mixFormToArgs.js @@ -13,6 +13,7 @@ type MixStepArgs = MixFormData const mixFormToArgs = (hydratedFormData: FormData): MixStepArgs => { const {labware, pipette} = hydratedFormData const touchTip = !!hydratedFormData['touchTip'] + const touchTipMmFromBottom = hydratedFormData['mix_touchTipMmFromBottom'] let wells = hydratedFormData.wells || [] const orderFirst = hydratedFormData.aspirate_wellOrder_first @@ -28,21 +29,19 @@ const mixFormToArgs = (hydratedFormData: FormData): MixStepArgs => { const volume = Number(hydratedFormData.volume) || 0 const times = Number(hydratedFormData.times) || 0 + + const aspirateFlowRateUlSec = hydratedFormData['aspirate_flowRate'] + const dispenseFlowRateUlSec = hydratedFormData['dispense_flowRate'] + // NOTE: for mix, there is only one tip offset field, // and it applies to both aspirate and dispense - const aspirateOffsetFromBottomMm = Number(hydratedFormData['mmFromBottom']) - const dispenseOffsetFromBottomMm = Number(hydratedFormData['mmFromBottom']) + const aspirateOffsetFromBottomMm = hydratedFormData['mix_mmFromBottom'] + const dispenseOffsetFromBottomMm = hydratedFormData['mix_mmFromBottom'] // It's radiobutton, so one should always be selected. const changeTip = hydratedFormData['aspirate_changeTip'] || DEFAULT_CHANGE_TIP_OPTION - const blowoutLabwareId = hydratedFormData['dispense_blowout_labware'] - - const delay = hydratedFormData['dispense_delay_checkbox'] - ? ((Number(hydratedFormData['dispense_delayMinutes']) || 0) * 60) + - (Number(hydratedFormData['dispense_delaySeconds'] || 0)) - : null - // TODO Ian 2018-05-08 delay number parsing errors + const blowoutLocation = hydratedFormData['dispense_blowout_checkbox'] ? hydratedFormData['dispense_blowout_location'] : null return { stepType: 'mix', @@ -53,10 +52,12 @@ const mixFormToArgs = (hydratedFormData: FormData): MixStepArgs => { volume, times, touchTip, - delay, + touchTipMmFromBottom, changeTip, - blowout: blowoutLabwareId, + blowoutLocation, pipette: pipette.id, + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, aspirateOffsetFromBottomMm, dispenseOffsetFromBottomMm, } diff --git a/protocol-designer/src/steplist/formLevel/stepFormToArgs/transferLikeFormToArgs.js b/protocol-designer/src/steplist/formLevel/stepFormToArgs/transferLikeFormToArgs.js index b3801043fef..fe8a94c2c22 100644 --- a/protocol-designer/src/steplist/formLevel/stepFormToArgs/transferLikeFormToArgs.js +++ b/protocol-designer/src/steplist/formLevel/stepFormToArgs/transferLikeFormToArgs.js @@ -8,11 +8,10 @@ import type { DistributeFormData, TransferFormData, } from '../../../step-generation' +import {SOURCE_WELL_BLOWOUT_DESTINATION} from '../../../step-generation/utils' import { DEFAULT_CHANGE_TIP_OPTION } from '../../../constants' import { orderWells } from '../../utils' -export const SOURCE_WELL_DISPOSAL_DESTINATION = 'source_well' - function getMixData (hydratedFormData, checkboxField, volumeField, timesField) { const checkbox = hydratedFormData[checkboxField] const volume = parseFloat(hydratedFormData[volumeField]) @@ -31,14 +30,20 @@ const transferLikeFormToArgs = (hydratedFormData: FormData): TransferLikeStepArg const volume = Number(hydratedFormData['volume']) const sourceLabware = hydratedFormData['aspirate_labware'] const destLabware = hydratedFormData['dispense_labware'] - const blowoutLabwareId = hydratedFormData['dispense_blowout_checkbox'] ? hydratedFormData['dispense_blowout_labware'] : null - const aspirateOffsetFromBottomMm = Number(hydratedFormData['aspirate_mmFromBottom']) - const dispenseOffsetFromBottomMm = Number(hydratedFormData['dispense_mmFromBottom']) + const aspirateFlowRateUlSec = hydratedFormData['aspirate_flowRate'] + const dispenseFlowRateUlSec = hydratedFormData['dispense_flowRate'] + + const aspirateOffsetFromBottomMm = hydratedFormData['aspirate_mmFromBottom'] + const dispenseOffsetFromBottomMm = hydratedFormData['dispense_mmFromBottom'] - const delayAfterDispense = hydratedFormData['dispense_delay_checkbox'] - ? ((Number(hydratedFormData['dispense_delayMinutes']) || 0) * 60) + - (Number(hydratedFormData['dispense_delaySeconds'] || 0)) + const touchTipAfterAspirate = hydratedFormData['aspirate_touchTip'] || false + const touchTipAfterAspirateOffsetMmFromBottom = touchTipAfterAspirate + ? hydratedFormData['aspirate_touchTipMmFromBottom'] + : null + const touchTipAfterDispense = hydratedFormData['dispense_touchTip'] || false + const touchTipAfterDispenseOffsetMmFromBottom = touchTipAfterDispense + ? hydratedFormData['dispense_touchTipMmFromBottom'] : null const mixFirstAspirate = hydratedFormData['aspirate_mix_checkbox'] @@ -64,6 +69,8 @@ const transferLikeFormToArgs = (hydratedFormData: FormData): TransferLikeStepArg const changeTip = hydratedFormData['aspirate_changeTip'] || DEFAULT_CHANGE_TIP_OPTION + const blowoutLocation = hydratedFormData['dispense_blowout_checkbox'] ? hydratedFormData['dispense_blowout_location'] : null + const commonFields = { pipette: pipette.id, volume, @@ -71,16 +78,18 @@ const transferLikeFormToArgs = (hydratedFormData: FormData): TransferLikeStepArg sourceLabware: sourceLabware.id, destLabware: destLabware.id, + aspirateFlowRateUlSec, + dispenseFlowRateUlSec, aspirateOffsetFromBottomMm, dispenseOffsetFromBottomMm, - blowout: blowoutLabwareId, changeTip, - delayAfterDispense, mixInDestination, preWetTip: hydratedFormData['aspirate_preWetTip'] || false, - touchTipAfterAspirate: hydratedFormData['aspirate_touchTip'] || false, - touchTipAfterDispense: hydratedFormData['dispense_touchTip'] || false, + touchTipAfterAspirate, + touchTipAfterAspirateOffsetMmFromBottom, + touchTipAfterDispense, + touchTipAfterDispenseOffsetMmFromBottom, description: 'description would be here 2018-03-01', // TODO get from form } @@ -114,14 +123,15 @@ const transferLikeFormToArgs = (hydratedFormData: FormData): TransferLikeStepArg } } + // TODO: BC 2018-11-26 move this check into step generation like blowoutLocation let disposalVolume = null let disposalDestination = null let disposalLabware = null let disposalWell = null if (hydratedFormData['aspirate_disposalVol_checkbox']) { disposalVolume = Number(hydratedFormData['aspirate_disposalVol_volume']) - disposalDestination = hydratedFormData['aspirate_disposalVol_destination'] - if (disposalDestination === SOURCE_WELL_DISPOSAL_DESTINATION) { + disposalDestination = hydratedFormData['dispense_blowout_location'] + if (disposalDestination === SOURCE_WELL_BLOWOUT_DESTINATION) { disposalLabware = sourceLabware.id disposalWell = sourceWells[0] } else { @@ -135,7 +145,7 @@ const transferLikeFormToArgs = (hydratedFormData: FormData): TransferLikeStepArg case 'transfer': { const transferStepArguments: TransferFormData = { ...commonFields, - disposalVolume, + blowoutLocation, stepType: 'transfer', sourceWells, destWells, @@ -147,7 +157,7 @@ const transferLikeFormToArgs = (hydratedFormData: FormData): TransferLikeStepArg case 'consolidate': { const consolidateStepArguments: ConsolidateFormData = { ...commonFields, - disposalVolume, + blowoutLocation, mixFirstAspirate, sourceWells, destWell: destWells[0], diff --git a/protocol-designer/src/steplist/formLevel/warnings.js b/protocol-designer/src/steplist/formLevel/warnings.js index 7a34c51dc72..665796ac51f 100644 --- a/protocol-designer/src/steplist/formLevel/warnings.js +++ b/protocol-designer/src/steplist/formLevel/warnings.js @@ -1,10 +1,9 @@ // @flow import * as React from 'react' -import {getWellTotalVolume} from '@opentrons/shared-data' -import type {StepFieldName} from '../fieldLevel' +import {getWellTotalVolume, getPipetteNameSpecs} from '@opentrons/shared-data' +import type {StepFieldName} from '../../form-types' import KnowledgeBaseLink from '../../components/KnowledgeBaseLink' -export const DISPOSAL_PERCENTAGE = 0.2 // 20% percent of pipette capacity /******************* ** Warning Messages ** ********************/ @@ -19,6 +18,7 @@ export type FormWarning = { body?: React.Node, dependentFields: Array, } +// TODO: Ian 2018-12-06 use i18n for title/body text const FORM_WARNINGS: {[FormWarningType]: FormWarning} = { OVER_MAX_WELL_VOLUME: { type: 'OVER_MAX_WELL_VOLUME', @@ -30,8 +30,7 @@ const FORM_WARNINGS: {[FormWarningType]: FormWarning} = { title: 'Below Recommended disposal volume', body: ( - For accuracy in distribute actions we recommend you use a disposal volume - of at least 20% of the tip's capacity. + For accuracy in distribute actions we recommend you use a disposal volume of at least the pipette's minimum. Read more here. ), @@ -59,10 +58,11 @@ export const maxDispenseWellVolume = (fields: HydratedFormData): ?FormWarning => export const minDisposalVolume = (fields: HydratedFormData): ?FormWarning => { const {aspirate_disposalVol_checkbox, aspirate_disposalVol_volume, pipette} = fields - if (!pipette) return null + const pipetteSpecs = getPipetteNameSpecs(pipette.model) + if (!pipette || !pipetteSpecs) return null const isUnselected = !aspirate_disposalVol_checkbox || !aspirate_disposalVol_volume if (isUnselected) return FORM_WARNINGS.BELOW_MIN_DISPOSAL_VOLUME - const isBelowMin = aspirate_disposalVol_volume < (DISPOSAL_PERCENTAGE * pipette.maxVolume) + const isBelowMin = aspirate_disposalVol_volume < (pipetteSpecs.minVolume) return isBelowMin ? FORM_WARNINGS.BELOW_MIN_DISPOSAL_VOLUME : null } diff --git a/protocol-designer/src/steplist/generateSubsteps.js b/protocol-designer/src/steplist/generateSubsteps.js index 22ca615ae03..087c3fea9c7 100644 --- a/protocol-designer/src/steplist/generateSubsteps.js +++ b/protocol-designer/src/steplist/generateSubsteps.js @@ -25,6 +25,7 @@ import { mix, } from '../step-generation' +import type {StepIdType} from '../form-types' import type {RobotState} from '../step-generation' import type { @@ -46,7 +47,7 @@ function transferLikeSubsteps (args: { allPipetteData: AllPipetteData, getLabwareType: GetLabwareType, robotState: RobotState, - stepId: number, + stepId: StepIdType, }): ?SourceDestSubstepItem { const { stepArgs, @@ -138,7 +139,9 @@ function transferLikeSubsteps (args: { preIngreds: nextMultiRow.dest.preIngreds[destChannelWell], postIngreds: nextMultiRow.dest.postIngreds[destChannelWell], } + const activeTips = currentMultiRow.activeTips return { + activeTips, source, dest: stepArgs.stepType === 'mix' ? source : dest, // NOTE: since source and dest are same for mix, we're showing source on both sides. Otherwise dest would show the intermediate volume state volume: showDispenseVol ? nextMultiRow.volume : currentMultiRow.volume, @@ -157,7 +160,8 @@ function transferLikeSubsteps (args: { preIngreds: currentMultiRow.dest.preIngreds[currentMultiRow.dest.wells[channelIndex]], postIngreds: currentMultiRow.dest.postIngreds[currentMultiRow.dest.wells[channelIndex]], } - return { source, dest, volume: currentMultiRow.volume } + const activeTips = currentMultiRow.activeTips + return {activeTips, source, dest, volume: currentMultiRow.volume} }) ) ) @@ -203,7 +207,12 @@ function transferLikeSubsteps (args: { preIngreds: currentRow.dest.preIngreds, postIngreds: currentRow.dest.postIngreds, } - return {source, dest, volume: currentRow.volume} + return { + activeTips: currentRow.activeTips, + source, + dest, + volume: currentRow.volume, + } } ) @@ -222,7 +231,7 @@ export function generateSubsteps ( allPipetteData: AllPipetteData, getLabwareType: GetLabwareType, robotState: ?RobotState, - stepId: number // stepId is used only for substeps to reference parent step + stepId: string ): ?SubstepItemData { if (!robotState) { console.info(`No robot state, could not generate substeps for step ${stepId}.` + diff --git a/protocol-designer/src/steplist/reducers.js b/protocol-designer/src/steplist/reducers.js index ac868ae1612..d0ab5c708f1 100644 --- a/protocol-designer/src/steplist/reducers.js +++ b/protocol-designer/src/steplist/reducers.js @@ -4,6 +4,7 @@ import {handleActions} from 'redux-actions' import type {ActionType, Reducer} from 'redux-actions' import omit from 'lodash/omit' import mapValues from 'lodash/mapValues' +import reduce from 'lodash/reduce' import {getPDMetadata} from '../file-types' @@ -23,7 +24,9 @@ import type { AddStepAction, ChangeFormInputAction, DeleteStepAction, + ReorderStepsAction, ReorderSelectedStepAction, + DuplicateStepAction, SaveStepFormAction, SelectStepAction, SelectTerminalItemAction, @@ -45,6 +48,7 @@ import { toggleStepCollapsed, type ChangeSavedStepFormAction, } from './actions' +import {getChangeLabwareEffects} from './actions/handleFormChange' type FormState = FormData | null @@ -125,19 +129,19 @@ const steps: Reducer = handleActions({ } }, {...initialStepState}) }, + DUPLICATE_STEP: (state: StepsState, action: DuplicateStepAction): StepsState => ({ + ...state, + [action.payload.duplicateStepId]: { + ...(action.payload.stepId != null ? state[action.payload.stepId] : {}), + id: action.payload.duplicateStepId, + }, + }), }, initialStepState) type SavedStepFormState = { [StepIdType]: FormData, } -const LABWARE_FIELD_NAMES = [ - 'aspirate_labware', - 'dispense_blowout_labware', - 'dispense_labware', - 'labware', -] - const savedStepForms: Reducer = handleActions({ SAVE_STEP_FORM: (state, action: SaveStepFormAction) => ({ ...state, @@ -151,46 +155,40 @@ const savedStepForms: Reducer = handleActions({ ...stepForm, })) }, - DELETE_CONTAINER: (state: SavedStepFormState, action: DeleteContainerAction): SavedStepFormState => { - const {payload} = action - return mapValues(state, savedForm => { - let dependentFields = [] - const withoutDeletedLabware = mapValues(savedForm, (value, fieldName) => { - const isLabware = LABWARE_FIELD_NAMES.includes(fieldName) - if (isLabware && value === payload.containerId) { - switch (fieldName) { - case 'aspirate_labware': { - dependentFields = [...dependentFields, 'aspirate_wells'] - break - } - case 'dispense_labware': { - dependentFields = [...dependentFields, 'dispense_wells'] - break - } - case 'labware': { - dependentFields = [...dependentFields, 'wells'] - break - } + DELETE_CONTAINER: (state: SavedStepFormState, action: DeleteContainerAction): SavedStepFormState => ( + mapValues(state, savedForm => { + const deleteLabwareUpdate = reduce(savedForm, (acc, value, fieldName) => { + if (value === action.payload.containerId) { + const formLabwareFieldUpdate = {[fieldName]: null} + return { + ...acc, + ...formLabwareFieldUpdate, + ...getChangeLabwareEffects(formLabwareFieldUpdate), } - return null } else { - return value + return acc } - }) - const withoutDependentFields = mapValues(withoutDeletedLabware, (value, fieldName) => { - if (dependentFields.includes(fieldName)) return null - return value - }) - return withoutDependentFields + }, {}) + return { + ...savedForm, + ...deleteLabwareUpdate, + } }) - }, + ), CHANGE_SAVED_STEP_FORM: (state: SavedStepFormState, action: ChangeSavedStepFormAction): SavedStepFormState => ({ ...state, [action.payload.stepId]: { - ...(action.payload.stepId ? state[action.payload.stepId] : {}), + ...(action.payload.stepId != null ? state[action.payload.stepId] : {}), ...action.payload.update, }, }), + DUPLICATE_STEP: (state: SavedStepFormState, action: DuplicateStepAction): SavedStepFormState => ({ + ...state, + [action.payload.duplicateStepId]: { + ...(action.payload.stepId != null ? state[action.payload.stepId] : {}), + id: action.payload.duplicateStepId, + }, + }), }, {}) type CollapsedStepsState = { @@ -222,11 +220,11 @@ const orderedSteps: Reducer = handleActions({ ADD_STEP: (state: OrderedStepsState, action: AddStepAction) => [...state, action.payload.id], DELETE_STEP: (state: OrderedStepsState, action: DeleteStepAction) => - // TODO Ian 2018-05-10 standardize StepIdType to string, number is implicitly cast to string somewhere - state.filter(stepId => !(stepId === action.payload || `${stepId}` === action.payload)), + state.filter(stepId => stepId !== action.payload), LOAD_FILE: (state: OrderedStepsState, action: LoadFileAction): OrderedStepsState => getPDMetadata(action.payload).orderedSteps, REORDER_SELECTED_STEP: (state: OrderedStepsState, action: ReorderSelectedStepAction): OrderedStepsState => { + // TODO: BC 2018-11-27 make util function for reordering and use it everywhere const {delta, stepId} = action.payload const stepsWithoutSelectedStep = state.filter(s => s !== stepId) const selectedIndex = state.findIndex(s => s === stepId) @@ -240,6 +238,19 @@ const orderedSteps: Reducer = handleActions({ ...stepsWithoutSelectedStep.slice(nextIndex), ] }, + DUPLICATE_STEP: (state: OrderedStepsState, action: DuplicateStepAction): OrderedStepsState => { + const {stepId, duplicateStepId} = action.payload + const selectedIndex = state.findIndex(s => s === stepId) + + return [ + ...state.slice(0, selectedIndex + 1), + duplicateStepId, + ...state.slice(selectedIndex + 1, state.length), + ] + }, + REORDER_STEPS: (state: OrderedStepsState, action: ReorderStepsAction): OrderedStepsState => ( + action.payload.stepIds + ), }, []) export type SelectableItem = { @@ -252,7 +263,7 @@ export type SelectableItem = { type SelectedItemState = ?SelectableItem -function stepIdHelper (id: StepIdType): SelectedItemState { +function stepIdHelper (id: ?StepIdType): SelectedItemState { if (id == null) return null return { isStep: true, @@ -260,7 +271,7 @@ function stepIdHelper (id: StepIdType): SelectedItemState { } } -function terminalItemIdHelper (id: TerminalItemId): SelectedItemState { +function terminalItemIdHelper (id: ?TerminalItemId): SelectedItemState { if (id == null) return null return { isStep: false, diff --git a/protocol-designer/src/steplist/selectors.js b/protocol-designer/src/steplist/selectors.js index 3e57d5de1ba..d980b1b7aea 100644 --- a/protocol-designer/src/steplist/selectors.js +++ b/protocol-designer/src/steplist/selectors.js @@ -3,7 +3,6 @@ import {createSelector} from 'reselect' import last from 'lodash/last' import reduce from 'lodash/reduce' import mapValues from 'lodash/mapValues' -import max from 'lodash/max' import isEmpty from 'lodash/isEmpty' import each from 'lodash/each' import some from 'lodash/some' @@ -54,27 +53,23 @@ const getUnsavedForm: Selector = createSelector( const getStepFormContextualState: Selector = createSelector( labwareIngredSelectors.rootSelector, pipetteSelectors.rootSelector, - (labwareIngred, _pipettes) => ({ - labwareIngred: labwareIngred, - pipettes: _pipettes, + (labwareIngred, pipettes) => ({ + labwareIngred, + pipettes, }) ) const getHydratedUnsavedForm: Selector = createSelector( getUnsavedForm, getStepFormContextualState, - (_unsavedForm, _contextualState) => ( - _unsavedForm && mapValues(_unsavedForm, (value, name) => ( - hydrateField(_contextualState, name, value) + (unsavedForm, contextualState) => ( + unsavedForm && mapValues(unsavedForm, (value, name) => ( + hydrateField(contextualState, name, value) )) ) ) -// TODO Ian 2018-02-08 rename formData to something like getUnsavedForm or unsavedFormFields -// NOTE: DEPRECATED use getUnsavedForm instead -const formData = getUnsavedForm - -const formModalData = createSelector( +const getFormModalData = createSelector( rootSelector, (state: RootState) => state.unsavedFormModal ) @@ -139,7 +134,7 @@ const getCollapsedSteps = createSelector( (state: RootState) => state.collapsedSteps ) -const orderedStepsSelector: Selector = createSelector( +const getOrderedSteps: Selector = createSelector( rootSelector, (state: RootState) => state.orderedSteps ) @@ -147,7 +142,7 @@ const orderedStepsSelector: Selector = createSelector( /** This is just a simple selector, but has some debugging logic. TODO Ian 2018-03-20: use assert here */ const getSavedForms: Selector<{[StepIdType]: FormData}> = createSelector( getSteps, - orderedStepsSelector, + getOrderedSteps, (state: BaseState) => rootSelector(state).savedStepForms, (steps, orderedSteps, savedStepForms) => { orderedSteps.forEach(stepId => { @@ -200,7 +195,7 @@ const getAllErrorsFromHydratedForm = (hydratedForm: FormData): StepFormAndFieldE const getArgsAndErrorsByStepId: Selector<{[StepIdType]: StepArgsAndErrors}> = createSelector( getSteps, getHydratedSavedForms, - orderedStepsSelector, + getOrderedSteps, (steps, savedStepForms, orderedSteps) => { return reduce(orderedSteps, (acc, stepId) => { let nextStepData @@ -242,19 +237,19 @@ const getFormAndFieldErrorsByStepId: Selector<{[StepIdType]: StepFormAndFieldErr ) ) -const isNewStepForm = createSelector( +const getIsNewStepForm = createSelector( getUnsavedForm, getSavedForms, (formData, savedForms) => !!(formData && formData.id != null && !savedForms[formData.id]) ) /** Array of labware (labwareId's) involved in hovered Step, or [] */ -const hoveredStepLabware: Selector> = createSelector( +const getHoveredStepLabware: Selector> = createSelector( getArgsAndErrorsByStepId, getHoveredStepId, (allStepArgsAndErrors, hoveredStep) => { const blank = [] - if (typeof hoveredStep !== 'number' || !allStepArgsAndErrors[hoveredStep]) { + if (!hoveredStep || !allStepArgsAndErrors[hoveredStep]) { return blank } @@ -284,29 +279,19 @@ const hoveredStepLabware: Selector> = createSelector( // step types that have no labware that gets highlighted if (!(stepForm.stepType === 'pause')) { // TODO Ian 2018-05-08 use assert here - console.warn(`hoveredStepLabware does not support step type "${stepForm.stepType}"`) + console.warn(`getHoveredStepLabware does not support step type "${stepForm.stepType}"`) } return blank } ) -const stepCreationButtonExpandedSelector: Selector = createSelector( +const getStepCreationButtonExpanded: Selector = createSelector( rootSelector, (state: RootState) => state.stepCreationButtonExpanded ) -const nextStepId: Selector = createSelector( // generates the next step ID to use - getSteps, - (steps): number => { - const allStepIds = Object.keys(steps).map(stepId => parseInt(stepId)) - return allStepIds.length === 0 - ? 0 - : max(allStepIds) + 1 - } -) - -const formLevelWarnings: Selector> = createSelector( +const getFormLevelWarnings: Selector> = createSelector( getUnsavedForm, getStepFormContextualState, (unsavedFormData, contextualState) => { @@ -317,7 +302,7 @@ const formLevelWarnings: Selector> = createSelector( } ) -const formLevelErrors: Selector> = createSelector( +const getFormLevelErrors: Selector> = createSelector( getUnsavedForm, getStepFormContextualState, (unsavedFormData, contextualState) => { @@ -328,16 +313,16 @@ const formLevelErrors: Selector> = createSelector( } ) -const formSectionCollapseSelector: Selector = createSelector( +const getFormSectionCollapsed: Selector = createSelector( rootSelector, s => s.formSectionCollapse ) -export const allSteps: Selector<{[stepId: StepIdType]: StepItemData}> = createSelector( +export const getAllSteps: Selector<{[stepId: StepIdType]: StepItemData}> = createSelector( getSteps, getCollapsedSteps, getSavedForms, - labwareIngredSelectors.getLabware, + labwareIngredSelectors.getLabwareById, (steps, collapsedSteps, savedForms, labware) => { return mapValues( steps, @@ -365,26 +350,26 @@ export const allSteps: Selector<{[stepId: StepIdType]: StepItemData}> = createSe ) const getSelectedStep = createSelector( - allSteps, + getAllSteps, getSelectedStepId, - (_allSteps, selectedStepId) => { + (allSteps, selectedStepId) => { const stepId = selectedStepId - if (!_allSteps || stepId == null) { + if (!allSteps || stepId == null) { return null } - return _allSteps[stepId] + return allSteps[stepId] } ) // TODO: BC: 2018-10-26 remove this when we decide to not block save -export const currentFormCanBeSaved: Selector = createSelector( +export const getCurrentFormCanBeSaved: Selector = createSelector( getHydratedUnsavedForm, getSelectedStepId, - allSteps, - (hydratedForm, selectedStepId, _allSteps) => { - if (selectedStepId == null || !_allSteps[selectedStepId] || !hydratedForm) return null + getAllSteps, + (hydratedForm, selectedStepId, allSteps) => { + if (selectedStepId == null || !allSteps[selectedStepId] || !hydratedForm) return null return isEmpty(getAllErrorsFromHydratedForm(hydratedForm)) } ) @@ -397,13 +382,13 @@ export const getWellSelectionLabwareKey: Selector = createSelector( export default { rootSelector, - allSteps, + getAllSteps, getFormAndFieldErrorsByStepId, - currentFormCanBeSaved, + getCurrentFormCanBeSaved, getSelectedStep, - stepCreationButtonExpanded: stepCreationButtonExpandedSelector, - orderedSteps: orderedStepsSelector, + getStepCreationButtonExpanded, + getOrderedSteps, getSelectedStepId, getSelectedTerminalItemId, getHoveredTerminalItemId, @@ -412,20 +397,17 @@ export default { getHoveredSubstep, getUnsavedForm, getHydratedUnsavedForm, - formData, // TODO: remove after sunset - formModalData, - nextStepId, + getFormModalData, getArgsAndErrorsByStepId, - isNewStepForm, - formLevelWarnings, - formLevelErrors, - formSectionCollapse: formSectionCollapseSelector, - hoveredStepLabware, + getIsNewStepForm, + getFormLevelWarnings, + getFormLevelErrors, + getFormSectionCollapsed, + getHoveredStepLabware, getWellSelectionLabwareKey, // NOTE: these are exposed only for substeps/selectors.js getSteps, - orderedStepsSelector, getCollapsedSteps, getSavedForms, } diff --git a/protocol-designer/src/steplist/substepTimeline.js b/protocol-designer/src/steplist/substepTimeline.js index 75244782dd2..03dd745a871 100644 --- a/protocol-designer/src/steplist/substepTimeline.js +++ b/protocol-designer/src/steplist/substepTimeline.js @@ -1,47 +1,86 @@ // @flow +import assert from 'assert' +import last from 'lodash/last' import pick from 'lodash/pick' import type {Channels} from '@opentrons/components' -import type {CommandCreator, RobotState, CommandCreatorError} from '../step-generation/types' +import type { + CommandCreator, + CommandCreatorError, + CommandsAndRobotState, + RobotState, +} from '../step-generation/types' import {getWellsForTips} from '../step-generation/utils' -import type {SubstepTimelineFrame} from './types' +import type {SubstepTimelineFrame, TipLocation} from './types' -type SubstepTimeline = { +function _conditionallyUpdateActiveTips (acc: SubstepTimelineAcc, nextFrame: CommandsAndRobotState) { + const lastNewTipCommand = last(nextFrame.commands.filter(c => c.command === 'pick-up-tip')) + const newTipParams = lastNewTipCommand && + lastNewTipCommand.command === 'pick-up-tip' && + lastNewTipCommand.params + + if (newTipParams) { + return {...acc, prevActiveTips: {...newTipParams}} + } + return acc +} + +type SubstepTimelineAcc = { timeline: Array, errors: ?Array, + prevActiveTips: ?TipLocation, + prevRobotState: RobotState, } + const substepTimelineSingle = (commandCreators: Array) => (initialRobotState: RobotState): Array => { - let prevRobotState = initialRobotState - const timeline = commandCreators.reduce((acc: SubstepTimeline, commandCreator: CommandCreator, index: number) => { + const timeline = commandCreators.reduce((acc: SubstepTimelineAcc, commandCreator: CommandCreator, index: number) => { // error short-circuit if (acc.errors) return acc - const nextFrame = commandCreator(prevRobotState) + const nextFrame = commandCreator(acc.prevRobotState) if (nextFrame.errors) { - return {timeline: acc.timeline, errors: nextFrame.errors} + return {...acc, errors: nextFrame.errors} } // NOTE: only aspirate and dispense commands will appear alone in atomic commands // from compound command creators (e.g. transfer, distribute, etc.) - const isAtomic = nextFrame.commands.length === 1 - const commandGroup = nextFrame.commands[0] - if (isAtomic && (commandGroup.command === 'aspirate' || commandGroup.command === 'dispense')) { + const firstCommand = nextFrame.commands[0] + if ( + firstCommand.command === 'aspirate' || + firstCommand.command === 'dispense') { + assert(nextFrame.commands.length === 1, + `substepTimeline expected nextFrame to have only single commands for ${firstCommand.command}`) + + const commandGroup = firstCommand const {well, volume, labware} = commandGroup.params const wellInfo = { labware, wells: [well], - preIngreds: prevRobotState.liquidState.labware[labware][well], + preIngreds: acc.prevRobotState.liquidState.labware[labware][well], postIngreds: nextFrame.robotState.liquidState.labware[labware][well], } - prevRobotState = nextFrame.robotState const ingredKey = commandGroup.command === 'aspirate' ? 'source' : 'dest' - return {timeline: [...acc.timeline, {volume, [ingredKey]: wellInfo}], errors: null} + return { + ...acc, + timeline: [ + ...acc.timeline, + { + volume, + [ingredKey]: wellInfo, + activeTips: acc.prevActiveTips, + }, + ], + prevRobotState: nextFrame.robotState, + } } else { - return acc + return { + ..._conditionallyUpdateActiveTips(acc, nextFrame), + prevRobotState: nextFrame.robotState, + } } - }, {timeline: [], errors: null}) + }, {timeline: [], errors: null, prevActiveTips: null, prevRobotState: initialRobotState}) return timeline.timeline } @@ -54,38 +93,57 @@ const substepTimeline = ( if (context.channels === 1) { return substepTimelineSingle(commandCreators) } else { + // timeline for multi-channel substep context return ( (initialRobotState: RobotState): Array => { - let prevRobotState = initialRobotState - const timeline = commandCreators.reduce((acc: SubstepTimeline, commandCreator: CommandCreator, index: number) => { + const timeline = commandCreators.reduce((acc: SubstepTimelineAcc, commandCreator: CommandCreator, index: number) => { // error short-circuit if (acc.errors) return acc - const nextFrame = commandCreator(prevRobotState) + const nextFrame = commandCreator(acc.prevRobotState) if (nextFrame.errors) { - return {timeline: acc.timeline, errors: nextFrame.errors} + return {...acc, errors: nextFrame.errors} } - const isAtomic = nextFrame.commands.length === 1 - const commandGroup = nextFrame.commands[0] - if (isAtomic && (commandGroup.command === 'aspirate' || commandGroup.command === 'dispense')) { - const {well, volume, labware} = commandGroup.params + const firstCommand = nextFrame.commands[0] + if ( + firstCommand.command === 'aspirate' || + firstCommand.command === 'dispense' + ) { + assert(nextFrame.commands.length === 1, + `substepTimeline expected nextFrame to have only single commands for ${firstCommand.command}`) + + const {well, volume, labware} = firstCommand.params const labwareType = context.getLabwareType && context.getLabwareType(labware) const wellsForTips = context.channels && labwareType && getWellsForTips(context.channels, labwareType, well).wellsForTips const wellInfo = { labware, wells: wellsForTips || [], - preIngreds: wellsForTips ? pick(prevRobotState.liquidState.labware[labware], wellsForTips) : {}, + preIngreds: wellsForTips ? pick(acc.prevRobotState.liquidState.labware[labware], wellsForTips) : {}, postIngreds: wellsForTips ? pick(nextFrame.robotState.liquidState.labware[labware], wellsForTips) : {}, } - prevRobotState = nextFrame.robotState - const ingredKey = commandGroup.command === 'aspirate' ? 'source' : 'dest' - return {timeline: [...acc.timeline, {volume, [ingredKey]: wellInfo}], errors: null} + + const ingredKey = firstCommand.command === 'aspirate' ? 'source' : 'dest' + return { + ...acc, + timeline: [ + ...acc.timeline, + { + volume, + [ingredKey]: wellInfo, + activeTips: acc.prevActiveTips, + }, + ], + prevRobotState: nextFrame.robotState, + } } else { - return acc + return { + ..._conditionallyUpdateActiveTips(acc, nextFrame), + prevRobotState: nextFrame.robotState, + } } - }, {timeline: [], errors: null}) + }, {timeline: [], errors: null, prevActiveTips: null, prevRobotState: initialRobotState}) return timeline.timeline } diff --git a/protocol-designer/src/steplist/test/reducers.test.js b/protocol-designer/src/steplist/test/reducers.test.js index c397589bff1..719117c0d20 100644 --- a/protocol-designer/src/steplist/test/reducers.test.js +++ b/protocol-designer/src/steplist/test/reducers.test.js @@ -14,12 +14,12 @@ describe('steps reducer', () => { const state = {} const action = { type: 'ADD_STEP', - payload: {id: 123, stepType: 'transfer'}, + payload: {id: '123', stepType: 'transfer'}, } expect(steps(state, action)).toEqual({ '123': { - id: 123, + id: '123', stepType: 'transfer', title: 'transfer', // title gets added }, @@ -29,24 +29,24 @@ describe('steps reducer', () => { test('second add step', () => { const state = { '333': { - id: 333, + id: '333', stepType: 'mix', title: 'mix', }, } const action = { type: 'ADD_STEP', - payload: {id: 123, stepType: 'transfer'}, + payload: {id: '123', stepType: 'transfer'}, } expect(steps(state, action)).toEqual({ '333': { - id: 333, + id: '333', stepType: 'mix', title: 'mix', }, '123': { - id: 123, + id: '123', stepType: 'transfer', title: 'transfer', }, @@ -59,7 +59,7 @@ describe('collapsedSteps reducer', () => { const state = {} const action = { type: 'ADD_STEP', - payload: {id: 1, stepType: 'transfer'}, + payload: {id: '1', stepType: 'transfer'}, } expect(collapsedSteps(state, action)).toEqual({ '1': false, // default is false: not collapsed @@ -75,7 +75,7 @@ describe('collapsedSteps reducer', () => { } const action = { type: 'TOGGLE_STEP_COLLAPSED', - payload: 3, + payload: '3', } expect(collapsedSteps(state, action)).toEqual({ '1': true, @@ -94,7 +94,7 @@ describe('collapsedSteps reducer', () => { } const action = { type: 'TOGGLE_STEP_COLLAPSED', - payload: 2, + payload: '2', } expect(collapsedSteps(state, action)).toEqual({ '1': true, @@ -110,18 +110,18 @@ describe('orderedSteps reducer', () => { const state = [] const action = { type: 'ADD_STEP', - payload: {id: 123, stepType: 'transfer'}, + payload: {id: '123', stepType: 'transfer'}, } - expect(orderedSteps(state, action)).toEqual([123]) + expect(orderedSteps(state, action)).toEqual(['123']) }) test('second add step', () => { - const state = [123] + const state = ['123'] const action = { type: 'ADD_STEP', - payload: {id: 22, stepType: 'transfer'}, + payload: {id: '22', stepType: 'transfer'}, } - expect(orderedSteps(state, action)).toEqual([123, 22]) + expect(orderedSteps(state, action)).toEqual(['123', '22']) }) describe('reorder steps', () => { @@ -209,7 +209,7 @@ describe('orderedSteps reducer', () => { describe('selectedItem reducer', () => { test('select step', () => { - const stepId = 123 + const stepId = '123' const action = { type: 'SELECT_STEP', payload: stepId, @@ -237,7 +237,7 @@ describe('stepCreationButtonExpanded reducer', () => { test('close (or stay closed) on newly added step', () => { const action = { type: 'ADD_STEP', - payload: {id: 123, stepType: 'transfer'}, + payload: {id: '123', stepType: 'transfer'}, } expect(stepCreationButtonExpanded(true, action)).toEqual(false) expect(stepCreationButtonExpanded(false, action)).toEqual(false) diff --git a/protocol-designer/src/steplist/types.js b/protocol-designer/src/steplist/types.js index dc0e707afac..6cf59e343cf 100644 --- a/protocol-designer/src/steplist/types.js +++ b/protocol-designer/src/steplist/types.js @@ -1,9 +1,14 @@ // @flow import type {PauseFormData, CommandCreatorData} from '../step-generation' -import type {FormData, StepIdType, StepType, TransferLikeStepType} from '../form-types' +import type { + FormData, + StepIdType, + StepFieldName, + StepType, + TransferLikeStepType, +} from '../form-types' import type {BaseState} from '../types' import type {FormError} from './formLevel/errors' -import type {StepFieldName} from './fieldLevel' // sections of the form that are expandable/collapsible export type FormSectionState = {aspirate: boolean, dispense: boolean} @@ -15,8 +20,8 @@ export const END_TERMINAL_ITEM_ID: '__end__' = '__end__' export type TerminalItemId = typeof START_TERMINAL_ITEM_ID | typeof END_TERMINAL_ITEM_ID export type WellIngredientNames = {[ingredId: string]: string} - export type WellIngredientVolumeData = {[ingredId: string]: {volume: number}} +export type TipLocation = {labware: string, well: string} export type SubstepIdentifier = {| stepId: StepIdType, @@ -36,6 +41,7 @@ export type SourceDestData = { export type SubstepTimelineFrame = { substepIndex?: number, + activeTips: ?TipLocation, source?: SourceDestData, dest?: SourceDestData, volume?: ?number, @@ -49,6 +55,7 @@ export type SubstepWellData = { } export type StepItemSourceDestRow = { + activeTips: ?TipLocation, substepIndex?: number, source?: SubstepWellData, dest?: SubstepWellData, diff --git a/protocol-designer/src/top-selectors/substep-highlight.js b/protocol-designer/src/top-selectors/substep-highlight.js index 2c11597e09f..1ccce981cb1 100644 --- a/protocol-designer/src/top-selectors/substep-highlight.js +++ b/protocol-designer/src/top-selectors/substep-highlight.js @@ -12,7 +12,7 @@ import {selectors as fileDataSelectors} from '../file-data' import type {Selector} from '../types' import type {SubstepItemData} from '../steplist/types' -type AllWellHighlights = {[wellName: string]: true} // NOTE: all keys are true. There's a TODO in SelectablePlate.js about making this a Set of well strings +type AllWellHighlights = {[wellName: string]: true} // NOTE: all keys are true. There's a TODO in HighlightableLabware.js about making this a Set of well strings type AllWellHighlightsAllLabware = {[labwareId: string]: AllWellHighlights} function _wellsForPipette (pipetteChannels: 1 | 8, labwareType: string, wells: Array): Array { @@ -135,12 +135,12 @@ function _getSelectedWellsForSubstep ( } export const wellHighlightsByLabwareId: Selector = createSelector( - fileDataSelectors.robotStateTimeline, + fileDataSelectors.getRobotStateTimeline, steplistSelectors.getArgsAndErrorsByStepId, steplistSelectors.getHoveredStepId, steplistSelectors.getHoveredSubstep, allSubsteps, - steplistSelectors.orderedSteps, + steplistSelectors.getOrderedSteps, (robotStateTimeline, allStepArgsAndErrors, hoveredStepId, hoveredSubstep, allSubsteps, orderedSteps) => { const timeline = robotStateTimeline.timeline const stepId = hoveredStepId diff --git a/protocol-designer/src/top-selectors/substeps.js b/protocol-designer/src/top-selectors/substeps.js index 70e41b93250..15451d71805 100644 --- a/protocol-designer/src/top-selectors/substeps.js +++ b/protocol-designer/src/top-selectors/substeps.js @@ -17,10 +17,10 @@ import type {SubstepItemData} from '../steplist/types' type AllSubsteps = {[StepIdType]: ?SubstepItemData} export const allSubsteps: Selector = createSelector( steplistSelectors.getArgsAndErrorsByStepId, - pipetteSelectors.equippedPipettes, + pipetteSelectors.getEquippedPipettes, labwareIngredSelectors.getLabwareTypes, - steplistSelectors.orderedSteps, - fileDataSelectors.robotStateTimeline, + steplistSelectors.getOrderedSteps, + fileDataSelectors.getRobotStateTimeline, fileDataSelectors.getInitialRobotState, ( allStepArgsAndErrors, @@ -30,8 +30,9 @@ export const allSubsteps: Selector = createSelector( robotStateTimeline, _initialRobotState, ) => { + const timeline = [{robotState: _initialRobotState}, ...robotStateTimeline.timeline] + return orderedSteps.reduce((acc: AllSubsteps, stepId, timelineIndex) => { - const timeline = [{robotState: _initialRobotState}, ...robotStateTimeline.timeline] const robotState = timeline[timelineIndex] && timeline[timelineIndex].robotState const substeps = generateSubsteps( @@ -41,6 +42,7 @@ export const allSubsteps: Selector = createSelector( robotState, stepId ) + return { ...acc, [stepId]: substeps, diff --git a/protocol-designer/src/top-selectors/tip-contents/index.js b/protocol-designer/src/top-selectors/tip-contents/index.js index a131261c814..8578b4d0fe1 100644 --- a/protocol-designer/src/top-selectors/tip-contents/index.js +++ b/protocol-designer/src/top-selectors/tip-contents/index.js @@ -2,6 +2,7 @@ import {createSelector} from 'reselect' import noop from 'lodash/noop' import * as StepGeneration from '../../step-generation' +import {allSubsteps as getAllSubsteps} from '../substeps' import { selectors as steplistSelectors, START_TERMINAL_ITEM_ID, @@ -32,16 +33,16 @@ function getTipHighlighted ( if (c.command === 'pick-up-tip' && c.params.labware === labwareId) { const commandWellName = c.params.well const pipetteId = c.params.pipette - const labwareName = StepGeneration.getLabwareType(labwareId, robotState) + const labwareType = StepGeneration.getLabwareType(labwareId, robotState) const channels = StepGeneration.getPipetteChannels(pipetteId, robotState) - if (!labwareName) { - console.error(`Labware ${labwareId} missing labwareName. Could not get tip highlight state`) + if (!labwareType) { + console.error(`Labware ${labwareId} missing labwareType. Could not get tip highlight state`) return false } else if (channels === 1) { return commandWellName === wellName } else if (channels === 8) { - const wellSet = getWellSetForMultichannel(labwareName, commandWellName) + const wellSet = getWellSetForMultichannel(labwareType, commandWellName) return Boolean(wellSet && wellSet.includes(wellName)) } else { console.error(`Unexpected number of channels: ${channels || '?'}. Could not get tip highlight state`) @@ -86,14 +87,16 @@ const getLastValidTips: GetTipSelector = createSelector( ) export const getTipsForCurrentStep: GetTipSelector = createSelector( - steplistSelectors.orderedSteps, - fileDataSelectors.robotStateTimeline, + steplistSelectors.getOrderedSteps, + fileDataSelectors.getRobotStateTimeline, steplistSelectors.getHoveredStepId, steplistSelectors.getActiveItem, getInitialTips, getLastValidTips, getLabwareIdProp, - (orderedSteps, robotStateTimeline, hoveredStepId, activeItem, initialTips, lastValidTips, labwareId) => { + steplistSelectors.getHoveredSubstep, + getAllSubsteps, + (orderedSteps, robotStateTimeline, hoveredStepId, activeItem, initialTips, lastValidTips, labwareId, hoveredSubstepIdentifier, allSubsteps) => { if (!activeItem.isStep) { const terminalId = activeItem.id if (terminalId === START_TERMINAL_ITEM_ID) { @@ -128,9 +131,39 @@ export const getTipsForCurrentStep: GetTipSelector = createSelector( : false // show highlights of tips used by current frame, if user is hovering - const highlighted = (hovered && currentFrame) - ? getTipHighlighted(labwareId, wellName, currentFrame) - : false + let highlighted = false + if (hoveredSubstepIdentifier && currentFrame) { + const {substepIndex} = hoveredSubstepIdentifier + const substepsForStep = allSubsteps[hoveredSubstepIdentifier.stepId] + + if (substepsForStep && substepsForStep.stepType !== 'pause') { + if (substepsForStep.multichannel) { + const hoveredSubstepData = substepsForStep.multiRows[substepIndex][0] // just use first multi row + + const labwareType = StepGeneration.getLabwareType(labwareId, currentFrame.robotState) + const wellSet = (labwareType && hoveredSubstepData.activeTips) + ? getWellSetForMultichannel(labwareType, hoveredSubstepData.activeTips.well) + : [] + + highlighted = (hoveredSubstepData && + hoveredSubstepData.activeTips && + hoveredSubstepData.activeTips.labware === labwareId && + Boolean(wellSet && wellSet.includes(wellName)) + ) || false + } else { + // single-channel + const hoveredSubstepData = substepsForStep.rows[substepIndex] + + highlighted = (hoveredSubstepData && + hoveredSubstepData.activeTips && + hoveredSubstepData.activeTips.labware === labwareId && + hoveredSubstepData.activeTips.well === wellName + ) || false + } + } + } else if (hovered && currentFrame) { + highlighted = getTipHighlighted(labwareId, wellName, currentFrame) + } return { empty, diff --git a/protocol-designer/src/top-selectors/well-contents/__tests__/wellContentsAllLabware.test.js b/protocol-designer/src/top-selectors/well-contents/__tests__/getWellContentsAllLabware.test.js similarity index 89% rename from protocol-designer/src/top-selectors/well-contents/__tests__/wellContentsAllLabware.test.js rename to protocol-designer/src/top-selectors/well-contents/__tests__/getWellContentsAllLabware.test.js index a7a54fa4fae..18d2a2cd280 100644 --- a/protocol-designer/src/top-selectors/well-contents/__tests__/wellContentsAllLabware.test.js +++ b/protocol-designer/src/top-selectors/well-contents/__tests__/getWellContentsAllLabware.test.js @@ -1,4 +1,4 @@ -import wellContentsAllLabware from '../wellContentsAllLabware' +import getWellContentsAllLabware from '../getWellContentsAllLabware' // FIXTURES const baseIngredFields = { @@ -53,8 +53,8 @@ const defaultWellContents = { const container1MaxVolume = 400 -describe('wellContentsAllLabware', () => { - const singleIngredResult = wellContentsAllLabware.resultFunc( +describe('getWellContentsAllLabware', () => { + const singleIngredResult = getWellContentsAllLabware.resultFunc( containerState, // all labware ingredsByLabwareXXSingleIngred, {id: 'container1Id'}, // selected labware @@ -63,7 +63,7 @@ describe('wellContentsAllLabware', () => { ) // TODO: 2nd test case - // const twoIngredResult = selectors.wellContentsAllLabware.resultFunc( + // const twoIngredResult = selectors.getWellContentsAllLabware.resultFunc( // containerState, // all labware // ingredsByLabwareXXTwoIngred, // containerState.container2Id, // selected labware diff --git a/protocol-designer/src/top-selectors/well-contents/wellContentsAllLabware.js b/protocol-designer/src/top-selectors/well-contents/getWellContentsAllLabware.js similarity index 71% rename from protocol-designer/src/top-selectors/well-contents/wellContentsAllLabware.js rename to protocol-designer/src/top-selectors/well-contents/getWellContentsAllLabware.js index 829c7f5507a..6e5448828a6 100644 --- a/protocol-designer/src/top-selectors/well-contents/wellContentsAllLabware.js +++ b/protocol-designer/src/top-selectors/well-contents/getWellContentsAllLabware.js @@ -54,32 +54,32 @@ const _getWellContents = ( }, {}) } -const wellContentsAllLabware: Selector = createSelector( - labwareIngredSelectors.getLabware, - labwareIngredSelectors.getIngredientLocations, - labwareIngredSelectors.getSelectedContainer, +const getWellContentsAllLabware: Selector = createSelector( + labwareIngredSelectors.getLabwareById, + labwareIngredSelectors.getLiquidsByLabwareId, + labwareIngredSelectors.getSelectedLabware, wellSelectionSelectors.getSelectedWells, wellSelectionSelectors.getHighlightedWells, - (_labware, _ingredsByLabware, _selectedLabware, _selectedWells, _highlightedWells) => { - const allLabwareIds: Array = Object.keys(_labware) // TODO Ian 2018-05-29 weird flow error w/o annotation + (labwareById, liquidsByLabware, selectedLabware, selectedWells, highlightedWells) => { + const allLabwareIds: Array = Object.keys(labwareById) // TODO Ian 2018-05-29 weird flow error w/o annotation return allLabwareIds.reduce((acc: {[labwareId: string]: ContentsByWell | null}, labwareId: string) => { - const ingredsForLabware = _ingredsByLabware[labwareId] - const isSelectedLabware = _selectedLabware && (_selectedLabware.id === labwareId) + const liquidsForLabware = liquidsByLabware[labwareId] + const isSelectedLabware = selectedLabware && (selectedLabware.id === labwareId) - // Skip labware ids with no ingreds + // Skip labware ids with no liquids return { ...acc, [labwareId]: _getWellContents( - _labware[labwareId] && _labware[labwareId].type, - ingredsForLabware, + labwareById[labwareId] && labwareById[labwareId].type, + liquidsForLabware, // Only give _getWellContents the selection data if it's a selected container - isSelectedLabware ? _selectedWells : null, - isSelectedLabware ? _highlightedWells : null + isSelectedLabware ? selectedWells : null, + isSelectedLabware ? highlightedWells : null ), } }, {}) } ) -export default wellContentsAllLabware +export default getWellContentsAllLabware diff --git a/protocol-designer/src/top-selectors/well-contents/index.js b/protocol-designer/src/top-selectors/well-contents/index.js index 56b277b8247..f8aefba994a 100644 --- a/protocol-designer/src/top-selectors/well-contents/index.js +++ b/protocol-designer/src/top-selectors/well-contents/index.js @@ -22,8 +22,8 @@ import type { // TODO Ian 2018-04-19: factor out all these selectors to their own files, // and make this index.js just imports and exports. -import wellContentsAllLabwareExport from './wellContentsAllLabware' -export const wellContentsAllLabware = wellContentsAllLabwareExport +import getWellContentsAllLabware from './getWellContentsAllLabware' +export {getWellContentsAllLabware} export type {WellContentsByLabware} function _wellContentsForWell ( @@ -68,11 +68,11 @@ export function _wellContentsForLabware ( ) } -export const allWellContentsForSteps: Selector> = createSelector( +export const getAllWellContentsForSteps: Selector> = createSelector( fileDataSelectors.getInitialRobotState, - fileDataSelectors.robotStateTimeline, - (_initialRobotState, _robotStateTimeline) => { - const timeline = [{robotState: _initialRobotState}, ..._robotStateTimeline.timeline] + fileDataSelectors.getRobotStateTimeline, + (initialRobotState, robotStateTimeline) => { + const timeline = [{robotState: initialRobotState}, ...robotStateTimeline.timeline] return timeline.map((timelineStep, timelineIndex) => { const liquidState = timelineStep.robotState.liquidState.labware @@ -93,7 +93,7 @@ export const allWellContentsForSteps: Selector> = c } ) -export const lastValidWellContents: Selector = createSelector( +export const getLastValidWellContents: Selector = createSelector( fileDataSelectors.lastValidRobotState, (robotState) => { return mapValues( @@ -109,9 +109,9 @@ export const lastValidWellContents: Selector = createSele } ) -export const selectedWellsMaxVolume: Selector = createSelector( +export const getSelectedWellsMaxVolume: Selector = createSelector( wellSelectionSelectors.getSelectedWells, - labwareIngredSelectors.getSelectedContainer, + labwareIngredSelectors.getSelectedLabware, (selectedWells, selectedContainer) => { const selectedWellNames = Object.keys(selectedWells) const selectedContainerType = selectedContainer && selectedContainer.type @@ -135,8 +135,8 @@ type CommonWellValues = {ingredientId: ?string, volume: ?number} * or null if there is not a single common ingredient group */ export const getSelectedWellsCommonValues: Selector = createSelector( wellSelectionSelectors.getSelectedWells, - labwareIngredSelectors.getSelectedContainerId, - labwareIngredSelectors.getIngredientLocations, + labwareIngredSelectors.getSelectedLabwareId, + labwareIngredSelectors.getLiquidsByLabwareId, (selectedWellsObj, labwareId, allIngreds) => { if (!labwareId) return {ingredientId: null, volume: null} const ingredsInLabware = allIngreds[labwareId] diff --git a/protocol-designer/src/tutorial/actions.js b/protocol-designer/src/tutorial/actions.js index 06af8c4c9d6..001e637aa43 100644 --- a/protocol-designer/src/tutorial/actions.js +++ b/protocol-designer/src/tutorial/actions.js @@ -23,3 +23,7 @@ export const removeHint = (hintKey: HintKey, rememberDismissal: boolean): Remove type: 'REMOVE_HINT', payload: {hintKey, rememberDismissal}, }) + +export const clearAllHintDismissals = () => ({ + type: 'CLEAR_ALL_HINT_DISMISSALS', +}) diff --git a/protocol-designer/src/tutorial/reducers.js b/protocol-designer/src/tutorial/reducers.js index ad472b13c47..2d9aab0cbbe 100644 --- a/protocol-designer/src/tutorial/reducers.js +++ b/protocol-designer/src/tutorial/reducers.js @@ -23,6 +23,7 @@ const dismissedHints = handleActions({ const {hintKey, rememberDismissal} = action.payload return {...state, [hintKey]: {rememberDismissal}} }, + CLEAR_ALL_HINT_DISMISSALS: () => dismissedHintsInitialState, }, dismissedHintsInitialState) export function dismissedHintsPersist (state: DismissedHintReducerState) { diff --git a/protocol-designer/src/tutorial/selectors.js b/protocol-designer/src/tutorial/selectors.js index 768a7372727..bce813ef7b0 100644 --- a/protocol-designer/src/tutorial/selectors.js +++ b/protocol-designer/src/tutorial/selectors.js @@ -1,12 +1,13 @@ // @flow import {createSelector} from 'reselect' -import type {BaseState} from '../types' +import isEmpty from 'lodash/isEmpty' +import type {BaseState, Selector} from '../types' const rootSelector = (state: BaseState) => state.tutorial export const getHint = createSelector( rootSelector, - tutorial => { + (tutorial) => { const dismissedKeys = Object.keys(tutorial.dismissedHints) const hints = tutorial.hints.filter(hintKey => !dismissedKeys.includes(hintKey)) @@ -15,3 +16,8 @@ export const getHint = createSelector( return hints[0] } ) + +export const getCanClearHintDismissals: Selector = createSelector( + rootSelector, + (tutorial) => !isEmpty(tutorial.dismissedHints) +) diff --git a/protocol-designer/src/utils/index.js b/protocol-designer/src/utils/index.js index 6a62a6eb667..6f96112c864 100644 --- a/protocol-designer/src/utils/index.js +++ b/protocol-designer/src/utils/index.js @@ -24,7 +24,7 @@ export const formConnectorFactory = ( export const uuid: () => string = uuidv1 -// Collision detection for SelectionRect / SelectablePlate +// Collision detection for SelectionRect / SelectableLabware export const rectCollision = (rect1: BoundingRect, rect2: BoundingRect) => ( rect1.x < rect2.x + rect2.width && diff --git a/protocol-designer/src/well-selection/actions.js b/protocol-designer/src/well-selection/actions.js index c1fd9d78f05..5fa4285a9fa 100644 --- a/protocol-designer/src/well-selection/actions.js +++ b/protocol-designer/src/well-selection/actions.js @@ -7,8 +7,8 @@ import {selectors as steplistSelectors} from '../steplist' import {selectors as pipetteSelectors} from '../pipettes' import {selectors as labwareIngredSelectors} from '../labware-ingred/reducers' -import type {StepFieldName} from '../steplist/fieldLevel' import type {ThunkDispatch, GetState} from '../types' +import type {StepFieldName} from '../form-types' import type {Wells} from '../labware-ingred/types' import type {Channels} from '@opentrons/components' @@ -59,7 +59,7 @@ export const openWellSelectionModal = (payload: OpenWellSelectionModalPayload) = (dispatch: ThunkDispatch<*>, getState: GetState) => { const state = getState() const accessor = payload.formFieldAccessor - const formData = steplistSelectors.formData(state) + const formData = steplistSelectors.getUnsavedForm(state) const wells: Wells = (accessor && formData && formData[accessor] && _wellArrayToObj(formData[accessor])) || {} @@ -67,8 +67,8 @@ export const openWellSelectionModal = (payload: OpenWellSelectionModalPayload) = // initially selected wells in form get selected in state before modal opens dispatch(selectWells(wells)) - const pipettes = pipetteSelectors.equippedPipettes(state) - const labware = labwareIngredSelectors.getLabware(state) + const pipettes = pipetteSelectors.getEquippedPipettes(state) + const labware = labwareIngredSelectors.getLabwareById(state) // TODO type this action, make an underline fn action creator dispatch({ @@ -89,13 +89,13 @@ export const closeWellSelectionModal = (): * => ({ export const saveWellSelectionModal = () => (dispatch: ThunkDispatch<*>, getState: GetState) => { const state = getState() - const wellSelectionModalData = selectors.wellSelectionModalData(state) + const wellSelectionModalData = selectors.getWellSelectionModalData(state) // this if-else is mostly for Flow if (wellSelectionModalData) { dispatch(changeFormInput({ update: { - [wellSelectionModalData.formFieldAccessor]: selectors.selectedWellNames(state), + [wellSelectionModalData.formFieldAccessor]: selectors.getSelectedWellNames(state), }, })) } else { diff --git a/protocol-designer/src/well-selection/selectors.js b/protocol-designer/src/well-selection/selectors.js index a350521d2fd..caeb8889399 100644 --- a/protocol-designer/src/well-selection/selectors.js +++ b/protocol-designer/src/well-selection/selectors.js @@ -9,7 +9,7 @@ import type {OpenWellSelectionModalPayload} from './actions' const rootSelector = (state: BaseState) => state.wellSelection -const wellSelectionModalData: Selector = createSelector( +const getWellSelectionModalData: Selector = createSelector( rootSelector, s => s.wellSelectionModal ) @@ -47,24 +47,24 @@ function _primaryToAllWells ( const getSelectedWells: Selector = createSelector( getSelectedPrimaryWells, - wellSelectionModalData, + getWellSelectionModalData, _primaryToAllWells ) const getHighlightedWells: Selector = createSelector( getHighlightedPrimaryWells, - wellSelectionModalData, + getWellSelectionModalData, _primaryToAllWells ) -const selectedWellNames: Selector> = createSelector( +const getSelectedWellNames: Selector> = createSelector( (state: BaseState) => rootSelector(state).selectedWells.selected, selectedWells => Object.keys(selectedWells).sort(sortWells) ) export default { - selectedWellNames, + getSelectedWellNames, getSelectedWells, getHighlightedWells, - wellSelectionModalData, + getWellSelectionModalData, } diff --git a/protocol-library-kludge/CHANGELOG.md b/protocol-library-kludge/CHANGELOG.md index d169702e0db..b9c5f63c91e 100644 --- a/protocol-library-kludge/CHANGELOG.md +++ b/protocol-library-kludge/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + +**Note:** Version bump only for package protocol-library-kludge + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + +**Note:** Version bump only for package protocol-library-kludge + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + +**Note:** Version bump only for package protocol-library-kludge + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/protocol-library-kludge/package.json b/protocol-library-kludge/package.json index 24b51364806..0fff39d9bdf 100644 --- a/protocol-library-kludge/package.json +++ b/protocol-library-kludge/package.json @@ -9,7 +9,7 @@ }, "name": "protocol-library-kludge", "private": true, - "version": "3.6.0-beta.0", + "version": "3.6.1", "productName": "Opentrons Protocol Library", "description": "Protocol library stuff (WIP)", "main": "src/index.js", @@ -19,11 +19,11 @@ "homepage": "https://github.com/Opentrons/opentrons", "license": "Apache-2.0", "dependencies": { - "@opentrons/components": "3.6.0-beta.0", + "@opentrons/components": "3.6.1", "classnames": "^2.2.5", "lodash": "^4.17.4", - "react": "^16.2.0", - "react-dom": "^16.2.0", + "react": "^16.6.3", + "react-dom": "^16.6.3", "react-hot-loader": "^3.0.0-beta.7", "react-redux": "^5.0.6", "react-router-dom": "^4.1.1" diff --git a/scripts/travis-env.sh b/scripts/travis-env.sh deleted file mode 100755 index be9a4c99b29..00000000000 --- a/scripts/travis-env.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -app_os_target=$TRAVIS_OS_NAME - -# if os is linux and osx won't run, build both linux and osx -# osx runs on tags and mainline/RC (edge, release_*) branches -if [[ - $TRAVIS_OS_NAME = linux && - ! $TRAVIS_TAG && - ! $TRAVIS_BRANCH =~ ^(edge|release_.+)$ -]]; then - # TODO(mc, 2018-03-27): remove posix target in favor of individual - # build_$(OS) variables - app_os_target="posix" -fi - -export APP_OS_TARGET=$app_os_target diff --git a/scripts/travis-install.sh b/scripts/travis-install.sh deleted file mode 100755 index 9802634b06f..00000000000 --- a/scripts/travis-install.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -# install node.js -nvm install - -# install osx dependencies -if [ "$TRAVIS_OS_NAME" = "osx" ]; then - brew update - brew upgrade pyenv - brew install yarn --without-node - pyenv install --skip-existing - eval "$(pyenv init -)" -fi - -# report versions for sanity -echo "make --version" -make --version - -echo "python --version" -python --version - -echo "pip --version" -pip --version - -echo "node --version" -node --version - -echo "yarn --version" -yarn --version diff --git a/shared-data/CHANGELOG.md b/shared-data/CHANGELOG.md index 4c057cd740d..9f4ada8f6f1 100644 --- a/shared-data/CHANGELOG.md +++ b/shared-data/CHANGELOG.md @@ -3,6 +3,45 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + +**Note:** Version bump only for package @opentrons/shared-data + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + + +### Bug Fixes + +* **shared-data:** fix total-liquid-volume of opentrons-tuberack-50ml ([#2744](https://github.com/Opentrons/opentrons/issues/2744)) ([aef8cc8](https://github.com/Opentrons/opentrons/commit/aef8cc8)), closes [#2743](https://github.com/Opentrons/opentrons/issues/2743) + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + + +### Bug Fixes + +* **api:** re-position p1000 droptip/blowout positions ([#2681](https://github.com/Opentrons/opentrons/issues/2681)) ([f0cf01b](https://github.com/Opentrons/opentrons/commit/f0cf01b)) + + +### Features + +* **api:** Add 1.5ml tuberack to old labware definition section ([#2679](https://github.com/Opentrons/opentrons/issues/2679)) ([2739038](https://github.com/Opentrons/opentrons/commit/2739038)) +* **api:** Adds pipette models v1.4 to robot config ([#2689](https://github.com/Opentrons/opentrons/issues/2689)) ([fd9c38a](https://github.com/Opentrons/opentrons/commit/fd9c38a)) + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/shared-data/definitions/opentrons-tuberack-1.5ml-eppendorf.json b/shared-data/definitions/opentrons-tuberack-1.5ml-eppendorf.json new file mode 100644 index 00000000000..430b1c34c31 --- /dev/null +++ b/shared-data/definitions/opentrons-tuberack-1.5ml-eppendorf.json @@ -0,0 +1,311 @@ +{ + "metadata": { + "name": "opentrons-tuberack-1.5ml-eppendorf", + "format": "irregular", + "displayCategory": "tube-rack" + }, + "ordering": [ + [ + "A1", + "B1", + "C1", + "D1" + ], + [ + "A2", + "B2", + "C2", + "D2" + ], + [ + "A3", + "B3", + "C3", + "D3" + ], + [ + "A4", + "B4", + "C4", + "D4" + ], + [ + "A5", + "B5", + "C5", + "D5" + ], + [ + "A6", + "B6", + "C6", + "D6" + ] + ], + "wells": { + "A1": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 13.71, + "y": 68.91, + "z": 43.3 + }, + "A2": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 33.6, + "y": 68.91, + "z": 43.3 + }, + "A3": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 53.49, + "y": 68.91, + "z": 43.3 + }, + "A4": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 73.38, + "y": 68.91, + "z": 43.3 + }, + "A5": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 93.27, + "y": 68.91, + "z": 43.3 + }, + "A6": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 113.16, + "y": 68.91, + "z": 43.3 + }, + "B1": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 13.71, + "y": 49.63, + "z": 43.3 + }, + "B2": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 33.6, + "y": 49.63, + "z": 43.3 + }, + "B3": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 53.49, + "y": 49.63, + "z": 43.3 + }, + "B4": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 73.38, + "y": 49.63, + "z": 43.3 + }, + "B5": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 93.27, + "y": 49.63, + "z": 43.3 + }, + "B6": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 113.16, + "y": 49.63, + "z": 43.3 + }, + "C1": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 13.71, + "y": 30.35, + "z": 43.3 + }, + "C2": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 33.6, + "y": 30.35, + "z": 43.3 + }, + "C3": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 53.49, + "y": 30.35, + "z": 43.3 + }, + "C4": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 73.38, + "y": 30.35, + "z": 43.3 + }, + "C5": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 93.27, + "y": 30.35, + "z": 43.3 + }, + "C6": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 113.16, + "y": 30.35, + "z": 43.3 + }, + "D1": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 13.71, + "y": 11.07, + "z": 43.3 + }, + "D2": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 33.6, + "y": 11.07, + "z": 43.3 + }, + "D3": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 53.49, + "y": 11.07, + "z": 43.3 + }, + "D4": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 73.38, + "y": 11.07, + "z": 43.3 + }, + "D5": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 93.27, + "y": 11.07, + "z": 43.3 + }, + "D6": { + "depth": 37.0, + "diameter": 9, + "height": 38.5, + "length": 9, + "total-liquid-volume": 1500, + "width": 9, + "x": 113.16, + "y": 11.07, + "z": 43.3 + } + } +} diff --git a/shared-data/definitions/opentrons-tuberack-50ml.json b/shared-data/definitions/opentrons-tuberack-50ml.json index 43e617749f6..dd63341fb34 100644 --- a/shared-data/definitions/opentrons-tuberack-50ml.json +++ b/shared-data/definitions/opentrons-tuberack-50ml.json @@ -24,7 +24,7 @@ "diameter": 17, "height": 117.98, "length": 17, - "total-liquid-volume": 15000, + "total-liquid-volume": 50000, "width": 17, "x": 28.5, "y": 54.105, @@ -35,7 +35,7 @@ "diameter": 17, "height": 117.98, "length": 17, - "total-liquid-volume": 15000, + "total-liquid-volume": 50000, "width": 17, "x": 63.5, "y": 54.105, @@ -46,7 +46,7 @@ "diameter": 17, "height": 117.98, "length": 17, - "total-liquid-volume": 15000, + "total-liquid-volume": 50000, "width": 17, "x": 98.5, "y": 54.105, @@ -57,7 +57,7 @@ "diameter": 17, "height": 117.98, "length": 17, - "total-liquid-volume": 15000, + "total-liquid-volume": 50000, "width": 17, "x": 28.5, "y": 19.105, @@ -68,7 +68,7 @@ "diameter": 17, "height": 117.98, "length": 17, - "total-liquid-volume": 15000, + "total-liquid-volume": 50000, "width": 17, "x": 63.5, "y": 19.105, @@ -79,11 +79,11 @@ "diameter": 17, "height": 117.98, "length": 17, - "total-liquid-volume": 15000, + "total-liquid-volume": 50000, "width": 17, "x": 98.5, "y": 19.105, "z": 7.78 } } -} \ No newline at end of file +} diff --git a/shared-data/definitions2/Opentrons_24_tuberack_1.5_mL_Eppendorf.json b/shared-data/definitions2/Opentrons_24_tuberack_1.5_mL_Eppendorf.json new file mode 100644 index 00000000000..bc5579f8199 --- /dev/null +++ b/shared-data/definitions2/Opentrons_24_tuberack_1.5_mL_Eppendorf.json @@ -0,0 +1,284 @@ +{ + "ordering": [ + [ + "A1", + "B1", + "C1", + "D1" + ], + [ + "A2", + "B2", + "C2", + "D2" + ], + [ + "A3", + "B3", + "C3", + "D3" + ], + [ + "A4", + "B4", + "C4", + "D4" + ], + [ + "A5", + "B5", + "C5", + "D5" + ], + [ + "A6", + "B6", + "C6", + "D6" + ] + ], + "otId": "b7df6160-e775-11e8-b0a9-079879741b02", + "deprecated": false, + "metadata": { + "displayName": "Opentrons 2mL Eppendorf tube rack", + "displayCategory": "tuberack", + "displayVolumeUnits": "mL" + }, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "dimensions": { + "overallLength": 127.76, + "overallWidth": 85.48, + "overallHeight": 79.85 + }, + "parameters": { + "format": "irregular", + "isTiprack": false, + "loadName": "Opentrons_24_tuberack_1.5_mL_Eppendorf", + "isMagneticModuleCompatible": false + }, + "wells": { + "D1": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 18.21, + "y": 10.08, + "z": 41.27 + }, + "C1": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 18.21, + "y": 29.35, + "z": 41.27 + }, + "B1": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 18.21, + "y": 48.63, + "z": 41.27 + }, + "A1": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 18.21, + "y": 67.91, + "z": 41.27 + }, + "D2": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 38.11, + "y": 10.08, + "z": 41.27 + }, + "C2": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 38.11, + "y": 29.35, + "z": 41.27 + }, + "B2": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 38.11, + "y": 48.63, + "z": 41.27 + }, + "A2": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 38.11, + "y": 67.91, + "z": 41.27 + }, + "D3": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 58, + "y": 10.08, + "z": 41.27 + }, + "C3": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 58, + "y": 29.35, + "z": 41.27 + }, + "B3": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 58, + "y": 48.63, + "z": 41.27 + }, + "A3": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 58, + "y": 67.91, + "z": 41.27 + }, + "D4": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 77.89, + "y": 10.08, + "z": 41.27 + }, + "C4": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 77.89, + "y": 29.35, + "z": 41.27 + }, + "B4": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 77.89, + "y": 48.63, + "z": 41.27 + }, + "A4": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 77.89, + "y": 67.91, + "z": 41.27 + }, + "D5": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 97.78, + "y": 10.08, + "z": 41.27 + }, + "C5": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 97.78, + "y": 29.35, + "z": 41.27 + }, + "B5": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 97.78, + "y": 48.63, + "z": 41.27 + }, + "A5": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 97.78, + "y": 67.91, + "z": 41.27 + }, + "D6": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 117.67, + "y": 10.08, + "z": 41.27 + }, + "C6": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 117.67, + "y": 29.35, + "z": 41.27 + }, + "B6": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 117.67, + "y": 48.63, + "z": 41.27 + }, + "A6": { + "depth": 38.58, + "shape": "circular", + "diameter": 9.9, + "totalLiquidVolume": 1.5, + "x": 117.67, + "y": 67.91, + "z": 41.27 + } + }, + "brand": { + "brand": "Opentrons" + } +} diff --git a/shared-data/definitions2/Opentrons_6x15_mL_4x50_mL_tuberack.json b/shared-data/definitions2/Opentrons_6x15_mL_4x50_mL_tuberack.json index fb233a93cda..566b5ddfa55 100644 --- a/shared-data/definitions2/Opentrons_6x15_mL_4x50_mL_tuberack.json +++ b/shared-data/definitions2/Opentrons_6x15_mL_4x50_mL_tuberack.json @@ -48,7 +48,8 @@ "parameters": { "isTiprack": false, "format": "irregular", - "loadName": "Opentrons_6x15_mL_4x50_mL_tuberack" + "loadName": "Opentrons_6x15_mL_4x50_mL_tuberack", + "isMagneticModuleCompatible": false }, "wells": { "A1": { diff --git a/shared-data/definitions2/Opentrons_96_tiprack_300_uL.json b/shared-data/definitions2/Opentrons_96_tiprack_300_uL.json index 1a161b78627..13a1e138d8a 100644 --- a/shared-data/definitions2/Opentrons_96_tiprack_300_uL.json +++ b/shared-data/definitions2/Opentrons_96_tiprack_300_uL.json @@ -149,7 +149,8 @@ "format": "96Standard", "isTiprack": true, "tipLength": 59.17, - "loadName": "Opentrons_96_tiprack_300_uL" + "loadName": "Opentrons_96_tiprack_300_uL", + "isMagneticModuleCompatible": false }, "wells": { "H1": { diff --git a/shared-data/definitions2/biorad_96_wellPlate_pcr_200_uL.json b/shared-data/definitions2/biorad_96_wellPlate_pcr_200_uL.json new file mode 100644 index 00000000000..874119d039f --- /dev/null +++ b/shared-data/definitions2/biorad_96_wellPlate_pcr_200_uL.json @@ -0,0 +1,1039 @@ +{ + "ordering": [ + [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1" + ], + [ + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2" + ], + [ + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3" + ], + [ + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4" + ], + [ + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5" + ], + [ + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6" + ], + [ + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7" + ], + [ + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8" + ], + [ + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9" + ], + [ + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10" + ], + [ + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11" + ], + [ + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12" + ] + ], + "otId": "a07a3f50-ec38-11e8-a3cc-d7bd32b6c4b1", + "deprecated": false, + "metadata": { + "displayName": "Bio-Rad HardShell 96-Well PCR Plate", + "displayCategory": "wellPlate", + "displayVolumeUnits": "uL", + "displayLengthUnits": "mm", + "tags": [ + "flat", + "plate", + "pcr", + "magdeck", + "biorad", + "low_profile", + "hardshell", + "thin_wall", + "96_well" + ] + }, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "dimensions": { + "overallWidth": 85.48, + "overallLength": 127.76, + "overallHeight": 16.06 + }, + "parameters": { + "format": "96Standard", + "isTiprack": false, + "loadName": "biorad_96_wellPlate_pcr_200_uL", + "isMagneticModuleCompatible": true, + "magneticModuleEngageHeight": 18 + }, + "wells": { + "H1": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 14.38, + "y": 11.24, + "z": 1.25 + }, + "G1": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 14.38, + "y": 20.24, + "z": 1.25 + }, + "F1": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 14.38, + "y": 29.24, + "z": 1.25 + }, + "E1": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 14.38, + "y": 38.24, + "z": 1.25 + }, + "D1": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 14.38, + "y": 47.24, + "z": 1.25 + }, + "C1": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 14.38, + "y": 56.24, + "z": 1.25 + }, + "B1": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 14.38, + "y": 65.24, + "z": 1.25 + }, + "A1": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 14.38, + "y": 74.24, + "z": 1.25 + }, + "H2": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 23.38, + "y": 11.24, + "z": 1.25 + }, + "G2": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 23.38, + "y": 20.24, + "z": 1.25 + }, + "F2": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 23.38, + "y": 29.24, + "z": 1.25 + }, + "E2": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 23.38, + "y": 38.24, + "z": 1.25 + }, + "D2": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 23.38, + "y": 47.24, + "z": 1.25 + }, + "C2": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 23.38, + "y": 56.24, + "z": 1.25 + }, + "B2": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 23.38, + "y": 65.24, + "z": 1.25 + }, + "A2": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 23.38, + "y": 74.24, + "z": 1.25 + }, + "H3": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 32.38, + "y": 11.24, + "z": 1.25 + }, + "G3": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 32.38, + "y": 20.24, + "z": 1.25 + }, + "F3": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 32.38, + "y": 29.24, + "z": 1.25 + }, + "E3": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 32.38, + "y": 38.24, + "z": 1.25 + }, + "D3": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 32.38, + "y": 47.24, + "z": 1.25 + }, + "C3": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 32.38, + "y": 56.24, + "z": 1.25 + }, + "B3": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 32.38, + "y": 65.24, + "z": 1.25 + }, + "A3": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 32.38, + "y": 74.24, + "z": 1.25 + }, + "H4": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 41.38, + "y": 11.24, + "z": 1.25 + }, + "G4": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 41.38, + "y": 20.24, + "z": 1.25 + }, + "F4": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 41.38, + "y": 29.24, + "z": 1.25 + }, + "E4": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 41.38, + "y": 38.24, + "z": 1.25 + }, + "D4": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 41.38, + "y": 47.24, + "z": 1.25 + }, + "C4": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 41.38, + "y": 56.24, + "z": 1.25 + }, + "B4": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 41.38, + "y": 65.24, + "z": 1.25 + }, + "A4": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 41.38, + "y": 74.24, + "z": 1.25 + }, + "H5": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 50.38, + "y": 11.24, + "z": 1.25 + }, + "G5": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 50.38, + "y": 20.24, + "z": 1.25 + }, + "F5": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 50.38, + "y": 29.24, + "z": 1.25 + }, + "E5": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 50.38, + "y": 38.24, + "z": 1.25 + }, + "D5": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 50.38, + "y": 47.24, + "z": 1.25 + }, + "C5": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 50.38, + "y": 56.24, + "z": 1.25 + }, + "B5": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 50.38, + "y": 65.24, + "z": 1.25 + }, + "A5": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 50.38, + "y": 74.24, + "z": 1.25 + }, + "H6": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 59.38, + "y": 11.24, + "z": 1.25 + }, + "G6": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 59.38, + "y": 20.24, + "z": 1.25 + }, + "F6": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 59.38, + "y": 29.24, + "z": 1.25 + }, + "E6": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 59.38, + "y": 38.24, + "z": 1.25 + }, + "D6": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 59.38, + "y": 47.24, + "z": 1.25 + }, + "C6": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 59.38, + "y": 56.24, + "z": 1.25 + }, + "B6": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 59.38, + "y": 65.24, + "z": 1.25 + }, + "A6": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 59.38, + "y": 74.24, + "z": 1.25 + }, + "H7": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 68.38, + "y": 11.24, + "z": 1.25 + }, + "G7": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 68.38, + "y": 20.24, + "z": 1.25 + }, + "F7": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 68.38, + "y": 29.24, + "z": 1.25 + }, + "E7": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 68.38, + "y": 38.24, + "z": 1.25 + }, + "D7": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 68.38, + "y": 47.24, + "z": 1.25 + }, + "C7": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 68.38, + "y": 56.24, + "z": 1.25 + }, + "B7": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 68.38, + "y": 65.24, + "z": 1.25 + }, + "A7": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 68.38, + "y": 74.24, + "z": 1.25 + }, + "H8": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 77.38, + "y": 11.24, + "z": 1.25 + }, + "G8": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 77.38, + "y": 20.24, + "z": 1.25 + }, + "F8": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 77.38, + "y": 29.24, + "z": 1.25 + }, + "E8": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 77.38, + "y": 38.24, + "z": 1.25 + }, + "D8": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 77.38, + "y": 47.24, + "z": 1.25 + }, + "C8": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 77.38, + "y": 56.24, + "z": 1.25 + }, + "B8": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 77.38, + "y": 65.24, + "z": 1.25 + }, + "A8": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 77.38, + "y": 74.24, + "z": 1.25 + }, + "H9": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 86.38, + "y": 11.24, + "z": 1.25 + }, + "G9": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 86.38, + "y": 20.24, + "z": 1.25 + }, + "F9": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 86.38, + "y": 29.24, + "z": 1.25 + }, + "E9": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 86.38, + "y": 38.24, + "z": 1.25 + }, + "D9": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 86.38, + "y": 47.24, + "z": 1.25 + }, + "C9": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 86.38, + "y": 56.24, + "z": 1.25 + }, + "B9": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 86.38, + "y": 65.24, + "z": 1.25 + }, + "A9": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 86.38, + "y": 74.24, + "z": 1.25 + }, + "H10": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 95.38, + "y": 11.24, + "z": 1.25 + }, + "G10": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 95.38, + "y": 20.24, + "z": 1.25 + }, + "F10": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 95.38, + "y": 29.24, + "z": 1.25 + }, + "E10": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 95.38, + "y": 38.24, + "z": 1.25 + }, + "D10": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 95.38, + "y": 47.24, + "z": 1.25 + }, + "C10": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 95.38, + "y": 56.24, + "z": 1.25 + }, + "B10": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 95.38, + "y": 65.24, + "z": 1.25 + }, + "A10": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 95.38, + "y": 74.24, + "z": 1.25 + }, + "H11": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 104.38, + "y": 11.24, + "z": 1.25 + }, + "G11": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 104.38, + "y": 20.24, + "z": 1.25 + }, + "F11": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 104.38, + "y": 29.24, + "z": 1.25 + }, + "E11": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 104.38, + "y": 38.24, + "z": 1.25 + }, + "D11": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 104.38, + "y": 47.24, + "z": 1.25 + }, + "C11": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 104.38, + "y": 56.24, + "z": 1.25 + }, + "B11": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 104.38, + "y": 65.24, + "z": 1.25 + }, + "A11": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 104.38, + "y": 74.24, + "z": 1.25 + }, + "H12": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 113.38, + "y": 11.24, + "z": 1.25 + }, + "G12": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 113.38, + "y": 20.24, + "z": 1.25 + }, + "F12": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 113.38, + "y": 29.24, + "z": 1.25 + }, + "E12": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 113.38, + "y": 38.24, + "z": 1.25 + }, + "D12": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 113.38, + "y": 47.24, + "z": 1.25 + }, + "C12": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 113.38, + "y": 56.24, + "z": 1.25 + }, + "B12": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 113.38, + "y": 65.24, + "z": 1.25 + }, + "A12": { + "depth": 14.81, + "shape": "circular", + "diameter": 5.46, + "totalLiquidVolume": 200, + "x": 113.38, + "y": 74.24, + "z": 1.25 + } + }, + "brand": { + "brand": "Bio-Rad", + "brandId": [ + "hsp9601", + "hsp9601b", + "hsp9611", + "hsp9621", + "hsp9631", + "hsp9641", + "hsp9661", + "hsp9xxx" + ] + } +} diff --git a/shared-data/definitions2/generic_96_wellPlate_380_uL.json b/shared-data/definitions2/generic_96_wellPlate_380_uL.json index da0c83b47ee..333f3d78b08 100644 --- a/shared-data/definitions2/generic_96_wellPlate_380_uL.json +++ b/shared-data/definitions2/generic_96_wellPlate_380_uL.json @@ -149,7 +149,8 @@ "parameters": { "format": "96Standard", "isTiprack": false, - "loadName": "generic_96_wellPlate_380_uL" + "loadName": "generic_96_wellPlate_380_uL", + "isMagneticModuleCompatible": false }, "wells": { "H1": { diff --git a/shared-data/js/__tests__/fixtures/irregularLabwareExample1.json b/shared-data/js/__tests__/fixtures/irregularLabwareExample1.json index 0fc8d6f9534..2652ebfcab9 100644 --- a/shared-data/js/__tests__/fixtures/irregularLabwareExample1.json +++ b/shared-data/js/__tests__/fixtures/irregularLabwareExample1.json @@ -101,7 +101,8 @@ "parameters": { "isTiprack": false, "format": "irregular", - "loadName": "generic_50x3_mL_5x10_mL_irregular" + "loadName": "generic_50x3_mL_5x10_mL_irregular", + "isMagneticModuleCompatible": false }, "wells": { "A1": { diff --git a/shared-data/js/__tests__/fixtures/labwareExample.json b/shared-data/js/__tests__/fixtures/labwareExample.json index 62a4509702b..46e7b5b72e2 100644 --- a/shared-data/js/__tests__/fixtures/labwareExample.json +++ b/shared-data/js/__tests__/fixtures/labwareExample.json @@ -14,7 +14,8 @@ "parameters": { "loadName": "opentrons_2_wellPlate_100_uL", "format": "96Standard", - "isTiprack": false + "isTiprack": false, + "isMagneticModuleCompatible": false }, "cornerOffsetFromSlot": { "x": 0, diff --git a/shared-data/js/__tests__/fixtures/labwareExample2.json b/shared-data/js/__tests__/fixtures/labwareExample2.json index 4d8261aebae..f0f5c443e79 100644 --- a/shared-data/js/__tests__/fixtures/labwareExample2.json +++ b/shared-data/js/__tests__/fixtures/labwareExample2.json @@ -10,7 +10,8 @@ "parameters": { "format": "irregular", "isTiprack": false, - "loadName": "6_wellPlate_100_uL" + "loadName": "6_wellPlate_100_uL", + "isMagneticModuleCompatible": false }, "cornerOffsetFromSlot": { "x": -77.76, diff --git a/shared-data/js/constants.js b/shared-data/js/constants.js index 18ab40b295a..4923df4bdba 100644 --- a/shared-data/js/constants.js +++ b/shared-data/js/constants.js @@ -1,5 +1,9 @@ // @flow -// in millimeters -export const SLOT_WIDTH_MM = 127.76 -export const SLOT_HEIGHT_MM = 85.48 +// constants for dealing with robot coordinate system (eg in labwareTools) +export const SLOT_LENGTH_MM = 127.76 // along X axis in robot coordinate system +export const SLOT_WIDTH_MM = 85.48 // along Y axis in robot coordinate system + +// constants for SVG renders of the deck +export const SLOT_RENDER_WIDTH = SLOT_LENGTH_MM // along X axis in SVG coords +export const SLOT_RENDER_HEIGHT = SLOT_WIDTH_MM // along Y axis in SVG coords diff --git a/shared-data/js/getLabware.js b/shared-data/js/getLabware.js index 9604cbd7c5d..b872f337786 100644 --- a/shared-data/js/getLabware.js +++ b/shared-data/js/getLabware.js @@ -1,7 +1,7 @@ // @flow import mapValues from 'lodash/mapValues' import definitions from '../build/labware.json' -import {SLOT_HEIGHT_MM} from './constants' +import {SLOT_RENDER_HEIGHT} from './constants' import type {LabwareDefinition, WellDefinition} from './types' export default function getLabware (labwareName: string): ?LabwareDefinition { @@ -34,6 +34,6 @@ export function getWellDefsForSVG (labwareName: string) { ...wellDef, x: wellDef.x + xCorrection, // flip y axis to match SVG y axis direction - y: SLOT_HEIGHT_MM - wellDef.y + yCorrection, + y: SLOT_RENDER_HEIGHT - wellDef.y + yCorrection, })) } diff --git a/shared-data/js/labwareTools/__tests__/createIrregularLabware.test.js b/shared-data/js/labwareTools/__tests__/createIrregularLabware.test.js index 4ad49b162de..e553e904d7a 100644 --- a/shared-data/js/labwareTools/__tests__/createIrregularLabware.test.js +++ b/shared-data/js/labwareTools/__tests__/createIrregularLabware.test.js @@ -74,6 +74,7 @@ describe('test createIrregularLabware function', () => { parameters: { format: 'irregular', isTiprack: false, + isMagneticModuleCompatible: false, }, dimensions: { overallLength: 127.76, @@ -95,8 +96,8 @@ describe('test createIrregularLabware function', () => { }, ], offset: [ - {x: 10, y: 10, z: 5}, - {x: 15, y: 15, z: 5}, + {x: 10, y: 10, z: 69.48}, + {x: 15, y: 15, z: 69.48}, ], grid: [ {row: 5, column: 10}, diff --git a/shared-data/js/labwareTools/__tests__/createLabware.test.js b/shared-data/js/labwareTools/__tests__/createLabware.test.js index 99ceddabd2b..37917e79ca6 100644 --- a/shared-data/js/labwareTools/__tests__/createLabware.test.js +++ b/shared-data/js/labwareTools/__tests__/createLabware.test.js @@ -17,8 +17,8 @@ describe('createLabware', () => { beforeEach(() => { well1 = omit(exampleLabware1.wells.A1, ['x', 'y', 'z']) well2 = omit(exampleLabware2.wells.A1, ['x', 'y', 'z']) - const offset1 = {x: 10, y: 10, z: 5} - const offset2 = {x: 10, y: 10, z: 0} + const offset1 = {x: 10, y: 10, z: 55} + const offset2 = {x: 10, y: 10, z: 50} labware1 = createRegularLabware({ metadata: exampleLabware1.metadata, parameters: exampleLabware1.parameters, @@ -62,7 +62,7 @@ describe('createLabware', () => { test('well XYZ generates correctly', () => { const spacing = {row: 11.8, column: 12.1} const grid = {row: 8, column: 12} - const offset = {x: 10, y: 10, z: 5} + const offset = {x: 10, y: 10, z: 55} const labware3 = createRegularLabware({ metadata: exampleLabware2.metadata, parameters: exampleLabware2.parameters, @@ -80,7 +80,7 @@ describe('createLabware', () => { const well = labware3.wells[wellName] expect(well.x).toBeCloseTo(expectedXByCol[cIndex], 2) expect(well.y).toBeCloseTo(expectedYByRow[rIndex], 2) - expect(well.z).toBeCloseTo(exampleLabware2.dimensions.overallHeight + offset.z - well.depth, 2) + expect(well.z).toBeCloseTo(offset.z - well.depth, 2) }) }) }) diff --git a/shared-data/js/labwareTools/index.js b/shared-data/js/labwareTools/index.js index de968c772da..5b991329cd7 100644 --- a/shared-data/js/labwareTools/index.js +++ b/shared-data/js/labwareTools/index.js @@ -6,8 +6,8 @@ import assignId from './assignId' import {toWellName, sortWells, splitWellsOnColumn} from '../helpers/index' import labwareSchema from '../../labware-json-schema/labware-schema.json' import { - SLOT_WIDTH_MM as SLOT_LENGTH_MM, - SLOT_HEIGHT_MM as SLOT_WIDTH_MM, + SLOT_WIDTH_MM, + SLOT_LENGTH_MM, } from '../constants' type Metadata = { @@ -36,6 +36,8 @@ type Params = { isTiprack: boolean, tipLength?: number, loadName?: string, + isMagneticModuleCompatible: boolean, + magneticModuleEngageHeight?: number, } type Well = { @@ -205,7 +207,6 @@ function calculateCoordinates ( // or the labware definition schema in labware-json-schema export function createRegularLabware (args: RegularLabwareProps): Schema { const ordering = determineOrdering(args.grid) - const offset = {...args.offset, z: round(args.dimensions.overallHeight + args.offset.z, 2)} const definition: Schema = { ordering, otId: assignId(), @@ -217,7 +218,7 @@ export function createRegularLabware (args: RegularLabwareProps): Schema { z: 0}, dimensions: args.dimensions, parameters: args.parameters, - wells: calculateCoordinates(args.well, ordering, args.spacing, offset), + wells: calculateCoordinates(args.well, ordering, args.spacing, args.offset), } const numWells = args.grid.row * args.grid.column const brand = (args.brand && args.brand.brand) || 'generic' @@ -238,15 +239,10 @@ export function createRegularLabware (args: RegularLabwareProps): Schema { // Generator function for labware definitions within an irregular grid format // e.g. crystalization plates, 15_50ml tuberacks and anything with multiple "grids" export function createIrregularLabware (args: IrregularLabwareProps): Schema { - const offset = args.offset.map(offsetObj => ({ - ...offsetObj, - z: round(args.dimensions.overallHeight + offsetObj.z, 2), - })) - const wellsArray = determineLayout( args.grid, args.spacing, - offset, + args.offset, args.gridStart, args.well) diff --git a/shared-data/labware-json-schema/labware-schema.json b/shared-data/labware-json-schema/labware-schema.json index 0a5e846334d..79fc46a0efa 100644 --- a/shared-data/labware-json-schema/labware-schema.json +++ b/shared-data/labware-json-schema/labware-schema.json @@ -70,7 +70,7 @@ "type": "object", "description": "Internal describers used to determine pipette movement to labware", "additionalProperties": false, - "required": ["format", "isTiprack", "loadName"], + "required": ["format", "isTiprack", "loadName", "isMagneticModuleCompatible"], "properties": { "format": { "description": "Property to determine compatibility with multichannel pipette", @@ -88,6 +88,14 @@ "loadName": { "description": "Generated unique name of container", "type": "string" + }, + "isMagneticModuleCompatible": { + "description": "Flag marking whether a labware is compatible by default with the Magnetic Module", + "type": "boolean" + }, + "magneticModuleEngageHeight": { + "description": "Distance to move magnetic module magnets to engage", + "$ref": "#/definitions/positiveNumber" } } @@ -130,8 +138,8 @@ "$ref": "#/definitions/positiveNumber" } } - }, + "wells": { "type": "object", "description": "Unordered object of well objects with position and dimensional information", diff --git a/shared-data/package.json b/shared-data/package.json index 4d5cbbd4e0a..df339120540 100755 --- a/shared-data/package.json +++ b/shared-data/package.json @@ -1,6 +1,6 @@ { "name": "@opentrons/shared-data", - "version": "3.6.0-beta.0", + "version": "3.6.1", "description": "Default labware definitions for Opentrons robots", "repository": { "type": "git", diff --git a/shared-data/robot-data/moduleSpecs.json b/shared-data/robot-data/moduleSpecs.json new file mode 100644 index 00000000000..9021a486ea7 --- /dev/null +++ b/shared-data/robot-data/moduleSpecs.json @@ -0,0 +1,38 @@ +{ + "magdeck": { + "labwareOffset": { + "x": 0.125, + "y": -0.125, + "z": 82.25 + }, + "dimensions": { + "bareOverallHeight": 110.152, + "overLabwareHeight": 4.052 + }, + "calibrationPoints": { + "x": 124.875, + "y": 2.75 + }, + "displayName": "Magnetic Module", + "loadName": "magdeck", + "quirks": [] + }, + "tempdeck": { + "labwareOffset": { + "x": -0.15, + "y": -0.15, + "z": 80.09 + }, + "dimensions": { + "bareOverallHeight": 84, + "overLabwareHeight": 0 + }, + "calibrationPoint": { + "x": 12.0, + "y":8.75 + }, + "displayName": "Temperature Module", + "loadName": "tempdeck", + "quirks": [] + } +} diff --git a/shared-data/robot-data/pipetteModelSpecs.json b/shared-data/robot-data/pipetteModelSpecs.json index 3c2e77e443f..b7745065c55 100644 --- a/shared-data/robot-data/pipetteModelSpecs.json +++ b/shared-data/robot-data/pipetteModelSpecs.json @@ -14,11 +14,11 @@ "dropTipCurrent": 0.5, "ulPerMm": { "aspirate": [ - [1.8263, -0.0958, 1.088], - [ 2.5222, -0.104, 1.1031], - [ 3.2354, -0.0447, 0.9536], - [ 3.9984, -0.012, 0.8477], - [12.5135, -0.0021, 0.8079] + [1.438649211, 0.01931415115, 0.691538317], + [1.836824579, 0.03868955123, 0.6636639129], + [2.960052684, 0.00470371018, 0.7260899411], + [4.487508789, 0.005175245625, 0.7246941713], + [10.59661421, 0.001470408978, 0.7413196584] ], "dispense": [ [12.5135, 0, 0.7945] @@ -42,11 +42,39 @@ "dropTipCurrent": 0.5, "ulPerMm": { "aspirate": [ - [1.8263, -0.0958, 1.088], - [ 2.5222, -0.104, 1.1031], - [ 3.2354, -0.0447, 0.9536], - [ 3.9984, -0.012, 0.8477], - [12.5135, -0.0021, 0.8079] + [1.438649211, 0.01931415115, 0.691538317], + [1.836824579, 0.03868955123, 0.6636639129], + [2.960052684, 0.00470371018, 0.7260899411], + [4.487508789, 0.005175245625, 0.7246941713], + [10.59661421, 0.001470408978, 0.7413196584] + ], + "dispense": [ + [12.5135, 0, 0.7945] + ] + }, + "quirks": [], + "tipLength": 33 + }, + "p10_single_v1.4": { + "name": "p10_single", + "plungerPositions": { + "top": 19.5, + "bottom": 1.5, + "blowOut": -1.5, + "dropTip": -5.5 + }, + "pickUpCurrent": 0.1, + "pickUpDistance": 10, + "modelOffset": [0.0, 0.0, -13], + "plungerCurrent": 0.3, + "dropTipCurrent": 0.5, + "ulPerMm": { + "aspirate": [ + [1.438649211, 0.01931415115, 0.691538317], + [1.836824579, 0.03868955123, 0.6636639129], + [2.960052684, 0.00470371018, 0.7260899411], + [4.487508789, 0.005175245625, 0.7246941713], + [10.59661421, 0.001470408978, 0.7413196584] ], "dispense": [ [12.5135, 0, 0.7945] @@ -109,6 +137,33 @@ "quirks": [], "tipLength": 33 }, + "p10_multi_v1.4": { + "name": "p10_multi", + "plungerPositions": { + "top": 19.5, + "bottom": 2, + "blowOut": -1, + "dropTip": -4.5 + }, + "pickUpCurrent": 0.4, + "pickUpDistance": 10, + "modelOffset": [0.0, 31.5, -25.8], + "plungerCurrent": 0.5, + "dropTipCurrent": 0.5, + "ulPerMm": { + "aspirate": [ + [1.893415617, -1.1069, 3.042593193], + [2.497849452, -0.1888, 1.30410391], + [5.649462387, -0.0081, 0.8528667891], + [12.74444519, -0.0018, 0.8170558891] + ], + "dispense": [ + [12.74444519, 0, 0.8058688085] + ] + }, + "quirks": [], + "tipLength": 33 + }, "p50_single_v1": { "name": "p50_single", "plungerPositions": { @@ -159,6 +214,31 @@ "quirks": [], "tipLength": 51.7 }, + "p50_single_v1.4": { + "name": "p50_single", + "plungerPositions": { + "top": 19.5, + "bottom": 2, + "blowOut": 0.5, + "dropTip": -5 + }, + "pickUpCurrent": 0.1, + "pickUpDistance": 10, + "modelOffset": [0.0, 0.0, 0.0], + "plungerCurrent": 0.3, + "dropTipCurrent": 0.5, + "ulPerMm": { + "aspirate": [ + [11.79687499, -0.0098, 3.064988953], + [50, -0.0004, 2.954068131] + ], + "dispense": [ + [50, 0, 2.931601299] + ] + }, + "quirks": [], + "tipLength": 51.7 + }, "p50_multi_v1": { "name": "p50_multi", "plungerPositions": { @@ -209,6 +289,31 @@ "quirks": [], "tipLength": 51.7 }, + "p50_multi_v1.4": { + "name": "p50_multi", + "plungerPositions": { + "top": 19.5, + "bottom": 2, + "blowOut": 0.5, + "dropTip": -4 + }, + "pickUpCurrent": 0.6, + "pickUpDistance": 10, + "modelOffset": [0.0, 31.5, -25.8], + "plungerCurrent": 0.5, + "dropTipCurrent": 0.5, + "ulPerMm": { + "aspirate": [ + [12.29687531, -0.0049, 3.134703694], + [50, -0.0002, 3.077116024] + ], + "dispense": [ + [50, 0, 3.06368702] + ] + }, + "quirks": [], + "tipLength": 51.7 + }, "p300_single_v1": { "name": "p300_single", "plungerPositions": { @@ -265,6 +370,34 @@ "quirks": [], "tipLength": 51.7 }, + "p300_single_v1.4": { + "name": "p300_single", + "plungerPositions": { + "top": 19.5, + "bottom": 3, + "blowOut": 0, + "dropTip": -5.5 + }, + "pickUpCurrent": 0.1, + "pickUpDistance": 10, + "modelOffset": [0.0, 0.0, 0.0], + "plungerCurrent": 0.3, + "dropTipCurrent": 0.5, + "ulPerMm": { + "aspirate": [ + [36.19844973, 0.043, 16.548], + [54.98518519, 0.012, 17.658], + [73.90077516, 0.008, 17.902], + [111.8437953, 0.004, 18.153], + [302.3895337, 0.001, 18.23] + ], + "dispense": [ + [302.3895337, 0, 18.83156277] + ] + }, + "quirks": [], + "tipLength": 51.7 + }, "p300_multi_v1": { "name": "p300_multi", "plungerPositions": { @@ -315,6 +448,31 @@ "quirks": [], "tipLength": 51.7 }, + "p300_multi_v1.4": { + "name": "p300_multi", + "plungerPositions": { + "top": 19.5, + "bottom": 3.5, + "blowOut": 1.5, + "dropTip": -3.5 + }, + "pickUpCurrent": 0.6, + "pickUpDistance": 10, + "modelOffset": [0.0, 31.5, -25.8], + "plungerCurrent": 0.5, + "dropTipCurrent": 0.5, + "ulPerMm": { + "aspirate": [ + [57.25698968, 0.017, 18.132], + [309.2612689, 0.001, 19.03] + ], + "dispense": [ + [309.2612689, 0, 19.29389273] + ] + }, + "quirks": [], + "tipLength": 51.7 + }, "p1000_single_v1": { "name": "p1000_single", "plungerPositions": { @@ -348,8 +506,36 @@ "plungerPositions": { "top": 19.5, "bottom": 2.5, - "blowOut": -0.5, - "dropTip": -3.7 + "blowOut": 0.5, + "dropTip": -4 + }, + "pickUpCurrent": 0.1, + "pickUpDistance": 15, + "modelOffset": [0.0, 0.0, 20.0], + "plungerCurrent": 0.5, + "dropTipCurrent": 0.7, + "ulPerMm": { + "aspirate": [ + [88.2951, 0.0647, 53.153], + [119.062, 0.0217, 56.9474], + [211.8242, 0.0086, 58.9607], + [490.5573, 0.0029, 59.9144], + [1000, 0.0008, 60.9102] + ], + "dispense": [ + [1000, 0, 61.3275] + ] + }, + "quirks": ["needs-pickup-shake"], + "tipLength": 76.7 + }, + "p1000_single_v1.4": { + "name": "p1000_single", + "plungerPositions": { + "top": 19.5, + "bottom": 2.5, + "blowOut": 0.5, + "dropTip": -4 }, "pickUpCurrent": 0.1, "pickUpDistance": 15, diff --git a/update-server/otupdate/CHANGELOG.md b/update-server/otupdate/CHANGELOG.md index b4e0ae32809..532f66d6a1f 100644 --- a/update-server/otupdate/CHANGELOG.md +++ b/update-server/otupdate/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + +**Note:** Version bump only for package @opentrons/update-server + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + +**Note:** Version bump only for package @opentrons/update-server + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + +**Note:** Version bump only for package @opentrons/update-server + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/update-server/otupdate/package.json b/update-server/otupdate/package.json index 8dfc40590b7..dcb20e79636 100644 --- a/update-server/otupdate/package.json +++ b/update-server/otupdate/package.json @@ -1,6 +1,6 @@ { "name": "@opentrons/update-server", - "version": "3.6.0-beta.0", + "version": "3.6.1", "description": "Update server for Opentrons robots", "repository": { "type": "git", diff --git a/webpack-config/CHANGELOG.md b/webpack-config/CHANGELOG.md index 6aad1c06ca5..a0ddde18511 100644 --- a/webpack-config/CHANGELOG.md +++ b/webpack-config/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [3.6.1](https://github.com/Opentrons/opentrons/compare/v3.6.0...v3.6.1) (2018-12-05) + +**Note:** Version bump only for package @opentrons/webpack-config + + + + + + +# [3.6.0](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.1...v3.6.0) (2018-11-29) + +**Note:** Version bump only for package @opentrons/webpack-config + + + + + + +# [3.6.0-beta.1](https://github.com/Opentrons/opentrons/compare/v3.6.0-beta.0...v3.6.0-beta.1) (2018-11-27) + +**Note:** Version bump only for package @opentrons/webpack-config + + + + + # [3.6.0-beta.0](https://github.com/Opentrons/opentrons/compare/v3.5.1...v3.6.0-beta.0) (2018-11-13) diff --git a/webpack-config/package.json b/webpack-config/package.json index b76c59e9311..7a10844e602 100644 --- a/webpack-config/package.json +++ b/webpack-config/package.json @@ -1,6 +1,6 @@ { "name": "@opentrons/webpack-config", - "version": "3.6.0-beta.0", + "version": "3.6.1", "description": "Shareable pieces of webpack configuration", "main": "index.js", "repository": { diff --git a/yarn.lock b/yarn.lock index 39b10e3d2b6..c32d1a8c2d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,31 +5,26 @@ "7zip-bin@~4.0.2": version "4.0.2" resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-4.0.2.tgz#6abbdc22f33cab742053777a26db2e25ca527179" - integrity sha512-XtGk+IF57pr852UK1AhQJXqmm1WmSgS5uISL+LPs0z/iAxXouMvdlLJrHPeukP6gd7yR2rDTMSMkHNODgwIq7A== "7zip@0.0.6": version "0.0.6" resolved "https://registry.yarnpkg.com/7zip/-/7zip-0.0.6.tgz#9cafb171af82329490353b4816f03347aa150a30" - integrity sha1-nK+xca+CMpSQNTtIFvAzR6oVCjA= "@babel/code-frame@7.0.0", "@babel/code-frame@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" - integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== dependencies: "@babel/highlight" "^7.0.0" "@babel/code-frame@7.0.0-beta.44": version "7.0.0-beta.44" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz#2a02643368de80916162be70865c97774f3adbd9" - integrity sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g== dependencies: "@babel/highlight" "7.0.0-beta.44" "@babel/generator@7.0.0-beta.44": version "7.0.0-beta.44" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.44.tgz#c7e67b9b5284afcf69b309b50d7d37f3e5033d42" - integrity sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ== dependencies: "@babel/types" "7.0.0-beta.44" jsesc "^2.5.1" @@ -40,7 +35,6 @@ "@babel/generator@^7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.1.3.tgz#2103ec9c42d9bdad9190a6ad5ff2d456fd7b8673" - integrity sha512-ZoCZGcfIJFJuZBqxcY9OjC1KW2lWK64qrX1o4UYL3yshVhwKFYgzpWZ0vvtGMNJdTlvkw0W+HR1VnYN8q3QPFQ== dependencies: "@babel/types" "^7.1.3" jsesc "^2.5.1" @@ -51,7 +45,6 @@ "@babel/helper-function-name@7.0.0-beta.44": version "7.0.0-beta.44" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz#e18552aaae2231100a6e485e03854bc3532d44dd" - integrity sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg== dependencies: "@babel/helper-get-function-arity" "7.0.0-beta.44" "@babel/template" "7.0.0-beta.44" @@ -60,7 +53,6 @@ "@babel/helper-function-name@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== dependencies: "@babel/helper-get-function-arity" "^7.0.0" "@babel/template" "^7.1.0" @@ -69,42 +61,36 @@ "@babel/helper-get-function-arity@7.0.0-beta.44": version "7.0.0-beta.44" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz#d03ca6dd2b9f7b0b1e6b32c56c72836140db3a15" - integrity sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw== dependencies: "@babel/types" "7.0.0-beta.44" "@babel/helper-get-function-arity@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== dependencies: "@babel/types" "^7.0.0" "@babel/helper-module-imports@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" - integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== dependencies: "@babel/types" "^7.0.0" "@babel/helper-split-export-declaration@7.0.0-beta.44": version "7.0.0-beta.44" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc" - integrity sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA== dependencies: "@babel/types" "7.0.0-beta.44" "@babel/helper-split-export-declaration@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813" - integrity sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag== dependencies: "@babel/types" "^7.0.0" "@babel/highlight@7.0.0-beta.44": version "7.0.0-beta.44" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.44.tgz#18c94ce543916a80553edcdcf681890b200747d5" - integrity sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ== dependencies: chalk "^2.0.0" esutils "^2.0.2" @@ -113,7 +99,6 @@ "@babel/highlight@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" - integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== dependencies: chalk "^2.0.0" esutils "^2.0.2" @@ -122,19 +107,22 @@ "@babel/parser@^7.0.0", "@babel/parser@^7.1.2", "@babel/parser@^7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.1.3.tgz#2c92469bac2b7fbff810b67fca07bd138b48af77" - integrity sha512-gqmspPZOMW3MIRb9HlrnbZHXI1/KHTOroBwN1NcLL6pWxzqzEKGvRTq0W/PxS45OtQGbaFikSQpkS5zbnsQm2w== "@babel/runtime@7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0.tgz#adeb78fedfc855aa05bc041640f3f6f98e85424c" - integrity sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA== + dependencies: + regenerator-runtime "^0.12.0" + +"@babel/runtime@^7.0.0": + version "7.1.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.1.5.tgz#4170907641cf1f61508f563ece3725150cc6fe39" dependencies: regenerator-runtime "^0.12.0" "@babel/template@7.0.0-beta.44": version "7.0.0-beta.44" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f" - integrity sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng== dependencies: "@babel/code-frame" "7.0.0-beta.44" "@babel/types" "7.0.0-beta.44" @@ -144,7 +132,6 @@ "@babel/template@^7.1.0": version "7.1.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.1.2.tgz#090484a574fef5a2d2d7726a674eceda5c5b5644" - integrity sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag== dependencies: "@babel/code-frame" "^7.0.0" "@babel/parser" "^7.1.2" @@ -153,7 +140,6 @@ "@babel/traverse@7.0.0-beta.44": version "7.0.0-beta.44" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966" - integrity sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA== dependencies: "@babel/code-frame" "7.0.0-beta.44" "@babel/generator" "7.0.0-beta.44" @@ -169,7 +155,6 @@ "@babel/traverse@^7.0.0": version "7.1.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.1.4.tgz#f4f83b93d649b4b2c91121a9087fa2fa949ec2b4" - integrity sha512-my9mdrAIGdDiSVBuMjpn/oXYpva0/EZwWL3sm3Wcy/AVWO2eXnsoZruOT9jOGNRXU8KbCIu5zsKnXcAJ6PcV6Q== dependencies: "@babel/code-frame" "^7.0.0" "@babel/generator" "^7.1.3" @@ -184,7 +169,6 @@ "@babel/types@7.0.0-beta.44": version "7.0.0-beta.44" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757" - integrity sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ== dependencies: esutils "^2.0.2" lodash "^4.2.0" @@ -193,7 +177,6 @@ "@babel/types@^7.0.0", "@babel/types@^7.1.2", "@babel/types@^7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.1.3.tgz#3a767004567060c2f40fca49a304712c525ee37d" - integrity sha512-RpPOVfK+yatXyn8n4PB1NW6k9qjinrXrRR8ugBN8fD6hCy5RXI6PSbVqpOJBO9oSaY7Nom4ohj35feb0UR9hSA== dependencies: esutils "^2.0.2" lodash "^4.17.10" @@ -202,7 +185,6 @@ "@emotion/babel-utils@^0.6.4": version "0.6.10" resolved "https://registry.yarnpkg.com/@emotion/babel-utils/-/babel-utils-0.6.10.tgz#83dbf3dfa933fae9fc566e54fbb45f14674c6ccc" - integrity sha512-/fnkM/LTEp3jKe++T0KyTszVGWNKPNOUJfjNKLO17BzQ6QPxgbg3whayom1Qr2oLFH3V92tDymU+dT5q676uow== dependencies: "@emotion/hash" "^0.6.6" "@emotion/memoize" "^0.6.6" @@ -214,17 +196,14 @@ "@emotion/hash@^0.6.2", "@emotion/hash@^0.6.6": version "0.6.6" resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.6.6.tgz#62266c5f0eac6941fece302abad69f2ee7e25e44" - integrity sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ== "@emotion/memoize@^0.6.1", "@emotion/memoize@^0.6.6": version "0.6.6" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.6.6.tgz#004b98298d04c7ca3b4f50ca2035d4f60d2eed1b" - integrity sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ== "@emotion/serialize@^0.9.1": version "0.9.1" resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.9.1.tgz#a494982a6920730dba6303eb018220a2b629c145" - integrity sha512-zTuAFtyPvCctHBEL8KZ5lJuwBanGSutFEncqLn/m9T1a6a93smBStK+bZzcNPgj4QS8Rkw9VTwJGhRIUVO8zsQ== dependencies: "@emotion/hash" "^0.6.6" "@emotion/memoize" "^0.6.6" @@ -234,22 +213,18 @@ "@emotion/stylis@^0.7.0": version "0.7.1" resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.7.1.tgz#50f63225e712d99e2b2b39c19c70fff023793ca5" - integrity sha512-/SLmSIkN13M//53TtNxgxo57mcJk/UJIDFRKwOiLIBEyBHEcipgR6hNMQ/59Sl4VjCJ0Z/3zeAZyvnSLPG/1HQ== "@emotion/unitless@^0.6.2", "@emotion/unitless@^0.6.7": version "0.6.7" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.6.7.tgz#53e9f1892f725b194d5e6a1684a7b394df592397" - integrity sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg== "@emotion/utils@^0.8.2": version "0.8.2" resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.8.2.tgz#576ff7fb1230185b619a75d258cbc98f0867a8dc" - integrity sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw== "@lerna/add@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.0.0-beta.21.tgz#5634492930b5f97eca3775b85f39f9e382680425" - integrity sha512-IPRCgioIuPacBS938p1DaB0glqUp32FXDBpwxePUyg/LydpDuxalqW6lDuGO5YhDDCfMcN8CT/nx+An2IB5mUw== dependencies: "@lerna/bootstrap" "^3.0.0-beta.21" "@lerna/command" "^3.0.0-beta.21" @@ -264,7 +239,6 @@ "@lerna/batch-packages@^3.0.0-beta.18": version "3.0.0-beta.18" resolved "https://registry.yarnpkg.com/@lerna/batch-packages/-/batch-packages-3.0.0-beta.18.tgz#69d5e3f5003e454a1615c38d9f0b65b10853625a" - integrity sha512-ZFbKNQkp0vy2M1JGNMj6wX08E3Vv5mlA+QtScwOR2DGV2nG2HK5F7HcVICOi1BW9bjvHKjfU+e8aebTCWizllA== dependencies: "@lerna/package-graph" "^3.0.0-beta.18" "@lerna/validation-error" "^3.0.0-beta.10" @@ -273,7 +247,6 @@ "@lerna/bootstrap@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.0.0-beta.21.tgz#de9233d0c7f9881bc7c27948e515f34d47f27710" - integrity sha512-UmLCrE9poTZ6F3itY/0tiJaTMTO88lQMjYOnNtmmj9nnmdXcfu6qAmmY062YpbYWbgHZd5gJ2/5rinl4EM19fA== dependencies: "@lerna/batch-packages" "^3.0.0-beta.18" "@lerna/command" "^3.0.0-beta.21" @@ -301,7 +274,6 @@ "@lerna/changed@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.0.0-beta.21.tgz#e768dba7573dbc9cfb96c4f47ae9efcec4cb5d65" - integrity sha512-qb7EkSNKMZjKayE4aiGZsSH9Ys/TOEWm4I9C/lv4vWjOhqYzpG0g56pH2s+m38Lk9iqj/Q9Dk1mn/8W+siVrDg== dependencies: "@lerna/collect-updates" "^3.0.0-beta.21" "@lerna/command" "^3.0.0-beta.21" @@ -312,7 +284,6 @@ "@lerna/child-process@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-3.0.0-beta.21.tgz#9fb32cb79ee75bf0806141bac5fc64bb38aa2dbd" - integrity sha512-9FO1UFujjOUAepwdW+Fe4fKm6zPlGI58LiwOg5X69VIBvVxxXU++RpKQGL+Xdj5/Q6p7+oMnpivWIlPyODqsUQ== dependencies: chalk "^2.3.1" execa "^0.10.0" @@ -321,7 +292,6 @@ "@lerna/clean@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.0.0-beta.21.tgz#e31ff8edce00fe6eea9fb68e6057630392da1f1e" - integrity sha512-OY/PigGfqRAFl430QLfhqL4ktdqgvzqU2MBIGljRi07H09Ux5UO7uhfGy3RaY4Wb+U+Xo91j/zkV3BdPQS1Uaw== dependencies: "@lerna/command" "^3.0.0-beta.21" "@lerna/filter-options" "^3.0.0-beta.18" @@ -334,7 +304,6 @@ "@lerna/cli@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/cli/-/cli-3.0.0-beta.21.tgz#ba4cd8512a851fedcdd45028d05c9e739ebc6feb" - integrity sha512-kEki2UDee0JWUQhfCv4qZknAST7C7OdIXb3T+IyOqpEP/MSbpYdGfwlxrkF7ZTVZHn4X0uP2op0fbQ1LRt757A== dependencies: "@lerna/add" "^3.0.0-beta.21" "@lerna/bootstrap" "^3.0.0-beta.21" @@ -358,7 +327,6 @@ "@lerna/collect-packages@^3.0.0-beta.17": version "3.0.0-beta.17" resolved "https://registry.yarnpkg.com/@lerna/collect-packages/-/collect-packages-3.0.0-beta.17.tgz#c4965df6328e191947dbcaa37c8c76ac89b515f8" - integrity sha512-ADGLVCKlIfGLkNk5iME6H3Wi2HjI5WwlB1MfGEDapv456uifWDZk+hmFbOK3402W+6MQvkCTrw3xeRZyX8mGTQ== dependencies: "@lerna/package" "^3.0.0-beta.17" "@lerna/validation-error" "^3.0.0-beta.10" @@ -369,7 +337,6 @@ "@lerna/collect-updates@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-3.0.0-beta.21.tgz#92d165476e586222e6edd5d3b61c26e838ccd7ee" - integrity sha512-4vYlELyws068eY35gDGZ7REHbRlYZo7eJKplVWuUEbWK21x0f8HIh4u6TLcG9WITXZ6HXWWdSP8pP7AKqa3I6w== dependencies: "@lerna/child-process" "^3.0.0-beta.21" minimatch "^3.0.4" @@ -380,7 +347,6 @@ "@lerna/command@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.0.0-beta.21.tgz#da4d3895e4ad458ffc2c8508156762785bcabc41" - integrity sha512-ijshJe404Kskyey3VQpjZVoEQX8Bx3MbEQTE+PQb7bEzV5zvJJTuHApjcf20bESiKj8DjDoO/bmq0TX8rhSumA== dependencies: "@lerna/child-process" "^3.0.0-beta.21" "@lerna/collect-packages" "^3.0.0-beta.17" @@ -398,7 +364,6 @@ "@lerna/conventional-commits@^3.0.0-beta.15": version "3.0.0-beta.15" resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-3.0.0-beta.15.tgz#42536ec435a20016205a0d30a683692bc1b93c98" - integrity sha512-r74KL1lclM7GJec6DvH7hIVDNYfqYPvK+7ZSRApbNfTEEzH+/IIyPqZnZflczrhWTQCoMWphbQK8zf9QazPcHQ== dependencies: "@lerna/validation-error" "^3.0.0-beta.10" conventional-changelog-angular "^1.6.6" @@ -414,7 +379,6 @@ "@lerna/create-symlink@^3.0.0-beta.0": version "3.0.0-beta.0" resolved "https://registry.yarnpkg.com/@lerna/create-symlink/-/create-symlink-3.0.0-beta.0.tgz#99457b7f636d35a665a2de3cae79c2c45045a0df" - integrity sha512-i9gm0h3RVM8Mhe+kliWmZmLPcaxOyn8ccOtIqHIUanOB4MrlRsg9xQJtlpsEsG3szCKZ+EqcpM9sknEyoHyt4Q== dependencies: cmd-shim "^2.0.2" fs-extra "^5.0.0" @@ -423,7 +387,6 @@ "@lerna/create@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.0.0-beta.21.tgz#53d86397403c12f350c859e30e2a582aed16612e" - integrity sha512-MxjaivJMSIm8VLLCspT6ob9BRus6+DMEizkF0kOiYTVHUh5PI2sCtsw7fa8sIGZQJeU0ELGrvMF4i4VXXFikSQ== dependencies: "@lerna/child-process" "^3.0.0-beta.21" "@lerna/command" "^3.0.0-beta.21" @@ -444,7 +407,6 @@ "@lerna/diff@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.0.0-beta.21.tgz#39c5842b425135e8d6cffbe0eb2e7a1a08faf048" - integrity sha512-/i/RrA6kPMGCsnYnsDixZtlzbM8Q21Ov31+UxP9Z4gAFMVbxyi3DmiQH+de9H8fuVVeqpSGg0XAnVN7nML+mIg== dependencies: "@lerna/child-process" "^3.0.0-beta.21" "@lerna/command" "^3.0.0-beta.21" @@ -454,7 +416,6 @@ "@lerna/exec@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.0.0-beta.21.tgz#5bbdd1b1ed22c42224f1ed21fe0873003182b0ec" - integrity sha512-JsGpl98dk2CrQ3iMw2tFk9dbmf2iFDeOmFIHUWxDwXSC+MLiFCl+XZeJ4AY3/OmF2sQev/HtysfnaqULxkYxUQ== dependencies: "@lerna/batch-packages" "^3.0.0-beta.18" "@lerna/child-process" "^3.0.0-beta.21" @@ -466,14 +427,12 @@ "@lerna/filter-options@^3.0.0-beta.18": version "3.0.0-beta.18" resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-3.0.0-beta.18.tgz#f4014951ec7f58446ee0e29c0fb62c553433530a" - integrity sha512-2TiOR9+7hTv95CEYEIVxSpBFiU4UM6bi7VYwEgErfc8Q72Do9hx9Q1y1wAf2exdAUW5KYx1U+l2Ho/ovq8XEwQ== dependencies: dedent "^0.7.0" "@lerna/filter-packages@^3.0.0-beta.10": version "3.0.0-beta.10" resolved "https://registry.yarnpkg.com/@lerna/filter-packages/-/filter-packages-3.0.0-beta.10.tgz#793a9f53964d2a1e2292fec63a2d337a559b7a78" - integrity sha512-w8Q+tj5h4N4zPauTIdtgBiTD4pPJrV8kbnerxA2A3gWLbjKjDzn8XD7NJJ7HtNMc1x8M7mgyOdXeBZFu474Jgw== dependencies: "@lerna/validation-error" "^3.0.0-beta.10" multimatch "^2.1.0" @@ -482,19 +441,16 @@ "@lerna/get-npm-exec-opts@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-3.0.0-beta.21.tgz#ca2c721411a95ee3c1fb0292ebd89d1855706557" - integrity sha512-+pIB/6wF0Xfz9+an/EDKC+vsba3UI+6GSkS6HyOfLhjCw6kDDGDC0oPmfJtr0DXavrunvKzYTOEm2cD/okEvkw== dependencies: npmlog "^4.1.2" "@lerna/global-options@^3.0.0-beta.13": version "3.0.0-beta.13" resolved "https://registry.yarnpkg.com/@lerna/global-options/-/global-options-3.0.0-beta.13.tgz#4ca84443056f0dce3f4a55528ad5345237675f3a" - integrity sha512-xQv3fdjMSXImeq424rauW5hfOYDTBZAq4kQn2Wbm0q4or+uznECwkfDUHwOY1RwYu40OkjJ1Wtt7DL+WTHSngQ== "@lerna/import@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.0.0-beta.21.tgz#a459988605986c75e017f45d4657d47e0aefc0b1" - integrity sha512-D9+SqWMOdRvB3/vUlauX7BLy84cQ17tG9wzLIiK79JmxTXwnm7zK51oHQ8B51AE4GT96Ht421YAoOCFEpKAdbA== dependencies: "@lerna/child-process" "^3.0.0-beta.21" "@lerna/command" "^3.0.0-beta.21" @@ -507,7 +463,6 @@ "@lerna/init@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.0.0-beta.21.tgz#7cf225b7d2add644fc262408df8cd5c9861c81bb" - integrity sha512-uI4FSNwsBZ3ulBWtJt09z90qfBDTPugyyEoFH5ZpoZ06rdXVoM3i1vbdzPnVGX5qsvIIjNfSu0/zUAw2kM3OJg== dependencies: "@lerna/child-process" "^3.0.0-beta.21" "@lerna/command" "^3.0.0-beta.21" @@ -518,7 +473,6 @@ "@lerna/link@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.0.0-beta.21.tgz#5fd5435092e17a0e558a81b5b0c2422486232ba3" - integrity sha512-thQb6Bq2BI1bFoTw2ADfGRG1DhBRCPteJmQxJZpPrzA6iB9dIFSQb3mXl/piUlF79Cv6Wliwi+3irtM9F5MgPw== dependencies: "@lerna/command" "^3.0.0-beta.21" "@lerna/package-graph" "^3.0.0-beta.18" @@ -529,7 +483,6 @@ "@lerna/list@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.0.0-beta.21.tgz#840866592a6460302a4587da3aa4e5d3850eb8b9" - integrity sha512-m++8Tb8vGj/1qtxomT7ic83DTR+8zY248X9XqOyLxlNnPyB/307lmA3Q5VHaTMLQ41d08BKdh0Sv9O++TYWUtA== dependencies: "@lerna/command" "^3.0.0-beta.21" "@lerna/filter-options" "^3.0.0-beta.18" @@ -540,7 +493,6 @@ "@lerna/npm-conf@^3.0.0-beta.19": version "3.0.0-beta.19" resolved "https://registry.yarnpkg.com/@lerna/npm-conf/-/npm-conf-3.0.0-beta.19.tgz#957f164a33e958e60a1c1c70a2879e9fa1bb08b2" - integrity sha512-6E5dx52ZuN9aV4Pe3rED6fccGGuZPznJpCjfSU8QXYvLfbCOkUOEik8+TzvzpD2N301ThtUpQqD+wtaGI8WtNw== dependencies: config-chain "^1.1.11" pify "^3.0.0" @@ -548,7 +500,6 @@ "@lerna/npm-dist-tag@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-3.0.0-beta.21.tgz#c15a2dc7c57d3f50b590b206e0ebb66d4eb47a7f" - integrity sha512-G4RNx07THCsPQuHTXZZntiLCv2WeYdZkFZk/vcR3sHDaYR6JUaIPDIfwK7XGWRtU9uziRkeTnyi7QbJITyd+Xw== dependencies: "@lerna/child-process" "^3.0.0-beta.21" "@lerna/get-npm-exec-opts" "^3.0.0-beta.21" @@ -557,7 +508,6 @@ "@lerna/npm-install@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-3.0.0-beta.21.tgz#726057f1bd684ad9fa6f87a70d9c246b966e7491" - integrity sha512-qYB7ZUWXura0PSBDkXfuyBSJMVPbOiFWuxB0O8fpSFW4o+/HaL137Ayjdr5Nxr6r4r0hlY4liKNYpXxyFAKE4g== dependencies: "@lerna/child-process" "^3.0.0-beta.21" "@lerna/get-npm-exec-opts" "^3.0.0-beta.21" @@ -570,7 +520,6 @@ "@lerna/npm-publish@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-3.0.0-beta.21.tgz#25a65820a6036c72fb37c914fa0fb2d615346e1d" - integrity sha512-bgXejqsOZMquDGBmedAjHczun16X/E76BB9uwys02jTSKBqtYggaBii1kGaUVNL5dZ2mPyumj/8+Aps24DwdjA== dependencies: "@lerna/child-process" "^3.0.0-beta.21" "@lerna/get-npm-exec-opts" "^3.0.0-beta.21" @@ -579,7 +528,6 @@ "@lerna/npm-run-script@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/npm-run-script/-/npm-run-script-3.0.0-beta.21.tgz#8f45cbee40061946942a5184f09a2b086c41fe0b" - integrity sha512-2vmDsVVMEu1tGiF/gGXDW2Axm3ADzsJUn5O0PbrANZvoGEnMHY3dN4m8gDLOBb1B04h3jU8gbXQXUqrmZWvxUA== dependencies: "@lerna/child-process" "^3.0.0-beta.21" "@lerna/get-npm-exec-opts" "^3.0.0-beta.21" @@ -588,14 +536,12 @@ "@lerna/output@^3.0.0-beta.0": version "3.0.0-beta.0" resolved "https://registry.yarnpkg.com/@lerna/output/-/output-3.0.0-beta.0.tgz#0fba8a24f425ac6705b4949ab90f74aae05955bc" - integrity sha512-jfndeh1Bf3bQHLkq7zTEV3dcgV+jIxekBqlhVs7KTZrGc/pXz4v+sqGd2HLByDxMTixELzslzntJIyKJ7RO4GA== dependencies: npmlog "^4.1.2" "@lerna/package-graph@^3.0.0-beta.18": version "3.0.0-beta.18" resolved "https://registry.yarnpkg.com/@lerna/package-graph/-/package-graph-3.0.0-beta.18.tgz#8c33a6a10453d310e14fc9d317dc51e845e11963" - integrity sha512-7hmli0geLBhKPZylt4osZYXTlx+V7TwlKWjsndobx8DmCfu7l1IM8OLJ1WBBh/pjXIAdo277twX5uUVYunv2/g== dependencies: npm-package-arg "^6.0.0" semver "^5.5.0" @@ -603,7 +549,6 @@ "@lerna/package@^3.0.0-beta.17": version "3.0.0-beta.17" resolved "https://registry.yarnpkg.com/@lerna/package/-/package-3.0.0-beta.17.tgz#ccc833926ddfce5cac6194d2e6b415899a8e753e" - integrity sha512-eLEbzMcNdCCMZmkG3IsIpAe04bq4unWkF6GaVplvv0UmP7ZmNPkopAJ3Mre5kpz7g6ICF96yjXJ8I3VCPJWELQ== dependencies: npm-package-arg "^6.0.0" write-pkg "^3.1.0" @@ -611,7 +556,6 @@ "@lerna/project@^3.0.0-beta.20": version "3.0.0-beta.20" resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.0.0-beta.20.tgz#27a0330b7b13d8eebe9266f03eb60de94b15c86d" - integrity sha512-bS0gD1ReT9l4ZwZXLM4bZBCb1tlJAzVZXJj4RVDgJ1pGt2h4UVMpWJCZqCuYhhiyu6J0v7ntwK3TQH+C3rlqcw== dependencies: "@lerna/package" "^3.0.0-beta.17" "@lerna/validation-error" "^3.0.0-beta.10" @@ -627,7 +571,6 @@ "@lerna/prompt@^3.0.0-beta.0": version "3.0.0-beta.0" resolved "https://registry.yarnpkg.com/@lerna/prompt/-/prompt-3.0.0-beta.0.tgz#f1baa4d1fe30eef4cf3f2add49aac917cfc1368b" - integrity sha512-hEBT3TiMzJgkxUx7vrvTfCn8ZwYEFy/e/FlFvoDV/MheX4OQ3+cb73mW7ya7J1akJ6jRXUvwmEcZnKXkKQgo/w== dependencies: inquirer "^5.1.0" npmlog "^4.1.2" @@ -635,7 +578,6 @@ "@lerna/publish@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.0.0-beta.21.tgz#8d2563793ba5b2e8f9914e799746b5a711adbc5f" - integrity sha512-xsKcWFF8mlRCfmEvPE4G0R84JCmFpmmah/gVsviCLLmhkdoTwDugnp++Ij2ONx5wW+kSYhw7MflcbuygOU8t6w== dependencies: "@lerna/batch-packages" "^3.0.0-beta.18" "@lerna/child-process" "^3.0.0-beta.21" @@ -666,7 +608,6 @@ "@lerna/resolve-symlink@^3.0.0-beta.0": version "3.0.0-beta.0" resolved "https://registry.yarnpkg.com/@lerna/resolve-symlink/-/resolve-symlink-3.0.0-beta.0.tgz#ca170d8190acf915c5160dc19111543989191987" - integrity sha512-eF2iqrQWcgGFKCSGGPm23+6WD+8hChGGEa2uHebo3UHGGbzXVnyMKHYC9Z8WK7mzt8k+s1BiwC0YYtqHcOFDvg== dependencies: fs-extra "^5.0.0" npmlog "^4.1.2" @@ -675,7 +616,6 @@ "@lerna/rimraf-dir@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/rimraf-dir/-/rimraf-dir-3.0.0-beta.21.tgz#006b4e61e8d76e369e3749936862fb182def1dff" - integrity sha512-fHluLhYnQuaCoSd/PxhVMy095vETH47iw0V0RhwbYBNdrdsMI6zQoDNr+uSzuVawGIkQku1HuNt/olmMLYf6fg== dependencies: "@lerna/child-process" "^3.0.0-beta.21" npmlog "^4.1.2" @@ -685,7 +625,6 @@ "@lerna/run-lifecycle@^3.0.0-beta.0": version "3.0.0-beta.0" resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-3.0.0-beta.0.tgz#b30442df543dcfafa863c854c2d7338fe3bd13b3" - integrity sha512-QAmgToyNTKpPeyPm3lE6FEaTf58x3Rm5hHgzCA+e8kYeJ3XkopDfOcLJlpW0YA1pST5EbNGUipvS8P8zI1Va3Q== dependencies: npm-lifecycle "^2.0.0" npmlog "^4.1.2" @@ -693,7 +632,6 @@ "@lerna/run-parallel-batches@^3.0.0-beta.0": version "3.0.0-beta.0" resolved "https://registry.yarnpkg.com/@lerna/run-parallel-batches/-/run-parallel-batches-3.0.0-beta.0.tgz#24d69314ad0fd6fa65c70d239b4f2ccdd08a2eeb" - integrity sha512-G8reoAaDwpF9mYhVfnxCUYm63RVXaTdT8zWHxnIamtdMhH1vPq+goUzLgCTAZuDO8c51H1SHu8XK/4agGwoP+A== dependencies: p-map "^1.2.0" p-map-series "^1.0.0" @@ -701,7 +639,6 @@ "@lerna/run@^3.0.0-beta.21": version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.0.0-beta.21.tgz#f7fce5d1b1043a48b0bf33a7565527ee6e26061e" - integrity sha512-RhyXznUi0xcHj3PbeW0M1Dm5wH5z+oEUVLDyJJE+eqYjQiDfctYo9U4IgFw6wom/mPTUbE3j4BxAyR1U/ynuSg== dependencies: "@lerna/batch-packages" "^3.0.0-beta.18" "@lerna/command" "^3.0.0-beta.21" @@ -715,7 +652,6 @@ "@lerna/symlink-binary@^3.0.0-beta.17": version "3.0.0-beta.17" resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-3.0.0-beta.17.tgz#e0be4394ee4e828a496aa8b9f8f48084ed7cb0f3" - integrity sha512-OlDHER9NboPnrcC5LLRNW1yFhCrOPtr551yccTqaa2TQ0GNcfirztcgKsrWRJeiaH0nxs1Rwi4ZQmOk/sYB+sw== dependencies: "@lerna/create-symlink" "^3.0.0-beta.0" "@lerna/package" "^3.0.0-beta.17" @@ -726,7 +662,6 @@ "@lerna/symlink-dependencies@^3.0.0-beta.17": version "3.0.0-beta.17" resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-3.0.0-beta.17.tgz#82d3f2d5b76606772773d306e7640fcf309b8c56" - integrity sha512-gawfpPH85rFXJCWrPJLHhnsloQr+wx6sjZK6aS9CwmWJAnsp9RAF6xODwG4C2kuHr4OsQCpIInhR7fCiVzGMLQ== dependencies: "@lerna/create-symlink" "^3.0.0-beta.0" "@lerna/resolve-symlink" "^3.0.0-beta.0" @@ -739,14 +674,12 @@ "@lerna/validation-error@^3.0.0-beta.10": version "3.0.0-beta.10" resolved "https://registry.yarnpkg.com/@lerna/validation-error/-/validation-error-3.0.0-beta.10.tgz#cf5cbc39c4d27b89c6080e326de745f6fb7451ab" - integrity sha512-Ff7DPJzlgO7DIRp5812SxdWOWPJsF8kbhuEe79gcqyNJYxD+03tGnXDQcXt4zr9d8Np8Kmcl65xGhQDIH1q8lQ== dependencies: npmlog "^4.1.2" "@lerna/write-log-file@^3.0.0-beta.0": version "3.0.0-beta.0" resolved "https://registry.yarnpkg.com/@lerna/write-log-file/-/write-log-file-3.0.0-beta.0.tgz#e128fee7cd7cb218ed767598ac45c6d2db5c6c89" - integrity sha512-2KJ2Zw4t8uHg827ihAmDpbWfuN6/5Yow5qWrw86Ip1ihMQ+CGMLqx5FDotlHLmOM7Io+xD5wh8yWOD+iDjKDPw== dependencies: npmlog "^4.1.2" write-file-atomic "^2.3.0" @@ -754,14 +687,12 @@ "@mapbox/hast-util-table-cell-style@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@mapbox/hast-util-table-cell-style/-/hast-util-table-cell-style-0.1.3.tgz#5b7166ae01297d72216932b245e4b2f0b642dca6" - integrity sha512-QsEsh5YaDvHoMQ2YHdvZy2iDnU3GgKVBTcHf6cILyoWDZtPSdlG444pL/ioPYO/GpXSfODBb9sefEetfC4v9oA== dependencies: unist-util-visit "^1.3.0" "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" - integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== dependencies: call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" @@ -769,12 +700,10 @@ "@nodelib/fs.stat@^1.0.1": version "1.1.0" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz#50c1e2260ac0ed9439a181de3725a0168d59c48a" - integrity sha512-LAQ1d4OPfSJ/BMbI2DuizmYrrkD9JMaTdi2hQTlI53lQ4kRQPyZQRS4CYQ7O66bnBBnP/oYdRxbk++X0xuFU6A== "@octokit/rest@^15.2.6": version "15.9.4" resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-15.9.4.tgz#c6cf0f483275d9c798b18419b7c9d417493bb70f" - integrity sha512-v3CS1qW4IjriMvGgm4lDnYFBJlkwvzIbTxiipOcwVP8xeK8ih2pJofRhk7enmLngTtNEa+sIApJNkXxyyDKqLg== dependencies: before-after-hook "^1.1.0" btoa-lite "^1.0.0" @@ -788,22 +717,18 @@ "@std/esm@^0.19.1": version "0.19.1" resolved "https://registry.yarnpkg.com/@std/esm/-/esm-0.19.1.tgz#8bdf8ed0e759eea1c7010d22fb9789e462ec0a9b" - integrity sha512-4Ph4hdaDIkt5sChK565oU16Wa9jcBwLbiNAMEB6fyQZlBw5uz3UpxTo/ZohjeILgJfNtb/l1HzVql1ys5s74Ww== "@thi.ng/checks@^1.5.3": version "1.5.3" resolved "https://registry.npmjs.org/@thi.ng/checks/-/checks-1.5.3.tgz#566df9d173f4ee7a928406f56fafa0c263c5a73a" - integrity sha1-Vm350XP07nqShAb1b6+gwmPFpzo= "@thi.ng/errors@^0.1.3": version "0.1.3" resolved "https://registry.npmjs.org/@thi.ng/errors/-/errors-0.1.3.tgz#42d5382b174fc21320f42ddbc0edcc8bfeea96e6" - integrity sha1-QtU4KxdPwhMg9C3bwO3Mi/7qluY= "@thi.ng/paths@^1.3.8": version "1.3.8" resolved "https://registry.npmjs.org/@thi.ng/paths/-/paths-1.3.8.tgz#815ad89aebdf1bd2b9013ef874fddb97fcc67f47" - integrity sha1-gVrYmuvfG9K5AT74dP3bl/zGf0c= dependencies: "@thi.ng/checks" "^1.5.3" "@thi.ng/errors" "^0.1.3" @@ -811,19 +736,16 @@ "@types/node@^8.0.24": version "8.9.5" resolved "http://registry.npmjs.org/@types/node/-/node-8.9.5.tgz#162b864bc70be077e6db212b322754917929e976" - integrity sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ== "@vxna/mini-html-webpack-template@^0.1.7": version "0.1.7" resolved "https://registry.yarnpkg.com/@vxna/mini-html-webpack-template/-/mini-html-webpack-template-0.1.7.tgz#2a8270e513ee14f395cc17c2ce22ced383c45d22" - integrity sha512-qV2VslV48ECPwyuG7c4O6JpYgjnvdm88YYkMncIXzakXXwVUxhcg6YipXxWK7U+pixHkWWSnDX/8DIOmWeh+PQ== dependencies: common-tags "^1.7.2" "@webassemblyjs/ast@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.10.tgz#0cfc61d61286240b72fc522cb755613699eea40a" - integrity sha512-wTUeaByYN2EA6qVqhbgavtGc7fLTOx0glG2IBsFlrFG51uXIGlYBTyIZMf4SPLo3v1bgV/7lBN3l7Z0R6Hswew== dependencies: "@webassemblyjs/helper-module-context" "1.7.10" "@webassemblyjs/helper-wasm-bytecode" "1.7.10" @@ -832,44 +754,36 @@ "@webassemblyjs/floating-point-hex-parser@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.10.tgz#ee63d729c6311a85863e369a473f9983f984e4d9" - integrity sha512-gMsGbI6I3p/P1xL2UxqhNh1ga2HCsx5VBB2i5VvJFAaqAjd2PBTRULc3BpTydabUQEGlaZCzEUQhLoLG7TvEYQ== "@webassemblyjs/helper-api-error@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.10.tgz#bfcb3bbe59775357475790a2ad7b289f09b2f198" - integrity sha512-DoYRlPWtuw3yd5BOr9XhtrmB6X1enYF0/54yNvQWGXZEPDF5PJVNI7zQ7gkcKfTESzp8bIBWailaFXEK/jjCsw== "@webassemblyjs/helper-buffer@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.10.tgz#0a8c624c67ad0b214d2e003859921a1988cb151b" - integrity sha512-+RMU3dt/dPh4EpVX4u5jxsOlw22tp3zjqE0m3ftU2tsYxnPULb4cyHlgaNd2KoWuwasCQqn8Mhr+TTdbtj3LlA== "@webassemblyjs/helper-code-frame@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.10.tgz#0ab7e22fad0241a173178c73976fc0edf50832ce" - integrity sha512-UiytbpKAULOEab2hUZK2ywXen4gWJVrgxtwY3Kn+eZaaSWaRM8z/7dAXRSoamhKFiBh1uaqxzE/XD9BLlug3gw== dependencies: "@webassemblyjs/wast-printer" "1.7.10" "@webassemblyjs/helper-fsm@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.10.tgz#0915e7713fbbb735620a9d3e4fa3d7951f97ac64" - integrity sha512-w2vDtUK9xeSRtt5+RnnlRCI7wHEvLjF0XdnxJpgx+LJOvklTZPqWkuy/NhwHSLP19sm9H8dWxKeReMR7sCkGZA== "@webassemblyjs/helper-module-context@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.10.tgz#9beb83f72740f5ac8075313b5cac5e796510f755" - integrity sha512-yE5x/LzZ3XdPdREmJijxzfrf+BDRewvO0zl8kvORgSWmxpRrkqY39KZSq6TSgIWBxkK4SrzlS3BsMCv2s1FpsQ== "@webassemblyjs/helper-wasm-bytecode@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.10.tgz#797b1e734bbcfdea8399669cdc58308ef1c7ffc0" - integrity sha512-u5qy4SJ/OrxKxZqJ9N3qH4ZQgHaAzsopsYwLvoWJY6Q33r8PhT3VPyNMaJ7ZFoqzBnZlCcS/0f4Sp8WBxylXfg== "@webassemblyjs/helper-wasm-section@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.10.tgz#c0ea3703c615d7bc3e3507c3b7991c8767b2f20e" - integrity sha512-Ecvww6sCkcjatcyctUrn22neSJHLN/TTzolMGG/N7S9rpbsTZ8c6Bl98GpSpV77EvzNijiNRHBG0+JO99qKz6g== dependencies: "@webassemblyjs/ast" "1.7.10" "@webassemblyjs/helper-buffer" "1.7.10" @@ -879,26 +793,22 @@ "@webassemblyjs/ieee754@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.7.10.tgz#62c1728b7ef0f66ef8221e2966a0afd75db430df" - integrity sha512-HRcWcY+YWt4+s/CvQn+vnSPfRaD4KkuzQFt5MNaELXXHSjelHlSEA8ZcqT69q0GTIuLWZ6JaoKar4yWHVpZHsQ== dependencies: "@xtuc/ieee754" "^1.2.0" "@webassemblyjs/leb128@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.7.10.tgz#167e0bb4b06d7701585772a73fba9f4df85439f6" - integrity sha512-og8MciYlA8hvzCLR71hCuZKPbVBfLQeHv7ImKZ4nlyxrYbG7uJHYtHiHu6OV9SqrGuD03H/HtXC4Bgdjfm9FHw== dependencies: "@xtuc/long" "4.2.1" "@webassemblyjs/utf8@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.7.10.tgz#b6728f5b6f50364abc155be029f9670e6685605a" - integrity sha512-Ng6Pxv6siyZp635xCSnH3mKmIFgqWPCcGdoo0GBYgyGdxu7cUj4agV7Uu1a8REP66UYUFXJLudeGgd4RvuJAnQ== "@webassemblyjs/wasm-edit@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.10.tgz#83fe3140f5a58f5a30b914702be9f0e59a399092" - integrity sha512-e9RZFQlb+ZuYcKRcW9yl+mqX/Ycj9+3/+ppDI8nEE/NCY6FoK8f3dKBcfubYV/HZn44b+ND4hjh+4BYBt+sDnA== dependencies: "@webassemblyjs/ast" "1.7.10" "@webassemblyjs/helper-buffer" "1.7.10" @@ -912,7 +822,6 @@ "@webassemblyjs/wasm-gen@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.10.tgz#4de003806ae29c97ab3707782469b53299570174" - integrity sha512-M0lb6cO2Y0PzDye/L39PqwV+jvO+2YxEG5ax+7dgq7EwXdAlpOMx1jxyXJTScQoeTpzOPIb+fLgX/IkLF8h2yw== dependencies: "@webassemblyjs/ast" "1.7.10" "@webassemblyjs/helper-wasm-bytecode" "1.7.10" @@ -923,7 +832,6 @@ "@webassemblyjs/wasm-opt@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.10.tgz#d151e31611934a556c82789fdeec41a814993c2a" - integrity sha512-R66IHGCdicgF5ZliN10yn5HaC7vwYAqrSVJGjtJJQp5+QNPBye6heWdVH/at40uh0uoaDN/UVUfXK0gvuUqtVg== dependencies: "@webassemblyjs/ast" "1.7.10" "@webassemblyjs/helper-buffer" "1.7.10" @@ -933,7 +841,6 @@ "@webassemblyjs/wasm-parser@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.10.tgz#0367be7bf8f09e3e6abc95f8e483b9206487ec65" - integrity sha512-AEv8mkXVK63n/iDR3T693EzoGPnNAwKwT3iHmKJNBrrALAhhEjuPzo/lTE4U7LquEwyvg5nneSNdTdgrBaGJcA== dependencies: "@webassemblyjs/ast" "1.7.10" "@webassemblyjs/helper-api-error" "1.7.10" @@ -945,7 +852,6 @@ "@webassemblyjs/wast-parser@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.7.10.tgz#058f598b52f730b23fc874d4775b6286b6247264" - integrity sha512-YTPEtOBljkCL0VjDp4sHe22dAYSm3ZwdJ9+2NTGdtC7ayNvuip1wAhaAS8Zt9Q6SW9E5Jf5PX7YE3XWlrzR9cw== dependencies: "@webassemblyjs/ast" "1.7.10" "@webassemblyjs/floating-point-hex-parser" "1.7.10" @@ -957,7 +863,6 @@ "@webassemblyjs/wast-printer@1.7.10": version "1.7.10" resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.7.10.tgz#d817909d2450ae96c66b7607624d98a33b84223b" - integrity sha512-mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA== dependencies: "@webassemblyjs/ast" "1.7.10" "@webassemblyjs/wast-parser" "1.7.10" @@ -966,17 +871,14 @@ "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== "@xtuc/long@4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.1.tgz#5c85d662f76fa1d34575766c5dcd6615abcd30d8" - integrity sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g== JSONStream@^1.0.4: version "1.3.3" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.3.tgz#27b4b8fbbfeab4e71bcf551e7f27be8d952239bf" - integrity sha512-3Sp6WZZ/lXl+nTDoGpGWHEpTnnC6X5fnkolYZR6nwIfzbxxvA8utPWe1gCt7i0m9uVGsSz2IS8K8mJ7HmlduMg== dependencies: jsonparse "^1.2.0" through ">=2.2.7 <3" @@ -984,17 +886,14 @@ JSONStream@^1.0.4: abab@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" - integrity sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4= abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== accepts@~1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" - integrity sha1-hiRnWMfdbSGmR0/whKR0DsBesh8= dependencies: mime-types "~2.1.16" negotiator "0.6.1" @@ -1002,7 +901,6 @@ accepts@~1.3.4: accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" - integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= dependencies: mime-types "~2.1.18" negotiator "0.6.1" @@ -1010,87 +908,72 @@ accepts@~1.3.5: acorn-dynamic-import@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278" - integrity sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg== dependencies: acorn "^5.0.0" acorn-globals@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf" - integrity sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8= dependencies: acorn "^4.0.4" acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= dependencies: acorn "^3.0.4" acorn-jsx@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e" - integrity sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw== dependencies: acorn "^5.0.3" acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= acorn@^4.0.4: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= acorn@^5.0.0: version "5.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822" - integrity sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug== acorn@^5.0.3, acorn@^5.4.1, acorn@^5.5.0, acorn@^5.6.2, acorn@^5.7.1, acorn@^5.7.3: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== address@1.0.3, address@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" - integrity sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg== agent-base@4, agent-base@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" - integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== dependencies: es6-promisify "^5.0.0" ajv-errors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59" - integrity sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk= ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" - integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= ajv-keywords@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.1.0.tgz#ac2b27939c543e95d2c06e7f7f5c27be4aa543be" - integrity sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74= ajv-keywords@^3.1.0, ajv-keywords@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" - integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" @@ -1098,7 +981,6 @@ ajv@^4.9.1: ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" @@ -1108,7 +990,6 @@ ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0: ajv@^6.0.1: version "6.4.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.4.0.tgz#d3aff78e9277549771daf0164cff48482b754fc6" - integrity sha1-06/3jpJ3VJdx2vAWTP9ISCt1T8Y= dependencies: fast-deep-equal "^1.0.0" fast-json-stable-stringify "^2.0.0" @@ -1118,7 +999,6 @@ ajv@^6.0.1: ajv@^6.1.0: version "6.5.4" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.4.tgz#247d5274110db653706b550fcc2b797ca28cfc59" - integrity sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -1128,7 +1008,6 @@ ajv@^6.1.0: ajv@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.2.1.tgz#28a6abc493a2abe0fb4c8507acaedb43fa550671" - integrity sha1-KKarxJOiq+D7TIUHrK7bQ/pVBnE= dependencies: fast-deep-equal "^1.0.0" fast-json-stable-stringify "^2.0.0" @@ -1137,7 +1016,6 @@ ajv@^6.2.1: ajv@^6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.3.tgz#71a569d189ecf4f4f321224fecb166f071dd90f9" - integrity sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -1147,7 +1025,6 @@ ajv@^6.5.2: align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= dependencies: kind-of "^3.0.2" longest "^1.0.1" @@ -1156,73 +1033,60 @@ align-text@^0.1.1, align-text@^0.1.3: alphanum-sort@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= ansi-align@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" - integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38= dependencies: string-width "^2.0.0" ansi-colors@^3.0.0: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.1.tgz#9638047e4213f3428a11944a7d4b31cba0a3ff95" - integrity sha512-Xt+zb6nqgvV9SWAVp0EG3lRsHcbq5DDgqjPPz6pwgtj6RKz65zGXMNa82oJfOSBA/to6GmRP7Dr+6o+kbApTzQ== ansi-escapes@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= ansi-escapes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" - integrity sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ== ansi-html@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" - integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= ansi-regex@^2.0.0, ansi-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= ansi-styles@^3.0.0, ansi-styles@^3.1.0, ansi-styles@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" - integrity sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug== dependencies: color-convert "^1.9.0" ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" - integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== dependencies: micromatch "^2.1.5" normalize-path "^2.0.0" @@ -1230,7 +1094,6 @@ anymatch@^1.3.0: anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" normalize-path "^2.1.1" @@ -1238,17 +1101,14 @@ anymatch@^2.0.0: app-builder-bin@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-2.0.0.tgz#bda985bee14370b254841a9982753b8f383415c5" - integrity sha512-JUJ1Wiaig1589MxF110HHh5I5v9hn2Qu4ZeleNwSZHfD1S2LrCxm4H+q7Snr/rWlWdEChFoWM2lj11Cdl4LP0Q== app-builder-bin@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-2.1.2.tgz#528ce8e543aa595210c9595f91bdf5638cecd79b" - integrity sha512-PZJspzAqB0+z60OalXChP9I05BzODd/ffDz6RvTmDG3qclr7YrnpqzvPF+T7vGVtk2nN7syuveTQROJfXcB8xA== app-builder-lib@20.28.4, app-builder-lib@~20.28.3: version "20.28.4" resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-20.28.4.tgz#0bee3366364c65d17a2aaab75b30bb10df76ece5" - integrity sha512-RY4/NJs1HCFWAOpLMivuDzbesU5VyaZVKuQllxgCNZ56+ihgO5aGexla2DVjG/bBQleWfF3DPnEsF3sbZPlpHw== dependencies: "7zip-bin" "~4.0.2" app-builder-bin "2.1.2" @@ -1278,19 +1138,16 @@ app-builder-lib@20.28.4, app-builder-lib@~20.28.3: append-transform@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" - integrity sha1-126/jKlNJ24keja61EpLdKthGZE= dependencies: default-require-extensions "^1.0.0" aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== are-we-there-yet@~1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" - integrity sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0= dependencies: delegates "^1.0.0" readable-stream "^2.0.6" @@ -1298,76 +1155,62 @@ are-we-there-yet@~1.1.2: argparse@^1.0.7: version "1.0.9" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" - integrity sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY= dependencies: sprintf-js "~1.0.2" argv@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/argv/-/argv-0.0.2.tgz#ecbd16f8949b157183711b1bda334f37840185ab" - integrity sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas= arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= dependencies: arr-flatten "^1.0.1" arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= array-differ@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" - integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= array-filter@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" - integrity sha1-fajPLiZijtcygDWB/SH2fKzS7uw= array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= array-flatten@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.1.tgz#426bb9da84090c1838d812c8150af20a8331e296" - integrity sha1-Qmu52oQJDBg42BLIFQryCoMx4pY= array-ify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" - integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= array-includes@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" - integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= dependencies: define-properties "^1.1.2" es-abstract "^1.7.0" @@ -1375,54 +1218,44 @@ array-includes@^3.0.3: array-iterate@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-1.1.1.tgz#865bf7f8af39d6b0982c60902914ac76bc0108f6" - integrity sha1-hlv3+K851rCYLGCQKRSsdrwBCPY= array-map@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" - integrity sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI= array-reduce@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" - integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys= array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= dependencies: array-uniq "^1.0.1" array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -asap@^2.0.0, asap@~2.0.3: +asap@^2.0.0, asap@^2.0.6, asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= asn1.js@^4.0.0: version "4.9.2" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.2.tgz#8117ef4f7ed87cd8f89044b5bff97ac243a16c9a" - integrity sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg== dependencies: bn.js "^4.0.0" inherits "^2.0.1" @@ -1431,101 +1264,82 @@ asn1.js@^4.0.0: asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y= assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assert-plus@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - integrity sha1-104bh+ev/A24qttwIfP+SBAasjQ= assert@^1.1.1: version "1.4.1" resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= dependencies: util "0.10.3" assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= ast-types@0.10.2: version "0.10.2" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.10.2.tgz#aef76a04fde54634976fc94defaad1a67e2eadb0" - integrity sha512-ufWX953VU1eIuWqxS0nRDMYlGyFH+yxln5CsmIHlpzEt3fdYqUnRtsFt0XAsQot8OaVCwFqxT1RiwvtzYjeYeg== ast-types@0.11.5: version "0.11.5" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.5.tgz#9890825d660c03c28339f315e9fa0a360e31ec28" - integrity sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw== ast-types@^0.11.6: version "0.11.6" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.6.tgz#4e2266c2658829aef3b40cc33ad599c4e9eb89ef" - integrity sha512-nHiuV14upVGl7MWwFUYbzJ6YlfwWS084CU9EA8HajfYQjMSli5TQi3UTRygGF58LFWVkXxS1rbgRhROEqlQkXg== ast-types@^0.7.2: version "0.7.8" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.7.8.tgz#902d2e0d60d071bdcd46dc115e1809ed11c138a9" - integrity sha1-kC0uDWDQcb3NRtwRXhgJ7RHBOKk= async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= async-exit-hook@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3" - integrity sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw== async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== async@^1.4.0, async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= async@^2.1.4, async@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" - integrity sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw== dependencies: lodash "^4.14.0" async@~0.2.10: version "0.2.10" resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" - integrity sha1-trvgsGdLnXGXCMo43owjfLUmw9E= async@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" - integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k= asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= atob@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" - integrity sha1-GcenYEc3dEaPILLS0DNyrX1Mv10= autoprefixer@^7.1.1, autoprefixer@^7.1.2: version "7.2.5" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.2.5.tgz#04ccbd0c6a61131b6d13f53d371926092952d192" - integrity sha512-XqHfo8Ht0VU+T5P+eWEVoXza456KJ4l62BPewu3vpNf3LP9s2+zYXkXBznzYby4XeECXgG3N4i+hGvOhXErZmA== dependencies: browserslist "^2.11.1" caniuse-lite "^1.0.30000791" @@ -1537,7 +1351,6 @@ autoprefixer@^7.1.1, autoprefixer@^7.1.2: aws-sdk@^2.264.1: version "2.318.0" resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.318.0.tgz#b9e8e795d4ae9d5ba428cdaa75dde49acce708d4" - integrity sha512-w2XT+DOKOczoRaB9R0cRCZSwHkw4JfngMlUKeRhMbzOvW9orOZB2SeMgz+Pz1jKU3VSJDMpvB/Z3P68nvDxb8Q== dependencies: buffer "4.9.1" events "1.1.1" @@ -1552,27 +1365,22 @@ aws-sdk@^2.264.1: aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - integrity sha1-FDQt0428yU0OW4fXY81jYSwOeU8= aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.2.1, aws4@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - integrity sha1-g+9cqGCysy5KDe7e6MdxudtXRx4= aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== babel-cli@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.26.0.tgz#502ab54874d7db88ad00b887a06383ce03d002f1" - integrity sha1-UCq1SHTX24itALiHoGODzgPQAvE= dependencies: babel-core "^6.26.0" babel-polyfill "^6.26.0" @@ -1594,7 +1402,6 @@ babel-cli@^6.26.0: babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= dependencies: chalk "^1.1.3" esutils "^2.0.2" @@ -1603,7 +1410,6 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: babel-core@^6.0.0, babel-core@^6.25.0, babel-core@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" - integrity sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g= dependencies: babel-code-frame "^6.26.0" babel-generator "^6.26.0" @@ -1628,7 +1434,6 @@ babel-core@^6.0.0, babel-core@^6.25.0, babel-core@^6.26.0: babel-eslint@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.1.tgz#919681dc099614cd7d31d45c8908695092a1faed" - integrity sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ== dependencies: "@babel/code-frame" "^7.0.0" "@babel/parser" "^7.0.0" @@ -1640,7 +1445,6 @@ babel-eslint@^10.0.1: babel-eslint@^8.2.3: version "8.2.6" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.6.tgz#6270d0c73205628067c0f7ae1693a9e797acefd9" - integrity sha512-aCdHjhzcILdP8c9lej7hvXKvQieyRt20SF102SIGyY4cUIiw6UaAtK4j2o3dXX74jEmy0TJ0CEhv4fTIM3SzcA== dependencies: "@babel/code-frame" "7.0.0-beta.44" "@babel/traverse" "7.0.0-beta.44" @@ -1652,7 +1456,6 @@ babel-eslint@^8.2.3: babel-generator@^6.18.0, babel-generator@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" - integrity sha1-rBriAHC3n248odMmlhMFN3TyDcU= dependencies: babel-messages "^6.23.0" babel-runtime "^6.26.0" @@ -1666,7 +1469,6 @@ babel-generator@^6.18.0, babel-generator@^6.26.0: babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= dependencies: babel-helper-explode-assignable-expression "^6.24.1" babel-runtime "^6.22.0" @@ -1675,7 +1477,6 @@ babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: babel-helper-builder-react-jsx@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" - integrity sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA= dependencies: babel-runtime "^6.26.0" babel-types "^6.26.0" @@ -1684,7 +1485,6 @@ babel-helper-builder-react-jsx@^6.24.1: babel-helper-call-delegate@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -1694,7 +1494,6 @@ babel-helper-call-delegate@^6.24.1: babel-helper-define-map@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.26.0" @@ -1704,7 +1503,6 @@ babel-helper-define-map@^6.24.1: babel-helper-explode-assignable-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= dependencies: babel-runtime "^6.22.0" babel-traverse "^6.24.1" @@ -1713,7 +1511,6 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= dependencies: babel-helper-get-function-arity "^6.24.1" babel-runtime "^6.22.0" @@ -1724,7 +1521,6 @@ babel-helper-function-name@^6.24.1: babel-helper-get-function-arity@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -1732,7 +1528,6 @@ babel-helper-get-function-arity@^6.24.1: babel-helper-hoist-variables@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -1740,7 +1535,6 @@ babel-helper-hoist-variables@^6.24.1: babel-helper-optimise-call-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -1748,7 +1542,6 @@ babel-helper-optimise-call-expression@^6.24.1: babel-helper-regex@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= dependencies: babel-runtime "^6.26.0" babel-types "^6.26.0" @@ -1757,7 +1550,6 @@ babel-helper-regex@^6.24.1: babel-helper-remap-async-to-generator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -1768,7 +1560,6 @@ babel-helper-remap-async-to-generator@^6.24.1: babel-helper-replace-supers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= dependencies: babel-helper-optimise-call-expression "^6.24.1" babel-messages "^6.23.0" @@ -1780,7 +1571,6 @@ babel-helper-replace-supers@^6.24.1: babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -1788,7 +1578,6 @@ babel-helpers@^6.24.1: babel-jest@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-20.0.3.tgz#e4a03b13dc10389e140fc645d09ffc4ced301671" - integrity sha1-5KA7E9wQOJ4UD8ZF0J/8TO0wFnE= dependencies: babel-core "^6.0.0" babel-plugin-istanbul "^4.0.0" @@ -1797,7 +1586,6 @@ babel-jest@^20.0.3: babel-loader@7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.5.tgz#e3ee0cd7394aa557e013b02d3e492bfd07aa6d68" - integrity sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw== dependencies: find-cache-dir "^1.0.0" loader-utils "^1.0.2" @@ -1806,21 +1594,18 @@ babel-loader@7.1.5: babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= dependencies: babel-runtime "^6.22.0" babel-plugin-check-es2015-constants@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= dependencies: babel-runtime "^6.22.0" babel-plugin-emotion@^9.2.11: version "9.2.11" resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-9.2.11.tgz#319c005a9ee1d15bb447f59fe504c35fd5807728" - integrity sha512-dgCImifnOPPSeXod2znAmgc64NhaaOjGEHROR/M+lmStb3841yK1sgaDYAYMnlvWNz8GnpwIPN0VmNpbWYZ+VQ== dependencies: "@babel/helper-module-imports" "^7.0.0" "@emotion/babel-utils" "^0.6.4" @@ -1838,7 +1623,6 @@ babel-plugin-emotion@^9.2.11: babel-plugin-istanbul@^4.0.0: version "4.1.5" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.5.tgz#6760cdd977f411d3e175bb064f2bc327d99b2b6e" - integrity sha1-Z2DN2Xf0EdPhdbsGTyvDJ9mbK24= dependencies: find-up "^2.1.0" istanbul-lib-instrument "^1.7.5" @@ -1847,12 +1631,10 @@ babel-plugin-istanbul@^4.0.0: babel-plugin-jest-hoist@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-20.0.3.tgz#afedc853bd3f8dc3548ea671fbe69d03cc2c1767" - integrity sha1-r+3IU70/jcNUjqZx++adA8wsF2c= babel-plugin-macros@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.4.2.tgz#21b1a2e82e2130403c5ff785cba6548e9b644b28" - integrity sha512-NBVpEWN4OQ/bHnu1fyDaAaTPAjnhXCEPqr1RwqxrU7b6tZ2hypp+zX4hlNfmVGfClD5c3Sl6Hfj5TJNF5VG5aA== dependencies: cosmiconfig "^5.0.5" resolve "^1.8.1" @@ -1860,42 +1642,34 @@ babel-plugin-macros@^2.0.0: babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= babel-plugin-syntax-class-properties@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94= babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= babel-plugin-syntax-flow@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" - integrity sha1-TDqyCiryaqIM0lmVw5jE63AxDI0= babel-plugin-syntax-jsx@^6.18.0, babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY= babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= babel-plugin-transform-async-to-generator@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= dependencies: babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-functions "^6.8.0" @@ -1904,7 +1678,6 @@ babel-plugin-transform-async-to-generator@^6.22.0: babel-plugin-transform-class-properties@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw= dependencies: babel-helper-function-name "^6.24.1" babel-plugin-syntax-class-properties "^6.8.0" @@ -1914,21 +1687,18 @@ babel-plugin-transform-class-properties@^6.24.1: babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoping@^6.23.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= dependencies: babel-runtime "^6.26.0" babel-template "^6.26.0" @@ -1939,7 +1709,6 @@ babel-plugin-transform-es2015-block-scoping@^6.23.0: babel-plugin-transform-es2015-classes@^6.23.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= dependencies: babel-helper-define-map "^6.24.1" babel-helper-function-name "^6.24.1" @@ -1954,7 +1723,6 @@ babel-plugin-transform-es2015-classes@^6.23.0: babel-plugin-transform-es2015-computed-properties@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" @@ -1962,14 +1730,12 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0: babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-duplicate-keys@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -1977,14 +1743,12 @@ babel-plugin-transform-es2015-duplicate-keys@^6.22.0: babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-function-name@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= dependencies: babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" @@ -1993,14 +1757,12 @@ babel-plugin-transform-es2015-function-name@^6.22.0: babel-plugin-transform-es2015-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= dependencies: babel-plugin-transform-es2015-modules-commonjs "^6.24.1" babel-runtime "^6.22.0" @@ -2009,7 +1771,6 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1, babel-plugin-transform-es2015-modules-commonjs@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" - integrity sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo= dependencies: babel-plugin-transform-strict-mode "^6.24.1" babel-runtime "^6.26.0" @@ -2019,7 +1780,6 @@ babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-e babel-plugin-transform-es2015-modules-systemjs@^6.23.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= dependencies: babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" @@ -2028,7 +1788,6 @@ babel-plugin-transform-es2015-modules-systemjs@^6.23.0: babel-plugin-transform-es2015-modules-umd@^6.23.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= dependencies: babel-plugin-transform-es2015-modules-amd "^6.24.1" babel-runtime "^6.22.0" @@ -2037,7 +1796,6 @@ babel-plugin-transform-es2015-modules-umd@^6.23.0: babel-plugin-transform-es2015-object-super@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= dependencies: babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" @@ -2045,7 +1803,6 @@ babel-plugin-transform-es2015-object-super@^6.22.0: babel-plugin-transform-es2015-parameters@^6.23.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= dependencies: babel-helper-call-delegate "^6.24.1" babel-helper-get-function-arity "^6.24.1" @@ -2057,7 +1814,6 @@ babel-plugin-transform-es2015-parameters@^6.23.0: babel-plugin-transform-es2015-shorthand-properties@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -2065,14 +1821,12 @@ babel-plugin-transform-es2015-shorthand-properties@^6.22.0: babel-plugin-transform-es2015-spread@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-sticky-regex@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -2081,21 +1835,18 @@ babel-plugin-transform-es2015-sticky-regex@^6.22.0: babel-plugin-transform-es2015-template-literals@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-typeof-symbol@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-es2015-unicode-regex@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= dependencies: babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" @@ -2104,7 +1855,6 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0: babel-plugin-transform-exponentiation-operator@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= dependencies: babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" babel-plugin-syntax-exponentiation-operator "^6.8.0" @@ -2113,7 +1863,6 @@ babel-plugin-transform-exponentiation-operator@^6.22.0: babel-plugin-transform-flow-strip-types@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" - integrity sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988= dependencies: babel-plugin-syntax-flow "^6.18.0" babel-runtime "^6.22.0" @@ -2121,7 +1870,6 @@ babel-plugin-transform-flow-strip-types@^6.22.0: babel-plugin-transform-object-rest-spread@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= dependencies: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.26.0" @@ -2129,14 +1877,12 @@ babel-plugin-transform-object-rest-spread@^6.26.0: babel-plugin-transform-react-display-name@^6.23.0: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" - integrity sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE= dependencies: babel-runtime "^6.22.0" babel-plugin-transform-react-jsx-self@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" - integrity sha1-322AqdomEqEh5t3XVYvL7PBuY24= dependencies: babel-plugin-syntax-jsx "^6.8.0" babel-runtime "^6.22.0" @@ -2144,7 +1890,6 @@ babel-plugin-transform-react-jsx-self@^6.22.0: babel-plugin-transform-react-jsx-source@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" - integrity sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY= dependencies: babel-plugin-syntax-jsx "^6.8.0" babel-runtime "^6.22.0" @@ -2152,7 +1897,6 @@ babel-plugin-transform-react-jsx-source@^6.22.0: babel-plugin-transform-react-jsx@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" - integrity sha1-hAoCjn30YN/DotKfDA2R9jduZqM= dependencies: babel-helper-builder-react-jsx "^6.24.1" babel-plugin-syntax-jsx "^6.8.0" @@ -2161,14 +1905,12 @@ babel-plugin-transform-react-jsx@^6.24.1: babel-plugin-transform-regenerator@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= dependencies: regenerator-transform "^0.10.0" babel-plugin-transform-strict-mode@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" @@ -2176,12 +1918,10 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-plugin-unassert@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/babel-plugin-unassert/-/babel-plugin-unassert-2.1.2.tgz#a1ea61811726db747079443ec1b15c4b06c6b944" - integrity sha1-oephgRcm23RweUQ+wbFcSwbGuUQ= babel-polyfill@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" - integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM= dependencies: babel-runtime "^6.26.0" core-js "^2.5.0" @@ -2190,7 +1930,6 @@ babel-polyfill@^6.26.0: babel-preset-env@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48" - integrity sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA== dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-syntax-trailing-function-commas "^6.22.0" @@ -2226,21 +1965,18 @@ babel-preset-env@^1.6.1: babel-preset-flow@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" - integrity sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0= dependencies: babel-plugin-transform-flow-strip-types "^6.22.0" babel-preset-jest@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-20.0.3.tgz#cbacaadecb5d689ca1e1de1360ebfc66862c178a" - integrity sha1-y6yq3stdaJyh4d4TYOv8ZoYsF4o= dependencies: babel-plugin-jest-hoist "^20.0.3" babel-preset-react@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" - integrity sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A= dependencies: babel-plugin-syntax-jsx "^6.3.13" babel-plugin-transform-react-display-name "^6.23.0" @@ -2252,7 +1988,6 @@ babel-preset-react@^6.24.1: babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= dependencies: babel-core "^6.26.0" babel-runtime "^6.26.0" @@ -2265,7 +2000,6 @@ babel-register@^6.26.0: babel-runtime@6.x.x, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0, babel-runtime@^6.9.2: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= dependencies: core-js "^2.4.0" regenerator-runtime "^0.11.0" @@ -2273,7 +2007,6 @@ babel-runtime@6.x.x, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= dependencies: babel-runtime "^6.26.0" babel-traverse "^6.26.0" @@ -2284,7 +2017,6 @@ babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0: babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= dependencies: babel-code-frame "^6.26.0" babel-messages "^6.23.0" @@ -2299,7 +2031,6 @@ babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0: babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= dependencies: babel-runtime "^6.26.0" esutils "^2.0.2" @@ -2309,57 +2040,46 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26 babylon@7.0.0-beta.40: version "7.0.0-beta.40" resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.40.tgz#91fc8cd56d5eb98b28e6fde41045f2957779940a" - integrity sha512-AVxF2EcxvGD5hhOuLTOLAXBb0VhwWpEX0HyHdAI2zU+AAP4qEwtQj8voz1JR3uclGai0rfcE+dCTHnNMOnimFg== babylon@7.0.0-beta.44: version "7.0.0-beta.44" resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d" - integrity sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g== babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== bail@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.2.tgz#f7d6c1731630a9f9f0d4d35ed1f962e2074a1764" - integrity sha1-99bBcxYwqfnw1NNe0fli4gdKF2Q= balanced-match@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.1.0.tgz#b504bd05869b39259dd0c5efc35d843176dccc4a" - integrity sha1-tQS9BYabOSWd0MXvw12EMXbczEo= balanced-match@^0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" - integrity sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg= balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base64-js@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.0.tgz#a39992d723584811982be5e290bb6a53d86700f1" - integrity sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE= base64-js@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" - integrity sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw== base64-js@^1.2.3: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" class-utils "^0.3.5" @@ -2372,24 +2092,20 @@ base@^0.11.1: batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= bcrypt-pbkdf@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - integrity sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40= dependencies: tweetnacl "^0.14.3" before-after-hook@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-1.1.0.tgz#83165e15a59460d13702cb8febd6a1807896db5a" - integrity sha512-VOMDtYPwLbIncTxNoSzRyvaMxtXmLWLUqr8k5AfC1BzLk34HvBXaQX8snOwQZ4c0aX8aSERqtJSiI9/m2u5kuA== bfj@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.1.tgz#05a3b7784fbd72cfa3c22e56002ef99336516c48" - integrity sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ== dependencies: bluebird "^3.5.1" check-types "^7.3.0" @@ -2399,22 +2115,18 @@ bfj@^6.1.1: big-integer@^1.6.17: version "1.6.27" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.27.tgz#8e56c6f8b2dd6c4fe8d32102b83d4f25868e4b3a" - integrity sha512-NzUKMYW4SWme+H5K+mfEmBxEF/V04PhlzoxxXwSnDig78y2t7HLBVotfDBMUhRPRA3WWID3GmJB/OJSWPhVXtg== big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== binary-extensions@^1.0.0: version "1.11.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" - integrity sha1-RqoXUftqL5PuXmibsQh9SxTGwgU= binary@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79" - integrity sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk= dependencies: buffers "~0.1.1" chainsaw "~0.1.0" @@ -2422,36 +2134,30 @@ binary@~0.3.0: block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= dependencies: inherits "~2.0.0" bluebird-lst@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/bluebird-lst/-/bluebird-lst-1.0.5.tgz#bebc83026b7e92a72871a3dc599e219cbfb002a9" - integrity sha512-Ey0bDNys5qpYPhZ/oQ9vOEvD0TYQDTILMXWP2iGfvMg7rSDde+oV4aQQgqRH+CvBFNz2BSDQnPGMUl6LKBUUQA== dependencies: bluebird "^3.5.1" bluebird@^3.5.0, bluebird@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" - integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA== bluebird@~3.4.1: version "3.4.7" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" - integrity sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM= bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== body-parser@1.18.2: version "1.18.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" - integrity sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ= dependencies: bytes "3.0.0" content-type "~1.0.4" @@ -2467,7 +2173,6 @@ body-parser@1.18.2: body-parser@1.18.3: version "1.18.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" - integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= dependencies: bytes "3.0.0" content-type "~1.0.4" @@ -2483,7 +2188,6 @@ body-parser@1.18.3: bonjour@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= dependencies: array-flatten "^2.1.0" deep-equal "^1.0.1" @@ -2495,33 +2199,28 @@ bonjour@^3.5.0: boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= boom@2.x.x: version "2.10.1" resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - integrity sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8= dependencies: hoek "2.x.x" boom@4.x.x: version "4.3.1" resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - integrity sha1-T4owBctKfjiJ90kDD9JbluAdLjE= dependencies: hoek "4.x.x" boom@5.x.x: version "5.2.0" resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - integrity sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw== dependencies: hoek "4.x.x" boxen@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" - integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== dependencies: ansi-align "^2.0.0" camelcase "^4.0.0" @@ -2534,7 +2233,6 @@ boxen@^1.2.1: brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - integrity sha1-wHshHHyVLsH479Uad+8NHTmQopI= dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -2542,7 +2240,6 @@ brace-expansion@^1.1.7: braces@^1.8.2: version "1.8.5" resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= dependencies: expand-range "^1.8.1" preserve "^0.2.0" @@ -2551,7 +2248,6 @@ braces@^1.8.2: braces@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.0.tgz#a46941cb5fb492156b3d6a656e06c35364e3e66e" - integrity sha512-P4O8UQRdGiMLWSizsApmXVQDBS6KCt7dSexgLKBmH5Hr1CZq7vsnscFh8oR1sP1ab1Zj0uCHCEzZeV6SfUf3rA== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -2568,7 +2264,6 @@ braces@^2.3.0: braces@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.1.tgz#7086c913b4e5a08dbe37ac0ee6a2500c4ba691bb" - integrity sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -2586,19 +2281,16 @@ braces@^2.3.1: brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browser-resolve@^1.11.2: version "1.11.2" resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" - integrity sha1-j/CbCixCFxihBRwmCzLkj0QpOM4= dependencies: resolve "1.1.7" browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.1.1.tgz#38b7ab55edb806ff2dcda1a7f1620773a477c49f" - integrity sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg== dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -2610,7 +2302,6 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: browserify-cipher@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a" - integrity sha1-mYgkSHS/XtTijalWZtzWasj8Njo= dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" @@ -2619,7 +2310,6 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd" - integrity sha1-2qJ3cXRwki7S/hhZQRihdUOXId0= dependencies: cipher-base "^1.0.1" des.js "^1.0.0" @@ -2628,7 +2318,6 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= dependencies: bn.js "^4.1.0" randombytes "^2.0.1" @@ -2636,7 +2325,6 @@ browserify-rsa@^4.0.0: browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= dependencies: bn.js "^4.1.1" browserify-rsa "^4.0.0" @@ -2649,14 +2337,12 @@ browserify-sign@^4.0.0: browserify-zlib@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" browserslist@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.1.1.tgz#328eb4ff1215b12df6589e9ab82f8adaa4fc8cd6" - integrity sha512-VBorw+tgpOtZ1BYhrVSVTzTt/3+vSE3eFUh0N2GCFK1HffceOaf32YS/bs6WiFhjDAblAFrx85jMy3BG9fBK2Q== dependencies: caniuse-lite "^1.0.30000884" electron-to-chromium "^1.3.62" @@ -2665,7 +2351,6 @@ browserslist@4.1.1: browserslist@^2.0.0, browserslist@^2.1.2, browserslist@^2.11.1: version "2.11.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.1.tgz#02fda29d9a2164b879100126e7b0d0b57e43a7bb" - integrity sha512-Gp4oJOQOby5TpOJJuUtCrGE0KSJOUYVa/I+/3eD/TRWEK8jqZuJPAK1t+VuG6jp0keudrqtxlH4MbYbmylun9g== dependencies: caniuse-lite "^1.0.30000789" electron-to-chromium "^1.3.30" @@ -2673,7 +2358,6 @@ browserslist@^2.0.0, browserslist@^2.1.2, browserslist@^2.11.1: browserslist@^4.0.0: version "4.3.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.3.3.tgz#88a7d9ce2e5db561e160ab660bc59cb406a0c41d" - integrity sha512-6h84UD1mmHeuQ9IucX6yzBc+KBYcBBTLYt2CXtY7GYCra6iE5kOm7oM+zuGw/0tjGtbJxjm58OvxSBmogEMCRQ== dependencies: caniuse-lite "^1.0.30000898" electron-to-chromium "^1.3.81" @@ -2682,26 +2366,22 @@ browserslist@^4.0.0: bser@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169" - integrity sha1-OBEWlwsqbe6lZG3RXdcnhES1YWk= dependencies: node-int64 "^0.4.0" bser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" - integrity sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk= dependencies: node-int64 "^0.4.0" btoa-lite@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" - integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc= buble@0.19.4: version "0.19.4" resolved "https://registry.yarnpkg.com/buble/-/buble-0.19.4.tgz#0b51466592555ee34ff5fbe1030a97f3812e4d0a" - integrity sha512-xaTfnWdx80TiajGDZoSYB17nEDqjGnVxeug5W7tvXIAMn61yMa5AfTuWu3F4nLL2Fv/hK8T6GktZvQ6yvPZMpA== dependencies: acorn "^5.4.1" acorn-dynamic-import "^3.0.0" @@ -2716,12 +2396,10 @@ buble@0.19.4: buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== buffer-alloc@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== dependencies: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" @@ -2729,37 +2407,30 @@ buffer-alloc@^1.2.0: buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= buffer-from@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04" - integrity sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ== buffer-indexof-polyfill@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.1.tgz#a9fb806ce8145d5428510ce72f278bb363a638bf" - integrity sha1-qfuAbOgUXVQoUQznLyeLs2OmOL8= buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== buffer-shims@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" - integrity sha1-mXjOMXOIxkmth5MCjDR37wRKi1E= buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@4.9.1, buffer@^4.3.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -2768,12 +2439,10 @@ buffer@4.9.1, buffer@^4.3.0: buffers@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" - integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s= builder-util-runtime@4.4.1, builder-util-runtime@^4.4.0, builder-util-runtime@^4.4.1, builder-util-runtime@~4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-4.4.1.tgz#2770d03241e51fde46acacc7ed3ed8a9f45f02cb" - integrity sha512-8L2pbL6D3VdI1f8OMknlZJpw0c7KK15BRz3cY77AOUElc4XlCv2UhVV01jJM7+6Lx7henaQh80ALULp64eFYAQ== dependencies: bluebird-lst "^1.0.5" debug "^3.1.0" @@ -2783,7 +2452,6 @@ builder-util-runtime@4.4.1, builder-util-runtime@^4.4.0, builder-util-runtime@^4 builder-util@6.1.3, builder-util@~6.1.3: version "6.1.3" resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-6.1.3.tgz#6bd3a5253c99afa31e3574e6fc3b796e218f8cfd" - integrity sha512-MXeARNff9KHlzJYGJcAhLI/tpE57PmUnleaYfL22IE+viRt192Yr3wQL444ztsA+LUHJ8d12moUoG00jh1hfLA== dependencies: "7zip-bin" "~4.0.2" app-builder-bin "2.1.2" @@ -2803,7 +2471,6 @@ builder-util@6.1.3, builder-util@~6.1.3: builder-util@^5.13.0: version "5.20.1" resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-5.20.1.tgz#64544def24a9fbbdc77ac0c027661bb3dbb520a2" - integrity sha512-rqSl3Tbi/sECIVWAys8Blic4UEzUpZkGgmVXR2mZwdVPreNnfY3MHqSGSxlJRMTqxSsO0SgxnAEnanBNw4212g== dependencies: "7zip-bin" "~4.0.2" app-builder-bin "2.0.0" @@ -2823,32 +2490,26 @@ builder-util@^5.13.0: builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" - integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= byline@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" - integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE= bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= cacache@^10.0.4: version "10.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460" - integrity sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA== dependencies: bluebird "^3.5.1" chownr "^1.0.1" @@ -2867,7 +2528,6 @@ cacache@^10.0.4: cacache@^11.0.2: version "11.2.0" resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.2.0.tgz#617bdc0b02844af56310e411c0878941d5739965" - integrity sha512-IFWl6lfK6wSeYCHUXh+N1lY72UDrpyrYQJNIVQf48paDuWbv5RbAtJYf/4gUQFObTCHZwdZ5sI8Iw7nqwP6nlQ== dependencies: bluebird "^3.5.1" chownr "^1.0.1" @@ -2887,7 +2547,6 @@ cacache@^11.0.2: cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -2902,29 +2561,24 @@ cache-base@^1.0.1: call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= dependencies: callsites "^0.2.0" callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= camel-case@3.0.x: version "3.0.0" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" - integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= dependencies: no-case "^2.2.0" upper-case "^1.1.1" @@ -2932,7 +2586,6 @@ camel-case@3.0.x: camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= dependencies: camelcase "^2.0.0" map-obj "^1.0.0" @@ -2940,7 +2593,6 @@ camelcase-keys@^2.0.0: camelcase-keys@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" - integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c= dependencies: camelcase "^4.1.0" map-obj "^2.0.0" @@ -2949,27 +2601,22 @@ camelcase-keys@^4.0.0: camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk= camelcase@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= caniuse-api@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-2.0.0.tgz#b1ddb5a5966b16f48dc4998444d4bbc6c7d9d834" - integrity sha1-sd21pZZrFvSNxJmERNS7xsfZ2DQ= dependencies: browserslist "^2.0.0" caniuse-lite "^1.0.0" @@ -2979,7 +2626,6 @@ caniuse-api@^2.0.0: caniuse-api@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== dependencies: browserslist "^4.0.0" caniuse-lite "^1.0.0" @@ -2989,37 +2635,30 @@ caniuse-api@^3.0.0: caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000789, caniuse-lite@^1.0.30000791: version "1.0.30000791" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000791.tgz#8e35745efd483a3e23bb7d350990326d2319fc16" - integrity sha1-jjV0Xv1IOj4ju301CZAybSMZ/BY= caniuse-lite@^1.0.30000884: version "1.0.30000899" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000899.tgz#6febdbbc388a7982f620ee0e3d09aab0c061389e" - integrity sha512-enC3zKfUCJxxwvUIsBkbHd54CtJw1KtIWvrK0JZxWD/fEN2knHaai45lndJ4xXAkyRAPyk60J3yagkKDWhfeMA== caniuse-lite@^1.0.30000898: version "1.0.30000898" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000898.tgz#651306e690ca83caca5814da5afa3eb4de0f86c2" - integrity sha512-ytlTZqO4hYe4rNAJhMynUAIUI33jsP2Bb1two/9OVC39wZjPZ8exIO0eCLw5mqAtegOGiGF0kkTWTn3B02L+mw== capture-stack-trace@^1.0.0: version "1.0.0" resolved "http://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" - integrity sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0= caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= ccount@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.2.tgz#53b6a2f815bb77b9c2871f7b9a72c3a25f1d8e89" - integrity sha1-U7ai+BW7d7nChx97mnLDol8djok= center-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60= dependencies: align-text "^0.1.3" lazy-cache "^1.0.3" @@ -3027,14 +2666,12 @@ center-align@^0.1.1: chainsaw@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" - integrity sha1-XqtQsor+WAdNDVgpE4iCi15fvJg= dependencies: traverse ">=0.3.0 <0.4" chalk@2.4.1, chalk@^2.3.1, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -3043,7 +2680,6 @@ chalk@2.4.1, chalk@^2.3.1, chalk@^2.4.1: chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -3054,56 +2690,50 @@ chalk@^1.1.3: chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" - integrity sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q== dependencies: ansi-styles "^3.1.0" escape-string-regexp "^1.0.5" supports-color "^4.0.0" +change-emitter@^0.1.2: + version "0.1.6" + resolved "https://registry.yarnpkg.com/change-emitter/-/change-emitter-0.1.6.tgz#e8b2fe3d7f1ab7d69a32199aff91ea6931409515" + character-entities-html4@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.1.tgz#359a2a4a0f7e29d3dc2ac99bdbe21ee39438ea50" - integrity sha1-NZoqSg9+KdPcKsmb2+Ie45Q46lA= character-entities-legacy@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.1.tgz#f40779df1a101872bb510a3d295e1fccf147202f" - integrity sha1-9Ad53xoQGHK7UQo9KV4fzPFHIC8= character-entities@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.1.tgz#f76871be5ef66ddb7f8f8e3478ecc374c27d6dca" - integrity sha1-92hxvl72bdt/j440eOzDdMJ9bco= character-reference-invalid@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.1.tgz#942835f750e4ec61a308e60c2ef8cc1011202efc" - integrity sha1-lCg191Dk7GGjCOYMLvjMEBEgLvw= chardet@^0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= check-types@^7.3.0: version "7.4.0" resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.4.0.tgz#0378ec1b9616ec71f774931a3c6516fad8c152f4" - integrity sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg== chokidar@^1.6.1: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= dependencies: anymatch "^1.3.0" async-each "^1.0.0" @@ -3119,7 +2749,6 @@ chokidar@^1.6.1: chokidar@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.0.tgz#6686313c541d3274b2a5c01233342037948c911b" - integrity sha512-OgXCNv2U6TnG04D3tth0gsvdbV4zdbxFG3sYUqcoQMoEFVd1j1pZR6TZ8iknC45o9IJ6PeQI/J6wT/+cHcniAw== dependencies: anymatch "^2.0.0" async-each "^1.0.0" @@ -3137,7 +2766,6 @@ chokidar@^2.0.0: chokidar@^2.0.2: version "2.0.4" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" - integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ== dependencies: anymatch "^2.0.0" async-each "^1.0.0" @@ -3157,34 +2785,28 @@ chokidar@^2.0.2: chownr@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" - integrity sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE= chrome-trace-event@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz#45a91bd2c20c9411f0963b5aaeb9a1b95e09cc48" - integrity sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A== dependencies: tslib "^1.9.0" chromium-pickle-js@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205" - integrity sha1-BKEGZywYsIWrd02YPfo+oTjyIgU= ci-info@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.2.tgz#03561259db48d0474c8bdc90f5b47b068b6bbfb4" - integrity sha512-uTGIPNx/nSpBdsF6xnseRXLLtfr9VLqkz8ZqHXr3Y7b6SftyRxBGjwMtJj1OhNbmlc1wZzLNAlAcvyIiE8a6ZA== ci-info@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.5.1.tgz#17e8eb5de6f8b2b6038f0cbb714d410bfa9f3030" - integrity sha512-fKFIKXaYiL1exImwJ0AhR/6jxFPSKQBk2ayV5NiNoruUs2+rxC2kNw0EG+1Z9dugZRdCrppskQ8DN2cyaUM1Hw== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -3192,12 +2814,10 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" @@ -3207,58 +2827,48 @@ class-utils@^0.3.5: classnames@^2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" - integrity sha1-+zgB1FNGdknvNgPH1hoCvRKb3m0= classnames@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" - integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== clean-css@4.1.x: version "4.1.9" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.9.tgz#35cee8ae7687a49b98034f70de00c4edd3826301" - integrity sha1-Nc7ornaHpJuYA09w3gDE7dOCYwE= dependencies: source-map "0.5.x" clean-webpack-plugin@^0.1.19: version "0.1.19" resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-0.1.19.tgz#ceda8bb96b00fe168e9b080272960d20fdcadd6d" - integrity sha512-M1Li5yLHECcN2MahoreuODul5LkjohJGFxLPTjl3j1ttKrF5rgjZET1SJduuqxLAuT1gAPOdkhg03qcaaU1KeA== dependencies: rimraf "^2.6.1" cli-boxes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" - integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= dependencies: restore-cursor "^2.0.0" cli-spinners@^1.1.0: version "1.3.1" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" - integrity sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg== cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= clipboard-copy@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/clipboard-copy/-/clipboard-copy-2.0.1.tgz#25214db3aabc282109cfa3429ffd885b014fc8b3" - integrity sha512-/JBr7ryeWwl2w33SRMYGfOZU5SWPVNtpB9oTxUzFp7olKKd2HM+cnhSMeETblJMnjgqtL581ncI/pcZX7o7Big== cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE= dependencies: center-align "^0.1.1" right-align "^0.1.1" @@ -3267,7 +2877,6 @@ cliui@^2.1.0: cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -3276,7 +2885,6 @@ cliui@^3.2.0: cliui@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.0.0.tgz#743d4650e05f36d1ed2575b59638d87322bfbbcc" - integrity sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw== dependencies: string-width "^2.1.1" strip-ansi "^4.0.0" @@ -3285,7 +2893,6 @@ cliui@^4.0.0: clone-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.0.tgz#eae0a2413f55c0942f818c229fefce845d7f3b1c" - integrity sha1-6uCiQT9VwJQvgYwin+/OhF1/Oxw= dependencies: is-regexp "^1.0.0" is-supported-regexp-flag "^1.0.0" @@ -3293,12 +2900,10 @@ clone-regexp@^1.0.0: clone@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f" - integrity sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8= cmd-shim@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb" - integrity sha1-b8vamUg6j9FdfTChlspp1oii79s= dependencies: graceful-fs "^4.1.2" mkdirp "~0.5.0" @@ -3306,24 +2911,20 @@ cmd-shim@^2.0.2: co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= coa@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.1.tgz#f3f8b0b15073e35d70263fb1042cb2c023db38af" - integrity sha512-5wfTTO8E2/ja4jFSxePXlG5nRu5bBtL/r1HCIpJW/lzT6yDtKl0u0Z4o/Vpz32IpKmBn7HerheEZQgA9N2DarQ== dependencies: q "^1.1.2" code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= codecov@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/codecov/-/codecov-3.1.0.tgz#340bd968d361f256976b5af782dd8ba9f82bc849" - integrity sha512-aWQc/rtHbcWEQLka6WmBAOpV58J2TwyXqlpAQGhQaSiEUoigTTUk6lLd2vB3kXkhnDyzyH74RXfmV4dq2txmdA== dependencies: argv "^0.0.2" ignore-walk "^3.0.1" @@ -3334,22 +2935,18 @@ codecov@^3.1.0: codemirror@^5.39.0: version "5.41.0" resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.41.0.tgz#57e245be197643c39440d2840236d3edc4bb1162" - integrity sha512-mkCwbneCx2WHg1MNCYrI+8Zuq0KMMaZ5yTFpQlAZazy3yxME8bHcuSc9WUFzgPZ114WqWu1FIHlx8CavLzBDIg== collapse-white-space@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091" - integrity sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw== collapse-white-space@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.3.tgz#4b906f670e5a963a87b76b0e1689643341b6023c" - integrity sha1-S5BvZw5aljqHt2sOFolkM0G2Ajw= collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -3357,31 +2954,26 @@ collection-visit@^1.0.0: color-convert@^1.3.0, color-convert@^1.8.2, color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" - integrity sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ== dependencies: color-name "^1.1.1" color-convert@~0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd" - integrity sha1-vbbGnOZg+t/+CwAHzER+G59ygr0= color-name@^1.0.0, color-name@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= color-string@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" - integrity sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE= dependencies: color-name "^1.0.0" color-string@^1.4.0, color-string@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.2.tgz#26e45814bc3c9a7cbd6751648a41434514a773a9" - integrity sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k= dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" @@ -3389,7 +2981,6 @@ color-string@^1.4.0, color-string@^1.5.2: color@3.0.x: version "3.0.0" resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a" - integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w== dependencies: color-convert "^1.9.1" color-string "^1.5.2" @@ -3397,7 +2988,6 @@ color@3.0.x: color@^0.11.0: version "0.11.4" resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" - integrity sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q= dependencies: clone "^1.0.2" color-convert "^1.3.0" @@ -3406,7 +2996,6 @@ color@^0.11.0: color@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/color/-/color-1.0.3.tgz#e48e832d85f14ef694fb468811c2d5cfe729b55d" - integrity sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0= dependencies: color-convert "^1.8.2" color-string "^1.4.0" @@ -3414,7 +3003,6 @@ color@^1.0.3: color@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color/-/color-2.0.1.tgz#e4ed78a3c4603d0891eba5430b04b86314f4c839" - integrity sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw== dependencies: color-convert "^1.9.1" color-string "^1.5.2" @@ -3422,7 +3010,6 @@ color@^2.0.1: color@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/color/-/color-3.1.0.tgz#d8e9fb096732875774c84bf922815df0308d0ffc" - integrity sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg== dependencies: color-convert "^1.9.1" color-string "^1.5.2" @@ -3430,32 +3017,26 @@ color@^3.0.0: colornames@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/colornames/-/colornames-1.1.1.tgz#f8889030685c7c4ff9e2a559f5077eb76a816f96" - integrity sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y= colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= colors@^1.1.2, colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" - integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= colors@^1.2.1: version "1.2.5" resolved "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz#89c7ad9a374bc030df8013241f68136ed8835afc" - integrity sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg== colors@~0.6.0-1: version "0.6.2" resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc" - integrity sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w= colorspace@1.1.x: version "1.1.1" resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.1.tgz#9ac2491e1bc6f8fb690e2176814f8d091636d972" - integrity sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw== dependencies: color "3.0.x" text-hex "1.0.x" @@ -3463,7 +3044,6 @@ colorspace@1.1.x: columnify@^1.5.4: version "1.5.4" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" - integrity sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs= dependencies: strip-ansi "^3.0.0" wcwidth "^1.0.0" @@ -3471,92 +3051,76 @@ columnify@^1.5.4: combined-stream@1.0.6: version "1.0.6" resolved "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - integrity sha1-cj599ugBrFYTETp+RFqbactjKBg= dependencies: delayed-stream "~1.0.0" combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - integrity sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk= dependencies: delayed-stream "~1.0.0" combined-stream@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" - integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== dependencies: delayed-stream "~1.0.0" comma-separated-tokens@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz#b13793131d9ea2d2431cf5b507ddec258f0ce0db" - integrity sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA== dependencies: trim "0.0.1" commander@2.12.x, commander@~2.12.1: version "2.12.2" resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" - integrity sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA== commander@2.15.1: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== commander@^2.11.0: version "2.17.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.0.tgz#9d07b25e2a6f198b76d8b756a0e8a9604a6a1a60" - integrity sha512-477o1hdVORiFlZxw8wgsXYCef3lh0zl/OV0FTftqiDxJSWw6dPQ2ipS4k20J2qBcsmsmLKSyr2iFrf9e3JGi4w== commander@^2.18.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== commander@^2.9.0, commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" - integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA== commander@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781" - integrity sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E= commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== common-dir@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/common-dir/-/common-dir-2.0.2.tgz#cfea16f48564a0ecbb088065fad029047f469dc1" - integrity sha512-AiVcdIuevkFWyqrcHhpOWJbaFBLm+OLPiaRy3QikrMypalgA4ehU1SugZO2rPawgdzkTAycXGs3F65PGPA2DWg== dependencies: common-sequence "^1.0.2" common-sequence@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/common-sequence/-/common-sequence-1.0.2.tgz#30e07f3f8f6f7f9b3dee854f20b2d39eee086de8" - integrity sha1-MOB/P49vf5s97oVPILLTnu4Ibeg= common-tags@^1.7.2: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" - integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= compare-func@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.2.tgz#99dd0ba457e1f9bc722b12c08ec33eeab31fa648" - integrity sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg= dependencies: array-ify "^1.0.0" dot-prop "^3.0.0" @@ -3564,24 +3128,20 @@ compare-func@^1.3.1: compare-version@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/compare-version/-/compare-version-0.1.2.tgz#0162ec2d9351f5ddd59a9202cba935366a725080" - integrity sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA= component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= compressible@~2.0.11: version "2.0.12" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.12.tgz#c59a5c99db76767e9876500e271ef63b3493bd66" - integrity sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY= dependencies: mime-db ">= 1.30.0 < 2" compression@^1.5.2: version "1.7.1" resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.1.tgz#eff2603efc2e22cf86f35d2eb93589f9875373db" - integrity sha1-7/JgPvwuIs+G810uuTWJ+YdTc9s= dependencies: accepts "~1.3.4" bytes "3.0.0" @@ -3594,12 +3154,10 @@ compression@^1.5.2: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@1.6.0, concat-stream@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" - integrity sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc= dependencies: inherits "^2.0.3" readable-stream "^2.2.2" @@ -3608,7 +3166,6 @@ concat-stream@1.6.0, concat-stream@^1.5.0: concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" inherits "^2.0.3" @@ -3618,7 +3175,6 @@ concat-stream@^1.6.0: concurrently@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-4.0.1.tgz#f6310fbadf2f476dd95df952edb5c0ab789f672c" - integrity sha512-D8UI+mlI/bfvrA57SeKOht6sEpb01dKk+8Yee4fbnkk1Ue8r3S+JXoEdFZIpzQlXJGtnxo47Wvvg/kG4ba3U6Q== dependencies: chalk "^2.4.1" date-fns "^1.23.0" @@ -3633,7 +3189,6 @@ concurrently@^4.0.1: conf@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/conf/-/conf-2.0.0.tgz#43f7e282b32faca31f4d18bf279d6841ad657d5a" - integrity sha512-iCLzBsGFi8S73EANsEJZz0JnJ/e5VZef/kSaxydYZLAvw0rFNAUx5R7K5leC/CXXR2mZfXWhUvcZOO/dM2D5xg== dependencies: dot-prop "^4.1.0" env-paths "^1.0.0" @@ -3644,7 +3199,6 @@ conf@^2.0.0: config-chain@^1.1.11: version "1.1.11" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" - integrity sha1-q6CXR9++TD5w52am5BWG4YWfxvI= dependencies: ini "^1.3.4" proto-list "~1.2.1" @@ -3652,7 +3206,6 @@ config-chain@^1.1.11: configstore@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90" - integrity sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw== dependencies: dot-prop "^4.1.0" graceful-fs "^4.1.2" @@ -3664,49 +3217,40 @@ configstore@^3.0.0: connect-history-api-fallback@^1.3.0: version "1.5.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#b06873934bc5e344fef611a196a6faae0aee015a" - integrity sha1-sGhzk0vF40T+9hGhlqb6rgruAVo= console-browserify@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= dependencies: date-now "^0.1.4" console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= content-type-parser@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7" - integrity sha512-lM4l4CnMEwOLHAHr/P6MEZwZFPJFtAAKgL6pogbXmVZggIqXhdB6RbBtPOTsw2FcXwYhehRGERJmRrjOiIB8pQ== content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== conventional-changelog-angular@^1.6.6: version "1.6.6" resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-1.6.6.tgz#b27f2b315c16d0a1f23eb181309d0e6a4698ea0f" - integrity sha512-suQnFSqCxRwyBxY68pYTsFkG0taIdinHLNEAX5ivtw8bCRnIgnpvcHmlR/yjUyZIrNPYAoXlY1WiEKWgSE4BNg== dependencies: compare-func "^1.3.1" q "^1.5.1" @@ -3714,7 +3258,6 @@ conventional-changelog-angular@^1.6.6: conventional-changelog-core@^2.0.5: version "2.0.11" resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-2.0.11.tgz#19b5fbd55a9697773ed6661f4e32030ed7e30287" - integrity sha512-HvTE6RlqeEZ/NFPtQeFLsIDOLrGP3bXYr7lFLMhCVsbduF1MXIe8OODkwMFyo1i9ku9NWBwVnVn0jDmIFXjDRg== dependencies: conventional-changelog-writer "^3.0.9" conventional-commits-parser "^2.1.7" @@ -3733,12 +3276,10 @@ conventional-changelog-core@^2.0.5: conventional-changelog-preset-loader@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-1.1.8.tgz#40bb0f142cd27d16839ec6c74ee8db418099b373" - integrity sha512-MkksM4G4YdrMlT2MbTsV2F6LXu/hZR0Tc/yenRrDIKRwBl/SP7ER4ZDlglqJsCzLJi4UonBc52Bkm5hzrOVCcw== conventional-changelog-writer@^3.0.9: version "3.0.9" resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-3.0.9.tgz#4aecdfef33ff2a53bb0cf3b8071ce21f0e994634" - integrity sha512-n9KbsxlJxRQsUnK6wIBRnARacvNnN4C/nxnxCkH+B/R1JS2Fa+DiP1dU4I59mEDEjgnFaN2+9wr1P1s7GYB5/Q== dependencies: compare-func "^1.3.1" conventional-commits-filter "^1.1.6" @@ -3754,12 +3295,10 @@ conventional-changelog-writer@^3.0.9: conventional-commit-types@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-2.2.0.tgz#5db95739d6c212acbe7b6f656a11b940baa68946" - integrity sha1-XblXOdbCEqy+e29lahG5QLqmiUY= conventional-commits-filter@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-1.1.6.tgz#4389cd8e58fe89750c0b5fb58f1d7f0cc8ad3831" - integrity sha512-KcDgtCRKJCQhyk6VLT7zR+ZOyCnerfemE/CsR3iQpzRRFbLEs0Y6rwk3mpDvtOh04X223z+1xyJ582Stfct/0Q== dependencies: is-subset "^0.1.1" modify-values "^1.0.0" @@ -3767,7 +3306,6 @@ conventional-commits-filter@^1.1.6: conventional-commits-parser@^2.1.7: version "2.1.7" resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-2.1.7.tgz#eca45ed6140d72ba9722ee4132674d639e644e8e" - integrity sha512-BoMaddIEJ6B4QVMSDu9IkVImlGOSGA1I2BQyOZHeLQ6qVOJLcLKn97+fL6dGbzWEiqDzfH4OkcveULmeq2MHFQ== dependencies: JSONStream "^1.0.4" is-text-path "^1.0.0" @@ -3780,7 +3318,6 @@ conventional-commits-parser@^2.1.7: conventional-recommended-bump@^2.0.6: version "2.0.9" resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-2.0.9.tgz#7392421e7d0e3515f3df2040572a23cc73a68a93" - integrity sha512-YE6/o+648qkX3fTNvfBsvPW3tSnbZ6ec3gF0aBahCPgyoVHU2Mw0nUAZ1h1UN65GazpORngrgRC8QCltNYHPpQ== dependencies: concat-stream "^1.6.0" conventional-changelog-preset-loader "^1.1.8" @@ -3794,29 +3331,24 @@ conventional-recommended-bump@^2.0.6: convert-source-map@^1.4.0, convert-source-map@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" - integrity sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU= convert-source-map@^1.5.1: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== dependencies: safe-buffer "~5.1.1" cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" - integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== dependencies: aproba "^1.1.1" fs-write-stream-atomic "^1.0.8" @@ -3828,12 +3360,10 @@ copy-concurrently@^1.0.0: copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= copy-webpack-plugin@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-4.5.4.tgz#f2b2782b3cd5225535c3dc166a80067e7d940f27" - integrity sha512-0lstlEyj74OAtYMrDxlNZsU7cwFijAI3Ofz2fD6Mpo9r4xCv4yegfa3uHIKvZY1NSuOtE9nvG6TAhJ+uz9gDaQ== dependencies: cacache "^10.0.4" find-cache-dir "^1.0.0" @@ -3847,22 +3377,18 @@ copy-webpack-plugin@^4.5.4: core-js@^1.0.0: version "1.2.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" - integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0: version "2.5.3" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" - integrity sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4= core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= cosmiconfig@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-3.1.0.tgz#640a94bf9847f321800403cd273af60665c73397" - integrity sha512-zedsBhLSbPBms+kE7AH4vHg6JsKDz6epSv2/+5XHs8ILHlgDciSJfSWf8sX9aQ52Jb7KI7VswUTsLpR/G0cr2Q== dependencies: is-directory "^0.3.1" js-yaml "^3.9.0" @@ -3872,7 +3398,6 @@ cosmiconfig@^3.1.0: cosmiconfig@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" - integrity sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ== dependencies: is-directory "^0.3.1" js-yaml "^3.9.0" @@ -3882,7 +3407,6 @@ cosmiconfig@^4.0.0: cosmiconfig@^5.0.0: version "5.0.6" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" - integrity sha512-6DWfizHriCrFWURP1/qyhsiFvYdlJzbCzmtFWh744+KyWsJo5+kPzUZZaMRSSItoYc0pxFX7gEO7ZC1/gN/7AQ== dependencies: is-directory "^0.3.1" js-yaml "^3.9.0" @@ -3891,7 +3415,6 @@ cosmiconfig@^5.0.0: cosmiconfig@^5.0.2, cosmiconfig@^5.0.5: version "5.0.5" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.5.tgz#a809e3c2306891ce17ab70359dc8bdf661fe2cd0" - integrity sha512-94j37OtvxS5w7qr7Ta6dt67tWdnOxigBVN4VnSxNXFez9o18PGQ0D33SchKP17r9LAcWVTYV72G6vDayAUBFIg== dependencies: is-directory "^0.3.1" js-yaml "^3.9.0" @@ -3900,7 +3423,6 @@ cosmiconfig@^5.0.2, cosmiconfig@^5.0.5: create-ecdh@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d" - integrity sha1-iIxyNZbN92EvZJgjPuvXo1MBc30= dependencies: bn.js "^4.1.0" elliptic "^6.0.0" @@ -3908,7 +3430,6 @@ create-ecdh@^4.0.0: create-emotion@^9.2.12: version "9.2.12" resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-9.2.12.tgz#0fc8e7f92c4f8bb924b0fef6781f66b1d07cb26f" - integrity sha512-P57uOF9NL2y98Xrbl2OuiDQUZ30GVmASsv5fbsjF4Hlraip2kyAvMm+2PoYUvFFw03Fhgtxk3RqZSm2/qHL9hA== dependencies: "@emotion/hash" "^0.6.2" "@emotion/memoize" "^0.6.1" @@ -3921,14 +3442,12 @@ create-emotion@^9.2.12: create-error-class@^3.0.0: version "3.0.2" resolved "http://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" - integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y= dependencies: capture-stack-trace "^1.0.0" create-hash@^1.1.0, create-hash@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd" - integrity sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0= dependencies: cipher-base "^1.0.1" inherits "^2.0.1" @@ -3938,7 +3457,6 @@ create-hash@^1.1.0, create-hash@^1.1.2: create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: version "1.1.6" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06" - integrity sha1-rLniIaThe9sHbpBlfEK5PjcmzwY= dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -3950,7 +3468,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: create-react-context@^0.2.1: version "0.2.2" resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.2.tgz#9836542f9aaa22868cd7d4a6f82667df38019dca" - integrity sha512-KkpaLARMhsTsgp0d2NA/R94F/eDLbhXERdIq3LvX2biCAXcDvHYoOqHfWCHf1+OLj+HKBotLG3KqaOOf+C1C+A== dependencies: fbjs "^0.8.0" gud "^1.0.0" @@ -3958,7 +3475,6 @@ create-react-context@^0.2.1: create-react-context@^0.2.2: version "0.2.3" resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.3.tgz#9ec140a6914a22ef04b8b09b7771de89567cb6f3" - integrity sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag== dependencies: fbjs "^0.8.0" gud "^1.0.0" @@ -3966,7 +3482,6 @@ create-react-context@^0.2.2: cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== dependencies: nice-try "^1.0.4" path-key "^2.0.1" @@ -3977,7 +3492,6 @@ cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: cross-spawn@^5.0.1, cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= dependencies: lru-cache "^4.0.1" shebang-command "^1.2.0" @@ -3986,31 +3500,26 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: cross-unzip@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/cross-unzip/-/cross-unzip-0.0.2.tgz#5183bc47a09559befcf98cc4657964999359372f" - integrity sha1-UYO8R6CVWb78+YzEZXlkmZNZNy8= crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - integrity sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g= dependencies: boom "2.x.x" cryptiles@3.x.x: version "3.1.2" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" - integrity sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4= dependencies: boom "5.x.x" crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.0" @@ -4027,12 +3536,10 @@ crypto-browserify@^3.11.0: crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= css-color-function@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/css-color-function/-/css-color-function-1.3.3.tgz#8ed24c2c0205073339fafa004bc8c141fccb282e" - integrity sha1-jtJMLAIFBzM5+voAS8jBQfzLKC4= dependencies: balanced-match "0.1.0" color "^0.11.0" @@ -4042,12 +3549,10 @@ css-color-function@~1.3.3: css-color-names@0.0.4, css-color-names@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= css-declaration-sorter@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== dependencies: postcss "^7.0.1" timsort "^0.3.0" @@ -4055,12 +3560,10 @@ css-declaration-sorter@^4.0.1: css-initials@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/css-initials/-/css-initials-0.2.0.tgz#14c225bd8656255a6baee07231ef82fa55aacaa3" - integrity sha512-t80yjg0pi4VAIc5itIqLh6M+ZlA+cB+gUXEQkDR09+ExTDwLMGfJ8YviBsGW+DklIrb2k9fwB75Io8ooWXDxxw== css-loader@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-1.0.0.tgz#9f46aaa5ca41dbe31860e3b62b8e23c42916bf56" - integrity sha512-tMXlTYf3mIMt3b0dDCOQFJiVvxbocJ5Ho577WiGPYPZcqVEO218L2iU22pDXzkTZCLDE+9AmGSUkWxeh/nZReA== dependencies: babel-code-frame "^6.26.0" css-selector-tokenizer "^0.7.0" @@ -4078,12 +3581,10 @@ css-loader@^1.0.0: css-select-base-adapter@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== css-select@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= dependencies: boolbase "~1.0.0" css-what "2.1" @@ -4093,7 +3594,6 @@ css-select@^1.1.0: css-select@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" - integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== dependencies: boolbase "^1.0.0" css-what "^2.1.2" @@ -4103,7 +3603,6 @@ css-select@^2.0.0: css-selector-tokenizer@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86" - integrity sha1-5piEdK6MlTR3v15+/s/OzNnPTIY= dependencies: cssesc "^0.1.0" fastparse "^1.1.1" @@ -4112,7 +3611,6 @@ css-selector-tokenizer@^0.7.0: css-tree@1.0.0-alpha.28: version "1.0.0-alpha.28" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.28.tgz#8e8968190d886c9477bc8d61e96f61af3f7ffa7f" - integrity sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w== dependencies: mdn-data "~1.1.0" source-map "^0.5.3" @@ -4120,7 +3618,6 @@ css-tree@1.0.0-alpha.28: css-tree@1.0.0-alpha.29: version "1.0.0-alpha.29" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" - integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== dependencies: mdn-data "~1.1.0" source-map "^0.5.3" @@ -4128,37 +3625,30 @@ css-tree@1.0.0-alpha.29: css-unit-converter@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" - integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= css-url-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" - integrity sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w= css-what@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" - integrity sha1-lGfQMsOM+u+58teVASUwYvh/ob0= css-what@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.2.tgz#c0876d9d0480927d7d4920dcd72af3595649554d" - integrity sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ== cssesc@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" - integrity sha1-yBSQPkViM3GgR3tAEJqq++6t27Q= cssesc@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-1.0.1.tgz#ef7bd8d0229ed6a3a7051ff7771265fe7330e0a8" - integrity sha512-S2hzrpWvE6G/rW7i7IxJfWBYn27QWfOIncUW++8Rbo1VB5zsJDSVPcnI+Q8z7rhxT6/yZeLOCja4cZnghJrNGA== cssnano-preset-default@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.5.tgz#d1756c0259d98ad311e601ba76e95c60f6771ac1" - integrity sha512-f1uhya0ZAjPYtDD58QkBB0R+uYdzHPei7cDxJyQQIHt5acdhyGXaSXl2nDLzWHLwGFbZcHxQtkJS8mmNwnxTvw== dependencies: css-declaration-sorter "^4.0.1" cssnano-util-raw-cache "^4.0.1" @@ -4194,29 +3684,24 @@ cssnano-preset-default@^4.0.5: cssnano-util-get-arguments@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" - integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= cssnano-util-get-match@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" - integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= cssnano-util-raw-cache@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== dependencies: postcss "^7.0.0" cssnano-util-same-parent@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== cssnano@^4.1.0: version "4.1.7" resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.7.tgz#0bf112294bec103ab5f68d3f805732c8325a0b1b" - integrity sha512-AiXL90l+MDuQmRNyypG2P7ux7K4XklxYzNNUd5HXZCNcH8/N9bHPcpN97v8tXgRVeFL/Ed8iP8mVmAAu0ZpT7A== dependencies: cosmiconfig "^5.0.0" cssnano-preset-default "^4.0.5" @@ -4226,48 +3711,40 @@ cssnano@^4.1.0: csso@^3.5.0: version "3.5.1" resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" - integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== dependencies: css-tree "1.0.0-alpha.29" cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": version "0.3.2" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b" - integrity sha1-uANhcMefB6kP8vFuIihAJ6JDhIs= "cssstyle@>= 0.2.37 < 0.3.0": version "0.2.37" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54" - integrity sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ= dependencies: cssom "0.3.x" csstype@^2.5.2: version "2.5.7" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.7.tgz#bf9235d5872141eccfb2d16d82993c6b149179ff" - integrity sha512-Nt5VDyOTIIV4/nRFswoCKps1R5CD1hkiyjBE9/thNaNZILLEviVw9yWQw15+O+CpNjQKB/uvdcxFFOrSflY3Yw== currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= dependencies: array-find-index "^1.0.1" cycle@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" - integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI= cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" - integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= cz-conventional-changelog@2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-2.1.0.tgz#2f4bc7390e3244e4df293e6ba351e4c740a7c764" - integrity sha1-L0vHOQ4yROTfKT5ro1Hkx0Cnx2Q= dependencies: conventional-commit-types "^2.0.0" lodash.map "^4.5.1" @@ -4278,62 +3755,52 @@ cz-conventional-changelog@2.1.0: dargs@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17" - integrity sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc= dependencies: number-is-nan "^1.0.0" dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= dependencies: assert-plus "^1.0.0" date-fns@^1.23.0: version "1.29.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" - integrity sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw== date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= dateformat@^3.0.0, dateformat@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" - integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== debug@2.6.9, debug@^2.1.0, debug@^2.1.2, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" debug@3.1.0, debug@^3.0.0, debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" debug@^3.2.5: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" - integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= decamelize-keys@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= dependencies: decamelize "^1.1.0" map-obj "^1.0.0" @@ -4341,61 +3808,50 @@ decamelize-keys@^1.0.0: decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decamelize@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-2.0.0.tgz#656d7bbc8094c4c788ea53c5840908c9c7d063c7" - integrity sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg== dependencies: xregexp "4.0.0" decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= decompress-response@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= dependencies: mimic-response "^1.0.0" dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= deep-equal@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" - integrity sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8= deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= deepmerge@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" - integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA== default-gateway@^2.6.0: version "2.7.2" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-2.7.2.tgz#b7ef339e5e024b045467af403d50348db4642d0f" - integrity sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ== dependencies: execa "^0.10.0" ip-regex "^2.1.0" @@ -4403,28 +3859,24 @@ default-gateway@^2.6.0: default-require-extensions@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" - integrity sha1-836hXT4T/9m0N9M+GnW1+5eHTLg= dependencies: strip-bom "^2.0.0" defaults@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= dependencies: clone "^1.0.2" define-properties@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-properties@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" - integrity sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ= dependencies: foreach "^2.0.5" object-keys "^1.0.8" @@ -4432,21 +3884,18 @@ define-properties@^1.1.2: define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" @@ -4454,7 +3903,6 @@ define-property@^2.0.2: del@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag= dependencies: globby "^5.0.0" is-path-cwd "^1.0.0" @@ -4467,7 +3915,6 @@ del@^2.0.2: del@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5" - integrity sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU= dependencies: globby "^6.1.0" is-path-cwd "^1.0.0" @@ -4479,27 +3926,22 @@ del@^3.0.0: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= depd@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" - integrity sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k= depd@~1.1.1, depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -4507,41 +3949,34 @@ des.js@^1.0.0: destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= detab@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.1.tgz#531f5e326620e2fd4f03264a905fb3bcc8af4df4" - integrity sha512-/hhdqdQc5thGrqzjyO/pz76lDZ5GSuAs6goxOaKTsvPk7HNnzAyFN5lyHgqpX4/s1i66K8qMGj+VhA9504x7DQ== dependencies: repeat-string "^1.5.4" detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= dependencies: repeating "^2.0.0" detect-indent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" - integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= detect-node@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127" - integrity sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc= detect-port-alt@1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" - integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q== dependencies: address "^1.0.1" debug "^2.6.0" @@ -4549,7 +3984,6 @@ detect-port-alt@1.1.6: dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" - integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= dependencies: asap "^2.0.0" wrappy "1" @@ -4557,7 +3991,6 @@ dezalgo@^1.0.0: diagnostics@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/diagnostics/-/diagnostics-1.1.1.tgz#cab6ac33df70c9d9a727490ae43ac995a769b22a" - integrity sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ== dependencies: colorspace "1.1.x" enabled "1.0.x" @@ -4566,12 +3999,10 @@ diagnostics@^1.1.1: diff@^3.2.0: version "3.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" - integrity sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA== diffie-hellman@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" - integrity sha1-tYNXOScM/ias9jIJn97SoH8gnl4= dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" @@ -4580,7 +4011,6 @@ diffie-hellman@^5.0.0: dir-glob@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" - integrity sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag== dependencies: arrify "^1.0.1" path-type "^3.0.0" @@ -4588,7 +4018,6 @@ dir-glob@^2.0.0: dmg-builder@5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-5.3.1.tgz#b4d66d1dd010e1c9e7a5787bf1369e8157cac3cf" - integrity sha512-/+vtqlgvTtha/4Gc76XIRKS2KzYO58sTWXhZ/kgfNr05ZXY6bIw26v7xDu8ZBpTYnfWI09JRZTMv1yIXT/vvfg== dependencies: app-builder-lib "~20.28.3" bluebird-lst "^1.0.5" @@ -4599,15 +4028,22 @@ dmg-builder@5.3.1: parse-color "^1.0.0" sanitize-filename "^1.6.1" +dnd-core@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/dnd-core/-/dnd-core-6.0.0.tgz#d347266ebd72f0a2de6ecf5e26e4ef006ebde84b" + dependencies: + asap "^2.0.6" + invariant "^2.2.4" + lodash "^4.17.11" + redux "^4.0.1" + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= dns-js@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/dns-js/-/dns-js-0.2.1.tgz#5d66629b3c0e6a5eb0e14f0ae701d05f6ea46673" - integrity sha1-XWZimzwOal6w4U8K5wHQX26kZnM= dependencies: debug "^2.1.0" qap "^3.1.2" @@ -4615,7 +4051,6 @@ dns-js@~0.2.1: dns-packet@^1.0.1: version "1.3.1" resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" - integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg== dependencies: ip "^1.1.0" safe-buffer "^5.0.1" @@ -4623,14 +4058,12 @@ dns-packet@^1.0.1: dns-txt@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= dependencies: buffer-indexof "^1.0.0" doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= dependencies: esutils "^2.0.2" isarray "^1.0.0" @@ -4638,26 +4071,22 @@ doctrine@1.5.0: doctrine@^2.0.0, doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" dom-converter@~0.1: version "0.1.4" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.1.4.tgz#a45ef5727b890c9bffe6d7c876e7b19cb0e17f3b" - integrity sha1-pF71cnuJDJv/5tfIduexnLDhfzs= dependencies: utila "~0.3" dom-helpers@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6" - integrity sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg== dom-serializer@0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= dependencies: domelementtype "~1.1.1" entities "~1.1.1" @@ -4665,48 +4094,40 @@ dom-serializer@0: dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= domain-browser@^1.1.1: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" - integrity sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw= domelementtype@1, domelementtype@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" - integrity sha1-sXrtguirWeUt2cGbF1bg/BhyBMI= domelementtype@~1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= domhandler@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.1.0.tgz#d2646f5e57f6c3bab11cf6cb05d3c0acf7412594" - integrity sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ= dependencies: domelementtype "1" domhandler@^2.3.0: version "2.4.1" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259" - integrity sha1-iS5HAAqZvlW783dP/qBWHYh5wlk= dependencies: domelementtype "1" domutils@1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.1.6.tgz#bddc3de099b9a2efacc51c623f28f416ecc57485" - integrity sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU= dependencies: domelementtype "1" domutils@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= dependencies: dom-serializer "0" domelementtype "1" @@ -4714,7 +4135,6 @@ domutils@1.5.1: domutils@^1.5.1: version "1.6.2" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.6.2.tgz#1958cc0b4c9426e9ed367fb1c8e854891b0fa3ff" - integrity sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8= dependencies: dom-serializer "0" domelementtype "1" @@ -4722,7 +4142,6 @@ domutils@^1.5.1: domutils@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== dependencies: dom-serializer "0" domelementtype "1" @@ -4730,48 +4149,40 @@ domutils@^1.7.0: dot-prop@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177" - integrity sha1-G3CK8JSknJoOfbyteQq6U52sEXc= dependencies: is-obj "^1.0.0" dot-prop@^4.1.0, dot-prop@^4.1.1, dot-prop@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== dependencies: is-obj "^1.0.0" dotenv-expand@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-4.2.0.tgz#def1f1ca5d6059d24a766e587942c21106ce1275" - integrity sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU= dotenv@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.0.0.tgz#24e37c041741c5f4b25324958ebbc34bca965935" - integrity sha512-FlWbnhgjtwD+uNLUGHbMykMOYQaTivdHEmYwAKFjn6GKe/CqY0fNae93ZHTd20snh9ZLr8mTzIL9m0APQ1pjQg== duplexer2@~0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= dependencies: readable-stream "^2.0.2" duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= duplexer@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= duplexify@^3.4.2, duplexify@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.3.tgz#8b5818800df92fd0125b27ab896491912858243e" - integrity sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA== dependencies: end-of-stream "^1.0.0" inherits "^2.0.1" @@ -4781,24 +4192,20 @@ duplexify@^3.4.2, duplexify@^3.5.3: ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - integrity sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU= dependencies: jsbn "~0.1.0" ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= ejs@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" - integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== electron-builder@^20.28.4: version "20.28.4" resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.28.4.tgz#c9355b92b0971d51aaed0c945d2944bac41e9fbf" - integrity sha512-JMOzMfx9BrC9SJr6+UacuvQZmuodL02Zua8iFn0l5bv32GkWcNj1D6FwybV33BpsmdQ8sF1SkQj+7L+FEIxang== dependencies: app-builder-lib "20.28.4" bluebird-lst "^1.0.5" @@ -4817,7 +4224,6 @@ electron-builder@^20.28.4: electron-debug@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/electron-debug/-/electron-debug-2.0.0.tgz#3059a6557acbfb091f138d83875f57bac80cea6d" - integrity sha512-orGlw9uErUztdD7cgdKz78txq3czpOnKG/zvvsINkUsugqL+dn77UFrbwRGVgPwuLJ7Ejbjjk9EcxIcgTivMbA== dependencies: electron-is-dev "^0.3.0" electron-localshortcut "^3.0.0" @@ -4825,7 +4231,6 @@ electron-debug@^2.0.0: electron-devtools-installer@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/electron-devtools-installer/-/electron-devtools-installer-2.2.4.tgz#261a50337e37121d338b966f07922eb4939a8763" - integrity sha512-b5kcM3hmUqn64+RUcHjjr8ZMpHS2WJ5YO0pnG9+P/RTdx46of/JrEjuciHWux6pE+On6ynWhHJF53j/EDJN0PA== dependencies: "7zip" "0.0.6" cross-unzip "0.0.2" @@ -4835,7 +4240,6 @@ electron-devtools-installer@^2.2.4: electron-download@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8" - integrity sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg== dependencies: debug "^3.0.0" env-paths "^1.0.0" @@ -4850,17 +4254,14 @@ electron-download@^4.1.0: electron-is-accelerator@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz#509e510c26a56b55e17f863a4b04e111846ab27b" - integrity sha1-UJ5RDCala1Xhf4Y6SwThEYRqsns= electron-is-dev@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-0.3.0.tgz#14e6fda5c68e9e4ecbeff9ccf037cbd7c05c5afe" - integrity sha1-FOb9pcaOnk7L7/nM8DfL18BcWv4= electron-localshortcut@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/electron-localshortcut/-/electron-localshortcut-3.1.0.tgz#10c1ffd537b8d39170aaf6e1551341f7780dd2ce" - integrity sha512-MgL/j5jdjW7iA0R6cI7S045B0GlKXWM1FjjujVPjlrmyXRa6yH0bGSaIAfxXAF9tpJm3pLEiQzerYHkRh9JG/A== dependencies: debug "^2.6.8" electron-is-accelerator "^0.1.0" @@ -4870,7 +4271,6 @@ electron-localshortcut@^3.0.0: electron-osx-sign@0.4.10: version "0.4.10" resolved "https://registry.yarnpkg.com/electron-osx-sign/-/electron-osx-sign-0.4.10.tgz#be4f3b89b2a75a1dc5f1e7249081ab2929ca3a26" - integrity sha1-vk87ibKnWh3F8eckkIGrKSnKOiY= dependencies: bluebird "^3.5.0" compare-version "^0.1.2" @@ -4882,7 +4282,6 @@ electron-osx-sign@0.4.10: electron-publish@20.28.3: version "20.28.3" resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-20.28.3.tgz#0cc360ecaffd16e22780ee1630e0bd88fe6395e2" - integrity sha512-/2t5zk9EKgH7p7rFZ+ynTKLmpKGF9bktMP2UR6u4bbPz9w4r3WEUbPOeZ1TLqUCAqdfZECcj4ThjrlcAJTghCA== dependencies: bluebird-lst "^1.0.5" builder-util "~6.1.3" @@ -4895,7 +4294,6 @@ electron-publish@20.28.3: electron-publish@~20.17.2: version "20.17.2" resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-20.17.2.tgz#b44bb4ec51497a56e9a91fdaec63f61713ee9011" - integrity sha512-nJlE5jqqT1EiHdhmZlNqkcLadjnBd2KUs7rgXK/dmKkJAaJL+GnzYACrUUpH0dyb81al6CxUP+WVP4JCl00XoA== dependencies: bluebird-lst "^1.0.5" builder-util "^5.13.0" @@ -4908,7 +4306,6 @@ electron-publish@~20.17.2: electron-publisher-s3@^20.17.2: version "20.17.2" resolved "https://registry.yarnpkg.com/electron-publisher-s3/-/electron-publisher-s3-20.17.2.tgz#62962f25c879826dae0ba233c333fe05f06b0991" - integrity sha512-x+Yg5Z0xm+OIX8JpfaSJp6SDn1j0XajtvN2yg9nbUqgBgMNY0HnlmVOI2iDMFzgZEqy0QlCcI4Ks/UuYK0IaoQ== dependencies: aws-sdk "^2.264.1" bluebird-lst "^1.0.5" @@ -4920,36 +4317,30 @@ electron-publisher-s3@^20.17.2: electron-releases@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/electron-releases/-/electron-releases-2.1.0.tgz#c5614bf811f176ce3c836e368a0625782341fd4e" - integrity sha512-cyKFD1bTE/UgULXfaueIN1k5EPFzs+FRc/rvCY5tIynefAPqopQEgjr0EzY+U3Dqrk/G4m9tXSPuZ77v6dL/Rw== electron-store@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-2.0.0.tgz#1035cca2a95409d1f54c7466606345852450d64a" - integrity sha512-1WCFYHsYvZBqDsoaS0Relnz0rd81ZkBAI0Fgx7Nq2UWU77rSNs1qxm4S6uH7TCZ0bV3LQpJFk7id/is/ZgoOPA== dependencies: conf "^2.0.0" electron-to-chromium@^1.3.30: version "1.3.30" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.30.tgz#9666f532a64586651fc56a72513692e820d06a80" - integrity sha512-zx1Prv7kYLfc4OA60FhxGbSo4qrEjgSzpo1/37i7l9ltXPYOoQBtjQxY9KmsgfHnBxHlBGXwLlsbt/gub1w5lw== dependencies: electron-releases "^2.1.0" electron-to-chromium@^1.3.62: version "1.3.82" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.82.tgz#7d13ae4437d2a783de3f4efba96b186c540b67b1" - integrity sha512-NI4nB2IWGcU4JVT1AE8kBb/dFor4zjLHMLsOROPahppeHrR0FG5uslxMmkp/thO1MvPjM2xhlKoY29/I60s0ew== electron-to-chromium@^1.3.81: version "1.3.81" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.81.tgz#32af69206ef78973b6a6771b0c8450c2ce253913" - integrity sha512-+rym2xtzwPWmoi8AYRrCdW65QOT0vfUHjZb5mjgh0VLyj31pGM3CpP3znKhQNBzQaWujR/KEl/mfC2lnKYgADA== electron-updater@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-3.1.2.tgz#30d9790d5b16048e4afc74a31748790348b153bf" - integrity sha512-y3n37O01pdynMJHhJbOd2UVhVrmDW6zLvR2SOZ+gk3S6r16872+0nNbC48GXWwc26lTeus/Zja/XUpiqrvdw4A== dependencies: bluebird-lst "^1.0.5" builder-util-runtime "~4.4.1" @@ -4964,7 +4355,6 @@ electron-updater@^3.1.2: electron@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/electron/-/electron-3.0.2.tgz#0aed43a331b43dfe671ddb54d75fc4102d362959" - integrity sha512-BsU/KJRPODlEoaOZhsmFTIaG2h1Y28JCrqeTGVqGL+fef/7xQZdHx5ZCStUDXXUSTcoqiHlc5QvLH4PfZFbOmg== dependencies: "@types/node" "^8.0.24" electron-download "^4.1.0" @@ -4973,7 +4363,6 @@ electron@3.0.2: elliptic@^6.0.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" - integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8= dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -4986,17 +4375,14 @@ elliptic@^6.0.0: "emoji-regex@>=6.0.0 <=6.1.1": version "6.1.1" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e" - integrity sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4= emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= emotion@^9.1.2: version "9.2.12" resolved "https://registry.yarnpkg.com/emotion/-/emotion-9.2.12.tgz#53925aaa005614e65c6e43db8243c843574d1ea9" - integrity sha512-hcx7jppaI8VoXxIWEhxpDW7I+B4kq9RNzQLmsrF6LY8BGKqe2N+gFAQr0EfuFucFlPs2A9HM4+xNj4NeqEWIOQ== dependencies: babel-plugin-emotion "^9.2.11" create-emotion "^9.2.12" @@ -5004,38 +4390,32 @@ emotion@^9.1.2: enabled@1.0.x: version "1.0.2" resolved "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz#965f6513d2c2d1c5f4652b64a2e3396467fc2f93" - integrity sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M= dependencies: env-variable "0.0.x" encodeurl@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" - integrity sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA= encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= dependencies: iconv-lite "~0.4.13" end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== dependencies: once "^1.4.0" enhanced-resolve@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" - integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== dependencies: graceful-fs "^4.1.2" memory-fs "^0.4.0" @@ -5044,50 +4424,42 @@ enhanced-resolve@^4.1.0: entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - integrity sha1-blwtClYhtdra7O+AuQ7ftc13cvA= env-paths@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" - integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA= env-variable@0.0.x: version "0.0.4" resolved "https://registry.npmjs.org/env-variable/-/env-variable-0.0.4.tgz#0d6280cf507d84242befe35a512b5ae4be77c54e" - integrity sha512-+jpGxSWG4vr6gVxUHOc4p+ilPnql7NzZxOZBxNldsKGjCF+97df3CbuX7XMaDa5oAVkKQj4rKp38rYdC4VcpDg== errno@^0.1.3, errno@^0.1.4: version "0.1.6" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.6.tgz#c386ce8a6283f14fc09563b71560908c9bf53026" - integrity sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw== dependencies: prr "~1.0.1" errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== dependencies: prr "~1.0.1" error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" - integrity sha1-+FWobOYa3E6GIcPNoh56dhLDqNw= dependencies: is-arrayish "^0.2.1" error-stack-parser@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-1.3.6.tgz#e0e73b93e417138d1cd7c0b746b1a4a14854c292" - integrity sha1-4Oc7k+QXE40c18C3RrGkoUhUwpI= dependencies: stackframe "^0.3.1" es-abstract@^1.5.1, es-abstract@^1.6.1: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" - integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== dependencies: es-to-primitive "^1.1.1" function-bind "^1.1.1" @@ -5098,7 +4470,6 @@ es-abstract@^1.5.1, es-abstract@^1.6.1: es-abstract@^1.7.0: version "1.10.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864" - integrity sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ== dependencies: es-to-primitive "^1.1.1" function-bind "^1.1.1" @@ -5109,7 +4480,6 @@ es-abstract@^1.7.0: es-to-primitive@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" - integrity sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0= dependencies: is-callable "^1.1.1" is-date-object "^1.0.1" @@ -5118,39 +4488,32 @@ es-to-primitive@^1.1.1: es6-object-assign@^1.0.3, es6-object-assign@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" - integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= es6-promise@^4.0.3: version "4.2.4" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" - integrity sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ== es6-promise@^4.2.4: version "4.2.5" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054" - integrity sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg== es6-promisify@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= dependencies: es6-promise "^4.0.3" escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@^1.10.0: version "1.11.0" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" - integrity sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw== dependencies: esprima "^3.1.3" estraverse "^4.2.0" @@ -5162,7 +4525,6 @@ escodegen@^1.10.0: escodegen@^1.6.1: version "1.9.0" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.0.tgz#9811a2f265dc1cd3894420ee3717064b632b8852" - integrity sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw== dependencies: esprima "^3.1.3" estraverse "^4.2.0" @@ -5174,12 +4536,10 @@ escodegen@^1.6.1: eslint-config-standard@^10.2.1: version "10.2.1" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" - integrity sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE= eslint-import-resolver-node@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" - integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== dependencies: debug "^2.6.9" resolve "^1.5.0" @@ -5187,7 +4547,6 @@ eslint-import-resolver-node@^0.3.1: eslint-module-utils@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" - integrity sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw== dependencies: debug "^2.6.8" pkg-dir "^1.0.0" @@ -5195,14 +4554,12 @@ eslint-module-utils@^2.1.1: eslint-plugin-flowtype@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-3.0.0.tgz#4b72588d8a5a5c836439752fe52e8e0f4b9954df" - integrity sha512-84utjHfQeykSyNuhO885pp18yGKYuK2S03EFbhl/BpXR9jk0TABnDP/KhUAqDjjkB43mxK2WZjJesrhnncvR9Q== dependencies: lodash "^4.17.10" eslint-plugin-import@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz#fa1b6ef31fcb3c501c09859c1b86f1fc5b986894" - integrity sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g== dependencies: builtin-modules "^1.1.1" contains-path "^0.1.0" @@ -5218,7 +4575,6 @@ eslint-plugin-import@^2.8.0: eslint-plugin-node@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-6.0.0.tgz#5ad5ee6b5346aec6cc9cde0b8619caed2c6d8f25" - integrity sha512-Qj4dMF1N/wRALO1IRvnchn8c1i0awgrztrGx7MjF9ewDwlW/heNB+WeZ09bhp8Yp0TD+BZcADP8BRya0wmropA== dependencies: ignore "^3.3.6" minimatch "^3.0.4" @@ -5228,12 +4584,10 @@ eslint-plugin-node@^6.0.0: eslint-plugin-promise@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz#54b7658c8f454813dc2a870aff8152ec4969ba75" - integrity sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q== eslint-plugin-react@^7.11.1: version "7.11.1" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz#c01a7af6f17519457d6116aa94fc6d2ccad5443c" - integrity sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw== dependencies: array-includes "^3.0.3" doctrine "^2.1.0" @@ -5244,12 +4598,10 @@ eslint-plugin-react@^7.11.1: eslint-plugin-standard@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2" - integrity sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI= eslint-scope@3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" - integrity sha1-PWPD7f2gLgbgGkUq2IyqzHzctug= dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -5257,7 +4609,6 @@ eslint-scope@3.7.1: eslint-scope@^3.7.1: version "3.7.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" - integrity sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -5265,7 +4616,6 @@ eslint-scope@^3.7.1: eslint-scope@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" - integrity sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -5273,12 +4623,10 @@ eslint-scope@^4.0.0: eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== eslint@4.19.1: version "4.19.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" - integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== dependencies: ajv "^5.3.0" babel-code-frame "^6.22.0" @@ -5322,7 +4670,6 @@ eslint@4.19.1: espree@^3.5.4: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== dependencies: acorn "^5.5.0" acorn-jsx "^3.0.0" @@ -5330,29 +4677,24 @@ espree@^3.5.4: esprima@^2.1.0: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= esprima@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= esprima@^4.0.0, esprima@~4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" - integrity sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw== esquery@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== dependencies: estraverse "^4.0.0" esrecurse@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" - integrity sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM= dependencies: estraverse "^4.1.0" object-assign "^4.0.1" @@ -5360,51 +4702,42 @@ esrecurse@^4.1.0: estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eventemitter3@1.x.x: version "1.2.0" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" - integrity sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg= events@1.1.1, events@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== eventsource@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-0.1.6.tgz#0acede849ed7dd1ccc32c811bb11b944d4f29232" - integrity sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI= dependencies: original ">=0.0.5" eventsource@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0" - integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ== dependencies: original "^1.0.0" evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" @@ -5412,14 +4745,12 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: exec-sh@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.1.tgz#163b98a6e89e6b65b47c2a28d215bc1f63989c38" - integrity sha512-aLt95pexaugVtQerpmE51+4QfWrNc304uez7jvj6fWnN8GeEHpttB8F36n8N7uVhUMbH/1enbxQ9HImZ4w/9qg== dependencies: merge "^1.1.3" execa@0.10.0, execa@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" - integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw== dependencies: cross-spawn "^6.0.0" get-stream "^3.0.0" @@ -5432,7 +4763,6 @@ execa@0.10.0, execa@^0.10.0: execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" @@ -5445,21 +4775,18 @@ execa@^0.7.0: execall@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73" - integrity sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M= dependencies: clone-regexp "^1.0.0" expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= dependencies: is-posix-bracket "^0.1.0" expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -5472,21 +4799,18 @@ expand-brackets@^2.1.4: expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= dependencies: fill-range "^2.1.0" expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= dependencies: homedir-polyfill "^1.0.1" express@^4.16.2: version "4.16.2" resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c" - integrity sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w= dependencies: accepts "~1.3.4" array-flatten "1.1.1" @@ -5522,7 +4846,6 @@ express@^4.16.2: express@^4.16.3: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" - integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== dependencies: accepts "~1.3.5" array-flatten "1.1.1" @@ -5558,14 +4881,12 @@ express@^4.16.3: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -5573,17 +4894,14 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - integrity sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ= extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== external-editor@^2.0.4, external-editor@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== dependencies: chardet "^0.4.0" iconv-lite "^0.4.17" @@ -5592,7 +4910,6 @@ external-editor@^2.0.4, external-editor@^2.1.0: external-editor@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" - integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" @@ -5601,14 +4918,12 @@ external-editor@^3.0.0: extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= dependencies: is-extglob "^1.0.0" extglob@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.3.tgz#55e019d0c95bf873949c737b7e5172dba84ebb29" - integrity sha512-AyptZexgu7qppEPq59DtN/XJGZDrLcVxSHai+4hdgMMS9EpF4GBvygcWWApno8lL9qSjVpYt7Raao28qzJX1ww== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -5622,7 +4937,6 @@ extglob@^2.0.2: extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -5636,7 +4950,6 @@ extglob@^2.0.4: extract-zip@^1.0.3: version "1.6.6" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c" - integrity sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw= dependencies: concat-stream "1.6.0" debug "2.6.9" @@ -5646,32 +4959,26 @@ extract-zip@^1.0.3: extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= eyes@0.1.x: version "0.1.8" resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" - integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" - integrity sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8= fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-glob@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.2.tgz#71723338ac9b4e0e2fff1d6748a2a13d5ed352bf" - integrity sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g== dependencies: "@mrmlnc/readdir-enhanced" "^2.2.1" "@nodelib/fs.stat" "^1.0.1" @@ -5683,55 +4990,46 @@ fast-glob@^2.0.2: fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fast-safe-stringify@^2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz#04b26106cc56681f51a044cfc0d76cf0008ac2c2" - integrity sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg== fastparse@^1.0.0, fastparse@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" - integrity sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg= faye-websocket@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" - integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ= dependencies: websocket-driver ">=0.5.1" faye-websocket@~0.11.0, faye-websocket@~0.11.1: version "0.11.1" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.1.tgz#f0efe18c4f56e4f40afc7e06c719fd5ee6188f38" - integrity sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg= dependencies: websocket-driver ">=0.5.1" fb-watchman@^1.8.0: version "1.9.2" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-1.9.2.tgz#a24cf47827f82d38fb59a69ad70b76e3b6ae7383" - integrity sha1-okz0eCf4LTj7Waaa1wt247auc4M= dependencies: bser "1.0.2" fb-watchman@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" - integrity sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg= dependencies: bser "^2.0.0" -fbjs@^0.8.0: +fbjs@^0.8.0, fbjs@^0.8.1: version "0.8.17" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" - integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90= dependencies: core-js "^1.0.0" isomorphic-fetch "^2.1.1" @@ -5744,7 +5042,6 @@ fbjs@^0.8.0: fbjs@^0.8.16: version "0.8.16" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" - integrity sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s= dependencies: core-js "^1.0.0" isomorphic-fetch "^2.1.1" @@ -5757,31 +5054,26 @@ fbjs@^0.8.16: fd-slicer@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" - integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= dependencies: pend "~1.2.0" fecha@^2.3.3: version "2.3.3" resolved "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd" - integrity sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg== figgy-pudding@^3.1.0, figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" - integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= dependencies: flat-cache "^1.2.1" object-assign "^4.0.1" @@ -5789,7 +5081,6 @@ file-entry-cache@^2.0.0: file-loader@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-2.0.0.tgz#39749c82f020b9e85901dcff98e8004e6401cfde" - integrity sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ== dependencies: loader-utils "^1.0.2" schema-utils "^1.0.0" @@ -5797,12 +5088,10 @@ file-loader@^2.0.0: filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= fileset@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" - integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA= dependencies: glob "^7.0.3" minimatch "^3.0.3" @@ -5810,12 +5099,10 @@ fileset@^2.0.2: filesize@3.6.1, filesize@^3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" - integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== fill-range@^2.1.0: version "2.2.3" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" - integrity sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM= dependencies: is-number "^2.1.0" isobject "^2.0.0" @@ -5826,7 +5113,6 @@ fill-range@^2.1.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -5836,7 +5122,6 @@ fill-range@^4.0.0: finalhandler@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" - integrity sha1-zgtoVbRYU+eRsvzGgARtiCU91/U= dependencies: debug "2.6.9" encodeurl "~1.0.1" @@ -5849,7 +5134,6 @@ finalhandler@1.1.0: finalhandler@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" - integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== dependencies: debug "2.6.9" encodeurl "~1.0.2" @@ -5862,7 +5146,6 @@ finalhandler@1.1.1: find-cache-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" - integrity sha1-kojj6ePMN0hxfTnq3hfPcfww7m8= dependencies: commondir "^1.0.1" make-dir "^1.0.0" @@ -5871,7 +5154,6 @@ find-cache-dir@^1.0.0: find-cache-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d" - integrity sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA== dependencies: commondir "^1.0.1" make-dir "^1.0.0" @@ -5880,26 +5162,22 @@ find-cache-dir@^2.0.0: find-root@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" - integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== find-up@2.1.0, find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= dependencies: locate-path "^2.0.0" find-up@3.0.0, find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: locate-path "^3.0.0" find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" @@ -5907,7 +5185,6 @@ find-up@^1.0.0: findup@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/findup/-/findup-0.1.5.tgz#8ad929a3393bac627957a7e5de4623b06b0e2ceb" - integrity sha1-itkpozk7rGJ5V6fl3kYjsGsOLOs= dependencies: colors "~0.6.0-1" commander "~2.1.0" @@ -5915,7 +5192,6 @@ findup@^0.1.5: flat-cache@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" - integrity sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE= dependencies: circular-json "^0.3.1" del "^2.0.2" @@ -5925,17 +5201,14 @@ flat-cache@^1.2.1: flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" - integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I= flow-bin@^0.82.0: version "0.82.0" resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.82.0.tgz#fbec84c0d6cab7877565eca8214d655f3aefb8db" - integrity sha512-D7ViTCVJSVv19CB6dFWS9k2iKQlavtkRXn9el0ofVTTpGuybe+EPE8DZwdyohzEt6wRhHV8gwkteWvxdcVuOzg== flow-copy-source@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/flow-copy-source/-/flow-copy-source-2.0.2.tgz#096e579a9bb63a38afc5d4dd68ac847a5be27594" - integrity sha512-IHKgy45Q+Xs7UanUZyFFJae/ubMKtzj0dU4vs1YoqlfKl2wzLTaqehyTpjqO4vLAnL48yGvLfnttncX5Utn/4g== dependencies: chokidar "^2.0.0" fs-extra "^7.0.0" @@ -5946,7 +5219,6 @@ flow-copy-source@^2.0.2: flow-mono-cli@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/flow-mono-cli/-/flow-mono-cli-1.3.4.tgz#ebd80a565fc9238e0e4b4b60ee645a40d25dd340" - integrity sha512-Eg242POkUkuuc+ot3hBobpO7uNkgAMdJMIfsHhscZkoZJSI2LBpk//SosH8KrxkoMWGoxQVNneYpD9+KwTY63Q== dependencies: commander "2.15.1" cosmiconfig "^5.0.5" @@ -5962,7 +5234,6 @@ flow-mono-cli@^1.3.4: flow-typed@^2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/flow-typed/-/flow-typed-2.5.1.tgz#0ff565cc94d2af8c557744ba364b6f14726a6b9f" - integrity sha1-D/VlzJTSr4xVd0S6NktvFHJqa58= dependencies: "@octokit/rest" "^15.2.6" babel-polyfill "^6.26.0" @@ -5983,7 +5254,6 @@ flow-typed@^2.5.1: flush-write-stream@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.2.tgz#c81b90d8746766f1a609a46809946c45dd8ae417" - integrity sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc= dependencies: inherits "^2.0.1" readable-stream "^2.0.4" @@ -5991,34 +5261,28 @@ flush-write-stream@^1.0.0: fn-name@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7" - integrity sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc= for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= for-own@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= dependencies: for-in "^1.0.1" foreach@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= form-data@~2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - integrity sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE= dependencies: asynckit "^0.4.0" combined-stream "^1.0.5" @@ -6027,7 +5291,6 @@ form-data@~2.1.1: form-data@~2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" - integrity sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8= dependencies: asynckit "^0.4.0" combined-stream "^1.0.5" @@ -6036,7 +5299,6 @@ form-data@~2.3.1: form-data@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk= dependencies: asynckit "^0.4.0" combined-stream "1.0.6" @@ -6045,7 +5307,6 @@ form-data@~2.3.2: formik@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/formik/-/formik-1.3.1.tgz#ff2bb4c0144585297cf9a371081326e8d816fe6f" - integrity sha512-cOTpwP4vy8bj7HhEGC2IWFFhsztBlZOJoTRgGa64NxcM30rV15ub5nTliQA3Vs8vqWSlGEc6k67SR8YZIV7pew== dependencies: create-react-context "^0.2.2" deepmerge "^2.1.1" @@ -6060,24 +5321,20 @@ formik@^1.3.1: forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= from2@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= dependencies: inherits "^2.0.1" readable-stream "^2.0.0" @@ -6085,7 +5342,6 @@ from2@^2.1.0: fs-extra-p@^4.6.1: version "4.6.1" resolved "https://registry.yarnpkg.com/fs-extra-p/-/fs-extra-p-4.6.1.tgz#6156e0cc98097f415fcd17029578fc41c78b5092" - integrity sha512-IsTMbUS0svZKZTvqF4vDS9c/L7Mw9n8nZQWWeSzAGacOSe+8CzowhUN0tdZEZFIJNP5HC7L9j3MMikz/G4hDeQ== dependencies: bluebird-lst "^1.0.5" fs-extra "^6.0.1" @@ -6093,7 +5349,6 @@ fs-extra-p@^4.6.1: fs-extra@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -6102,7 +5357,6 @@ fs-extra@^4.0.1: fs-extra@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -6111,7 +5365,6 @@ fs-extra@^5.0.0: fs-extra@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" - integrity sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -6120,7 +5373,6 @@ fs-extra@^6.0.1: fs-extra@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.0.tgz#8cc3f47ce07ef7b3593a11b9fb245f7e34c041d6" - integrity sha512-EglNDLRpmaTWiD/qraZn6HREAEAHJcJOmxNEYwq6xeMKnVMAy3GUcFB+wXt2C6k4CNvB/mP1y/U3dzvKKj5OtQ== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -6129,19 +5381,16 @@ fs-extra@^7.0.0: fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== dependencies: minipass "^2.2.1" fs-readdir-recursive@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" - integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" - integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= dependencies: graceful-fs "^4.1.2" iferr "^0.1.5" @@ -6151,12 +5400,10 @@ fs-write-stream-atomic@^1.0.8: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" - integrity sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q== dependencies: nan "^2.3.0" node-pre-gyp "^0.6.39" @@ -6164,7 +5411,6 @@ fsevents@^1.0.0: fsevents@^1.2.2: version "1.2.4" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" - integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== dependencies: nan "^2.9.2" node-pre-gyp "^0.10.0" @@ -6172,7 +5418,6 @@ fsevents@^1.2.2: fstream-ignore@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" - integrity sha1-nDHa40dnAY/h0kmyTa2mfQktoQU= dependencies: fstream "^1.0.0" inherits "2" @@ -6181,7 +5426,6 @@ fstream-ignore@^1.0.5: fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2, fstream@~1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= dependencies: graceful-fs "^4.1.2" inherits "~2.0.0" @@ -6191,22 +5435,18 @@ fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2, fstream@~1.0.10: function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== function.name-polyfill@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/function.name-polyfill/-/function.name-polyfill-1.0.6.tgz#c54e37cae0a77dfcb49d47982815b0826b5c60d9" - integrity sha512-ejQivNFbBPTY5O/waFta6D5AzV8GJiM/fMDaT6LrsYax1cb4eipxuQqKNlugF2jlcXIjifsqvju3wsgV35TELg== functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -6220,17 +5460,14 @@ gauge@~2.7.3: get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" - integrity sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U= get-own-enumerable-property-symbols@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz#5c4ad87f2834c4b9b4e84549dc1e0650fb38c24b" - integrity sha512-TtY/sbOemiMKPRUDDanGCSgBYe7Mf0vbRsWnBZ+9yghpZ1MvcpSpuZFjHdEeY/LZjZy0vdLjS77L6HosisFiug== get-pkg-repo@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d" - integrity sha1-xztInAbYDMVTbCyFP54FIyBWly0= dependencies: hosted-git-info "^2.1.4" meow "^3.3.0" @@ -6241,39 +5478,32 @@ get-pkg-repo@^1.0.0: get-port@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" - integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= get-stdin@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" - integrity sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g= get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= dependencies: assert-plus "^1.0.0" git-describe@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/git-describe/-/git-describe-4.0.3.tgz#d81482a8ada7a1d81e060d438ac8e11b4a390336" - integrity sha1-2BSCqK2nodgeBg1DisjhG0o5AzY= dependencies: lodash "^4.16.6" optionalDependencies: @@ -6282,7 +5512,6 @@ git-describe@^4.0.3: git-raw-commits@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-1.3.6.tgz#27c35a32a67777c1ecd412a239a6c19d71b95aff" - integrity sha512-svsK26tQ8vEKnMshTDatSIQSMDdz8CxIIqKsvPqbtV23Etmw6VNaFAitu8zwZ0VrOne7FztwPyRLxK7/DIUTQg== dependencies: dargs "^4.0.1" lodash.template "^4.0.2" @@ -6293,7 +5522,6 @@ git-raw-commits@^1.3.6: git-remote-origin-url@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" - integrity sha1-UoJlna4hBxRaERJhEq0yFuxfpl8= dependencies: gitconfiglocal "^1.0.0" pify "^2.3.0" @@ -6301,7 +5529,6 @@ git-remote-origin-url@^2.0.0: git-semver-tags@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-1.3.6.tgz#357ea01f7280794fe0927f2806bee6414d2caba5" - integrity sha512-2jHlJnln4D/ECk9FxGEBh3k44wgYdWjWDtMmJPaecjoRmxKo3Y1Lh8GMYuOPu04CHw86NTAODchYjC5pnpMQig== dependencies: meow "^4.0.0" semver "^5.5.0" @@ -6309,21 +5536,18 @@ git-semver-tags@^1.3.6: gitconfiglocal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" - integrity sha1-QdBF84UaXqiPA/JMocYXgRRGS5s= dependencies: ini "^1.3.2" github-slugger@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.2.0.tgz#8ada3286fd046d8951c3c952a8d7854cfd90fd9a" - integrity sha512-wIaa75k1vZhyPm9yWrD08A5Xnx/V+RmzGrpjQuLemGKSb77Qukiaei58Bogrl/LZSADDfPzKJX8jhLs4CRTl7Q== dependencies: emoji-regex ">=6.0.0 <=6.1.1" glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= dependencies: glob-parent "^2.0.0" is-glob "^2.0.0" @@ -6331,14 +5555,12 @@ glob-base@^0.3.0: glob-parent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= dependencies: is-glob "^2.0.0" glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" @@ -6346,12 +5568,10 @@ glob-parent@^3.1.0: glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -6363,19 +5583,16 @@ glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: global-dirs@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" - integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= dependencies: ini "^1.3.4" global-modules-path@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.3.0.tgz#b0e2bac6beac39745f7db5c59d26a36a0b94f7dc" - integrity sha512-HchvMJNYh9dGSCy8pOQ2O8u/hoXaL+0XhnrwH0RyLiSXMMTl9W3N6KUU73+JFOg5PGjtzl6VZzUQsnrpm7Szag== global-modules@1.0.0, global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== dependencies: global-prefix "^1.0.1" is-windows "^1.0.1" @@ -6384,7 +5601,6 @@ global-modules@1.0.0, global-modules@^1.0.0: global-prefix@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= dependencies: expand-tilde "^2.0.2" homedir-polyfill "^1.0.1" @@ -6395,7 +5611,6 @@ global-prefix@^1.0.1: global@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" - integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= dependencies: min-document "^2.19.0" process "~0.5.1" @@ -6403,17 +5618,14 @@ global@^4.3.0: globals@^11.0.1, globals@^11.1.0: version "11.8.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" - integrity sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA== globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0= dependencies: array-union "^1.0.1" arrify "^1.0.0" @@ -6425,7 +5637,6 @@ globby@^5.0.0: globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= dependencies: array-union "^1.0.1" glob "^7.0.3" @@ -6436,7 +5647,6 @@ globby@^6.1.0: globby@^7.0.0, globby@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" - integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA= dependencies: array-union "^1.0.1" dir-glob "^2.0.0" @@ -6448,7 +5658,6 @@ globby@^7.0.0, globby@^7.1.1: globby@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.1.tgz#b5ad48b8aa80b35b814fc1281ecc851f1d2b5b50" - integrity sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw== dependencies: array-union "^1.0.1" dir-glob "^2.0.0" @@ -6461,26 +5670,22 @@ globby@^8.0.1: globjoin@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" - integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM= glogg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810" - integrity sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw== dependencies: sparkles "^1.0.0" gonzales-pe@^4.0.3: version "4.2.3" resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.3.tgz#41091703625433285e0aee3aa47829fc1fbeb6f2" - integrity sha512-Kjhohco0esHQnOiqqdJeNz/5fyPkOMD/d6XVjwTAoPGUFh0mCollPUTUTa2OZy4dYNAqlPIQdTiNzJTWdd9Htw== dependencies: minimist "1.1.x" got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" - integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA= dependencies: create-error-class "^3.0.0" duplexer3 "^0.1.4" @@ -6497,7 +5702,6 @@ got@^6.7.1: got@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== dependencies: decompress-response "^3.2.0" duplexer3 "^0.1.4" @@ -6517,22 +5721,18 @@ got@^7.1.0: graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" - integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= gud@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" - integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== gzip-size@5.0.0, gzip-size@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80" - integrity sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA== dependencies: duplexer "^0.1.1" pify "^3.0.0" @@ -6540,12 +5740,10 @@ gzip-size@5.0.0, gzip-size@^5.0.0: handle-thing@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4" - integrity sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ= handlebars-loader@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/handlebars-loader/-/handlebars-loader-1.7.0.tgz#4f750bc62c350fb922e52d8564d667887e909723" - integrity sha512-tfS3n+PrDB2gnDnrx0/DGvdb4wF4JqV7CEiVof3RymOIWYrcmD+ZiaXTlZ/f7fZ7+aQPEv6JRG0HS7nTlyvGlQ== dependencies: async "~0.2.10" fastparse "^1.0.0" @@ -6555,7 +5753,6 @@ handlebars-loader@^1.7.0: handlebars@^4.0.11, handlebars@^4.0.2, handlebars@^4.0.3: version "4.0.11" resolved "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" - integrity sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw= dependencies: async "^1.4.0" optimist "^0.6.1" @@ -6566,17 +5763,14 @@ handlebars@^4.0.11, handlebars@^4.0.2, handlebars@^4.0.3: har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" - integrity sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4= har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" - integrity sha1-M0gdDxu/9gDdID11gSpqX7oALio= dependencies: ajv "^4.9.1" har-schema "^1.0.5" @@ -6584,7 +5778,6 @@ har-validator@~4.2.1: har-validator@~5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0= dependencies: ajv "^5.1.0" har-schema "^2.0.0" @@ -6592,7 +5785,6 @@ har-validator@~5.0.3: har-validator@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" - integrity sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA== dependencies: ajv "^5.3.0" har-schema "^2.0.0" @@ -6600,51 +5792,42 @@ har-validator@~5.1.0: harmony-reflect@^1.4.6: version "1.5.1" resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.5.1.tgz#b54ca617b00cc8aef559bbb17b3d85431dc7e329" - integrity sha1-tUymF7AMyK71Wbuxez2FQx3H4yk= has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= dependencies: ansi-regex "^2.0.0" has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-symbol-support-x@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.1.tgz#66ec2e377e0c7d7ccedb07a3a84d77510ff1bc4c" - integrity sha512-JkaetveU7hFbqnAC1EV1sF4rlojU2D4Usc5CmS69l6NfmPDnpnFUegzFg33eDkkpNCxZ0mQp65HwUDrNFS/8MA== has-to-string-tag-x@^1.2.0: version "1.4.1" resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== dependencies: has-symbol-support-x "^1.4.1" has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -6653,7 +5836,6 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -6662,12 +5844,10 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" @@ -6675,28 +5855,24 @@ has-values@^1.0.0: has@^1.0.0, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" has@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" - integrity sha1-hGFzP1OLCDfJNh45qauelwTcLyg= dependencies: function-bind "^1.0.2" hash-base@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1" - integrity sha1-ZuodhW206KVHDK32/OI65SRO8uE= dependencies: inherits "^2.0.1" hash-base@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" @@ -6704,7 +5880,6 @@ hash-base@^3.0.0: hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.3" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" - integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.0" @@ -6712,7 +5887,6 @@ hash.js@^1.0.0, hash.js@^1.0.3: hast-to-hyperscript@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-4.0.0.tgz#3eb25483ec72a8e9a71e4b1ad7eb8f7c86f755db" - integrity sha512-4kOn4ihjDJTQg7B53ZcZ6NyExtTeG3hLNZv6rSKhq4haQvD52zCllE+49iLiC1VWuc4DbHmt96FHPGlHbslZqQ== dependencies: comma-separated-tokens "^1.0.0" is-nan "^1.2.1" @@ -6725,14 +5899,12 @@ hast-to-hyperscript@^4.0.0: hast-util-sanitize@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/hast-util-sanitize/-/hast-util-sanitize-1.2.0.tgz#1a46bc8e8554f4747d219dd1d85f9cb245b1b08d" - integrity sha512-VwCTqjt6fbMGacxGB1FKV5sBJaVVkyCGVMDwb4nnqvCW2lkqscA2GEpOyBx4ZWRXty1eAZF58MHBrllEoQEoBg== dependencies: xtend "^4.0.1" hawk@3.1.3, hawk@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - integrity sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ= dependencies: boom "2.x.x" cryptiles "2.x.x" @@ -6742,7 +5914,6 @@ hawk@3.1.3, hawk@~3.1.3: hawk@~6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - integrity sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ== dependencies: boom "4.x.x" cryptiles "3.x.x" @@ -6752,22 +5923,18 @@ hawk@~6.0.2: he@1.1.x: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= hex-color-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" - integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== highlight.js@^9.12.0: version "9.12.0" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" - integrity sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4= history@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b" - integrity sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA== dependencies: invariant "^2.2.1" loose-envify "^1.2.0" @@ -6778,7 +5945,6 @@ history@^4.7.2: hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" @@ -6787,27 +5953,28 @@ hmac-drbg@^1.0.0: hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= hoek@4.x.x: version "4.2.0" resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" - integrity sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ== hoist-non-react-statics@^2.2.1, hoist-non-react-statics@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0" - integrity sha1-ND24TGAYxlB3iJgkATWhQg7iLOA= -hoist-non-react-statics@^2.5.5: +hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.5: version "2.5.5" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" - integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== + +hoist-non-react-statics@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.1.0.tgz#42414ccdfff019cd2168168be998c7b3bd5245c0" + dependencies: + react-is "^16.3.2" home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.1" @@ -6815,34 +5982,28 @@ home-or-tmp@^2.0.0: homedir-polyfill@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" - integrity sha1-TCu8inWJmP7r9e1oWA921GdotLw= dependencies: parse-passwd "^1.0.0" hoopy@^0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" - integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== hosted-git-info@^2.1.4: version "2.5.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" - integrity sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg== hosted-git-info@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz#23235b29ab230c576aab0d4f13fc046b0b038222" - integrity sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw== hosted-git-info@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= dependencies: inherits "^2.0.1" obuf "^1.0.0" @@ -6852,34 +6013,28 @@ hpack.js@^2.1.6: hsl-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" - integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= hsla-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" - integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= html-comment-regex@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e" - integrity sha1-ZouTd26q5V696POtRkswekljYl4= html-encoding-sniffer@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" - integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== dependencies: whatwg-encoding "^1.0.1" html-entities@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" - integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= html-minifier@^3.2.3: version "3.5.8" resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.8.tgz#5ccdb1f73a0d654e6090147511f6e6b2ee312700" - integrity sha512-WX7D6PB9PFq05fZ1/CyxPUuyqXed6vh2fGOM80+zJT5wAO93D/cUjLs0CcbBFjQmlwmCgRvl97RurtArIpOnkw== dependencies: camel-case "3.0.x" clean-css "4.1.x" @@ -6893,12 +6048,10 @@ html-minifier@^3.2.3: html-tags@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b" - integrity sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos= html-webpack-plugin@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b" - integrity sha1-sBq71yOsqqeze2r0SS69oD2d03s= dependencies: html-minifier "^3.2.3" loader-utils "^0.2.16" @@ -6911,7 +6064,6 @@ html-webpack-plugin@^3.2.0: htmlparser2@^3.9.2: version "3.9.2" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" - integrity sha1-G9+HrMoPP55T+k/M6w9LTLsAszg= dependencies: domelementtype "^1.3.0" domhandler "^2.3.0" @@ -6923,7 +6075,6 @@ htmlparser2@^3.9.2: htmlparser2@~3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.3.0.tgz#cc70d05a59f6542e43f0e685c982e14c924a9efe" - integrity sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4= dependencies: domelementtype "1" domhandler "2.1" @@ -6933,12 +6084,10 @@ htmlparser2@~3.3.0: http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= http-errors@1.6.2, http-errors@~1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" - integrity sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY= dependencies: depd "1.1.1" inherits "2.0.3" @@ -6948,7 +6097,6 @@ http-errors@1.6.2, http-errors@~1.6.2: http-errors@1.6.3, http-errors@~1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= dependencies: depd "~1.1.2" inherits "2.0.3" @@ -6958,12 +6106,10 @@ http-errors@1.6.3, http-errors@~1.6.3: http-parser-js@>=0.4.0: version "0.4.9" resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.9.tgz#ea1a04fb64adff0242e9974f297dd4c3cad271e1" - integrity sha1-6hoE+2St/wJC6ZdPKX3Uw8rSceE= http-proxy-agent@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" - integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== dependencies: agent-base "4" debug "3.1.0" @@ -6971,7 +6117,6 @@ http-proxy-agent@^2.1.0: http-proxy-middleware@~0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz#0987e6bb5a5606e5a69168d8f967a87f15dd8aab" - integrity sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q== dependencies: http-proxy "^1.16.2" is-glob "^4.0.0" @@ -6981,7 +6126,6 @@ http-proxy-middleware@~0.18.0: http-proxy@^1.16.2: version "1.16.2" resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742" - integrity sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I= dependencies: eventemitter3 "1.x.x" requires-port "1.x.x" @@ -6989,7 +6133,6 @@ http-proxy@^1.16.2: http-signature@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - integrity sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8= dependencies: assert-plus "^0.2.0" jsprim "^1.2.2" @@ -6998,7 +6141,6 @@ http-signature@~1.1.0: http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" @@ -7007,12 +6149,10 @@ http-signature@~1.2.0: https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= https-proxy-agent@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" - integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ== dependencies: agent-base "^4.1.0" debug "^3.1.0" @@ -7020,96 +6160,80 @@ https-proxy-agent@^2.2.0: hyphenate-style-name@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b" - integrity sha1-MRYKNpMK2vH8BMYHT360FGXU7Es= i18next@^11.5.0: version "11.5.0" resolved "https://registry.yarnpkg.com/i18next/-/i18next-11.5.0.tgz#1e8df15d5d7e96b27da964abde6e7367169fb4c1" - integrity sha512-PM2G3iY1LoHonDwygLT9xyBAINuHujXnisnrib7RXdLtE9Tb1dT8RKXwWB+MCl9VOcM5rJwWO9iLw/3KftVEoA== iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@~0.4.13: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" - integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ== iconv-lite@0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" - integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@^0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" icss-replace-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" - integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= icss-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962" - integrity sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI= dependencies: postcss "^6.0.1" identity-obj-proxy@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" - integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ= dependencies: harmony-reflect "^1.4.6" ieee754@1.1.8, ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" - integrity sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q= iferr@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" - integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= ignore-walk@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== dependencies: minimatch "^3.0.4" ignore@^3.3.3, ignore@^3.3.5, ignore@^3.3.6: version "3.3.7" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" - integrity sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA== import-cwd@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" - integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= dependencies: import-from "^2.1.0" import-from@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" - integrity sha1-M1238qev/VOqpHHUuAId7ja387E= dependencies: resolve-from "^3.0.0" import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= import-local@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" - integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ== dependencies: pkg-dir "^2.0.0" resolve-cwd "^2.0.0" @@ -7117,7 +6241,6 @@ import-local@^1.0.0: import-local@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== dependencies: pkg-dir "^3.0.0" resolve-cwd "^2.0.0" @@ -7125,34 +6248,28 @@ import-local@^2.0.0: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= indent-string@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= dependencies: repeating "^2.0.0" indent-string@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" - integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" @@ -7160,22 +6277,18 @@ inflight@^1.0.4: inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= ini@^1.3.2, ini@^1.3.4, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== init-package-json@^1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.3.tgz#45ffe2f610a8ca134f2bd1db5637b235070f6cbe" - integrity sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw== dependencies: glob "^7.1.1" npm-package-arg "^4.0.0 || ^5.0.0 || ^6.0.0" @@ -7189,7 +6302,6 @@ init-package-json@^1.10.3: inquirer@5.2.0, inquirer@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-5.2.0.tgz#db350c2b73daca77ff1243962e9f22f099685726" - integrity sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -7208,7 +6320,6 @@ inquirer@5.2.0, inquirer@^5.1.0: inquirer@6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" - integrity sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -7227,7 +6338,6 @@ inquirer@6.2.0: inquirer@^3.0.6: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" - integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -7247,7 +6357,6 @@ inquirer@^3.0.6: internal-ip@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-3.0.1.tgz#df5c99876e1d2eb2ea2d74f520e3f669a00ece27" - integrity sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q== dependencies: default-gateway "^2.6.0" ipaddr.js "^1.5.2" @@ -7255,90 +6364,74 @@ internal-ip@^3.0.1: interpret@^1.0.0, interpret@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" - integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= invariant@^2.0.0, invariant@^2.2.1, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" - integrity sha1-nh9WrArNtr8wMwbzOL47IErmA2A= dependencies: loose-envify "^1.0.0" -invariant@^2.2.0: +invariant@^2.1.0, invariant@^2.2.0, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" - integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= ip@^1.1.0, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= ipaddr.js@1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0" - integrity sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A= ipaddr.js@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" - integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= ipaddr.js@^1.5.2: version "1.8.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.1.tgz#fa4b79fa47fd3def5e3b159825161c0a519c9427" - integrity sha1-+kt5+kf9Pe9eOxWYJRYcClGclCc= is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-alphabetical@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.1.tgz#c77079cc91d4efac775be1034bf2d243f95e6f08" - integrity sha1-x3B5zJHU76x3W+EDS/LSQ/lebwg= is-alphanumeric@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz#4a9cef71daf4c001c1d81d63d140cf53fd6889f4" - integrity sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ= is-alphanumerical@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.1.tgz#dfb4aa4d1085e33bdb61c2dee9c80e9c6c19f53b" - integrity sha1-37SqTRCF4zvbYcLe6cgOnGwZ9Ts= dependencies: is-alphabetical "^1.0.0" is-decimal "^1.0.0" @@ -7346,55 +6439,46 @@ is-alphanumerical@^1.0.0: is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= is-arrayish@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.1.tgz#c2dfc386abaa0c3e33c48db3fe87059e69065efd" - integrity sha1-wt/DhquqDD4zxI2z/ocFnmkGXv0= is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-buffer@^1.1.4, is-buffer@^1.1.5, is-buffer@~1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= dependencies: builtin-modules "^1.0.0" is-callable@^1.1.1, is-callable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" - integrity sha1-hut1OSgF3cM69xySoO7fdO52BLI= is-ci@^1.0.10, is-ci@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.1.0.tgz#247e4162e7860cebbdaf30b774d6b0ac7dcfe7a5" - integrity sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg== dependencies: ci-info "^1.0.0" is-ci@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" - integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== dependencies: ci-info "^1.5.0" is-color-stop@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" - integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= dependencies: css-color-names "^0.0.4" hex-color-regex "^1.1.0" @@ -7406,31 +6490,26 @@ is-color-stop@^1.0.0: is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= is-decimal@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.1.tgz#f5fb6a94996ad9e8e3761fbfbd091f1fca8c4e82" - integrity sha1-9ftqlJlq2ejjdh+/vQkfH8qMToI= is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" @@ -7439,7 +6518,6 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" @@ -7448,96 +6526,80 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-directory@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= is-equal-shallow@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= dependencies: is-primitive "^2.0.0" is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= dependencies: is-extglob "^1.0.0" is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" is-glob@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= dependencies: is-extglob "^2.1.1" is-hexadecimal@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz#6e084bbc92061fbb0971ec58b6ce6d404e24da69" - integrity sha1-bghLvJIGH7sJcexYts5tQE4k2mk= is-in-browser@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835" - integrity sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU= is-installed-globally@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" - integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= dependencies: global-dirs "^0.1.0" is-path-inside "^1.0.0" @@ -7545,258 +6607,212 @@ is-installed-globally@^0.1.0: is-nan@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.2.1.tgz#9faf65b6fb6db24b7f5c0628475ea71f988401e2" - integrity sha1-n69ltvttskt/XAYoR16nH5iEAeI= dependencies: define-properties "^1.1.1" is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" - integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= dependencies: kind-of "^3.0.2" is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== is-obj@^1.0.0, is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= is-odd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-1.0.0.tgz#3b8a932eb028b3775c39bb09e91767accdb69088" - integrity sha1-O4qTLrAos3dcObsJ6RdnrM22kIg= dependencies: is-number "^3.0.0" is-odd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" - integrity sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ== dependencies: is-number "^4.0.0" is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= is-path-in-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" - integrity sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw= dependencies: is-path-inside "^1.0.0" is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= dependencies: path-is-inside "^1.0.1" is-plain-obj@^1.0.0, is-plain-obj@^1.1, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" - integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= dependencies: has "^1.0.1" is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= is-resolvable@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.1.tgz#acca1cd36dbe44b974b924321555a70ba03b1cf4" - integrity sha512-y5CXYbzvB3jTnWAZH1Nl7ykUWb6T3BcTs56HUruwBf8MhF56n1HWqhDWnVFo8GHrUPDgvUUNVhrc2U8W7iqz5g== is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" - integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= is-root@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.0.0.tgz#838d1e82318144e5a6f77819d90207645acc7019" - integrity sha512-F/pJIk8QD6OX5DNhRB7hWamLsUilmkDGho48KbgZ6xg/lmAZXHxzXQ91jzB3yRSw5kdQGGGc4yz8HYhTYIMWPg== is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-subset@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" - integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY= is-supported-regexp-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz#8b520c85fae7a253382d4b02652e045576e13bb8" - integrity sha1-i1IMhfrnolM4LUsCZS4EVXbhO7g= is-svg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" - integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== dependencies: html-comment-regex "^1.1.0" is-symbol@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" - integrity sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI= is-text-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" - integrity sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4= dependencies: text-extensions "^1.0.0" is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= is-whitespace-character@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz#9ae0176f3282b65457a1992cdb084f8a5f833e3b" - integrity sha1-muAXbzKCtlRXoZks2whPil+DPjs= is-windows@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" - integrity sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk= is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== is-word-character@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.1.tgz#5a03fa1ea91ace8a6eb0c7cd770eb86d65c8befb" - integrity sha1-WgP6HqkazopusMfNdw64bWXIvvs= is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isbinaryfile@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621" - integrity sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE= isbinaryfile@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" - integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw== dependencies: buffer-alloc "^1.2.0" isemail@2.x.x: version "2.2.1" resolved "https://registry.yarnpkg.com/isemail/-/isemail-2.2.1.tgz#0353d3d9a62951080c262c2aa0a42b8ea8e9e2a6" - integrity sha1-A1PT2aYpUQgMJiwqoKQrjqjp4qY= isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isnumeric@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/isnumeric/-/isnumeric-0.2.0.tgz#a2347ba360de19e33d0ffd590fddf7755cbf2e64" - integrity sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ= isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isomorphic-fetch@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= dependencies: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" @@ -7804,12 +6820,10 @@ isomorphic-fetch@^2.1.1: isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= istanbul-api@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.2.1.tgz#0c60a0515eb11c7d65c6b50bba2c6e999acd8620" - integrity sha512-oFCwXvd65amgaPCzqrR+a2XjanS1MvpXN6l/MlMUTv6uiA1NOgGX+I0uyq8Lg3GDxsxPsaP1049krz3hIJ5+KA== dependencies: async "^2.1.4" fileset "^2.0.2" @@ -7826,19 +6840,16 @@ istanbul-api@^1.1.1: istanbul-lib-coverage@^1.0.1, istanbul-lib-coverage@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" - integrity sha512-0+1vDkmzxqJIn5rcoEqapSB4DmPxE31EtI2dF2aCkV5esN9EWHxZ0dwgDClivMXJqE7zaYQxq30hj5L0nlTN5Q== istanbul-lib-hook@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz#8538d970372cb3716d53e55523dd54b557a8d89b" - integrity sha512-U3qEgwVDUerZ0bt8cfl3dSP3S6opBoOtk3ROO5f2EfBr/SRiD9FQqzwaZBqFORu8W7O0EXpai+k7kxHK13beRg== dependencies: append-transform "^0.4.0" istanbul-lib-instrument@^1.4.2, istanbul-lib-instrument@^1.7.5, istanbul-lib-instrument@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz#250b30b3531e5d3251299fdd64b0b2c9db6b558e" - integrity sha512-RQmXeQ7sphar7k7O1wTNzVczF9igKpaeGQAG9qR2L+BS4DCJNTI9nytRmIVYevwO0bbq+2CXvJmYDuz0gMrywA== dependencies: babel-generator "^6.18.0" babel-template "^6.16.0" @@ -7851,7 +6862,6 @@ istanbul-lib-instrument@^1.4.2, istanbul-lib-instrument@^1.7.5, istanbul-lib-ins istanbul-lib-report@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.2.tgz#922be27c13b9511b979bd1587359f69798c1d425" - integrity sha512-UTv4VGx+HZivJQwAo1wnRwe1KTvFpfi/NYwN7DcsrdzMXwpRT/Yb6r4SBPoHWj4VuQPakR32g4PUUeyKkdDkBA== dependencies: istanbul-lib-coverage "^1.1.1" mkdirp "^0.5.1" @@ -7861,7 +6871,6 @@ istanbul-lib-report@^1.1.2: istanbul-lib-source-maps@^1.1.0, istanbul-lib-source-maps@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.2.tgz#750578602435f28a0c04ee6d7d9e0f2960e62c1c" - integrity sha512-8BfdqSfEdtip7/wo1RnrvLpHVEd8zMZEDmOFEnpC6dg0vXflHt9nvoAyQUzig2uMSXfF2OBEYBV3CVjIL9JvaQ== dependencies: debug "^3.1.0" istanbul-lib-coverage "^1.1.1" @@ -7872,14 +6881,12 @@ istanbul-lib-source-maps@^1.1.0, istanbul-lib-source-maps@^1.2.2: istanbul-reports@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.3.tgz#3b9e1e8defb6d18b1d425da8e8b32c5a163f2d10" - integrity sha512-ZEelkHh8hrZNI5xDaKwPMFwDsUf5wIEI2bXAFGp1e6deR2mnEKBPhLJEgr4ZBt8Gi6Mj38E/C8kcy9XLggVO2Q== dependencies: handlebars "^4.0.3" isurl@^1.0.0-alpha5: version "1.0.0" resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== dependencies: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" @@ -7887,22 +6894,18 @@ isurl@^1.0.0-alpha5: items@2.x.x: version "2.1.1" resolved "https://registry.yarnpkg.com/items/-/items-2.1.1.tgz#8bd16d9c83b19529de5aea321acaada78364a198" - integrity sha1-i9FtnIOxlSneWuoyGsqtp4NkoZg= javascript-stringify@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-1.6.0.tgz#142d111f3a6e3dae8f4a9afd77d45855b5a9cce3" - integrity sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM= jest-changed-files@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-20.0.3.tgz#9394d5cc65c438406149bef1bf4d52b68e03e3f8" - integrity sha1-k5TVzGXEOEBhSb7xv01Sto4D4/g= jest-cli@^20.0.4: version "20.0.4" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-20.0.4.tgz#e532b19d88ae5bc6c417e8b0593a6fe954b1dc93" - integrity sha1-5TKxnYiuW8bEF+iwWTpv6VSx3JM= dependencies: ansi-escapes "^1.4.0" callsites "^2.0.0" @@ -7938,7 +6941,6 @@ jest-cli@^20.0.4: jest-config@^20.0.4: version "20.0.4" resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-20.0.4.tgz#e37930ab2217c913605eff13e7bd763ec48faeea" - integrity sha1-43kwqyIXyRNgXv8T5712PsSPruo= dependencies: chalk "^1.1.3" glob "^7.1.1" @@ -7954,7 +6956,6 @@ jest-config@^20.0.4: jest-diff@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-20.0.3.tgz#81f288fd9e675f0fb23c75f1c2b19445fe586617" - integrity sha1-gfKI/Z5nXw+yPHXxwrGURf5YZhc= dependencies: chalk "^1.1.3" diff "^3.2.0" @@ -7964,12 +6965,10 @@ jest-diff@^20.0.3: jest-docblock@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712" - integrity sha1-F76phDQswz2DxQ++FUXqDvqkRxI= jest-environment-jsdom@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-20.0.3.tgz#048a8ac12ee225f7190417713834bb999787de99" - integrity sha1-BIqKwS7iJfcZBBdxODS7mZeH3pk= dependencies: jest-mock "^20.0.3" jest-util "^20.0.3" @@ -7978,7 +6977,6 @@ jest-environment-jsdom@^20.0.3: jest-environment-node@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-20.0.3.tgz#d488bc4612af2c246e986e8ae7671a099163d403" - integrity sha1-1Ii8RhKvLCRumG6K52caCZFj1AM= dependencies: jest-mock "^20.0.3" jest-util "^20.0.3" @@ -7986,7 +6984,6 @@ jest-environment-node@^20.0.3: jest-haste-map@^20.0.4: version "20.0.5" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.0.5.tgz#abad74efb1a005974a7b6517e11010709cab9112" - integrity sha512-0IKAQjUvuZjMCNi/0VNQQF74/H9KB67hsHJqGiwTWQC6XO5Azs7kLWm+6Q/dwuhvDUvABDOBMFK2/FwZ3sZ07Q== dependencies: fb-watchman "^2.0.0" graceful-fs "^4.1.11" @@ -7998,7 +6995,6 @@ jest-haste-map@^20.0.4: jest-jasmine2@^20.0.4: version "20.0.4" resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-20.0.4.tgz#fcc5b1411780d911d042902ef1859e852e60d5e1" - integrity sha1-/MWxQReA2RHQQpAu8YWehS5g1eE= dependencies: chalk "^1.1.3" graceful-fs "^4.1.11" @@ -8013,7 +7009,6 @@ jest-jasmine2@^20.0.4: jest-matcher-utils@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-20.0.3.tgz#b3a6b8e37ca577803b0832a98b164f44b7815612" - integrity sha1-s6a443yld4A7CDKpixZPRLeBVhI= dependencies: chalk "^1.1.3" pretty-format "^20.0.3" @@ -8021,7 +7016,6 @@ jest-matcher-utils@^20.0.3: jest-matchers@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-matchers/-/jest-matchers-20.0.3.tgz#ca69db1c32db5a6f707fa5e0401abb55700dfd60" - integrity sha1-ymnbHDLbWm9wf6XgQBq7VXAN/WA= dependencies: jest-diff "^20.0.3" jest-matcher-utils "^20.0.3" @@ -8031,7 +7025,6 @@ jest-matchers@^20.0.3: jest-message-util@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-20.0.3.tgz#6aec2844306fcb0e6e74d5796c1006d96fdd831c" - integrity sha1-auwoRDBvyw5udNV5bBAG2W/dgxw= dependencies: chalk "^1.1.3" micromatch "^2.3.11" @@ -8040,24 +7033,20 @@ jest-message-util@^20.0.3: jest-mock@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-20.0.3.tgz#8bc070e90414aa155c11a8d64c869a0d5c71da59" - integrity sha1-i8Bw6QQUqhVcEajWTIaaDVxx2lk= jest-regex-util@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-20.0.3.tgz#85bbab5d133e44625b19faf8c6aa5122d085d762" - integrity sha1-hburXRM+RGJbGfr4xqpRItCF12I= jest-resolve-dependencies@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-20.0.3.tgz#6e14a7b717af0f2cb3667c549de40af017b1723a" - integrity sha1-bhSntxevDyyzZnxUneQK8Bexcjo= dependencies: jest-regex-util "^20.0.3" jest-resolve@^20.0.4: version "20.0.4" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-20.0.4.tgz#9448b3e8b6bafc15479444c6499045b7ffe597a5" - integrity sha1-lEiz6La6/BVHlETGSZBFt//ll6U= dependencies: browser-resolve "^1.11.2" is-builtin-module "^1.0.0" @@ -8066,7 +7055,6 @@ jest-resolve@^20.0.4: jest-runtime@^20.0.4: version "20.0.4" resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-20.0.4.tgz#a2c802219c4203f754df1404e490186169d124d8" - integrity sha1-osgCIZxCA/dU3xQE5JAYYWnRJNg= dependencies: babel-core "^6.0.0" babel-jest "^20.0.3" @@ -8087,7 +7075,6 @@ jest-runtime@^20.0.4: jest-snapshot@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-20.0.3.tgz#5b847e1adb1a4d90852a7f9f125086e187c76566" - integrity sha1-W4R+GtsaTZCFKn+fElCG4YfHZWY= dependencies: chalk "^1.1.3" jest-diff "^20.0.3" @@ -8099,7 +7086,6 @@ jest-snapshot@^20.0.3: jest-util@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-20.0.3.tgz#0c07f7d80d82f4e5a67c6f8b9c3fe7f65cfd32ad" - integrity sha1-DAf32A2C9OWmfG+LnD/n9lz9Mq0= dependencies: chalk "^1.1.3" graceful-fs "^4.1.11" @@ -8112,7 +7098,6 @@ jest-util@^20.0.3: jest-validate@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-20.0.3.tgz#d0cfd1de4f579f298484925c280f8f1d94ec3cab" - integrity sha1-0M/R3k9XnymEhJJcKA+PHZTsPKs= dependencies: chalk "^1.1.3" jest-matcher-utils "^20.0.3" @@ -8122,19 +7107,16 @@ jest-validate@^20.0.3: jest@^20.0.4: version "20.0.4" resolved "https://registry.yarnpkg.com/jest/-/jest-20.0.4.tgz#3dd260c2989d6dad678b1e9cc4d91944f6d602ac" - integrity sha1-PdJgwpidba1nix6cxNkZRPbWAqw= dependencies: jest-cli "^20.0.4" jmespath@0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" - integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc= joi@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/joi/-/joi-9.2.0.tgz#3385ac790192130cbe230e802ec02c9215bbfeda" - integrity sha1-M4WseQGSEwy+Iw6ALsAskhW7/to= dependencies: hoek "4.x.x" isemail "2.x.x" @@ -8145,22 +7127,18 @@ joi@^9.2.0: js-base64@^2.1.9: version "2.4.0" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.0.tgz#9e566fee624751a1d720c966cd6226d29d4025aa" - integrity sha512-Wehd+7Pf9tFvGb+ydPm9TjYjV8X1YHOVyG8QyELZxEMqOhemVwGRmoG8iQ/soqI3n8v4xn59zaLxiCJiaaRzKA== js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.12.0, js-yaml@^3.9.1: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" - integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -8168,7 +7146,6 @@ js-yaml@^3.12.0, js-yaml@^3.9.1: js-yaml@^3.7.0, js-yaml@^3.9.0: version "3.10.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" - integrity sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -8176,12 +7153,10 @@ js-yaml@^3.7.0, js-yaml@^3.9.0: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsdom@^9.12.0: version "9.12.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.12.0.tgz#e8c546fffcb06c00d4833ca84410fed7f8a097d4" - integrity sha1-6MVG//ywbADUgzyoRBD+1/igl9Q= dependencies: abab "^1.0.3" acorn "^4.0.4" @@ -8206,98 +7181,80 @@ jsdom@^9.12.0: jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= jsesc@^2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" - integrity sha1-5CGiqOINawgZ3yiQj3glJrlt0f4= jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-parse-better-errors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" - integrity sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw== json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= dependencies: jsonify "~0.0.0" json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json3@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== dependencies: minimist "^1.2.0" jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= optionalDependencies: graceful-fs "^4.1.6" jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: assert-plus "1.0.0" extsprintf "1.3.0" @@ -8307,45 +7264,38 @@ jsprim@^1.2.2: jss-camel-case@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/jss-camel-case/-/jss-camel-case-6.1.0.tgz#ccb1ff8d6c701c02a1fed6fb6fb6b7896e11ce44" - integrity sha512-HPF2Q7wmNW1t79mCqSeU2vdd/vFFGpkazwvfHMOhPlMgXrJDzdj9viA2SaHk9ZbD5pfL63a8ylp4++irYbbzMQ== dependencies: hyphenate-style-name "^1.0.2" jss-compose@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/jss-compose/-/jss-compose-5.0.0.tgz#ce01b2e4521d65c37ea42cf49116e5f7ab596484" - integrity sha512-YofRYuiA0+VbeOw0VjgkyO380sA4+TWDrW52nSluD9n+1FWOlDzNbgpZ/Sb3Y46+DcAbOS21W5jo6SAqUEiuwA== dependencies: warning "^3.0.0" jss-default-unit@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/jss-default-unit/-/jss-default-unit-8.0.2.tgz#cc1e889bae4c0b9419327b314ab1c8e2826890e6" - integrity sha512-WxNHrF/18CdoAGw2H0FqOEvJdREXVXLazn7PQYU7V6/BWkCV0GkmWsppNiExdw8dP4TU1ma1dT9zBNJ95feLmg== jss-global@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/jss-global/-/jss-global-3.0.0.tgz#e19e5c91ab2b96353c227e30aa2cbd938cdaafa2" - integrity sha512-wxYn7vL+TImyQYGAfdplg7yaxnPQ9RaXY/cIA8hawaVnmmWxDHzBK32u1y+RAvWboa3lW83ya3nVZ/C+jyjZ5Q== jss-isolate@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/jss-isolate/-/jss-isolate-5.1.0.tgz#8eff1294c3659f86535852f4aeb79370743d890e" - integrity sha512-8OVa/SObXRMaKvFeCqzpDOZY8So4fAcTH0K6LsITiYpEQNABICSx1NCmubnt/JbPQaqnnQsF5F47uG86uQ9ZRA== dependencies: css-initials "^0.2.0" jss-nested@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/jss-nested/-/jss-nested-6.0.1.tgz#ef992b79d6e8f63d939c4397b9d99b5cbbe824ca" - integrity sha512-rn964TralHOZxoyEgeq3hXY8hyuCElnvQoVrQwKHVmu55VRDd6IqExAx9be5HgK0yN/+hQdgAXQl/GUrBbbSTA== dependencies: warning "^3.0.0" jss@^9.8.7: version "9.8.7" resolved "https://registry.yarnpkg.com/jss/-/jss-9.8.7.tgz#ed9763fc0f2f0260fc8260dac657af61e622ce05" - integrity sha512-awj3XRZYxbrmmrx9LUSj5pXSUfm12m8xzi/VKeqI1ZwWBtQ0kVPTs3vYs32t4rFw83CgFDukA8wKzOE9sMQnoQ== dependencies: is-in-browser "^1.1.3" symbol-observable "^1.1.0" @@ -8354,82 +7304,68 @@ jss@^9.8.7: jsx-ast-utils@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f" - integrity sha1-6AGxs5mF4g//yHtA43SAgOLcrH8= dependencies: array-includes "^3.0.3" kebab-case@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/kebab-case/-/kebab-case-1.0.0.tgz#3f9e4990adcad0c686c0e701f7645868f75f91eb" - integrity sha1-P55JkK3K0MaGwOcB92RYaPdfkes= kefir@^3.7.3: version "3.8.3" resolved "https://registry.yarnpkg.com/kefir/-/kefir-3.8.3.tgz#8e0ab10084ed8a01cbb5d4f7f18a0b859f7b9bd9" - integrity sha512-HMxsCDX2IzAU6Oj+7Uex8ysK9rl1OKH7D583CXZ0yjScuqeq+CA34nP+SX2Mx3gqKeriOKPWMaKL04Maw9K2xg== dependencies: symbol-observable "1.0.4" keyboardevent-from-electron-accelerator@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/keyboardevent-from-electron-accelerator/-/keyboardevent-from-electron-accelerator-1.1.0.tgz#324614f6e33490c37ffc5be5876b3e85fe223c84" - integrity sha512-VDC4vKWGrR3VgIKCE4CsXnvObGgP8C2idnTKEMUkuEuvDGE1GEBX9FtNdJzrD00iQlhI3xFxRaeItsUmlERVng== keyboardevents-areequal@^0.2.1: version "0.2.2" resolved "https://registry.yarnpkg.com/keyboardevents-areequal/-/keyboardevents-areequal-0.2.2.tgz#88191ec738ce9f7591c25e9056de928b40277194" - integrity sha512-Nv+Kr33T0mEjxR500q+I6IWisOQ0lK1GGOncV0kWE6n4KFmpcu7RUX5/2B0EUtX51Cb0HjZ9VJsSY3u4cBa0kw== killable@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.0.tgz#da8b84bd47de5395878f95d64d02f2449fe05e6b" - integrity sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms= kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0, kind-of@^5.0.2: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== kleur@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300" - integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ== known-css-properties@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.5.0.tgz#6ff66943ed4a5b55657ee095779a91f4536f8084" - integrity sha512-LOS0CoS8zcZnB1EjLw4LLqDXw8nvt3AGH5dXLQP3D9O1nLLA+9GC5GnPl5mmF+JiQAtSX4VyZC7KvEtcA4kUtA== kuler@1.0.x: version "1.0.0" resolved "https://registry.yarnpkg.com/kuler/-/kuler-1.0.0.tgz#904ad31c373b781695854d32be33818bf1d60250" - integrity sha512-oyy6pu/yWRjiVfCoJebNUKFL061sNtrs9ejKTbirIwY3oiHmENVCSkHhxDV85Dkm7JYR/czMCBeoM87WilTdSg== dependencies: colornames "^1.1.1" last-call-webpack-plugin@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" - integrity sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w== dependencies: lodash "^4.17.5" webpack-sources "^1.1.0" @@ -8437,45 +7373,38 @@ last-call-webpack-plugin@^3.0.0: latest-version@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" - integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU= dependencies: package-json "^4.0.0" lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= lazy-cache@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" - integrity sha1-uRkKT5EzVGlIQIWfio9whNiCImQ= dependencies: set-getter "^0.1.0" lazy-val@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc" - integrity sha512-pjCf3BYk+uv3ZcPzEVM0BFvO9Uw58TmlrU0oG5tTrr9Kcid3+kdKxapH8CjdYmVa2nO5wOoZn2rdvZx2PKj/xg== lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= dependencies: invert-kv "^1.0.0" lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" - integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== dependencies: invert-kv "^2.0.0" lerna@^3.0.0-beta.21: version "3.0.0-beta.21" resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.0.0-beta.21.tgz#866252f70e5e6d95faab8eca193fd66488cc6d1b" - integrity sha512-dSMbr+Zho9zBR8UyHB+8NLu0dwjzkJ3l0nU8W8v+Aoe5bD1rSsXwUpVX7rwJNTXAqe474BmpAjrmV0gcFjEAXA== dependencies: "@lerna/cli" "^3.0.0-beta.21" import-local "^1.0.0" @@ -8484,12 +7413,10 @@ lerna@^3.0.0-beta.21: leven@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" - integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" @@ -8497,17 +7424,14 @@ levn@^0.3.0, levn@~0.3.0: listenercount@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937" - integrity sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc= listify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/listify/-/listify-1.0.0.tgz#03ca7ba2d150d4267773f74e57558d1053d2bee3" - integrity sha1-A8p7otFQ1CZ3c/dOV1WNEFPSvuM= load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -8518,7 +7442,6 @@ load-json-file@^1.0.0: load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" @@ -8528,7 +7451,6 @@ load-json-file@^2.0.0: load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= dependencies: graceful-fs "^4.1.2" parse-json "^4.0.0" @@ -8538,12 +7460,10 @@ load-json-file@^4.0.0: loader-runner@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" - integrity sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI= loader-utils@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.0.4.tgz#13f56197f1523a305891248b4c7244540848426c" - integrity sha1-E/Vhl/FSOjBYkSSLTHJEVAhIQmw= dependencies: big.js "^3.1.3" emojis-list "^2.0.0" @@ -8552,7 +7472,6 @@ loader-utils@1.0.x: loader-utils@1.1.0, loader-utils@^1.0.0, loader-utils@^1.0.2, loader-utils@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" - integrity sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0= dependencies: big.js "^3.1.3" emojis-list "^2.0.0" @@ -8561,7 +7480,6 @@ loader-utils@1.1.0, loader-utils@^1.0.0, loader-utils@^1.0.2, loader-utils@^1.1. loader-utils@^0.2.16: version "0.2.17" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" - integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= dependencies: big.js "^3.1.3" emojis-list "^2.0.0" @@ -8571,7 +7489,6 @@ loader-utils@^0.2.16: locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -8579,7 +7496,6 @@ locate-path@^2.0.0: locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== dependencies: p-locate "^3.0.0" path-exists "^3.0.0" @@ -8587,67 +7503,54 @@ locate-path@^3.0.0: lodash-es@^4.17.4, lodash-es@^4.2.0, lodash-es@^4.2.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7" - integrity sha1-3MHXVS4VCgZABzupyzHXDwMpUOc= lodash._reinterpolate@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= lodash.cond@^4.3.0: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" - integrity sha1-9HGh2khr5g9quVXRcRVSPdHSVdU= lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= lodash.map@^4.5.1: version "4.6.0" resolved "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" - integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= lodash.merge@^4.6.1: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54" - integrity sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ== lodash.template@^4.0.2, lodash.template@^4.2.4: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" - integrity sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A= dependencies: lodash._reinterpolate "~3.0.0" lodash.templatesettings "^4.0.0" @@ -8655,39 +7558,32 @@ lodash.template@^4.0.2, lodash.template@^4.2.4: lodash.templatesettings@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316" - integrity sha1-K01OlbpEDZFf8IvImeRVNmZxMxY= dependencies: lodash._reinterpolate "~3.0.0" lodash.topath@4.5.2: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.topath/-/lodash.topath-4.5.2.tgz#3616351f3bba61994a0931989660bd03254fd009" - integrity sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak= lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= lodash@^4.13.1, lodash@^4.14.0, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.6.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4= lodash@^4.16.6, lodash@^4.17.5: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" - integrity sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg== -lodash@^4.17.10: +lodash@^4.17.10, lodash@^4.17.11: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== log-fancy@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/log-fancy/-/log-fancy-1.3.2.tgz#0d328bef0e6dca3d8b3758179c8ff35f1cd3860b" - integrity sha512-8lYdFr4RfrB1b9222G9IGuLAqYugBAKuSvXXFFLEL1KrBgp0YeDv5RSTndMzC10t9slEyFvEZ4HvwszvH6A4Lg== dependencies: chalk "^2.1.0" debug "^3.0.0" @@ -8697,21 +7593,18 @@ log-fancy@1.3.2: log-symbols@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.1.0.tgz#f35fa60e278832b538dc4dddcbb478a45d3e3be6" - integrity sha512-zLeLrzMA1A2vRF1e/0Mo+LNINzi6jzBylHj5WqvQ/WK/5WCZt8si9SyN4p9llr/HRYvVR1AoXHRHl4WTHyQAzQ== dependencies: chalk "^2.0.1" log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== dependencies: chalk "^2.0.1" logform@^1.9.1: version "1.10.0" resolved "https://registry.yarnpkg.com/logform/-/logform-1.10.0.tgz#c9d5598714c92b546e23f4e78147c40f1e02012e" - integrity sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg== dependencies: colors "^1.2.1" fast-safe-stringify "^2.0.4" @@ -8722,36 +7615,30 @@ logform@^1.9.1: loglevel@^1.4.1: version "1.6.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" - integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po= longest-streak@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e" - integrity sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA== longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" - integrity sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg= dependencies: js-tokens "^3.0.0" loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lost@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/lost/-/lost-8.2.0.tgz#107d0733b286029a3587bc1230f98d2a6eb21ef7" - integrity sha512-oslLiTJOpsT1d6WxjOGiYFpyf8u8klRdcJUTLnUubaB11NvjqY+SpAojApT0+o+WWp+CNjJ4KIL49lYpFjLplQ== dependencies: object-assign "^4.1.0" postcss "^6.0.6" @@ -8759,7 +7646,6 @@ lost@^8.2.0: loud-rejection@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= dependencies: currently-unhandled "^0.4.1" signal-exit "^3.0.0" @@ -8767,22 +7653,18 @@ loud-rejection@^1.0.0: lower-case@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" - integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= lowercase-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" - integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY= lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== lru-cache@^4.0.1, lru-cache@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" - integrity sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -8790,7 +7672,6 @@ lru-cache@^4.0.1, lru-cache@^4.1.1: lru-cache@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" - integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -8798,67 +7679,56 @@ lru-cache@^4.1.3: magic-string@^0.22.4: version "0.22.4" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.4.tgz#31039b4e40366395618c1d6cf8193c53917475ff" - integrity sha512-kxBL06p6iO2qPBHsqGK2b3cRwiRGpnmSuVWNhwHcMX7qJOUr1HvricYP1LZOCdkQBUp0jiWg2d6WJwR3vYgByw== dependencies: vlq "^0.2.1" make-dir@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.1.0.tgz#19b4369fe48c116f53c2af95ad102c0e39e85d51" - integrity sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA== dependencies: pify "^3.0.0" makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" - integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= dependencies: tmpl "1.0.x" map-age-cleaner@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz#098fb15538fd3dbe461f12745b0ca8568d4e3f74" - integrity sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ== dependencies: p-defer "^1.0.0" map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= map-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" - integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" markdown-escapes@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.1.tgz#1994df2d3af4811de59a6714934c2b2292734518" - integrity sha1-GZTfLTr0gR3lmmcUk0wrIpJzRRg= markdown-table@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.1.tgz#4b3dd3a133d1518b8ef0dbc709bf2a1b4824bc8c" - integrity sha1-Sz3ToTPRUYuO8NvHCb8qG0gkvIw= markdown-to-jsx@^6.8.3: version "6.8.3" resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.8.3.tgz#c9c157e50ba680626700ffd2452bd01eb909eb7d" - integrity sha512-I/kRZDvHFMEoKCjFS119v6Op4R1wZJEUEwhWSNtsE7WHRVcxKrLZ9vApvNb1j80MAFIY4/e4m1f4vIwSgKUZ8g== dependencies: prop-types "^15.6.2" unquote "^1.1.0" @@ -8866,17 +7736,14 @@ markdown-to-jsx@^6.8.3: math-expression-evaluator@^1.2.14: version "1.2.17" resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" - integrity sha1-3oGf282E3M2PrlnGrreWFbnSZqw= mathml-tag-names@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.0.1.tgz#8d41268168bf86d1102b98109e28e531e7a34578" - integrity sha1-jUEmgWi/htEQK5gQnijlMeejRXg= md5.js@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" - integrity sha1-6b296UogpawYsENA/Fdk1bCdkB0= dependencies: hash-base "^3.0.0" inherits "^2.0.1" @@ -8884,7 +7751,6 @@ md5.js@^1.3.4: md5@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" - integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk= dependencies: charenc "~0.0.1" crypt "~0.0.1" @@ -8893,7 +7759,6 @@ md5@^2.1.0: mdast-util-compact@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz#cdb5f84e2b6a2d3114df33bd05d9cb32e3c4083a" - integrity sha1-zbX4TitqLTEU3zO9BdnLMuPECDo= dependencies: unist-util-modify-children "^1.0.0" unist-util-visit "^1.1.0" @@ -8901,14 +7766,12 @@ mdast-util-compact@^1.0.0: mdast-util-definitions@^1.2.0: version "1.2.3" resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-1.2.3.tgz#49f936b09207c45b438db19551652934312f04f0" - integrity sha512-P6wpRO8YVQ1iv30maMc93NLh7COvufglBE8/ldcOyYmk5EbfF0YeqlLgtqP/FOBU501Kqar1x5wYWwB3Nga74g== dependencies: unist-util-visit "^1.0.0" mdast-util-to-hast@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-3.0.2.tgz#26b1971f49d6db1e3428463a12e66c89db5021cb" - integrity sha512-YI8Ea3TFWEZrS31+6Q/d8ZYTOSDKM06IPc3l2+OMFX1o3JTG2mrztlmzDsUMwIXLWofEdTVl/WXBgRG6ddlU/A== dependencies: collapse-white-space "^1.0.0" detab "^2.0.0" @@ -8925,12 +7788,10 @@ mdast-util-to-hast@^3.0.0: mdn-data@~1.1.0: version "1.1.4" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" - integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== mdns-js@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mdns-js/-/mdns-js-1.0.1.tgz#89a0fd4d85dc6c7630da39d56fc88420bb357867" - integrity sha512-dwEtMzmoZCQcGlr004J4m2+W6dCMpCoGQ5kYIEY+7rMPdMM7ztT+1qD9ExmottvLGgbqAVsjllhwU8PyusecPg== dependencies: debug "^3.1.0" dns-js "~0.2.1" @@ -8939,24 +7800,20 @@ mdns-js@^1.0.1: mdurl@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= dependencies: mimic-fn "^1.0.0" mem@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf" - integrity sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA== dependencies: map-age-cleaner "^0.1.1" mimic-fn "^1.0.0" @@ -8965,12 +7822,10 @@ mem@^4.0.0: memoize-one@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-4.0.2.tgz#3fb8db695aa14ab9c0f1644e1585a8806adc1aee" - integrity sha512-ucx2DmXTeZTsS4GPPUZCbULAN7kdPT1G+H49Y34JjbQ5ESc6OGhVxKvb1iKhr9v19ZB9OtnHwNnhUnNR/7Wteg== memory-fs@^0.4.0, memory-fs@~0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= dependencies: errno "^0.1.3" readable-stream "^2.0.1" @@ -8978,7 +7833,6 @@ memory-fs@^0.4.0, memory-fs@~0.4.1: meow@^3.1.0, meow@^3.3.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= dependencies: camelcase-keys "^2.0.0" decamelize "^1.1.2" @@ -8994,7 +7848,6 @@ meow@^3.1.0, meow@^3.3.0: meow@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/meow/-/meow-4.0.0.tgz#fd5855dd008db5b92c552082db1c307cba20b29d" - integrity sha512-Me/kel335m6vMKmEmA6c87Z6DUFW3JqkINRnxkbC+A/PUm0D5Fl2dEBQrPKnqCL9Te/CIa1MUt/0InMJhuC/sw== dependencies: camelcase-keys "^4.0.0" decamelize-keys "^1.0.0" @@ -9009,34 +7862,28 @@ meow@^4.0.0: merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= merge-options@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz#2a64b24457becd4e4dc608283247e94ce589aa32" - integrity sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg== dependencies: is-plain-obj "^1.1" merge2@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.2.tgz#03212e3da8d86c4d8523cebd6318193414f94e34" - integrity sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg== merge@^1.1.3: version "1.2.0" resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" - integrity sha1-dTHjnUlJwoGma4xabgJl6LBYlNo= methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= micromatch@3.1.10, micromatch@^3.1.10, micromatch@^3.1.8, micromatch@^3.1.9: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -9055,7 +7902,6 @@ micromatch@3.1.10, micromatch@^3.1.10, micromatch@^3.1.8, micromatch@^3.1.9: micromatch@^2.1.5, micromatch@^2.3.11: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= dependencies: arr-diff "^2.0.0" array-unique "^0.2.1" @@ -9074,7 +7920,6 @@ micromatch@^2.1.5, micromatch@^2.3.11: micromatch@^3.1.4: version "3.1.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.5.tgz#d05e168c206472dfbca985bfef4f57797b4cd4ba" - integrity sha512-ykttrLPQrz1PUJcXjwsTUjGoPJ64StIGNE2lGVD1c9CuguJ+L7/navsE8IcDNndOoCMvYV0qc/exfVbMHkUhvA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -9093,7 +7938,6 @@ micromatch@^3.1.4: miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" brorand "^1.0.1" @@ -9101,75 +7945,62 @@ miller-rabin@^4.0.0: "mime-db@>= 1.30.0 < 2": version "1.32.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.32.0.tgz#485b3848b01a3cda5f968b4882c0771e58e09414" - integrity sha512-+ZWo/xZN40Tt6S+HyakUxnSOgff+JEdaneLWIm0Z6LmpCn5DMcZntLyUY5c/rTDog28LhXLKOUZKoTxTCAdBVw== mime-db@~1.30.0: version "1.30.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" - integrity sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE= mime-db@~1.36.0: version "1.36.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" - integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw== mime-db@~1.37.0: version "1.37.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" - integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg== mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.7: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" - integrity sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo= dependencies: mime-db "~1.30.0" mime-types@~2.1.18: version "2.1.21" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" - integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg== dependencies: mime-db "~1.37.0" mime-types@~2.1.19: version "2.1.20" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" - integrity sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A== dependencies: mime-db "~1.36.0" mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== mime@^2.0.3, mime@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369" - integrity sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg== mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" - integrity sha1-5md4PZLonb00KBi1IwudYqZyrRg= mimic-response@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e" - integrity sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4= min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= dependencies: dom-walk "^0.1.0" mini-css-extract-plugin@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.4.tgz#c10410a004951bd3cedac1da69053940fccb625d" - integrity sha512-o+Jm+ocb0asEngdM6FsZWtZsRzA8koFUudIDwYUfl94M3PejPHG7Vopw5hN9V8WsMkSFpm3tZP3Fesz89EyrfQ== dependencies: loader-utils "^1.1.0" schema-utils "^1.0.0" @@ -9178,31 +8009,26 @@ mini-css-extract-plugin@^0.4.4: mini-html-webpack-plugin@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/mini-html-webpack-plugin/-/mini-html-webpack-plugin-0.2.3.tgz#2dfbdc3f35f6ae03864a608808381f8137311ea0" - integrity sha512-wfkLf+CmyDg++K1S0QdAvUvS29DfVHe9SQ63syX8aX375mInzC5uwHxb/1+3exiiv84xnPrf6zsOnReRe15rjg== dependencies: webpack-sources "^1.1.0" minimalistic-assert@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3" - integrity sha1-cCvi3aazf0g2vLP121ZkG2Sh09M= minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimist-options@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" - integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ== dependencies: arrify "^1.0.1" is-plain-obj "^1.1.0" @@ -9210,32 +8036,26 @@ minimist-options@^3.0.1: minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= minimist@1.1.x: version "1.1.3" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" - integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= minimist@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de" - integrity sha1-md9lelJXTCHJBXSX33QnkLK0wN4= minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= minipass@^2.2.1, minipass@^2.3.3: version "2.3.5" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" @@ -9243,14 +8063,12 @@ minipass@^2.2.1, minipass@^2.3.3: minizlib@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42" - integrity sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg== dependencies: minipass "^2.2.1" mississippi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f" - integrity sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw== dependencies: concat-stream "^1.5.0" duplexify "^3.4.2" @@ -9266,7 +8084,6 @@ mississippi@^2.0.0: mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" - integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== dependencies: concat-stream "^1.5.0" duplexify "^3.4.2" @@ -9282,7 +8099,6 @@ mississippi@^3.0.0: mixin-deep@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.0.tgz#47a8732ba97799457c8c1eca28f95132d7e8150a" - integrity sha512-dgaCvoh6i1nosAUBKb0l0pfJ78K8+S9fluyIR2YvAeUD/QuMahnFnF3xYty5eYXMjhGSsB0DsW6A0uAZyetoAg== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" @@ -9290,41 +8106,34 @@ mixin-deep@^1.2.0: mixpanel-browser@^2.22.1: version "2.22.1" resolved "https://registry.npmjs.org/mixpanel-browser/-/mixpanel-browser-2.22.1.tgz#de9a80ee68982fecbae3d9b9b22b06d2c37b5a3f" - integrity sha512-rzrej3V+G3e0wqnRJMhj0X5aTwIsGYfTxymshAdB71mwABIgAkBLWM+grlt7I/AXtwvV0gO6jYAy96A9kCghtw== mkdirp@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" - integrity sha1-HXMHam35hs2TROFecfzAWkyavxI= dependencies: minimist "0.0.8" mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" - integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== moment@2.x.x, moment@^2.19.1: version "2.20.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd" - integrity sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg== moment@^2.6.0: version "2.22.2" resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" - integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y= move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= dependencies: aproba "^1.1.1" copy-concurrently "^1.0.0" @@ -9336,22 +8145,18 @@ move-concurrently@^1.0.1: ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== multicast-dns-service-types@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= multicast-dns@^6.0.1: version "6.2.1" resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.1.tgz#c5035defa9219d30640558a49298067352098060" - integrity sha512-uV3/ckdsffHx9IrGQrx613mturMdMqQ06WTq+C09NsStJ9iNG6RcUWgPKs1Rfjy+idZT6tfQoXEusGNnEZhT3w== dependencies: dns-packet "^1.0.1" thunky "^0.1.0" @@ -9359,7 +8164,6 @@ multicast-dns@^6.0.1: multimatch@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= dependencies: array-differ "^1.0.0" array-union "^1.0.1" @@ -9369,22 +8173,18 @@ multimatch@^2.1.0: mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= nan@^2.3.0: version "2.8.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" - integrity sha1-7XFfP+neArV6XmJS2QqWZ14fCFo= nan@^2.9.2: version "2.11.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" - integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== nanomatch@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.7.tgz#53cd4aa109ff68b7f869591fdc9d10daeeea3e79" - integrity sha512-/5ldsnyurvEw7wNpxLFgjVvBLMta43niEYOy0CJ4ntcYSbx6bugRUTQeFb4BR/WanEL1o3aQgHuVLHQaB6tOqg== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -9401,7 +8201,6 @@ nanomatch@^1.2.5: nanomatch@^1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2" - integrity sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -9419,19 +8218,16 @@ nanomatch@^1.2.9: natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= ncname@1.0.x: version "1.0.0" resolved "https://registry.yarnpkg.com/ncname/-/ncname-1.0.0.tgz#5b57ad18b1ca092864ef62b0b1ed8194f383b71c" - integrity sha1-W1etGLHKCShk72Kwse2BlPODtxw= dependencies: xml-char-classes "^1.0.0" needle@^2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== dependencies: debug "^2.1.2" iconv-lite "^0.4.4" @@ -9440,36 +8236,30 @@ needle@^2.2.1: negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= neo-async@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" - integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA== nice-try@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" - integrity sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA== no-case@^2.2.0: version "2.3.2" resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" - integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== dependencies: lower-case "^1.1.1" node-dir@^0.1.10: version "0.1.17" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" - integrity sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU= dependencies: minimatch "^3.0.2" node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== dependencies: encoding "^0.1.11" is-stream "^1.0.1" @@ -9477,17 +8267,14 @@ node-fetch@^1.0.1: node-fetch@^2.1.1, node-fetch@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" - integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U= node-forge@0.6.33: version "0.6.33" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.33.tgz#463811879f573d45155ad6a9f43dc296e8e85ebc" - integrity sha1-RjgRh59XPUUVWtap9D3ClujoXrw= node-gyp@^3.6.2: version "3.6.2" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60" - integrity sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA= dependencies: fstream "^1.0.0" glob "^7.0.3" @@ -9506,12 +8293,10 @@ node-gyp@^3.6.2: node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= node-libs-browser@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" - integrity sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg== dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -9540,7 +8325,6 @@ node-libs-browser@^2.0.0: node-notifier@^5.0.2: version "5.1.2" resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.1.2.tgz#2fa9e12605fa10009d44549d6fcd8a63dde0e4ff" - integrity sha1-L6nhJgX6EACdRFSdb82KY93g5P8= dependencies: growly "^1.3.0" semver "^5.3.0" @@ -9550,7 +8334,6 @@ node-notifier@^5.0.2: node-pre-gyp@^0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" - integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -9566,7 +8349,6 @@ node-pre-gyp@^0.10.0: node-pre-gyp@^0.6.39: version "0.6.39" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" - integrity sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ== dependencies: detect-libc "^1.0.2" hawk "3.1.3" @@ -9583,21 +8365,18 @@ node-pre-gyp@^0.6.39: node-releases@^1.0.0-alpha.11, node-releases@^1.0.0-alpha.15: version "1.0.0-alpha.15" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.0-alpha.15.tgz#bdb08730287cc50ddbfa3c1a358366a4a2f5d397" - integrity sha512-hKG6hd/g6a9OV/ARt2qrxbRhe/4WEMFohTLOB9PNyTYvvI59gICZFzt9/mMgpYUTts06qXlN8H6UjfbIRdnW8A== dependencies: semver "^5.3.0" "nopt@2 || 3": version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= dependencies: abbrev "1" nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= dependencies: abbrev "1" osenv "^0.1.4" @@ -9605,14 +8384,12 @@ nopt@^4.0.1: nopt@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= dependencies: abbrev "1" normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== dependencies: hosted-git-info "^2.1.4" is-builtin-module "^1.0.0" @@ -9622,34 +8399,28 @@ normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package- normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= normalize-selector@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" - integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= normalize-url@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" - integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" - integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== npm-lifecycle@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-2.0.3.tgz#696bedf1143371163e9cc16fe872357e25d8d90e" - integrity sha512-0U4Iim5ix2NHUT672G7FBpldJX0N2xKBjJqRTAzioEJjb6I6KpQXq+y1sB5EDSjKaAX8VCC9qPK31Jy+p3ix5A== dependencies: byline "^5.0.0" graceful-fs "^4.1.11" @@ -9663,7 +8434,6 @@ npm-lifecycle@^2.0.0: "npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1" - integrity sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA== dependencies: hosted-git-info "^2.6.0" osenv "^0.1.5" @@ -9673,7 +8443,6 @@ npm-lifecycle@^2.0.0: npm-packlist@^1.1.6: version "1.1.12" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" - integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -9681,14 +8450,12 @@ npm-packlist@^1.1.6: npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" "npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.2, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" console-control-strings "~1.1.0" @@ -9698,21 +8465,18 @@ npm-run-path@^2.0.0: nth-check@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== dependencies: boolbase "~1.0.0" nth-check@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" - integrity sha1-mSms32KPwsQQmN6rgqxYDPFJquQ= dependencies: boolbase "~1.0.0" nugget@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/nugget/-/nugget-2.0.1.tgz#201095a487e1ad36081b3432fa3cada4f8d071b0" - integrity sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA= dependencies: debug "^2.1.3" minimist "^1.1.0" @@ -9725,37 +8489,30 @@ nugget@^2.0.1: num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= "nwmatcher@>= 1.3.9 < 2.0.0": version "1.4.3" resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.3.tgz#64348e3b3d80f035b40ac11563d278f8b72db89c" - integrity sha512-IKdSTiDWCarf2JTS5e9e2+5tPZGdkRJ79XjYV0pzK8Q9BpsFyBq1RGKxzs7Q8UBushGw7m6TzVKz6fcY99iSWw== oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" @@ -9764,29 +8521,24 @@ object-copy@^0.1.0: object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" - integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== object-keys@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" - integrity sha1-xUYBd4rVYPEULODgG8yotW0TQm0= object-keys@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" object.getownpropertydescriptors@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= dependencies: define-properties "^1.1.2" es-abstract "^1.5.1" @@ -9794,7 +8546,6 @@ object.getownpropertydescriptors@^2.0.3: object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= dependencies: for-own "^0.1.4" is-extendable "^0.1.1" @@ -9802,14 +8553,12 @@ object.omit@^2.0.0: object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" object.values@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" - integrity sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo= dependencies: define-properties "^1.1.2" es-abstract "^1.6.1" @@ -9819,67 +8568,56 @@ object.values@^1.0.4: obuf@^1.0.0, obuf@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.1.tgz#104124b6c602c6796881a042541d36db43a5264e" - integrity sha1-EEEktsYCxnlogaBCVB0220OlJk4= on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= dependencies: ee-first "1.1.1" on-headers@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" - integrity sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c= once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" one-time@0.0.4: version "0.0.4" resolved "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz#f8cdf77884826fe4dff93e3a9cc37b1e4480742e" - integrity sha1-+M33eISCb+Tf+T46nMN7HkSAdC4= onecolor@^3.0.4: version "3.0.5" resolved "https://registry.yarnpkg.com/onecolor/-/onecolor-3.0.5.tgz#36eff32201379efdf1180fb445e51a8e2425f9f6" - integrity sha1-Nu/zIgE3nv3xGA+0ReUajiQl+fY= onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= dependencies: mimic-fn "^1.0.0" opener@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" - integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== opn@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.4.0.tgz#cb545e7aab78562beb11aa3bfabc7042e1761035" - integrity sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw== dependencies: is-wsl "^1.1.0" opn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519" - integrity sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg== dependencies: is-wsl "^1.1.0" optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= dependencies: minimist "~0.0.1" wordwrap "~0.0.2" @@ -9887,7 +8625,6 @@ optimist@^0.6.1: optimize-css-assets-webpack-plugin@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.1.tgz#9eb500711d35165b45e7fd60ba2df40cb3eb9159" - integrity sha512-Rqm6sSjWtx9FchdP0uzTQDc7GXDKnwVEGoSxjezPkzMewx7gEWE9IMUYKmigTRC4U3RaNSwYVnUDLuIdtTpm0A== dependencies: cssnano "^4.1.0" last-call-webpack-plugin "^3.0.0" @@ -9895,7 +8632,6 @@ optimize-css-assets-webpack-plugin@^5.0.1: optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.4" @@ -9907,7 +8643,6 @@ optionator@^0.8.1, optionator@^0.8.2: ora@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b" - integrity sha512-hNNlAd3gfv/iPmsNxYoAPLvxg7HuPozww7fFonMZvL84tP6Ox5igfk5j/+a9rtJJwqMgKK+JgWsAQik5o0HTLA== dependencies: chalk "^2.3.1" cli-cursor "^2.1.0" @@ -9919,38 +8654,32 @@ ora@^2.1.0: original@>=0.0.5: version "1.0.0" resolved "https://registry.yarnpkg.com/original/-/original-1.0.0.tgz#9147f93fa1696d04be61e01bd50baeaca656bd3b" - integrity sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs= dependencies: url-parse "1.0.x" original@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" - integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== dependencies: url-parse "^1.4.3" os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= os-locale@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= dependencies: lcid "^1.0.0" os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== dependencies: execa "^0.7.0" lcid "^1.0.0" @@ -9959,7 +8688,6 @@ os-locale@^2.0.0: os-locale@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.0.1.tgz#3b014fbf01d87f60a1e5348d80fe870dc82c4620" - integrity sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw== dependencies: execa "^0.10.0" lcid "^2.0.0" @@ -9968,12 +8696,10 @@ os-locale@^3.0.0: os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= osenv@0, osenv@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -9981,7 +8707,6 @@ osenv@0, osenv@^0.1.5: osenv@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" - integrity sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ= dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -9989,7 +8714,6 @@ osenv@^0.1.4: output-file-sync@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76" - integrity sha1-0KM+7+YaIF+suQCS6CZZjVJFznY= dependencies: graceful-fs "^4.1.4" mkdirp "^0.5.1" @@ -9998,96 +8722,80 @@ output-file-sync@^1.1.2: p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-is-promise@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" - integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4= p-limit@^1.0.0, p-limit@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" - integrity sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng== dependencies: p-try "^1.0.0" p-limit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" - integrity sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A== dependencies: p-try "^2.0.0" p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= dependencies: p-limit "^1.1.0" p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== dependencies: p-limit "^2.0.0" p-map-series@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" - integrity sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco= dependencies: p-reduce "^1.0.0" p-map@^1.1.1, p-map@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" - integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== p-reduce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" - integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= p-timeout@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= dependencies: p-finally "^1.0.0" p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= p-try@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" - integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ== p-waterfall@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-waterfall/-/p-waterfall-1.0.0.tgz#7ed94b3ceb3332782353af6aae11aa9fc235bb00" - integrity sha1-ftlLPOszMngjU69qrhGqn8I1uwA= dependencies: p-reduce "^1.0.0" package-json@^4.0.0, package-json@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" - integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0= dependencies: got "^6.7.1" registry-auth-token "^3.0.1" @@ -10097,12 +8805,10 @@ package-json@^4.0.0, package-json@^4.0.1: pako@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" - integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg== parallel-transform@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" - integrity sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY= dependencies: cyclist "~0.2.2" inherits "^2.0.3" @@ -10111,14 +8817,12 @@ parallel-transform@^1.1.0: param-case@2.1.x: version "2.1.1" resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" - integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= dependencies: no-case "^2.2.0" parse-asn1@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" - integrity sha1-N8T5t+06tlx0gXtfJICTf7+XxxI= dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -10129,14 +8833,12 @@ parse-asn1@^5.0.0: parse-color@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-color/-/parse-color-1.0.0.tgz#7b748b95a83f03f16a94f535e52d7f3d94658619" - integrity sha1-e3SLlag/A/FqlPU15S1/PZRlhhk= dependencies: color-convert "~0.5.0" parse-entities@^1.0.2: version "1.1.1" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.1.tgz#8112d88471319f27abae4d64964b122fe4e1b890" - integrity sha1-gRLYhHExnyerrk1klksSL+ThuJA= dependencies: character-entities "^1.0.0" character-entities-legacy "^1.0.0" @@ -10148,7 +8850,6 @@ parse-entities@^1.0.2: parse-entities@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.2.tgz#9eaf719b29dc3bd62246b4332009072e01527777" - integrity sha512-5N9lmQ7tmxfXf+hO3X6KRG6w7uYO/HL9fHalSySTdyn63C3WNvTM/1R8tn1u1larNcEbo3Slcy2bsVDQqvEpUg== dependencies: character-entities "^1.0.0" character-entities-legacy "^1.0.0" @@ -10160,12 +8861,10 @@ parse-entities@^1.1.0: parse-github-repo-url@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50" - integrity sha1-nn2LslKmy2ukJZUGC3v23z28H1A= parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= dependencies: glob-base "^0.3.0" is-dotfile "^1.0.0" @@ -10175,21 +8874,18 @@ parse-glob@^3.0.4: parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= dependencies: error-ex "^1.2.0" parse-json@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-3.0.0.tgz#fa6f47b18e23826ead32f263e744d0e1e847fb13" - integrity sha1-+m9HsY4jgm6tMvJj50TQ4ehH+xM= dependencies: error-ex "^1.3.1" parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= dependencies: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" @@ -10197,81 +8893,66 @@ parse-json@^4.0.0: parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= parse5@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94" - integrity sha1-m387DeMr543CQBsXVzzK8Pb1nZQ= parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= dependencies: pinkie-promise "^2.0.0" path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" - integrity sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME= path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= path-to-regexp@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" - integrity sha1-Wf3g9DW62suhA6hOnTvGTpa5k30= dependencies: isarray "0.0.1" path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= dependencies: graceful-fs "^4.1.2" pify "^2.0.0" @@ -10280,21 +8961,18 @@ path-type@^1.0.0: path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= dependencies: pify "^2.0.0" path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== dependencies: pify "^3.0.0" pbkdf2@^3.0.3: version "3.0.14" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade" - integrity sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -10305,44 +8983,36 @@ pbkdf2@^3.0.3: pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - integrity sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU= performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pixrem@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/pixrem/-/pixrem-4.0.1.tgz#2da4a1de6ec4423c5fc3794e930b81d4490ec686" - integrity sha1-LaSh3m7EQjxfw3lOkwuB1EkOxoY= dependencies: browserslist "^2.0.0" postcss "^6.0.0" @@ -10351,35 +9021,30 @@ pixrem@^4.0.0: pkg-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= dependencies: find-up "^1.0.0" pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= dependencies: find-up "^2.1.0" pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== dependencies: find-up "^3.0.0" pkg-up@2.0.0, pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" - integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= dependencies: find-up "^2.1.0" pleeease-filters@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/pleeease-filters/-/pleeease-filters-4.0.0.tgz#6632b2fb05648d2758d865384fbced79e1ccaec7" - integrity sha1-ZjKy+wVkjSdY2GU4T7zteeHMrsc= dependencies: onecolor "^3.0.4" postcss "^6.0.1" @@ -10387,7 +9052,6 @@ pleeease-filters@^4.0.0: plist@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/plist/-/plist-2.1.0.tgz#57ccdb7a0821df21831217a3cad54e3e146a1025" - integrity sha1-V8zbeggh3yGDEhejytVOPhRqECU= dependencies: base64-js "1.2.0" xmlbuilder "8.2.2" @@ -10396,7 +9060,6 @@ plist@^2.1.0: plist@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" - integrity sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ== dependencies: base64-js "^1.2.3" xmlbuilder "^9.0.7" @@ -10405,17 +9068,14 @@ plist@^3.0.1: pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== popper.js@^1.14.1: version "1.14.3" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" - integrity sha1-FDj5jQRqz3tNeM1QK/QYrGTU8JU= portfinder@^1.0.13, portfinder@^1.0.9: version "1.0.13" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9" - integrity sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek= dependencies: async "^1.5.2" debug "^2.2.0" @@ -10424,12 +9084,10 @@ portfinder@^1.0.13, portfinder@^1.0.9: posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-apply@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/postcss-apply/-/postcss-apply-0.8.0.tgz#14e544bbb5cb6f1c1e048857965d79ae066b1343" - integrity sha1-FOVEu7XLbxweBIhXll15rgZrE0M= dependencies: babel-runtime "^6.23.0" balanced-match "^0.4.2" @@ -10438,7 +9096,6 @@ postcss-apply@^0.8.0: postcss-attribute-case-insensitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-2.0.0.tgz#94dc422c8f90997f16bd33a3654bbbec084963b4" - integrity sha1-lNxCLI+QmX8WvTOjZUu77AhJY7Q= dependencies: postcss "^6.0.0" postcss-selector-parser "^2.2.3" @@ -10446,7 +9103,6 @@ postcss-attribute-case-insensitive@^2.0.0: postcss-calc@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-6.0.1.tgz#3d24171bbf6e7629d422a436ebfe6dd9511f4330" - integrity sha1-PSQXG79udinUIqQ26/5t2VEfQzA= dependencies: css-unit-converter "^1.1.1" postcss "^6.0.0" @@ -10456,7 +9112,6 @@ postcss-calc@^6.0.0: postcss-calc@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.0.tgz#cf0e78e1d7d9f75119b833abc786fa4b61afedda" - integrity sha512-o04XICBwDxXVYw1TXkzxs36WRgk9OECGiSUoyYMNoFWHLAQCKKeaqhrNBTUKdStMfwik3gSLLztHebTSV5kJOA== dependencies: css-unit-converter "^1.1.1" postcss "^7.0.2" @@ -10466,7 +9121,6 @@ postcss-calc@^7.0.0: postcss-color-function@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-color-function/-/postcss-color-function-4.0.1.tgz#402b3f2cebc3f6947e618fb6be3654fbecef6444" - integrity sha1-QCs/LOvD9pR+YY+2vjZU++zvZEQ= dependencies: css-color-function "~1.3.3" postcss "^6.0.1" @@ -10476,7 +9130,6 @@ postcss-color-function@^4.0.0: postcss-color-gray@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-4.1.0.tgz#e5581ed57eaa826fb652ca11b1e2b7b136a9f9df" - integrity sha512-L4iLKQLdqChz6ZOgGb6dRxkBNw78JFYcJmBz1orHpZoeLtuhDDGegRtX9gSyfoCIM7rWZ3VNOyiqqvk83BEN+w== dependencies: color "^2.0.1" postcss "^6.0.14" @@ -10486,7 +9139,6 @@ postcss-color-gray@^4.0.0: postcss-color-hex-alpha@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-3.0.0.tgz#1e53e6c8acb237955e8fd08b7ecdb1b8b8309f95" - integrity sha1-HlPmyKyyN5Vej9CLfs2xuLgwn5U= dependencies: color "^1.0.3" postcss "^6.0.1" @@ -10495,7 +9147,6 @@ postcss-color-hex-alpha@^3.0.0: postcss-color-hsl@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-color-hsl/-/postcss-color-hsl-2.0.0.tgz#12703666fa310430e3f30a454dac1386317d5844" - integrity sha1-EnA2ZvoxBDDj8wpFTawThjF9WEQ= dependencies: postcss "^6.0.1" postcss-value-parser "^3.3.0" @@ -10504,7 +9155,6 @@ postcss-color-hsl@^2.0.0: postcss-color-hwb@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-color-hwb/-/postcss-color-hwb-3.0.0.tgz#3402b19ef4d8497540c1fb5072be9863ca95571e" - integrity sha1-NAKxnvTYSXVAwftQcr6YY8qVVx4= dependencies: color "^1.0.3" postcss "^6.0.1" @@ -10514,7 +9164,6 @@ postcss-color-hwb@^3.0.0: postcss-color-rebeccapurple@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-3.0.0.tgz#eebaf03d363b4300b96792bd3081c19ed66513d3" - integrity sha1-7rrwPTY7QwC5Z5K9MIHBntZlE9M= dependencies: postcss "^6.0.1" postcss-value-parser "^3.3.0" @@ -10522,7 +9171,6 @@ postcss-color-rebeccapurple@^3.0.0: postcss-color-rgb@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-color-rgb/-/postcss-color-rgb-2.0.0.tgz#14539c8a7131494b482e0dd1cc265ff6514b5263" - integrity sha1-FFOcinExSUtILg3RzCZf9lFLUmM= dependencies: postcss "^6.0.1" postcss-value-parser "^3.3.0" @@ -10530,7 +9178,6 @@ postcss-color-rgb@^2.0.0: postcss-color-rgba-fallback@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-color-rgba-fallback/-/postcss-color-rgba-fallback-3.0.0.tgz#37d5c9353a07a09270912a82606bb42a0d702c04" - integrity sha1-N9XJNToHoJJwkSqCYGu0Kg1wLAQ= dependencies: postcss "^6.0.6" postcss-value-parser "^3.3.0" @@ -10539,7 +9186,6 @@ postcss-color-rgba-fallback@^3.0.0: postcss-colormin@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.2.tgz#93cd1fa11280008696887db1a528048b18e7ed99" - integrity sha512-1QJc2coIehnVFsz0otges8kQLsryi4lo19WD+U5xCWvXd0uw/Z+KKYnbiNDCnO9GP+PvErPHCG0jNvWTngk9Rw== dependencies: browserslist "^4.0.0" color "^3.0.0" @@ -10550,7 +9196,6 @@ postcss-colormin@^4.0.2: postcss-convert-values@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== dependencies: postcss "^7.0.0" postcss-value-parser "^3.0.0" @@ -10558,7 +9203,6 @@ postcss-convert-values@^4.0.1: postcss-cssnext@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/postcss-cssnext/-/postcss-cssnext-3.0.2.tgz#63b77adb0b8a4c1d5ec32cd345539535a3417d48" - integrity sha512-jA6kGdcUMZqLUgw6MdpyNWGFhk0LIITVhC/jTnLRZLoXSTR88qT2cFOn3LbY06udt1PVdTCHDG3plBjxVKf8BQ== dependencies: autoprefixer "^7.1.1" caniuse-api "^2.0.0" @@ -10595,14 +9239,12 @@ postcss-cssnext@^3.0.2: postcss-custom-media@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-6.0.0.tgz#be532784110ecb295044fb5395a18006eb21a737" - integrity sha1-vlMnhBEOyylQRPtTlaGABushpzc= dependencies: postcss "^6.0.1" postcss-custom-properties@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-6.2.0.tgz#5d929a7f06e9b84e0f11334194c0ba9a30acfbe9" - integrity sha512-eNR2h9T9ciKMoQEORrPjH33XeN/nuvVuxArOKmHtsFbGbNss631tgTrKou3/pmjAZbA4QQkhLIkPQkIk3WW+8w== dependencies: balanced-match "^1.0.0" postcss "^6.0.13" @@ -10610,7 +9252,6 @@ postcss-custom-properties@^6.1.0: postcss-custom-selectors@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-4.0.1.tgz#781382f94c52e727ef5ca4776ea2adf49a611382" - integrity sha1-eBOC+UxS5yfvXKR3bqKt9JphE4I= dependencies: postcss "^6.0.1" postcss-selector-matches "^3.0.0" @@ -10618,35 +9259,30 @@ postcss-custom-selectors@^4.0.1: postcss-discard-comments@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.1.tgz#30697735b0c476852a7a11050eb84387a67ef55d" - integrity sha512-Ay+rZu1Sz6g8IdzRjUgG2NafSNpp2MSMOQUb+9kkzzzP+kh07fP0yNbhtFejURnyVXSX3FYy2nVNW1QTnNjgBQ== dependencies: postcss "^7.0.0" postcss-discard-duplicates@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== dependencies: postcss "^7.0.0" postcss-discard-empty@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== dependencies: postcss "^7.0.0" postcss-discard-overridden@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== dependencies: postcss "^7.0.0" postcss-font-family-system-ui@^2.0.1: version "2.1.2" resolved "https://registry.yarnpkg.com/postcss-font-family-system-ui/-/postcss-font-family-system-ui-2.1.2.tgz#ff0289a44eeae02e1d6b267386d274a7153adc01" - integrity sha512-k9PNkX0sBbGevSdCPYuijNdgs1nxStR/X3a0EU7PO61ab6g4WMVZETnuoEjVVDPQR6ZL/IUSNxNxkMkh3dYpag== dependencies: "@std/esm" "^0.19.1" postcss "^6.0.1" @@ -10655,14 +9291,12 @@ postcss-font-family-system-ui@^2.0.1: postcss-font-variant@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-3.0.0.tgz#08ccc88f6050ba82ed8ef2cc76c0c6a6b41f183e" - integrity sha1-CMzIj2BQuoLtjvLMdsDGprQfGD4= dependencies: postcss "^6.0.1" postcss-html@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.12.0.tgz#39b6adb4005dfc5464df7999c0f81c95bced7e50" - integrity sha512-KxKUpj7AY7nlCbLcTOYxdfJnGE7QFAfU2n95ADj1Q90RM/pOLdz8k3n4avOyRFs7MDQHcRzJQWM1dehCwJxisQ== dependencies: htmlparser2 "^3.9.2" remark "^8.0.0" @@ -10671,7 +9305,6 @@ postcss-html@^0.12.0: postcss-image-set-polyfill@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/postcss-image-set-polyfill/-/postcss-image-set-polyfill-0.3.5.tgz#0f193413700cf1f82bd39066ef016d65a4a18181" - integrity sha1-Dxk0E3AM8fgr05Bm7wFtZaShgYE= dependencies: postcss "^6.0.1" postcss-media-query-parser "^0.2.3" @@ -10679,7 +9312,6 @@ postcss-image-set-polyfill@^0.3.5: postcss-import@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-11.0.0.tgz#a962e2df82d3bc5a6da6a386841747204f41ef5b" - integrity sha1-qWLi34LTvFptpqOGhBdHIE9B71s= dependencies: postcss "^6.0.1" postcss-value-parser "^3.2.3" @@ -10689,7 +9321,6 @@ postcss-import@^11.0.0: postcss-initial@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-2.0.0.tgz#72715f7336e0bb79351d99ee65c4a253a8441ba4" - integrity sha1-cnFfczbgu3k1HZnuZcSiU6hEG6Q= dependencies: lodash.template "^4.2.4" postcss "^6.0.1" @@ -10697,14 +9328,12 @@ postcss-initial@^2.0.0: postcss-less@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-1.1.3.tgz#6930525271bfe38d5793d33ac09c1a546b87bb51" - integrity sha512-WS0wsQxRm+kmN8wEYAGZ3t4lnoNfoyx9EJZrhiPR1K0lMHR0UNWnz52Ya5QRXChHtY75Ef+kDc05FpnBujebgw== dependencies: postcss "^5.2.16" postcss-load-config@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484" - integrity sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ== dependencies: cosmiconfig "^4.0.0" import-cwd "^2.0.0" @@ -10712,7 +9341,6 @@ postcss-load-config@^2.0.0: postcss-loader@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" - integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA== dependencies: loader-utils "^1.1.0" postcss "^7.0.0" @@ -10722,19 +9350,16 @@ postcss-loader@^3.0.0: postcss-media-minmax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-3.0.0.tgz#675256037a43ef40bc4f0760bfd06d4dc69d48d2" - integrity sha1-Z1JWA3pD70C8Twdgv9BtTcadSNI= dependencies: postcss "^6.0.1" postcss-media-query-parser@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" - integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ= postcss-merge-longhand@^4.0.9: version "4.0.9" resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.9.tgz#c2428b994833ffb2a072f290ca642e75ceabcd6f" - integrity sha512-UVMXrXF5K/kIwUbK/crPFCytpWbNX2Q3dZSc8+nQUgfOHrCT4+MHncpdxVphUlQeZxlLXUJbDyXc5NBhTnS2tA== dependencies: css-color-names "0.0.4" postcss "^7.0.0" @@ -10744,7 +9369,6 @@ postcss-merge-longhand@^4.0.9: postcss-merge-rules@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.2.tgz#2be44401bf19856f27f32b8b12c0df5af1b88e74" - integrity sha512-UiuXwCCJtQy9tAIxsnurfF0mrNHKc4NnNx6NxqmzNNjXpQwLSukUxELHTRF0Rg1pAmcoKLih8PwvZbiordchag== dependencies: browserslist "^4.0.0" caniuse-api "^3.0.0" @@ -10756,12 +9380,10 @@ postcss-merge-rules@^4.0.2: postcss-message-helpers@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" - integrity sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4= postcss-minify-font-values@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== dependencies: postcss "^7.0.0" postcss-value-parser "^3.0.0" @@ -10769,7 +9391,6 @@ postcss-minify-font-values@^4.0.2: postcss-minify-gradients@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.1.tgz#6da95c6e92a809f956bb76bf0c04494953e1a7dd" - integrity sha512-pySEW3E6Ly5mHm18rekbWiAjVi/Wj8KKt2vwSfVFAWdW6wOIekgqxKxLU7vJfb107o3FDNPkaYFCxGAJBFyogA== dependencies: cssnano-util-get-arguments "^4.0.0" is-color-stop "^1.0.0" @@ -10779,7 +9400,6 @@ postcss-minify-gradients@^4.0.1: postcss-minify-params@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.1.tgz#5b2e2d0264dd645ef5d68f8fec0d4c38c1cf93d2" - integrity sha512-h4W0FEMEzBLxpxIVelRtMheskOKKp52ND6rJv+nBS33G1twu2tCyurYj/YtgU76+UDCvWeNs0hs8HFAWE2OUFg== dependencies: alphanum-sort "^1.0.0" browserslist "^4.0.0" @@ -10791,7 +9411,6 @@ postcss-minify-params@^4.0.1: postcss-minify-selectors@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.1.tgz#a891c197977cc37abf60b3ea06b84248b1c1e9cd" - integrity sha512-8+plQkomve3G+CodLCgbhAKrb5lekAnLYuL1d7Nz+/7RANpBEVdgBkPNwljfSKvZ9xkkZTZITd04KP+zeJTJqg== dependencies: alphanum-sort "^1.0.0" has "^1.0.0" @@ -10801,14 +9420,12 @@ postcss-minify-selectors@^4.0.1: postcss-modules-extract-imports@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz#66140ecece38ef06bf0d3e355d69bf59d141ea85" - integrity sha1-ZhQOzs447wa/DT41XWm/WdFB6oU= dependencies: postcss "^6.0.1" postcss-modules-local-by-default@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" - integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk= dependencies: css-selector-tokenizer "^0.7.0" postcss "^6.0.1" @@ -10816,7 +9433,6 @@ postcss-modules-local-by-default@^1.2.0: postcss-modules-scope@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" - integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A= dependencies: css-selector-tokenizer "^0.7.0" postcss "^6.0.1" @@ -10824,7 +9440,6 @@ postcss-modules-scope@^1.1.0: postcss-modules-values@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" - integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA= dependencies: icss-replace-symbols "^1.1.0" postcss "^6.0.1" @@ -10832,21 +9447,18 @@ postcss-modules-values@^1.3.0: postcss-nesting@^4.0.1: version "4.2.1" resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-4.2.1.tgz#0483bce338b3f0828ced90ff530b29b98b00300d" - integrity sha512-IkyWXICwagCnlaviRexi7qOdwPw3+xVVjgFfGsxmztvRVaNxAlrypOIKqDE5mxY+BVxnId1rnUKBRQoNE2VDaA== dependencies: postcss "^6.0.11" postcss-normalize-charset@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== dependencies: postcss "^7.0.0" postcss-normalize-display-values@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.1.tgz#d9a83d47c716e8a980f22f632c8b0458cfb48a4c" - integrity sha512-R5mC4vaDdvsrku96yXP7zak+O3Mm9Y8IslUobk7IMP+u/g+lXvcN4jngmHY5zeJnrQvE13dfAg5ViU05ZFDwdg== dependencies: cssnano-util-get-match "^4.0.0" postcss "^7.0.0" @@ -10855,7 +9467,6 @@ postcss-normalize-display-values@^4.0.1: postcss-normalize-positions@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.1.tgz#ee2d4b67818c961964c6be09d179894b94fd6ba1" - integrity sha512-GNoOaLRBM0gvH+ZRb2vKCIujzz4aclli64MBwDuYGU2EY53LwiP7MxOZGE46UGtotrSnmarPPZ69l2S/uxdaWA== dependencies: cssnano-util-get-arguments "^4.0.0" has "^1.0.0" @@ -10865,7 +9476,6 @@ postcss-normalize-positions@^4.0.1: postcss-normalize-repeat-style@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.1.tgz#5293f234b94d7669a9f805495d35b82a581c50e5" - integrity sha512-fFHPGIjBUyUiswY2rd9rsFcC0t3oRta4wxE1h3lpwfQZwFeFjXFSiDtdJ7APCmHQOnUZnqYBADNRPKPwFAONgA== dependencies: cssnano-util-get-arguments "^4.0.0" cssnano-util-get-match "^4.0.0" @@ -10875,7 +9485,6 @@ postcss-normalize-repeat-style@^4.0.1: postcss-normalize-string@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.1.tgz#23c5030c2cc24175f66c914fa5199e2e3c10fef3" - integrity sha512-IJoexFTkAvAq5UZVxWXAGE0yLoNN/012v7TQh5nDo6imZJl2Fwgbhy3J2qnIoaDBrtUP0H7JrXlX1jjn2YcvCQ== dependencies: has "^1.0.0" postcss "^7.0.0" @@ -10884,7 +9493,6 @@ postcss-normalize-string@^4.0.1: postcss-normalize-timing-functions@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.1.tgz#8be83e0b9cb3ff2d1abddee032a49108f05f95d7" - integrity sha512-1nOtk7ze36+63ONWD8RCaRDYsnzorrj+Q6fxkQV+mlY5+471Qx9kspqv0O/qQNMeApg8KNrRf496zHwJ3tBZ7w== dependencies: cssnano-util-get-match "^4.0.0" postcss "^7.0.0" @@ -10893,7 +9501,6 @@ postcss-normalize-timing-functions@^4.0.1: postcss-normalize-unicode@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== dependencies: browserslist "^4.0.0" postcss "^7.0.0" @@ -10902,7 +9509,6 @@ postcss-normalize-unicode@^4.0.1: postcss-normalize-url@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== dependencies: is-absolute-url "^2.0.0" normalize-url "^3.0.0" @@ -10912,7 +9518,6 @@ postcss-normalize-url@^4.0.1: postcss-normalize-whitespace@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.1.tgz#d14cb639b61238418ac8bc8d3b7bdd65fc86575e" - integrity sha512-U8MBODMB2L+nStzOk6VvWWjZgi5kQNShCyjRhMT3s+W9Jw93yIjOnrEkKYD3Ul7ChWbEcjDWmXq0qOL9MIAnAw== dependencies: postcss "^7.0.0" postcss-value-parser "^3.0.0" @@ -10920,7 +9525,6 @@ postcss-normalize-whitespace@^4.0.1: postcss-ordered-values@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.1.tgz#2e3b432ef3e489b18333aeca1f1295eb89be9fc2" - integrity sha512-PeJiLgJWPzkVF8JuKSBcylaU+hDJ/TX3zqAMIjlghgn1JBi6QwQaDZoDIlqWRcCAI8SxKrt3FCPSRmOgKRB97Q== dependencies: cssnano-util-get-arguments "^4.0.0" postcss "^7.0.0" @@ -10929,7 +9533,6 @@ postcss-ordered-values@^4.1.1: postcss-pseudo-class-any-link@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-4.0.0.tgz#9152a0613d3450720513e8892854bae42d0ee68e" - integrity sha1-kVKgYT00UHIFE+iJKFS65C0O5o4= dependencies: postcss "^6.0.1" postcss-selector-parser "^2.2.3" @@ -10937,14 +9540,12 @@ postcss-pseudo-class-any-link@^4.0.0: postcss-pseudoelements@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/postcss-pseudoelements/-/postcss-pseudoelements-5.0.0.tgz#eef194e8d524645ca520a949e95e518e812402cb" - integrity sha1-7vGU6NUkZFylIKlJ6V5RjoEkAss= dependencies: postcss "^6.0.0" postcss-reduce-initial@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.2.tgz#bac8e325d67510ee01fa460676dc8ea9e3b40f15" - integrity sha512-epUiC39NonKUKG+P3eAOKKZtm5OtAtQJL7Ye0CBN1f+UQTHzqotudp+hki7zxXm7tT0ZAKDMBj1uihpPjP25ug== dependencies: browserslist "^4.0.0" caniuse-api "^3.0.0" @@ -10954,7 +9555,6 @@ postcss-reduce-initial@^4.0.2: postcss-reduce-transforms@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.1.tgz#8600d5553bdd3ad640f43bff81eb52f8760d4561" - integrity sha512-sZVr3QlGs0pjh6JAIe6DzWvBaqYw05V1t3d9Tp+VnFRT5j+rsqoWsysh/iSD7YNsULjq9IAylCznIwVd5oU/zA== dependencies: cssnano-util-get-match "^4.0.0" has "^1.0.0" @@ -10964,14 +9564,12 @@ postcss-reduce-transforms@^4.0.1: postcss-replace-overflow-wrap@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-2.0.0.tgz#794db6faa54f8db100854392a93af45768b4e25b" - integrity sha1-eU22+qVPjbEAhUOSqTr0V2i04ls= dependencies: postcss "^6.0.1" postcss-reporter@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-5.0.0.tgz#a14177fd1342829d291653f2786efd67110332c3" - integrity sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg== dependencies: chalk "^2.0.1" lodash "^4.17.4" @@ -10981,19 +9579,16 @@ postcss-reporter@^5.0.0: postcss-resolve-nested-selector@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e" - integrity sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4= postcss-safe-parser@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-3.0.1.tgz#b753eff6c7c0aea5e8375fbe4cde8bf9063ff142" - integrity sha1-t1Pv9sfArqXoN1++TN6L+QY/8UI= dependencies: postcss "^6.0.6" postcss-sass@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.2.0.tgz#e55516441e9526ba4b380a730d3a02e9eaa78c7a" - integrity sha512-cUmYzkP747fPCQE6d+CH2l1L4VSyIlAzZsok3HPjb5Gzsq3jE+VjpAdGlPsnQ310WKWI42sw+ar0UNN59/f3hg== dependencies: gonzales-pe "^4.0.3" postcss "^6.0.6" @@ -11001,14 +9596,12 @@ postcss-sass@^0.2.0: postcss-scss@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-1.0.3.tgz#4c00ab440fc1c994134e3d4e600c23341af6cd27" - integrity sha512-N2ZPDOV5PGEGVwdiB7b1QppxKkmkHodNWkemja7PV+/mHqbUlA6ZcYRreden5Ag5nwBBX8/aRE7lfg1xjdszyg== dependencies: postcss "^6.0.15" postcss-selector-matches@^3.0.0, postcss-selector-matches@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-3.0.1.tgz#e5634011e13950881861bbdd58c2d0111ffc96ab" - integrity sha1-5WNAEeE5UIgYYbvdWMLQER/8lqs= dependencies: balanced-match "^0.4.2" postcss "^6.0.1" @@ -11016,7 +9609,6 @@ postcss-selector-matches@^3.0.0, postcss-selector-matches@^3.0.1: postcss-selector-not@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-3.0.1.tgz#2e4db2f0965336c01e7cec7db6c60dff767335d9" - integrity sha1-Lk2y8JZTNsAefOx9tsYN/3ZzNdk= dependencies: balanced-match "^0.4.2" postcss "^6.0.1" @@ -11024,7 +9616,6 @@ postcss-selector-not@^3.0.1: postcss-selector-parser@^2.2.2, postcss-selector-parser@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" - integrity sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A= dependencies: flatten "^1.0.2" indexes-of "^1.0.1" @@ -11033,7 +9624,6 @@ postcss-selector-parser@^2.2.2, postcss-selector-parser@^2.2.3: postcss-selector-parser@^3.0.0, postcss-selector-parser@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" - integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= dependencies: dot-prop "^4.1.1" indexes-of "^1.0.1" @@ -11042,7 +9632,6 @@ postcss-selector-parser@^3.0.0, postcss-selector-parser@^3.1.0: postcss-selector-parser@^5.0.0-rc.3: version "5.0.0-rc.3" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0-rc.3.tgz#c4525dcc8eb90166c53dcbf0cb9317ceff5a15b5" - integrity sha512-kBl1vc+zJgWCBmmxEXE2/15tmmYdD50lO5r6tLNXEx3K4LtszdLFaSNo8SNVuoI+BGODbWhavoG/n1DrYphBsw== dependencies: babel-eslint "^8.2.3" cssesc "^1.0.1" @@ -11052,7 +9641,6 @@ postcss-selector-parser@^5.0.0-rc.3: postcss-svgo@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.1.tgz#5628cdb38f015de6b588ce6d0bf0724b492b581d" - integrity sha512-YD5uIk5NDRySy0hcI+ZJHwqemv2WiqqzDgtvgMzO8EGSkK5aONyX8HMVFRFJSdO8wUWTuisUFn/d7yRRbBr5Qw== dependencies: is-svg "^3.0.0" postcss "^7.0.0" @@ -11062,7 +9650,6 @@ postcss-svgo@^4.0.1: postcss-unique-selectors@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== dependencies: alphanum-sort "^1.0.0" postcss "^7.0.0" @@ -11071,17 +9658,14 @@ postcss-unique-selectors@^4.0.1: postcss-value-parser@^3.0.0: version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" - integrity sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU= postcss@^5.2.16: version "5.2.18" resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" - integrity sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg== dependencies: chalk "^1.1.3" js-base64 "^2.1.9" @@ -11091,7 +9675,6 @@ postcss@^5.2.16: postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.13, postcss@^6.0.14, postcss@^6.0.15, postcss@^6.0.16, postcss@^6.0.5, postcss@^6.0.6, postcss@^6.0.8: version "6.0.16" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.16.tgz#112e2fe2a6d2109be0957687243170ea5589e146" - integrity sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA== dependencies: chalk "^2.3.0" source-map "^0.6.1" @@ -11100,7 +9683,6 @@ postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.13, postcss@^6.0.1 postcss@^6.0.23: version "6.0.23" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== dependencies: chalk "^2.4.1" source-map "^0.6.1" @@ -11109,7 +9691,6 @@ postcss@^6.0.23: postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.2: version "7.0.5" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.5.tgz#70e6443e36a6d520b0fd4e7593fcca3635ee9f55" - integrity sha512-HBNpviAUFCKvEh7NZhw1e8MBPivRszIiUnhrJ+sBFVSYSqubrzwX3KG51mYgcRHX8j/cAgZJedONZcm5jTBdgQ== dependencies: chalk "^2.4.1" source-map "^0.6.1" @@ -11118,22 +9699,18 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.2: prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= pretty-bytes@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-1.0.4.tgz#0a22e8210609ad35542f8c8d5d2159aff0751c84" - integrity sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ= dependencies: get-stdin "^4.0.1" meow "^3.1.0" @@ -11141,7 +9718,6 @@ pretty-bytes@^1.0.2: pretty-error@^2.0.2: version "2.1.1" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" - integrity sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM= dependencies: renderkid "^2.0.1" utila "~0.4" @@ -11149,7 +9725,6 @@ pretty-error@^2.0.2: pretty-format@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-20.0.3.tgz#020e350a560a1fe1a98dc3beb6ccffb386de8b14" - integrity sha1-Ag41ClYKH+GpjcO+tsz/s4beixQ= dependencies: ansi-regex "^2.1.1" ansi-styles "^3.0.0" @@ -11157,32 +9732,26 @@ pretty-format@^20.0.3: private@^0.1.6, private@^0.1.7, private@~0.1.5: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= process@~0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" - integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= progress-stream@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-1.2.0.tgz#2cd3cfea33ba3a89c9c121ec3347abe9ab125f77" - integrity sha1-LNPP6jO6OonJwSHsM0er6asSX3c= dependencies: speedometer "~0.1.2" through2 "~0.2.3" @@ -11190,31 +9759,26 @@ progress-stream@^1.1.0: progress@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.1.tgz#c9242169342b1c29d275889c95734621b1952e31" - integrity sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg== promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= promise@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== dependencies: asap "~2.0.3" promzard@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" - integrity sha1-JqXW7ox97kyxIggwWs+5O6OCqe4= dependencies: read "1" prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.6.0: version "15.6.0" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" - integrity sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY= dependencies: fbjs "^0.8.16" loose-envify "^1.3.1" @@ -11223,7 +9787,6 @@ prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.6.0: prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" - integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== dependencies: loose-envify "^1.3.1" object-assign "^4.1.1" @@ -11231,22 +9794,18 @@ prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2: property-expr@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f" - integrity sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g== property-information@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/property-information/-/property-information-3.2.0.tgz#fd1483c8fbac61808f5fe359e7693a1f48a58331" - integrity sha1-/RSDyPusYYCPX+NZ52k6H0ilgzE= proto-list@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= proxy-addr@~2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec" - integrity sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew= dependencies: forwarded "~0.1.2" ipaddr.js "1.5.2" @@ -11254,7 +9813,6 @@ proxy-addr@~2.0.2: proxy-addr@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" - integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== dependencies: forwarded "~0.1.2" ipaddr.js "1.8.0" @@ -11262,22 +9820,18 @@ proxy-addr@~2.0.4: prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24: version "1.1.29" resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" - integrity sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ== public-encrypt@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6" - integrity sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY= dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" @@ -11288,7 +9842,6 @@ public-encrypt@^4.0.0: pump@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.0.tgz#7946da1c8d622b098e2ceb2d3476582470829c9d" - integrity sha512-6MYypjOvtiXhBSTOD0Zs5eNjCGfnqi5mPsCsW+dgKTxrZzQMZQNpBo3XRkLx7id753f3EeyHLBqzqqUymIolgw== dependencies: end-of-stream "^1.1.0" once "^1.3.1" @@ -11296,7 +9849,6 @@ pump@^2.0.0: pump@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== dependencies: end-of-stream "^1.1.0" once "^1.3.1" @@ -11304,7 +9856,6 @@ pump@^2.0.1: pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== dependencies: end-of-stream "^1.1.0" once "^1.3.1" @@ -11312,7 +9863,6 @@ pump@^3.0.0: pumpify@^1.3.3: version "1.3.6" resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.3.6.tgz#00d40e5ded0a3bf1e0788b1c0cf426a42882ab64" - integrity sha512-BurGAcvezsINL5US9T9wGHHcLNrG6MCp//ECtxron3vcR+Rfx5Anqq7HbZXNJvFQli8FGVsWCAvywEJFV5Hx/Q== dependencies: duplexify "^3.5.3" inherits "^2.0.3" @@ -11321,22 +9871,18 @@ pumpify@^1.3.3: punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= punycode@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" - integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= q-i@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/q-i/-/q-i-2.0.1.tgz#fec7e3f0e713f3467358bb5ac80bcc4c115187d6" - integrity sha512-tr7CzPNxkBDBuPzqi/HDUS4uBOppb91akNTeh56TYio8TiIeXp2Yp8ea9NmDu2DmGH35ZjJDq6C3E4SepVZ4bQ== dependencies: ansi-styles "^3.2.0" is-plain-object "^2.0.4" @@ -11345,69 +9891,56 @@ q-i@^2.0.1: q@^1.1.2, q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= qap@^3.1.2: version "3.3.1" resolved "https://registry.yarnpkg.com/qap/-/qap-3.3.1.tgz#11f9e8fa8890fe7cb99210c0f44d0613b7372cac" - integrity sha1-Efno+oiQ/ny5khDA9E0GE7c3LKw= qs@6.5.1, qs@~6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A== qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - integrity sha1-E+JtKK1rD/qpExLNO/cI7TUecjM= querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= querystringify@0.0.x: version "0.0.4" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-0.0.4.tgz#0cf7f84f9463ff0ae51c4c4b142d95be37724d9c" - integrity sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw= querystringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.0.tgz#7ded8dfbf7879dcc60d0a644ac6754b283ad17ef" - integrity sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg== querystringify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" - integrity sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs= quick-lru@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" - integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= raf@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" - integrity sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw== dependencies: performance-now "^2.1.0" randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" - integrity sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how== dependencies: is-number "^3.0.0" kind-of "^4.0.0" @@ -11415,14 +9948,12 @@ randomatic@^1.1.3: randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" - integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.3.tgz#b96b7df587f01dd91726c418f30553b1418e3d62" - integrity sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ== dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" @@ -11430,12 +9961,10 @@ randomfill@^1.0.3: range-parser@^1.0.3, range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= raw-body@2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" - integrity sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k= dependencies: bytes "3.0.0" http-errors "1.6.2" @@ -11445,7 +9974,6 @@ raw-body@2.3.2: raw-body@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" - integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== dependencies: bytes "3.0.0" http-errors "1.6.3" @@ -11455,7 +9983,6 @@ raw-body@2.3.3: rc@^1.0.1, rc@^1.1.6: version "1.2.6" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.6.tgz#eb18989c6d4f4f162c399f79ddd29f3835568092" - integrity sha1-6xiYnG1PTxYsOZ953dKfODVWgJI= dependencies: deep-extend "~0.4.0" ini "~1.3.0" @@ -11465,7 +9992,6 @@ rc@^1.0.1, rc@^1.1.6: rc@^1.1.7: version "1.2.3" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.3.tgz#51575a900f8dd68381c710b4712c2154c3e2035b" - integrity sha1-UVdakA+N1oOBxxC0cSwhVMPiA1s= dependencies: deep-extend "~0.4.0" ini "~1.3.0" @@ -11475,7 +10001,6 @@ rc@^1.1.7: rc@^1.2.1, rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" ini "~1.3.0" @@ -11485,17 +10010,14 @@ rc@^1.2.1, rc@^1.2.7: react-codemirror2@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-5.1.0.tgz#62de4460178adea40eb52eabf7491669bf3794b8" - integrity sha512-Cksbgbviuf2mJfMyrKmcu7ycK6zX/ukuQO8dvRZdFWqATf5joalhjFc6etnBdGCcPA2LbhIwz+OPnQxLN/j1Fw== react-deep-force-update@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-2.1.1.tgz#8ea4263cd6455a050b37445b3f08fd839d86e909" - integrity sha1-jqQmPNZFWgULN0RbPwj9g52G6Qk= react-dev-utils@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-6.0.5.tgz#6ef34d0a416dc1c97ac20025031ea1f0d819b21d" - integrity sha512-X3/q2y8GHvcn6qzqlFhFNoIQgU4TfyerYpBTc5BrMtrSO0q1ctIheAaxDQawNeRgsm2W7L3QSQ9po+YLAGcYFQ== dependencies: "@babel/code-frame" "7.0.0" address "1.0.3" @@ -11520,22 +10042,37 @@ react-dev-utils@^6.0.5: strip-ansi "4.0.0" text-table "0.2.0" +react-dnd-html5-backend@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-6.0.0.tgz#e70ad62a5df95cc993739aab1f1ffe0e725a9878" + dependencies: + dnd-core "^6.0.0" + lodash "^4.17.11" + +react-dnd@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/react-dnd/-/react-dnd-6.0.0.tgz#0780eafaa47293bf12dc8f79cf1e48ede8ba72f1" + dependencies: + dnd-core "^6.0.0" + hoist-non-react-statics "^3.1.0" + invariant "^2.1.0" + lodash "^4.17.11" + recompose "^0.30.0" + shallowequal "^1.1.0" + react-docgen-annotation-resolver@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/react-docgen-annotation-resolver/-/react-docgen-annotation-resolver-1.0.0.tgz#abbb343698b3b319537142082b6bb7d835fe2f1f" - integrity sha1-q7s0NpizsxlTcUIIK2u32DX+Lx8= react-docgen-displayname-handler@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/react-docgen-displayname-handler/-/react-docgen-displayname-handler-2.1.1.tgz#a7863a2cc0058ac3c72e6348fa5e40cc4278c5ae" - integrity sha512-Dmu+WnQt5TRDokaQ6uGvgcxrIh92c6uhuljsuueEphTcy/1nKh8/Ep6RUmpd77G1iN2rqg5+4ztGAT7LJjVdpg== dependencies: ast-types "0.11.5" react-docgen@3.0.0-beta12: version "3.0.0-beta12" resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-3.0.0-beta12.tgz#1285839296d6b616715b75c9d57f08d17c500be9" - integrity sha512-8DE3R6mPJSpBS2k6nw4hyZ/E+k60tE/AzLe/ncfyf3AQnd1pojo8cCn2ziXU33Vfny5u7G0pCrL01h9rcX6MTw== dependencies: async "^2.1.4" babel-runtime "^6.9.2" @@ -11545,37 +10082,32 @@ react-docgen@3.0.0-beta12: node-dir "^0.1.10" recast "^0.13.0" -react-dom@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" - integrity sha512-zpGAdwHVn9K0091d+hr+R0qrjoJ84cIBFL2uU60KvWBPfZ7LPSrfqviTxGHWN0sjPZb2hxWzMexwrvJdKePvjg== +react-dom@^16.6.3: + version "16.6.3" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.6.3.tgz#8fa7ba6883c85211b8da2d0efeffc9d3825cccc0" dependencies: - fbjs "^0.8.16" loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.0" + prop-types "^15.6.2" + scheduler "^0.11.2" react-error-overlay@^5.0.5: version "5.0.5" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.0.5.tgz#716ff1a92fda76bb89a39adf9ce046a5d740e71a" - integrity sha512-ab0HWBgxdIsngHtMGU8+8gYFdTBXpUGd4AE4lN2VZvOIlBmWx9dtaWEViihuGSIGosCKPeHCnzFoRWB42UtnLg== react-fast-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-1.0.0.tgz#813a039155e49b43ceffe99528fe5e9d97a6c938" - integrity sha512-dcQpdWr62flXQJuM8/bVEY5/10ad2SYBUafp8H4q4WHR3fTA/MMlp8mpzX12I0CCoEJc1P6QdiMg7U+7lFS6Rw== react-group@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/react-group/-/react-group-1.0.6.tgz#8dd7c00c3b35d05ce164021458bb07d580e3001a" - integrity sha1-jdfADDs10FzhZAIUWLsH1YDjABo= dependencies: prop-types "^15.6.0" react-hot-loader@^3.0.0-beta.7: version "3.1.3" resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-3.1.3.tgz#6f92877326958c7cb0134b512474517869126082" - integrity sha512-d7nZf78irxoGN5PY4zd6CSgZiroOhvIWzRast3qwTn4sSnBwlt08kV8WMQ9mitmxEdlCTwZt+5ClrRSjxWguMQ== dependencies: global "^4.3.0" react-deep-force-update "^2.1.1" @@ -11586,31 +10118,30 @@ react-hot-loader@^3.0.0-beta.7: react-icon-base@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/react-icon-base/-/react-icon-base-2.1.0.tgz#a196e33fdf1e7aaa1fda3aefbb68bdad9e82a79d" - integrity sha1-oZbjP98eeqof2jrvu2i9rZ6Cp50= react-icons@^2.2.7: version "2.2.7" resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-2.2.7.tgz#d7860826b258557510dac10680abea5ca23cf650" - integrity sha512-0n4lcGqzJFcIQLoQytLdJCE0DKSA9dkwEZRYoGrIDJZFvIT6Hbajx5mv9geqhqFiNjUgtxg8kPyDfjlhymbGFg== dependencies: react-icon-base "2.1.0" react-input-autosize@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8" - integrity sha512-3+K4CD13iE4lQQ2WlF8PuV5htfmTRLH6MDnfndHM6LuBRszuXnuyIfE7nhSKt8AzRBZ50bu0sAhkNMeS5pxQQA== dependencies: prop-types "^15.5.8" -react-lifecycles-compat@^3.0.4: +react-is@^16.3.2: + version "16.6.3" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.6.3.tgz#d2d7462fcfcbe6ec0da56ad69047e47e56e7eac0" + +react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" - integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== react-popper@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.0.0.tgz#b99452144e8fe4acc77fa3d959a8c79e07a65084" - integrity sha1-uZRSFE6P5KzHf6PZWajHngemUIQ= dependencies: babel-runtime "6.x.x" create-react-context "^0.2.1" @@ -11622,14 +10153,12 @@ react-popper@^1.0.0: react-proxy@^3.0.0-alpha.0: version "3.0.0-alpha.1" resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-3.0.0-alpha.1.tgz#4400426bcfa80caa6724c7755695315209fa4b07" - integrity sha1-RABCa8+oDKpnJMd1VpUxUgn6Swc= dependencies: lodash "^4.6.1" react-redux@^5.0.6: version "5.0.6" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.6.tgz#23ed3a4f986359d68b5212eaaa681e60d6574946" - integrity sha512-8taaaGu+J7PMJQDJrk/xiWEYQmdo3mkXw6wPr3K3LxvXis3Fymiq7c13S+Tpls/AyNUAsoONkU81AP0RA6y6Vw== dependencies: hoist-non-react-statics "^2.2.1" invariant "^2.0.0" @@ -11641,7 +10170,6 @@ react-redux@^5.0.6: react-router-dom@^4.1.1, react-router-dom@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.2.2.tgz#c8a81df3adc58bba8a76782e946cbd4eae649b8d" - integrity sha512-cHMFC1ZoLDfEaMFoKTjN7fry/oczMgRt5BKfMAkTu5zEuJvUiPp1J8d0eXSVTnBh6pxlbdqDhozunOOLtmKfPA== dependencies: history "^4.7.2" invariant "^2.2.2" @@ -11653,7 +10181,6 @@ react-router-dom@^4.1.1, react-router-dom@^4.2.2: react-router-redux@^5.0.0-alpha.6: version "5.0.0-alpha.9" resolved "https://registry.yarnpkg.com/react-router-redux/-/react-router-redux-5.0.0-alpha.9.tgz#825431516e0e6f1fd93b8807f6bd595e23ec3d10" - integrity sha512-euSgNIANnRXr4GydIuwA7RZCefrLQzIw5WdXspS8NPYbV+FxrKSS9MKG7U9vb6vsKHONnA4VxrVNWfnMUnUQAw== dependencies: history "^4.7.2" prop-types "^15.6.0" @@ -11662,7 +10189,6 @@ react-router-redux@^5.0.0-alpha.6: react-router@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.2.0.tgz#61f7b3e3770daeb24062dae3eedef1b054155986" - integrity sha512-DY6pjwRhdARE4TDw7XjxjZsbx9lKmIcyZoZ+SDO7SBJ1KUeWNxT22Kara2AC7u6/c2SYEHlEDLnzBCcNhLE8Vg== dependencies: history "^4.7.2" hoist-non-react-statics "^2.3.0" @@ -11675,7 +10201,6 @@ react-router@^4.2.0: react-select@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/react-select/-/react-select-2.1.0.tgz#95977a763b14f2fc42255a510acd73bef9561f7d" - integrity sha512-3SdRAKX64hNzDF/DT1J1Ei3fIoQlLMkMJuB3yOY6oOYwl2A9SFJMsqXLgsveiu7UGrdo+4lyZi3mSqvw8qeGMA== dependencies: classnames "^2.2.5" emotion "^9.1.2" @@ -11688,7 +10213,6 @@ react-select@^2.1.0: react-styleguidist@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/react-styleguidist/-/react-styleguidist-8.0.1.tgz#0da7d27a56131777767275ad0d13214f5aa5e990" - integrity sha512-WHjdUpibY/gNhQyfZ9CWKtTPProgICb+dozLtyqmRiZfi5abWoBZ8Ts7gByFcLQ69Nfk7pZsCxJKf5HMUdae9w== dependencies: "@vxna/mini-html-webpack-template" "^0.1.7" acorn "^5.7.1" @@ -11754,7 +10278,6 @@ react-styleguidist@^8.0.1: react-test-renderer@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.2.0.tgz#bddf259a6b8fcd8555f012afc8eacc238872a211" - integrity sha512-Kd4gJFtpNziR9ElOE/C23LeflKLZPRpNQYWP3nQBY43SJ5a+xyEGSeMrm2zxNKXcnCbBS/q1UpD9gqd5Dv+rew== dependencies: fbjs "^0.8.16" object-assign "^4.1.1" @@ -11763,41 +10286,36 @@ react-test-renderer@^16.2.0: react-transition-group@^2.2.1: version "2.5.0" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.5.0.tgz#70bca0e3546102c4dc5cf3f5f57f73447cce6874" - integrity sha512-qYB3JBF+9Y4sE4/Mg/9O6WFpdoYjeeYqx0AFb64PTazVy8RPMiE3A47CG9QmM4WJ/mzDiZYslV+Uly6O1Erlgw== dependencies: dom-helpers "^3.3.1" loose-envify "^1.4.0" prop-types "^15.6.2" react-lifecycles-compat "^3.0.4" -react@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba" - integrity sha512-ZmIomM7EE1DvPEnSFAHZn9Vs9zJl5A9H7el0EGTE6ZbW9FKe/14IYAlPbC8iH25YarEQxZL+E8VW7Mi7kfQrDQ== +react@^16.6.3: + version "16.6.3" + resolved "https://registry.yarnpkg.com/react/-/react-16.6.3.tgz#25d77c91911d6bbdd23db41e70fb094cc1e0871c" dependencies: - fbjs "^0.8.16" loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.0" + prop-types "^15.6.2" + scheduler "^0.11.2" read-cache@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" - integrity sha1-5mTvMRYRZsl1HNvo28+GtftY93Q= dependencies: pify "^2.3.0" read-cmd-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b" - integrity sha1-LV0Vd4ajfAVdIgd8MsU/gynpHHs= dependencies: graceful-fs "^4.1.2" read-config-file@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-3.1.2.tgz#9b299cb7a2bcec1511a4c22e71620df0a2e3b896" - integrity sha512-QCATYzlYHvmWps/W/eP7rcKuhYRYZg5XKeXFxSJRIXvn+KSw1+Ntz2et1aBz5TrEpawGrxWZ7zBipj+/v0xwWQ== dependencies: ajv "^6.5.2" ajv-keywords "^3.2.0" @@ -11812,7 +10330,6 @@ read-config-file@3.1.2: "read-package-json@1 || 2", read-package-json@^2.0.0: version "2.0.13" resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.13.tgz#2e82ebd9f613baa6d2ebe3aa72cefe3f68e41f4a" - integrity sha512-/1dZ7TRZvGrYqE0UAfN6qQb5GYBsNcqS1C0tNK601CFOJmtHI7NIGXwetEPU/OtoFHZL3hDxm4rolFFVE9Bnmg== dependencies: glob "^7.1.1" json-parse-better-errors "^1.0.1" @@ -11824,7 +10341,6 @@ read-config-file@3.1.2: read-package-tree@^5.1.6: version "5.2.1" resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.2.1.tgz#6218b187d6fac82289ce4387bbbaf8eef536ad63" - integrity sha512-2CNoRoh95LxY47LvqrehIAfUVda2JbuFE/HaGYs42bNrGG+ojbw1h3zOcPcQ+1GQ3+rkzNndZn85u1XyZ3UsIA== dependencies: debuglog "^1.0.1" dezalgo "^1.0.0" @@ -11835,7 +10351,6 @@ read-package-tree@^5.1.6: read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= dependencies: find-up "^1.0.0" read-pkg "^1.0.0" @@ -11843,7 +10358,6 @@ read-pkg-up@^1.0.1: read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= dependencies: find-up "^2.0.0" read-pkg "^2.0.0" @@ -11851,7 +10365,6 @@ read-pkg-up@^2.0.0: read-pkg-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= dependencies: find-up "^2.0.0" read-pkg "^3.0.0" @@ -11859,7 +10372,6 @@ read-pkg-up@^3.0.0: read-pkg@^1.0.0, read-pkg@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" @@ -11868,7 +10380,6 @@ read-pkg@^1.0.0, read-pkg@^1.1.0: read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= dependencies: load-json-file "^2.0.0" normalize-package-data "^2.3.2" @@ -11877,7 +10388,6 @@ read-pkg@^2.0.0: read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= dependencies: load-json-file "^4.0.0" normalize-package-data "^2.3.2" @@ -11886,7 +10396,6 @@ read-pkg@^3.0.0: read-pkg@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237" - integrity sha1-ljYlN48+HE1IyFhytabsfV0JMjc= dependencies: normalize-package-data "^2.3.2" parse-json "^4.0.0" @@ -11895,14 +10404,12 @@ read-pkg@^4.0.1: read@1, read@~1.0.1: version "1.0.7" resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" - integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= dependencies: mute-stream "~0.0.4" "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.9, readable-stream@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" - integrity sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -11915,7 +10422,6 @@ read@1, read@~1.0.1: readable-stream@1.0: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -11925,7 +10431,6 @@ readable-stream@1.0: readable-stream@^2.3.6: version "2.3.6" resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -11938,7 +10443,6 @@ readable-stream@^2.3.6: readable-stream@~1.1.9: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -11948,7 +10452,6 @@ readable-stream@~1.1.9: readable-stream@~2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0" - integrity sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA= dependencies: buffer-shims "^1.0.0" core-util-is "~1.0.0" @@ -11961,7 +10464,6 @@ readable-stream@~2.1.5: readdir-scoped-modules@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" - integrity sha1-n6+jfShr5dksuuve4DDcm19AZ0c= dependencies: debuglog "^1.0.1" dezalgo "^1.0.0" @@ -11971,7 +10473,6 @@ readdir-scoped-modules@^1.0.0: readdirp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" - integrity sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg= dependencies: graceful-fs "^4.1.2" minimatch "^3.0.2" @@ -11981,7 +10482,6 @@ readdirp@^2.0.0: recast@^0.13.0: version "0.13.2" resolved "https://registry.yarnpkg.com/recast/-/recast-0.13.2.tgz#919e7e856d5154f13284142ed1797753c6756137" - integrity sha512-Xqo0mKljGUWGUhnkdbODk7oJGFrMcpgKQ9cCyZ4y+G9VfoTKdum8nHbf/SxIdKx5aBSZ29VpVy20bTyt7jyC8w== dependencies: ast-types "0.10.2" esprima "~4.0.0" @@ -11991,21 +10491,29 @@ recast@^0.13.0: rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= dependencies: resolve "^1.1.6" +recompose@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/recompose/-/recompose-0.30.0.tgz#82773641b3927e8c7d24a0d87d65aeeba18aabd0" + dependencies: + "@babel/runtime" "^7.0.0" + change-emitter "^0.1.2" + fbjs "^0.8.1" + hoist-non-react-statics "^2.3.1" + react-lifecycles-compat "^3.0.2" + symbol-observable "^1.0.4" + recursive-readdir@2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" - integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== dependencies: minimatch "3.0.4" redbox-react@^1.3.6: version "1.5.0" resolved "https://registry.yarnpkg.com/redbox-react/-/redbox-react-1.5.0.tgz#04dab11557d26651bf3562a67c22ace56c5d3967" - integrity sha512-mdxArOI3sF8K5Nay5NG+lv/VW516TbXjjd4h1wcV1Iy4IMDQPnCayjoQXBAycAFSME4nyXRUXCjHxsw2rYpVRw== dependencies: error-stack-parser "^1.3.6" object-assign "^4.0.1" @@ -12015,7 +10523,6 @@ redbox-react@^1.3.6: redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= dependencies: indent-string "^2.1.0" strip-indent "^1.0.1" @@ -12023,7 +10530,6 @@ redent@^1.0.0: redent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" - integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= dependencies: indent-string "^3.0.0" strip-indent "^2.0.0" @@ -12031,7 +10537,6 @@ redent@^2.0.0: reduce-css-calc@^1.2.7: version "1.3.0" resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" - integrity sha1-dHyRTgSWFKTJz7umKYca0dKSdxY= dependencies: balanced-match "^0.4.2" math-expression-evaluator "^1.2.14" @@ -12040,7 +10545,6 @@ reduce-css-calc@^1.2.7: reduce-css-calc@^2.0.0: version "2.1.3" resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.3.tgz#63c4c6325ffbbf4ea6c23f1d4deb47c3953f3b81" - integrity sha1-Y8TGMl/7v06mwj8dTetHw5U/O4E= dependencies: css-unit-converter "^1.1.1" postcss-value-parser "^3.3.0" @@ -12048,19 +10552,16 @@ reduce-css-calc@^2.0.0: reduce-function-call@^1.0.1, reduce-function-call@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99" - integrity sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk= dependencies: balanced-match "^0.4.2" reduce-reducers@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/reduce-reducers/-/reduce-reducers-0.1.2.tgz#fa1b4718bc5292a71ddd1e5d839c9bea9770f14b" - integrity sha1-+htHGLxSkqcd3R5dg5yb6pdw8Us= redux-actions@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/redux-actions/-/redux-actions-2.2.1.tgz#d64186b25649a13c05478547d7cd7537b892410d" - integrity sha1-1kGGslZJoTwFR4VH1811N7iSQQ0= dependencies: invariant "^2.2.1" lodash "^4.13.1" @@ -12070,61 +10571,58 @@ redux-actions@^2.2.1: redux-mock-store@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/redux-mock-store/-/redux-mock-store-1.5.1.tgz#fca4335392e66605420b5559fe02fc5b8bb6d63c" - integrity sha512-B+iZ98ESHw4EAWVLKUknQlop1OdLKOayGRmd6KavNtC0zoSsycD8hTt0hEr1eUTw2gmYJOdfBY5QAgZweTUcLQ== dependencies: lodash.isplainobject "^4.0.6" redux-thunk@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5" - integrity sha1-5hWhbha0ehmlFXZhM9Hj6Zt4UuU= redux@^3.6.0, redux@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b" - integrity sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A== dependencies: lodash "^4.2.1" lodash-es "^4.2.1" loose-envify "^1.1.0" symbol-observable "^1.0.3" +redux@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.1.tgz#436cae6cc40fbe4727689d7c8fae44808f1bfef5" + dependencies: + loose-envify "^1.4.0" + symbol-observable "^1.2.0" + regenerate-unicode-properties@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c" - integrity sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw== dependencies: regenerate "^1.4.0" regenerate@^1.2.1: version "1.3.3" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" - integrity sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg== regenerate@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-runtime@^0.12.0: version "0.12.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" - integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== dependencies: babel-runtime "^6.18.0" babel-types "^6.19.0" @@ -12133,21 +10631,18 @@ regenerator-transform@^0.10.0: regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== dependencies: is-equal-shallow "^0.1.3" regex-not@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.0.tgz#42f83e39771622df826b02af176525d6a5f157f9" - integrity sha1-Qvg+OXcWIt+CawKvF2Ul1qXxV/k= dependencies: extend-shallow "^2.0.1" regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" @@ -12155,12 +10650,10 @@ regex-not@^1.0.2: regexpp@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" - integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== regexpu-core@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" - integrity sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs= dependencies: regenerate "^1.2.1" regjsgen "^0.2.0" @@ -12169,7 +10662,6 @@ regexpu-core@^1.0.0: regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= dependencies: regenerate "^1.2.1" regjsgen "^0.2.0" @@ -12178,7 +10670,6 @@ regexpu-core@^2.0.0: regexpu-core@^4.1.3: version "4.2.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.2.0.tgz#a3744fa03806cffe146dea4421a3e73bdcc47b1d" - integrity sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw== dependencies: regenerate "^1.4.0" regenerate-unicode-properties "^7.0.0" @@ -12190,7 +10681,6 @@ regexpu-core@^4.1.3: registry-auth-token@^3.0.1: version "3.3.1" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006" - integrity sha1-+w0yie4Nmtosu1KvXf5mywcNMAY= dependencies: rc "^1.1.6" safe-buffer "^5.0.1" @@ -12198,43 +10688,36 @@ registry-auth-token@^3.0.1: registry-url@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= dependencies: rc "^1.0.1" regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= regjsgen@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.4.0.tgz#c1eb4c89a209263f8717c782591523913ede2561" - integrity sha512-X51Lte1gCYUdlwhF28+2YMO0U6WeN0GLpgpA7LK7mbdDnkQYiwvEpmpe0F/cv5L14EbxgrdayAG3JETBv0dbXA== regjsparser@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= dependencies: jsesc "~0.5.0" regjsparser@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.3.0.tgz#3c326da7fcfd69fa0d332575a41c8c0cdf588c96" - integrity sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA== dependencies: jsesc "~0.5.0" relateurl@0.2.x: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= remark-parse@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-4.0.0.tgz#99f1f049afac80382366e2e0d0bd55429dd45d8b" - integrity sha512-XZgICP2gJ1MHU7+vQaRM+VA9HEL3X253uwUM/BGgx3iv6TH2B3bF3B8q00DKcyP9YrJV+/7WOWEWBFF/u8cIsw== dependencies: collapse-white-space "^1.0.2" is-alphabetical "^1.0.0" @@ -12255,7 +10738,6 @@ remark-parse@^4.0.0: remark-parse@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-5.0.0.tgz#4c077f9e499044d1d5c13f80d7a98cf7b9285d95" - integrity sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA== dependencies: collapse-white-space "^1.0.2" is-alphabetical "^1.0.0" @@ -12276,7 +10758,6 @@ remark-parse@^5.0.0: remark-react@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/remark-react/-/remark-react-4.0.3.tgz#980938f3bcc93bef220215b26b0b0a80f3158c7d" - integrity sha512-M2DxXfX8/GK0hV84PUcsvkvb+8yGLdV+krb8mW28eoa9ZgTrhC5rk01EPRMXRNGCAEl3JMDFs+VKdT/FbsN9vg== dependencies: "@mapbox/hast-util-table-cell-style" "^0.1.3" hast-to-hyperscript "^4.0.0" @@ -12286,7 +10767,6 @@ remark-react@^4.0.3: remark-stringify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-4.0.0.tgz#4431884c0418f112da44991b4e356cfe37facd87" - integrity sha512-xLuyKTnuQer3ke9hkU38SUYLiTmS078QOnoFavztmbt/pAJtNSkNtFgR0U//uCcmG0qnyxao+PDuatQav46F1w== dependencies: ccount "^1.0.0" is-alphanumeric "^1.0.0" @@ -12306,7 +10786,6 @@ remark-stringify@^4.0.0: remark-stringify@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-5.0.0.tgz#336d3a4d4a6a3390d933eeba62e8de4bd280afba" - integrity sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w== dependencies: ccount "^1.0.0" is-alphanumeric "^1.0.0" @@ -12326,7 +10805,6 @@ remark-stringify@^5.0.0: remark@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/remark/-/remark-8.0.0.tgz#287b6df2fe1190e263c1d15e486d3fa835594d6d" - integrity sha512-K0PTsaZvJlXTl9DN6qYlvjTkqSZBFELhROZMrblm2rB+085flN84nz4g/BscKRMqDvhzlK1oQ/xnWQumdeNZYw== dependencies: remark-parse "^4.0.0" remark-stringify "^4.0.0" @@ -12335,7 +10813,6 @@ remark@^8.0.0: remark@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/remark/-/remark-9.0.0.tgz#c5cfa8ec535c73a67c4b0f12bfdbd3a67d8b2f60" - integrity sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A== dependencies: remark-parse "^5.0.0" remark-stringify "^5.0.0" @@ -12344,12 +10821,10 @@ remark@^9.0.0: remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= renderkid@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.1.tgz#898cabfc8bede4b7b91135a3ffd323e58c0db319" - integrity sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk= dependencies: css-select "^1.1.0" dom-converter "~0.1" @@ -12360,29 +10835,24 @@ renderkid@^2.0.1: repeat-element@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo= repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= dependencies: is-finite "^1.0.0" replace-ext@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= request@2: version "2.87.0" resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" - integrity sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw== dependencies: aws-sign2 "~0.7.0" aws4 "^1.6.0" @@ -12408,7 +10878,6 @@ request@2: request@2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - integrity sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA= dependencies: aws-sign2 "~0.6.0" aws4 "^1.2.1" @@ -12436,7 +10905,6 @@ request@2.81.0: request@^2.45.0: version "2.85.0" resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" - integrity sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg== dependencies: aws-sign2 "~0.7.0" aws4 "^1.6.0" @@ -12464,7 +10932,6 @@ request@^2.45.0: request@^2.78.0, request@^2.79.0: version "2.83.0" resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" - integrity sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw== dependencies: aws-sign2 "~0.7.0" aws4 "^1.6.0" @@ -12492,7 +10959,6 @@ request@^2.78.0, request@^2.79.0: request@^2.87.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -12518,22 +10984,18 @@ request@^2.87.0: require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.1.tgz#c545233e9d7da6616e9d59adfb39fc9f588676ff" - integrity sha1-xUUjPp19pmFunVmt+zn8n1iGdv8= require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= dependencies: caller-path "^0.1.0" resolve-from "^1.0.0" @@ -12541,24 +11003,20 @@ require-uncached@^1.0.3: requires-port@1.0.x, requires-port@1.x.x, requires-port@^1.0.0, requires-port@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= reselect@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147" - integrity sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc= resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= dependencies: resolve-from "^3.0.0" resolve-dir@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= dependencies: expand-tilde "^2.0.0" global-modules "^1.0.0" @@ -12566,51 +11024,42 @@ resolve-dir@^1.0.0: resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-pathname@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879" - integrity sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg== resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" - integrity sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw== dependencies: path-parse "^1.0.5" resolve@^1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== dependencies: path-parse "^1.0.5" restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= dependencies: onetime "^2.0.0" signal-exit "^3.0.2" @@ -12618,51 +11067,42 @@ restore-cursor@^2.0.0: ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== rgb-hex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/rgb-hex/-/rgb-hex-2.1.0.tgz#c773c5fe2268a25578d92539a82a7a5ce53beda6" - integrity sha1-x3PF/iJoolV42SU5qCp6XOU77aY= rgb-regex@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" - integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= rgb@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/rgb/-/rgb-0.1.0.tgz#be27b291e8feffeac1bd99729721bfa40fc037b5" - integrity sha1-vieykej+/+rBvZlylyG/pA/AN7U= rgba-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" - integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= dependencies: align-text "^0.1.1" right-pad@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/right-pad/-/right-pad-1.0.1.tgz#8ca08c2cbb5b55e74dafa96bf7fd1a27d568c8d0" - integrity sha1-jKCMLLtbVedNr6lr9/0aJ9VoyNA= rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== dependencies: glob "^7.0.5" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7" - integrity sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc= dependencies: hash-base "^2.0.0" inherits "^2.0.1" @@ -12670,81 +11110,68 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= dependencies: is-promise "^2.1.0" run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= dependencies: aproba "^1.1.1" rx-lite-aggregates@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= dependencies: rx-lite "*" rx-lite@*, rx-lite@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= rx@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" - integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= rxjs@6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.2.2.tgz#eb75fa3c186ff5289907d06483a77884586e1cf9" - integrity sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ== dependencies: tslib "^1.9.0" rxjs@^5.5.2: version "5.5.8" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.8.tgz#b2b0809a57614ad6254c03d7446dea0d83ca3791" - integrity sha512-Bz7qou7VAIoGiglJZbzbXa4vpX5BmTTN2Dj/se6+SwADtw4SihqBIiEa7VmTXJ8pynvq0iFr5Gx9VLyye1rIxQ== dependencies: symbol-observable "1.0.1" rxjs@^6.1.0: version "6.3.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" - integrity sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw== dependencies: tslib "^1.9.0" safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== safe-buffer@5.1.2, safe-buffer@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sane@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/sane/-/sane-1.6.0.tgz#9610c452307a135d29c1fdfe2547034180c46775" - integrity sha1-lhDEUjB6E10pwf3+JUcDQYDEZ3U= dependencies: anymatch "^1.3.0" exec-sh "^0.2.0" @@ -12757,24 +11184,27 @@ sane@~1.6.0: sanitize-filename@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.1.tgz#612da1c96473fa02dccda92dcd5b4ab164a6772a" - integrity sha1-YS2hyWRz+gLczaktzVtKsWSmdyo= dependencies: truncate-utf8-bytes "^1.0.0" sax@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" - integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= sax@>=0.6.0, sax@^1.2.1, sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +scheduler@^0.11.2: + version "0.11.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.11.2.tgz#a8db5399d06eba5abac51b705b7151d2319d33d3" + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" schema-utils@^0.4.0, schema-utils@^0.4.4, schema-utils@^0.4.5: version "0.4.7" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" - integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ== dependencies: ajv "^6.1.0" ajv-keywords "^3.1.0" @@ -12782,7 +11212,6 @@ schema-utils@^0.4.0, schema-utils@^0.4.4, schema-utils@^0.4.5: schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== dependencies: ajv "^6.1.0" ajv-errors "^1.0.0" @@ -12791,53 +11220,44 @@ schema-utils@^1.0.0: script-ext-html-webpack-plugin@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/script-ext-html-webpack-plugin/-/script-ext-html-webpack-plugin-2.0.1.tgz#90ac3d77f1892ad9054c3752f0e4673607f6d9a3" - integrity sha512-kUH+XhpjG95ABMnWeKCguM7NCOqSrGlYEnJQKgvPIyq5+FzQuACMLzWOB/Lp7t0sKqKLWNLu8i6MmLRKRo1IUw== dependencies: debug "^3.1.0" select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= selfsigned@^1.9.1: version "1.10.1" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.1.tgz#bf8cb7b83256c4551e31347c6311778db99eec52" - integrity sha1-v4y3uDJWxFUeMTR8YxF3jbme7FI= dependencies: node-forge "0.6.33" semver-diff@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" - integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= dependencies: semver "^5.0.3" "semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== "semver@2.x || 3.x || 4 || 5", semver@^5.0.3, semver@^5.4.1, semver@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== semver@^5.5.1: version "5.5.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" - integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= send@0.16.1: version "0.16.1" resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" - integrity sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A== dependencies: debug "2.6.9" depd "~1.1.1" @@ -12856,7 +11276,6 @@ send@0.16.1: send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== dependencies: debug "2.6.9" depd "~1.1.2" @@ -12875,12 +11294,10 @@ send@0.16.2: serialize-javascript@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.4.0.tgz#7c958514db6ac2443a8abc062dc9f7886a7f6005" - integrity sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU= serve-index@^1.7.2: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= dependencies: accepts "~1.3.4" batch "0.6.1" @@ -12893,7 +11310,6 @@ serve-index@^1.7.2: serve-static@1.13.1: version "1.13.1" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719" - integrity sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ== dependencies: encodeurl "~1.0.1" escape-html "~1.0.3" @@ -12903,7 +11319,6 @@ serve-static@1.13.1: serve-static@1.13.2: version "1.13.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" - integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" @@ -12913,24 +11328,20 @@ serve-static@1.13.2: set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-getter@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" - integrity sha1-12nBgsnVpR9AkUXy+6guXoboA3Y= dependencies: to-object-path "^0.3.0" set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -12940,7 +11351,6 @@ set-value@^0.4.3: set-value@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -12950,42 +11360,39 @@ set-value@^2.0.0: setimmediate@^1.0.4, setimmediate@^1.0.5, setimmediate@~1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= setprototypeof@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" - integrity sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ= setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.9" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.9.tgz#98f64880474b74f4a38b8da9d3c0f2d104633e7d" - integrity sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" +shallowequal@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shell-quote@1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" - integrity sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c= dependencies: array-filter "~0.0.0" array-map "~0.0.0" @@ -12995,7 +11402,6 @@ shell-quote@1.6.1: shelljs@^0.7.3: version "0.7.8" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -13004,12 +11410,10 @@ shelljs@^0.7.3: shellwords@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" - integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== shx@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/shx/-/shx-0.2.2.tgz#0a304d020b0edf1306ad81570e80f0346df58a39" - integrity sha1-CjBNAgsO3xMGrYFXDoDwNG31ijk= dependencies: es6-object-assign "^1.0.3" minimist "^1.2.0" @@ -13018,43 +11422,36 @@ shx@^0.2.2: signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= dependencies: is-arrayish "^0.3.1" single-line-log@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-1.1.2.tgz#c2f83f273a3e1a16edb0995661da0ed5ef033364" - integrity sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q= dependencies: string-width "^1.0.1" slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= slice-ansi@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== dependencies: is-fullwidth-code-point "^2.0.0" slide@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -13063,14 +11460,12 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.1.tgz#e12b5487faded3e3dea0ac91e9400bf75b401370" - integrity sha1-4StUh/re0+PeoKyR6UAL91tAE3A= dependencies: base "^0.11.1" debug "^2.2.0" @@ -13084,21 +11479,18 @@ snapdragon@^0.8.1: sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - integrity sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg= dependencies: hoek "2.x.x" sntp@2.x.x: version "2.1.0" resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - integrity sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg== dependencies: hoek "4.x.x" sockjs-client@1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.1.5.tgz#1bb7c0f7222c40f42adf14f4442cbd1269771a83" - integrity sha1-G7fA9yIsQPQq3xT0RCy9Eml3GoM= dependencies: debug "^2.6.6" eventsource "0.1.6" @@ -13110,7 +11502,6 @@ sockjs-client@1.1.5: sockjs-client@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.3.0.tgz#12fc9d6cb663da5739d3dc5fb6e8687da95cb177" - integrity sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg== dependencies: debug "^3.2.5" eventsource "^1.0.7" @@ -13122,7 +11513,6 @@ sockjs-client@1.3.0: sockjs@0.3.19: version "0.3.19" resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d" - integrity sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw== dependencies: faye-websocket "^0.10.0" uuid "^3.0.1" @@ -13130,19 +11520,16 @@ sockjs@0.3.19: sort-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" - integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= dependencies: is-plain-obj "^1.0.0" source-list-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" - integrity sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A== source-map-resolve@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.1.tgz#7ad0f593f2281598e854df80f19aae4b92d7a11a" - integrity sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A== dependencies: atob "^2.0.0" decode-uri-component "^0.2.0" @@ -13153,14 +11540,12 @@ source-map-resolve@^0.5.0: source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== dependencies: source-map "^0.5.6" source-map-support@^0.5.6, source-map-support@^0.5.9, source-map-support@~0.5.6: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" - integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -13168,63 +11553,52 @@ source-map-support@^0.5.6, source-map-support@^0.5.9, source-map-support@~0.5.6: source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= source-map@0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" - integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - integrity sha1-66T12pwNyZneaAMti092FzZSA2s= dependencies: amdefine ">=0.0.4" source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@^0.7.2: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== sourcemapped-stacktrace@^1.1.6: version "1.1.8" resolved "https://registry.yarnpkg.com/sourcemapped-stacktrace/-/sourcemapped-stacktrace-1.1.8.tgz#6b7a3f1a6fb15f6d40e701e23ce404553480d688" - integrity sha512-OkVoI7GQOLl/laR1qsSo1c87tS8kF2VXhQq2SrQCDdXufBAcm8FgXogWso96ciMYoDtTw1Dn70CVdwYzoYs6Pg== dependencies: source-map "0.5.6" space-separated-tokens@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz#e95ab9d19ae841e200808cd96bc7bd0adbbb3412" - integrity sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA== dependencies: trim "0.0.1" sparkles@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" - integrity sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM= spawn-command@^0.0.2-1: version "0.0.2-1" resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" - integrity sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A= spdx-correct@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" - integrity sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -13232,19 +11606,16 @@ spdx-correct@^3.0.0: spdx-correct@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" - integrity sha1-SzBz2TP/UfORLwOsVRlJikFQ20A= dependencies: spdx-license-ids "^1.0.2" spdx-exceptions@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" - integrity sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg== spdx-expression-parse@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" @@ -13252,22 +11623,18 @@ spdx-expression-parse@^3.0.0: spdx-expression-parse@~1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" - integrity sha1-m98vIOH0DtRH++JzJmGR/O1RYmw= spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" - integrity sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc= spdx-license-ids@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" - integrity sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA== spdy-transport@^2.0.18: version "2.0.20" resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.20.tgz#735e72054c486b2354fe89e702256004a39ace4d" - integrity sha1-c15yBUxIayNU/onnAiVgBKOazk0= dependencies: debug "^2.6.8" detect-node "^2.0.3" @@ -13280,7 +11647,6 @@ spdy-transport@^2.0.18: spdy@^3.4.1: version "3.4.7" resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.7.tgz#42ff41ece5cc0f99a3a6c28aabb73f5c3b03acbc" - integrity sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw= dependencies: debug "^2.6.8" handle-thing "^1.2.5" @@ -13292,43 +11658,36 @@ spdy@^3.4.1: specificity@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.3.2.tgz#99e6511eceef0f8d9b57924937aac2cb13d13c42" - integrity sha512-Nc/QN/A425Qog7j9aHmwOrlwX2e7pNI47ciwxwy4jOlvbbMHkNNJchit+FX+UjF3IAdiaaV5BKeWuDUnws6G1A== speedometer@~0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d" - integrity sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0= split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" split2@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" - integrity sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw== dependencies: through2 "^2.0.2" split@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== dependencies: through "2" sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: version "1.13.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" - integrity sha1-US322mKHFEMW3EwY/hzx2UBzm+M= dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -13343,46 +11702,38 @@ sshpk@^1.7.0: ssri@^5.2.4: version "5.3.0" resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06" - integrity sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ== dependencies: safe-buffer "^5.1.1" ssri@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== dependencies: figgy-pudding "^3.5.1" stable@~0.1.6: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= stackframe@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-0.3.1.tgz#33aa84f1177a5548c8935533cbfeb3420975f5a4" - integrity sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ= stat-mode@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" - integrity sha1-5sgLYjEj19gM8TLOU480YokHJQI= state-toggle@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.0.tgz#d20f9a616bb4f0c3b98b91922d25b640aa2bc425" - integrity sha1-0g+aYWu08MO5i5GSLSW2QKorxCU= static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -13390,22 +11741,18 @@ static-extend@^0.1.1: "statuses@>= 1.3.1 < 2", statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== "statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" - integrity sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4= stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" - integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds= dependencies: inherits "~2.0.1" readable-stream "^2.0.2" @@ -13413,7 +11760,6 @@ stream-browserify@^2.0.1: stream-each@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd" - integrity sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA== dependencies: end-of-stream "^1.1.0" stream-shift "^1.0.0" @@ -13421,7 +11767,6 @@ stream-each@^1.1.0: stream-http@^2.7.2: version "2.7.2" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad" - integrity sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw== dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" @@ -13432,19 +11777,16 @@ stream-http@^2.7.2: stream-shift@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= string-length@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac" - integrity sha1-VpcPscOFWOnnC3KL894mmsRa36w= dependencies: strip-ansi "^3.0.0" string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" @@ -13453,7 +11795,6 @@ string-width@^1.0.1, string-width@^1.0.2: string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" @@ -13461,26 +11802,22 @@ string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: string_decoder@^1.0.0, string_decoder@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ== dependencies: safe-buffer "~5.1.0" string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" stringify-entities@^1.0.1: version "1.3.1" resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.1.tgz#b150ec2d72ac4c1b5f324b51fb6b28c9cdff058c" - integrity sha1-sVDsLXKsTBtfMktR+2soyc3/BYw= dependencies: character-entities-html4 "^1.0.0" character-entities-legacy "^1.0.0" @@ -13490,7 +11827,6 @@ stringify-entities@^1.0.1: stringify-object@^3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.2.1.tgz#2720c2eff940854c819f6ee252aaeb581f30624d" - integrity sha512-jPcQYw/52HUPP8uOE4kkjxl5bB9LfHkKCTptIk3qw7ozP5XMIMlHMLjt00GGSwW6DJAf/njY5EU6Vpwl4LlBKQ== dependencies: get-own-enumerable-property-symbols "^2.0.1" is-obj "^1.0.1" @@ -13499,60 +11835,50 @@ stringify-object@^3.2.0: stringstream@~0.0.4, stringstream@~0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - integrity sha1-TkhM1N5aC7vuGORjB3EKioFiGHg= strip-ansi@4.0.0, strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-bom@3.0.0, strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= dependencies: is-utf8 "^0.2.0" strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= dependencies: get-stdin "^4.0.1" strip-indent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" - integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= strong-log-transformer@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-1.0.6.tgz#f7fb93758a69a571140181277eea0c2eb1301fa3" - integrity sha1-9/uTdYpppXEUAYEnfuoMLrEwH6M= dependencies: byline "^5.0.0" duplexer "^0.1.1" @@ -13563,7 +11889,6 @@ strong-log-transformer@^1.0.6: style-loader@^0.23.1: version "0.23.1" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925" - integrity sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg== dependencies: loader-utils "^1.1.0" schema-utils "^1.0.0" @@ -13571,12 +11896,10 @@ style-loader@^0.23.1: style-search@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" - integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI= stylehacks@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.1.tgz#3186595d047ab0df813d213e51c8b94e0b9010f2" - integrity sha512-TK5zEPeD9NyC1uPIdjikzsgWxdQQN/ry1X3d1iOz1UkYDCmcr928gWD1KHgyC27F50UnE0xCTrBOO1l6KR8M4w== dependencies: browserslist "^4.0.0" postcss "^7.0.0" @@ -13585,19 +11908,16 @@ stylehacks@^4.0.0: stylelint-config-recommended@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-2.0.1.tgz#4746119ec85f5f4663c7b5107c05c13ed0e2ab0d" - integrity sha512-FXdgdOEGpaFQoKGhsi8IbsCI6dkxHQPa1CCqIybkN1d8LKtdxrn/A1rgu8DpJ6J+/4L30FOJeVdPttGfxCDHBQ== stylelint-config-standard@^18.0.0: version "18.0.0" resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-18.0.0.tgz#0d872b40fafdcddcf4188fb5b64ddb3887e8aefc" - integrity sha1-DYcrQPr9zdz0GI+1tk3bOIforvw= dependencies: stylelint-config-recommended "^2.0.0" stylelint@^8.4.0: version "8.4.0" resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-8.4.0.tgz#c2dbaeb17236917819f9206e1c0df5fddf6f83c3" - integrity sha512-56hPH5mTFnk8LzlEuTWq0epa34fHuS54UFYQidBOFt563RJBNi1nz1F2HK2MoT1X1waq47milvRsRahFCCJs/Q== dependencies: autoprefixer "^7.1.2" balanced-match "^1.0.0" @@ -13642,76 +11962,64 @@ stylelint@^8.4.0: stylis-rule-sheet@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430" - integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw== stylis@^3.5.0: version "3.5.3" resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.3.tgz#99fdc46afba6af4deff570825994181a5e6ce546" - integrity sha512-TxU0aAscJghF9I3V9q601xcK3Uw1JbXvpsBGj/HULqexKOKlOEzzlIpLFRbKkCK990ccuxfXUqmPbIIo7Fq/cQ== sugarss@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-1.0.1.tgz#be826d9003e0f247735f92365dc3fd7f1bae9e44" - integrity sha512-3qgLZytikQQEVn1/FrhY7B68gPUUGY3R1Q1vTiD5xT+Ti1DP/8iZuwFet9ONs5+bmL8pZoDQ6JrQHVgrNlK6mA== dependencies: postcss "^6.0.14" sumchecker@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-2.0.2.tgz#0f42c10e5d05da5d42eea3e56c3399a37d6c5b3e" - integrity sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4= dependencies: debug "^2.2.0" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= supports-color@^3.1.2, supports-color@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= dependencies: has-flag "^1.0.0" supports-color@^4.0.0, supports-color@^4.2.1, supports-color@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" - integrity sha1-vnoN5ITexcXN34s9WRJQRJEvY1s= dependencies: has-flag "^2.0.0" supports-color@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5" - integrity sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ== dependencies: has-flag "^2.0.0" supports-color@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" - integrity sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg== dependencies: has-flag "^3.0.0" supports-color@^5.4.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" svg-tags@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" - integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= svgo@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.1.1.tgz#12384b03335bcecd85cfa5f4e3375fed671cb985" - integrity sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g== dependencies: coa "~2.0.1" colors "~1.1.2" @@ -13731,32 +12039,30 @@ svgo@^1.0.0: symbol-observable@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" - integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ= symbol-observable@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" - integrity sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0= symbol-observable@^1.0.3, symbol-observable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.1.0.tgz#5c68fd8d54115d9dfb72a84720549222e8db9b32" - integrity sha512-dQoid9tqQ+uotGhuTKEY11X4xhyYePVnqGSoSm3OGKh2E8LZ6RPULp1uXTctk33IeERlrRJYoVSBglsL05F5Uw== + +symbol-observable@^1.0.4, symbol-observable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" symbol-tree@^3.2.1: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" - integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY= synchronous-promise@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.6.tgz#de76e0ea2b3558c1e673942e47e714a930fa64aa" - integrity sha512-TyOuWLwkmtPL49LHCX1caIwHjRzcVd62+GF6h8W/jHOeZUFHpnd2XJDVuUlaTaLPH1nuu2M69mfHr5XbQJnf/g== table@4.0.2, table@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" - integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== dependencies: ajv "^5.2.3" ajv-keywords "^2.1.0" @@ -13768,7 +12074,6 @@ table@4.0.2, table@^4.0.1: table@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc" - integrity sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg== dependencies: ajv "^6.0.1" ajv-keywords "^3.0.0" @@ -13780,12 +12085,10 @@ table@^4.0.2: tapable@^1.0.0, tapable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.0.tgz#0d076a172e3d9ba088fd2272b2668fb8d194b78c" - integrity sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA== tar-pack@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" - integrity sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg== dependencies: debug "^2.2.0" fstream "^1.0.10" @@ -13799,7 +12102,6 @@ tar-pack@^3.4.0: tar@^2.0.0, tar@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= dependencies: block-stream "*" fstream "^1.0.2" @@ -13808,7 +12110,6 @@ tar@^2.0.0, tar@^2.2.1: tar@^4: version "4.4.6" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" - integrity sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg== dependencies: chownr "^1.0.1" fs-minipass "^1.2.5" @@ -13821,12 +12122,10 @@ tar@^4: temp-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" - integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= temp-file@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/temp-file/-/temp-file-3.1.3.tgz#24c144994f033be1ccf6773280c8f7f1c91691a9" - integrity sha512-oz2J77loDE9sGrlRTqBzwbsUvoBD2BpyXeaRPKyGwBIwaamSs2jdqAfhutw7Tch9llr1u8E2ruoug09rNPa3PA== dependencies: async-exit-hook "^2.0.1" bluebird-lst "^1.0.5" @@ -13836,7 +12135,6 @@ temp-file@^3.1.3: temp-write@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-3.4.0.tgz#8cff630fb7e9da05f047c74ce4ce4d685457d492" - integrity sha1-jP9jD7fp2gXwR8dM5M5NaFRX1JI= dependencies: graceful-fs "^4.1.2" is-stream "^1.1.0" @@ -13848,14 +12146,12 @@ temp-write@^3.4.0: term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" - integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= dependencies: execa "^0.7.0" terser-webpack-plugin@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.1.0.tgz#cf7c25a1eee25bf121f4a587bb9e004e3f80e528" - integrity sha512-61lV0DSxMAZ8AyZG7/A4a3UPlrbOBo8NIQ4tJzLPAdGOQ+yoNC7l5ijEow27lBAL2humer01KLS6bGIMYQxKoA== dependencies: cacache "^11.0.2" find-cache-dir "^2.0.0" @@ -13869,7 +12165,6 @@ terser-webpack-plugin@^1.1.0: terser@^3.8.1: version "3.10.2" resolved "https://registry.yarnpkg.com/terser/-/terser-3.10.2.tgz#a61d2c97065f9fdc8c49a18655e2a80ca7298a94" - integrity sha512-+QrFoqBImmsQGB4c/HvaqgZynmbNvNBwoBxuu7fYXtq5EEtlLUzph+WimDj+xMkuqawXPMl2lgCIz81CdXvt+w== dependencies: commander "~2.17.1" source-map "~0.6.1" @@ -13878,7 +12173,6 @@ terser@^3.8.1: test-exclude@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" - integrity sha512-35+Asrsk3XHJDBgf/VRFexPgh3UyETv8IAn/LRTiZjVy6rjPVqdEk8dJcJYBzl1w0XCJM48lvTy8SfEsCWS4nA== dependencies: arrify "^1.0.1" micromatch "^2.3.11" @@ -13889,32 +12183,26 @@ test-exclude@^4.1.1: text-extensions@^1.0.0: version "1.7.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.7.0.tgz#faaaba2625ed746d568a23e4d0aacd9bf08a8b39" - integrity sha512-AKXZeDq230UaSzaO5s3qQUZOaC7iKbzq0jOFL614R7d9R593HLqAOL0cYoqLdkNrjBSOdmoQI06yigq1TSBXAg== text-hex@1.0.x: version "1.0.0" resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" - integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== text-table@0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= throat@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/throat/-/throat-3.2.0.tgz#50cb0670edbc40237b9e347d7e1f88e4620af836" - integrity sha512-/EY8VpvlqJ+sFtLPeOgc8Pl7kQVOWv0woD87KTXVHPIAE842FGT+rokxIhe8xIUP1cfgrkt0as0vDLjDiMtr8w== throttleit@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" - integrity sha1-z+34jmDADdlpe2H90qg0OptoDq8= through2@^2.0.0, through2@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= dependencies: readable-stream "^2.1.5" xtend "~4.0.1" @@ -13922,7 +12210,6 @@ through2@^2.0.0, through2@^2.0.2: through2@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f" - integrity sha1-6zKE2k6jEbbMis42U3SKUqvyWj8= dependencies: readable-stream "~1.1.9" xtend "~2.1.1" @@ -13930,51 +12217,42 @@ through2@~0.2.3: through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= thunky@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e" - integrity sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4= timed-out@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= timers-browserify@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.4.tgz#96ca53f4b794a5e7c0e1bd7cc88a372298fa01e6" - integrity sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg== dependencies: setimmediate "^1.0.4" timsort@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= to-ast@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/to-ast/-/to-ast-1.0.0.tgz#0c4a31c8c98edfde9aaf0192c794b4c8b11ee287" - integrity sha1-DEoxyMmO396arwGSx5S0yLEe4oc= dependencies: ast-types "^0.7.2" esprima "^2.1.0" @@ -13982,24 +12260,20 @@ to-ast@^1.0.0: to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -14007,7 +12281,6 @@ to-regex-range@^2.1.0: to-regex@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.1.tgz#15358bee4a2c83bd76377ba1dc049d0f18837aae" - integrity sha1-FTWL7kosg712N3uh3ASdDxiDeq4= dependencies: define-property "^0.2.5" extend-shallow "^2.0.1" @@ -14016,7 +12289,6 @@ to-regex@^3.0.1: to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" @@ -14026,38 +12298,32 @@ to-regex@^3.0.2: topo@2.x.x: version "2.0.2" resolved "https://registry.yarnpkg.com/topo/-/topo-2.0.2.tgz#cd5615752539057c0dc0491a621c3bc6fbe1d182" - integrity sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI= dependencies: hoek "4.x.x" toposort@^1.0.0: version "1.0.6" resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.6.tgz#c31748e55d210effc00fdcdc7d6e68d7d7bb9cec" - integrity sha1-wxdI5V0hDv/AD9zcfW5o19e7nOw= toposort@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" - integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= touch@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/touch/-/touch-2.0.2.tgz#ca0b2a3ae3211246a61b16ba9e6cbf1596287164" - integrity sha512-qjNtvsFXTRq7IuMLweVgFxmEuQ6gLbRs2jQxL80TtZ31dEKWYIxRXquij6w6VimyDek5hD3PytljHmEtAs2u0A== dependencies: nopt "~1.0.10" tough-cookie@^2.3.2, tough-cookie@~2.3.0, tough-cookie@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" - integrity sha1-C2GKVWW23qkL80JdBNVe3EdadWE= dependencies: punycode "^1.4.1" tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== dependencies: psl "^1.1.24" punycode "^1.4.1" @@ -14065,118 +12331,96 @@ tough-cookie@~2.4.3: tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= "traverse@>=0.3.0 <0.4": version "0.3.9" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" - integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk= tree-kill@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" - integrity sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg== trim-lines@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.1.tgz#da738ff58fa74817588455e30b11b85289f2a396" - integrity sha512-X+eloHbgJGxczUk1WSjIvn7aC9oN3jVE3rQfRVKcgpavi3jxtCn0VVKtjOBj64Yop96UYn/ujJRpTbCdAF1vyg== trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= trim-newlines@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" - integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= trim-off-newlines@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" - integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= trim-trailing-lines@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.0.tgz#7aefbb7808df9d669f6da2e438cac8c46ada7684" - integrity sha1-eu+7eAjfnWafbaLkOMrIxGradoQ= trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= triple-beam@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/triple-beam/-/triple-beam-1.2.0.tgz#8b5c1f3d491229bf6ddcf721c0ba84cef5ab51fa" - integrity sha512-nw1CkXiwTt0sdF0i+MRTvslFK7pme9sPGY1MjuZV14HB/pLL3Srw9LsphR1Qo0SYDPMFetpcY/bA3DjPA+R+1g== triple-beam@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" - integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== trough@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.1.tgz#a9fd8b0394b0ae8fff82e0633a0a36ccad5b5f86" - integrity sha1-qf2LA5Swro//guBjOgo2zK1bX4Y= truncate-utf8-bytes@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" - integrity sha1-QFkjkJWS1W94pYGENLC3hInKXys= dependencies: utf8-byte-length "^1.0.1" tryer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" - integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== tslib@^1.9.0, tslib@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== type-is@~1.6.15: version "1.6.15" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" - integrity sha1-yrEPtJCeRByChC6v4a1kbIGARBA= dependencies: media-typer "0.3.0" mime-types "~2.1.15" @@ -14184,7 +12428,6 @@ type-is@~1.6.15: type-is@~1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" - integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== dependencies: media-typer "0.3.0" mime-types "~2.1.18" @@ -14192,27 +12435,22 @@ type-is@~1.6.16: typed-styles@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.5.tgz#a60df245d482a9b1adf9c06c078d0f06085ed1cf" - integrity sha512-ht+rEe5UsdEBAa3gr64+QjUOqjOLJfWLvl5HZR5Ev9uo/OnD3p43wPeFSB1hNFc13GXQF/JU1Bn0YHLUqBRIlw== typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= ua-parser-js@^0.7.18: version "0.7.18" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" - integrity sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA== ua-parser-js@^0.7.9: version "0.7.17" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" - integrity sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g== uglify-es@^3.3.4: version "3.3.9" resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" - integrity sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ== dependencies: commander "~2.13.0" source-map "~0.6.1" @@ -14220,7 +12458,6 @@ uglify-es@^3.3.4: uglify-js@3.3.x: version "3.3.5" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.5.tgz#4c4143dfe08e8825746675cc49a6874a933b543e" - integrity sha512-ZebM2kgBL/UI9rKeAbsS2J0UPPv7SBy5hJNZml/YxB1zC6JK8IztcPs+cxilE4pu0li6vadVSFqiO7xFTKuSrg== dependencies: commander "~2.12.1" source-map "~0.6.1" @@ -14228,7 +12465,6 @@ uglify-js@3.3.x: uglify-js@^2.6: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= dependencies: source-map "~0.5.1" yargs "~3.10.0" @@ -14238,12 +12474,10 @@ uglify-js@^2.6: uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= uglifyjs-webpack-plugin@^1.2.4: version "1.3.0" resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz#75f548160858163a08643e086d5fefe18a5d67de" - integrity sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw== dependencies: cacache "^10.0.4" find-cache-dir "^1.0.0" @@ -14257,22 +12491,18 @@ uglifyjs-webpack-plugin@^1.2.4: uid-number@0.0.6, uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" - integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE= ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== umask@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" - integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0= unherit@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.0.tgz#6b9aaedfbf73df1756ad9e316dd981885840cd7d" - integrity sha1-a5qu379z3xdWrZ4xbdmBiFhAzX0= dependencies: inherits "^2.0.1" xtend "^4.0.1" @@ -14280,12 +12510,10 @@ unherit@^1.0.4: unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== unicode-match-property-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== dependencies: unicode-canonical-property-names-ecmascript "^1.0.4" unicode-property-aliases-ecmascript "^1.0.4" @@ -14293,17 +12521,14 @@ unicode-match-property-ecmascript@^1.0.4: unicode-match-property-value-ecmascript@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz#9f1dc76926d6ccf452310564fd834ace059663d4" - integrity sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ== unicode-property-aliases-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz#5a533f31b4317ea76f17d807fa0d116546111dd0" - integrity sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg== unified@^6.0.0: version "6.1.6" resolved "https://registry.yarnpkg.com/unified/-/unified-6.1.6.tgz#5ea7f807a0898f1f8acdeefe5f25faa010cc42b1" - integrity sha512-pW2f82bCIo2ifuIGYcV12fL96kMMYgw7JKVEgh7ODlrM9rj6vXSY3BV+H6lCcv1ksxynFf582hwWLnA1qRFy4w== dependencies: bail "^1.0.0" extend "^3.0.0" @@ -14316,7 +12541,6 @@ unified@^6.0.0: union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= dependencies: arr-union "^3.1.0" get-value "^2.0.6" @@ -14326,112 +12550,94 @@ union-value@^1.0.0: uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= uniqs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= unique-filename@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3" - integrity sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM= dependencies: unique-slug "^2.0.0" unique-slug@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.0.tgz#db6676e7c7cc0629878ff196097c78855ae9f4ab" - integrity sha1-22Z258fMBimHj/GWCXx4hVrp9Ks= dependencies: imurmurhash "^0.1.4" unique-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" - integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= dependencies: crypto-random-string "^1.0.0" unist-builder@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-1.0.3.tgz#ab0f9d0f10936b74f3e913521955b0478e0ff036" - integrity sha512-/KB8GEaoeHRyIqClL+Kam+Y5NWJ6yEiPsAfv1M+O1p+aKGgjR89WwoEHKTyOj17L6kAlqtKpAgv2nWvdbQDEig== dependencies: object-assign "^4.1.0" unist-util-find-all-after@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-1.0.1.tgz#4e5512abfef7e0616781aecf7b1ed751c00af908" - integrity sha1-TlUSq/734GFnga7Pex7XUcAK+Qg= dependencies: unist-util-is "^2.0.0" unist-util-generated@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.2.tgz#8b993f9239d8e560be6ee6e91c3f7b7208e5ce25" - integrity sha512-1HcwiEO62dr0XWGT+abVK4f0aAm8Ik8N08c5nAYVmuSxfvpA9rCcNyX/le8xXj1pJK5nBrGlZefeWB6bN8Pstw== unist-util-is@^2.0.0, unist-util-is@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.1.tgz#0c312629e3f960c66e931e812d3d80e77010947b" - integrity sha1-DDEmKeP5YMZukx6BLT2A53AQlHs= unist-util-is@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.2.tgz#1193fa8f2bfbbb82150633f3a8d2eb9a1c1d55db" - integrity sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw== unist-util-modify-children@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-1.1.1.tgz#66d7e6a449e6f67220b976ab3cb8b5ebac39e51d" - integrity sha1-ZtfmpEnm9nIguXarPLi166w55R0= dependencies: array-iterate "^1.0.0" unist-util-position@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.0.1.tgz#8e220c24658239bf7ddafada5725ed0ea1ebbc26" - integrity sha512-05QfJDPI7PE1BIUtAxeSV+cDx21xP7+tUZgSval5CA7tr0pHBwybF7OnEa1dOFqg6BfYH/qiMUnWwWj+Frhlww== unist-util-remove-position@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.1.tgz#5a85c1555fc1ba0c101b86707d15e50fa4c871bb" - integrity sha1-WoXBVV/BugwQG4ZwfRXlD6TIcbs= dependencies: unist-util-visit "^1.1.0" unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz#3ccbdc53679eed6ecf3777dd7f5e3229c1b6aa3c" - integrity sha1-PMvcU2ee7W7PN3fdf14yKcG2qjw= unist-util-visit-parents@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz#63fffc8929027bee04bfef7d2cce474f71cb6217" - integrity sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA== dependencies: unist-util-is "^2.1.2" unist-util-visit@^1.0.0, unist-util-visit@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.0.tgz#1cb763647186dc26f5e1df5db6bd1e48b3cc2fb1" - integrity sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw== dependencies: unist-util-visit-parents "^2.0.0" unist-util-visit@^1.1.0, unist-util-visit@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.3.0.tgz#41ca7c82981fd1ce6c762aac397fc24e35711444" - integrity sha512-9ntYcxPFtl44gnwXrQKZ5bMqXMY0ZHzUpqMFiU4zcc8mmf/jzYm8GhYgezuUlX4cJIM1zIDYaO6fG/fI+L6iiQ== dependencies: unist-util-is "^2.1.1" units-css@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/units-css/-/units-css-0.4.0.tgz#d6228653a51983d7c16ff28f8b9dc3b1ffed3a07" - integrity sha1-1iKGU6UZg9fBb/KPi53Dsf/tOgc= dependencies: isnumeric "^0.2.0" viewport-dimensions "^0.2.0" @@ -14439,22 +12645,18 @@ units-css@^0.4.0: universalify@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" - integrity sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc= unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= unquote@^1.1.0, unquote@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -14462,12 +12664,10 @@ unset-value@^1.0.0: unzip-response@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" - integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= unzipper@^0.8.11: version "0.8.12" resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.8.12.tgz#178de4e263d96a2550fb6f4804d26c06edb9c8bd" - integrity sha512-28pOCq67YXzn60NqJCLK2R7elkbFWHZX1o8mhHwlPZZTL5afoQpbX5+B4b+PqmUyXyTVyRoLUYcf4lw4/KLH1Q== dependencies: big-integer "^1.6.17" binary "~0.3.0" @@ -14482,12 +12682,10 @@ unzipper@^0.8.11: upath@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" - integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== update-notifier@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" - integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw== dependencies: boxen "^1.2.1" chalk "^2.0.1" @@ -14503,31 +12701,26 @@ update-notifier@^2.5.0: upper-case@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" - integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= uri-js@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-3.0.2.tgz#f90b858507f81dea4dcfbb3c4c3dbfa2b557faaa" - integrity sha1-+QuFhQf4HepNz7s8TD2/orVX+qo= dependencies: punycode "^2.1.0" uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-loader@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.1.2.tgz#b971d191b83af693c5e3fea4064be9e1f2d7f8d8" - integrity sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg== dependencies: loader-utils "^1.1.0" mime "^2.0.3" @@ -14536,14 +12729,12 @@ url-loader@^1.1.2: url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= dependencies: prepend-http "^1.0.1" url-parse@1.0.x: version "1.0.5" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b" - integrity sha1-CFSGBCKv3P7+tsllxmLUgAFpkns= dependencies: querystringify "0.0.x" requires-port "1.0.x" @@ -14551,7 +12742,6 @@ url-parse@1.0.x: url-parse@^1.1.8: version "1.2.0" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.2.0.tgz#3a19e8aaa6d023ddd27dcc44cb4fc8f7fec23986" - integrity sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw== dependencies: querystringify "~1.0.0" requires-port "~1.0.0" @@ -14559,7 +12749,6 @@ url-parse@^1.1.8: url-parse@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.3.tgz#bfaee455c889023219d757e045fa6a684ec36c15" - integrity sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw== dependencies: querystringify "^2.0.0" requires-port "^1.0.0" @@ -14567,17 +12756,14 @@ url-parse@^1.4.3: url-template@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" - integrity sha1-/FZaPMy/93MMd19WQflVV5FDnyE= url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= url@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ= dependencies: punycode "1.3.2" querystring "0.2.0" @@ -14585,7 +12771,6 @@ url@0.10.3: url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= dependencies: punycode "1.3.2" querystring "0.2.0" @@ -14593,12 +12778,10 @@ url@^0.11.0: urlgrey@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/urlgrey/-/urlgrey-0.4.4.tgz#892fe95960805e85519f1cd4389f2cb4cbb7652f" - integrity sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8= use@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/use/-/use-2.0.2.tgz#ae28a0d72f93bf22422a18a2e379993112dec8e8" - integrity sha1-riig1y+TvyJCKhii43mZMRLeyOg= dependencies: define-property "^0.2.5" isobject "^3.0.0" @@ -14607,22 +12790,18 @@ use@^2.0.0: user-home@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" - integrity sha1-K1viOjK2Onyd640PKNSFcko98ZA= utf8-byte-length@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" - integrity sha1-9F8VDExm7uloGGUFq5P8u4rWv2E= util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= util.promisify@1.0.0, util.promisify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== dependencies: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" @@ -14630,56 +12809,46 @@ util.promisify@1.0.0, util.promisify@~1.0.0: util@0.10.3, util@^0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= dependencies: inherits "2.0.1" utila@~0.3: version "0.3.3" resolved "https://registry.yarnpkg.com/utila/-/utila-0.3.3.tgz#d7e8e7d7e309107092b05f8d9688824d633a4226" - integrity sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY= utila@~0.4: version "0.4.0" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@3.1.0, uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" - integrity sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g== uuid@3.3.2, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== uuid@^3.2.1: version "3.2.1" resolved "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" - integrity sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA== v8-compile-cache@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" - integrity sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw== v8flags@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" - integrity sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ= dependencies: user-home "^1.1.1" validate-npm-package-license@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" - integrity sha1-KAS6vnEq0zeUWaz74kdGqywwP7w= dependencies: spdx-correct "~1.0.0" spdx-expression-parse "~1.0.0" @@ -14687,7 +12856,6 @@ validate-npm-package-license@^3.0.1: validate-npm-package-license@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" - integrity sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g== dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" @@ -14695,29 +12863,24 @@ validate-npm-package-license@^3.0.3: validate-npm-package-name@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" - integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34= dependencies: builtins "^1.0.3" value-equal@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7" - integrity sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw== vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= vendors@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22" - integrity sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI= verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" @@ -14726,19 +12889,16 @@ verror@1.10.0: vfile-location@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.2.tgz#d3675c59c877498e492b4756ff65e4af1a752255" - integrity sha1-02dcWch3SY5JK0dW/2Xkrxp1IlU= vfile-message@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.0.0.tgz#a6adb0474ea400fa25d929f1d673abea6a17e359" - integrity sha512-HPREhzTOB/sNDc9/Mxf8w0FmHnThg5CRSJdR9VRFkD2riqYWs+fuXlj5z8mIpv2LrD7uU41+oPWFOL4Mjlf+dw== dependencies: unist-util-stringify-position "^1.1.1" vfile@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" - integrity sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w== dependencies: is-buffer "^1.1.4" replace-ext "1.0.0" @@ -14748,29 +12908,24 @@ vfile@^2.0.0: viewport-dimensions@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz#de740747db5387fd1725f5175e91bac76afdf36c" - integrity sha1-3nQHR9tTh/0XJfUXXpG6x2r982w= vlq@^0.2.1: version "0.2.3" resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" - integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== vlq@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.0.tgz#8101be90843422954c2b13eb27f2f3122bdcc806" - integrity sha512-o3WmXySo+oI5thgqr7Qy8uBkT/v9Zr+sRyrh1lr8aWPUkgDWdWt4Nae2WKBrLsocgE8BuWWD0jLc+VW8LeU+2g== vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= dependencies: indexof "0.0.1" wait-on@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-2.1.0.tgz#3c4ace1f57266ca5be7fa25e0c15803b889ca46a" - integrity sha512-hDwJ674+7dfiiK/cxtYCwPxlnjXDjto/pCz1PF02sXUhqCqCWsgvxZln0699PReWqXXgkxqkF6DDo5Rj9sjNvw== dependencies: core-js "^2.4.1" joi "^9.2.0" @@ -14781,31 +12936,26 @@ wait-on@^2.1.0: walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" - integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= dependencies: makeerror "1.0.x" walkes@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/walkes/-/walkes-0.2.1.tgz#7eca144fe67ed32782fffe6e8e95fb4481864796" - integrity sha1-fsoUT+Z+0yeC//5ujpX7RIGGR5Y= warning@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" - integrity sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w= dependencies: loose-envify "^1.0.0" watch@~0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/watch/-/watch-0.10.0.tgz#77798b2da0f9910d595f1ace5b0c2258521f21dc" - integrity sha1-d3mLLaD5kQ1ZXxrOWwwiWFIfIdw= watchpack@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== dependencies: chokidar "^2.0.2" graceful-fs "^4.1.2" @@ -14814,31 +12964,26 @@ watchpack@^1.5.0: wbuf@^1.1.0, wbuf@^1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.2.tgz#d697b99f1f59512df2751be42769c1580b5801fe" - integrity sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4= dependencies: minimalistic-assert "^1.0.0" wcwidth@^1.0.0, wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= dependencies: defaults "^1.0.3" webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= webidl-conversions@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== webpack-bundle-analyzer@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.0.3.tgz#dbc7fff8f52058b6714a20fddf309d0790e3e0a0" - integrity sha512-naLWiRfmtH4UJgtUktRTLw6FdoZJ2RvCR9ePbwM9aRMsS/KjFerkPZG9epEvXRAw5d5oPdrs9+3p+afNjxW8Xw== dependencies: acorn "^5.7.3" bfj "^6.1.1" @@ -14856,7 +13001,6 @@ webpack-bundle-analyzer@^3.0.3: webpack-cli@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.1.2.tgz#17d7e01b77f89f884a2bbf9db545f0f6a648e746" - integrity sha512-Cnqo7CeqeSvC6PTdts+dywNi5CRlIPbLx1AoUPK2T6vC1YAugMG3IOoO9DmEscd+Dghw7uRlnzV1KwOe5IrtgQ== dependencies: chalk "^2.4.1" cross-spawn "^6.0.5" @@ -14872,7 +13016,6 @@ webpack-cli@^3.1.2: webpack-dev-middleware@3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz#1132fecc9026fd90f0ecedac5cbff75d1fb45890" - integrity sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA== dependencies: memory-fs "~0.4.1" mime "^2.3.1" @@ -14882,7 +13025,6 @@ webpack-dev-middleware@3.4.0: webpack-dev-server@^3.1.10: version "3.1.10" resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.10.tgz#507411bee727ee8d2fdffdc621b66a64ab3dea2b" - integrity sha512-RqOAVjfqZJtQcB0LmrzJ5y4Jp78lv9CK0MZ1YJDTaTmedMZ9PU9FLMQNrMCfVu8hHzaVLVOJKBlGEHMN10z+ww== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -14916,7 +13058,6 @@ webpack-dev-server@^3.1.10: webpack-log@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" - integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== dependencies: ansi-colors "^3.0.0" uuid "^3.3.2" @@ -14924,14 +13065,12 @@ webpack-log@^2.0.0: webpack-merge@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.1.4.tgz#0fde38eabf2d5fd85251c24a5a8c48f8a3f4eb7b" - integrity sha512-TmSe1HZKeOPey3oy1Ov2iS3guIZjWvMT2BBJDzzT5jScHTjVC3mpjJofgueEzaEd6ibhxRDD6MIblDr8tzh8iQ== dependencies: lodash "^4.17.5" webpack-sources@^1.1.0, webpack-sources@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" - integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== dependencies: source-list-map "^2.0.0" source-map "~0.6.1" @@ -14939,7 +13078,6 @@ webpack-sources@^1.1.0, webpack-sources@^1.3.0: webpack@^4.23.0: version "4.23.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.23.0.tgz#0cfbf324b7f6789ac2e6c98fa83eabe96fa56232" - integrity sha512-Osh/3U9y4swhEKDjy8fF48v2Qx5VC6VvdQ8bEm1HMaVVddiQBw4+mIyDrzVcVRCPT/+4uJFOcklPuoB+I3Zw0w== dependencies: "@webassemblyjs/ast" "1.7.10" "@webassemblyjs/helper-module-context" "1.7.10" @@ -14969,7 +13107,6 @@ webpack@^4.23.0: websocket-driver@>=0.5.1: version "0.7.0" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb" - integrity sha1-DK+dLXVdk67gSdS90NP+LMoqJOs= dependencies: http-parser-js ">=0.4.0" websocket-extensions ">=0.1.1" @@ -14977,24 +13114,20 @@ websocket-driver@>=0.5.1: websocket-extensions@>=0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" - integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== whatwg-encoding@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz#57c235bc8657e914d24e1a397d3c82daee0a6ba3" - integrity sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw== dependencies: iconv-lite "0.4.19" whatwg-fetch@>=0.10.0: version "2.0.3" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" - integrity sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ= whatwg-url@^4.3.0: version "4.8.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.8.0.tgz#d2981aa9148c1e00a41c5a6131166ab4683bbcc0" - integrity sha1-0pgaqRSMHgCkHFphMRZqtGg7vMA= dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" @@ -15002,55 +13135,46 @@ whatwg-url@^4.3.0: which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" - integrity sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg== dependencies: isexe "^2.0.0" wide-align@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" - integrity sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w== dependencies: string-width "^1.0.2" widest-line@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.0.tgz#0142a4e8a243f8882c0233aa0e0281aa76152273" - integrity sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM= dependencies: string-width "^2.1.1" window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= winston-transport@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.2.0.tgz#a20be89edf2ea2ca39ba25f3e50344d73e6520e5" - integrity sha512-0R1bvFqxSlK/ZKTH86nymOuKv/cT1PQBMuDdA7k7f0S9fM44dNH6bXnuxwXPrN8lefJgtZq08BKdyZ0DZIy/rg== dependencies: readable-stream "^2.3.6" triple-beam "^1.2.0" @@ -15058,7 +13182,6 @@ winston-transport@^4.2.0: winston@^2.2.0: version "2.4.0" resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.0.tgz#808050b93d52661ed9fb6c26b3f0c826708b0aee" - integrity sha1-gIBQuT1SZh7Z+2wms/DIJnCLCu4= dependencies: async "~1.0.0" colors "1.0.x" @@ -15070,7 +13193,6 @@ winston@^2.2.0: winston@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/winston/-/winston-3.1.0.tgz#80724376aef164e024f316100d5b178d78ac5331" - integrity sha512-FsQfEE+8YIEeuZEYhHDk5cILo1HOcWkGwvoidLrDgPog0r4bser1lEIOco2dN9zpDJ1M88hfDgZvxe5z4xNcwg== dependencies: async "^2.6.0" diagnostics "^1.1.1" @@ -15085,27 +13207,22 @@ winston@^3.1.0: word-wrap@^1.0.3: version "1.2.3" resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= worker-farm@^1.3.1: version "1.5.2" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.2.tgz#32b312e5dc3d5d45d79ef44acc2587491cd729ae" - integrity sha512-XxiQ9kZN5n6mmnW+mFJ+wXjNNI/Nx4DIdaAKLX1Bn6LYBWlN/zaBhu34DQYPZ1AJobQuu67S2OfDdNSVULvXkQ== dependencies: errno "^0.1.4" xtend "^4.0.1" @@ -15113,14 +13230,12 @@ worker-farm@^1.3.1: worker-farm@^1.5.2: version "1.6.0" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" - integrity sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ== dependencies: errno "~0.1.7" worker-loader@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-2.0.0.tgz#45fda3ef76aca815771a89107399ee4119b430ac" - integrity sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw== dependencies: loader-utils "^1.0.0" schema-utils "^0.4.0" @@ -15128,7 +13243,6 @@ worker-loader@^2.0.0: wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -15136,12 +13250,10 @@ wrap-ansi@^2.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write-file-atomic@^2.0.0, write-file-atomic@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" - integrity sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA== dependencies: graceful-fs "^4.1.11" imurmurhash "^0.1.4" @@ -15150,7 +13262,6 @@ write-file-atomic@^2.0.0, write-file-atomic@^2.3.0: write-json-file@^2.2.0, write-json-file@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.3.0.tgz#2b64c8a33004d54b8698c76d585a77ceb61da32f" - integrity sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8= dependencies: detect-indent "^5.0.0" graceful-fs "^4.1.2" @@ -15162,7 +13273,6 @@ write-json-file@^2.2.0, write-json-file@^2.3.0: write-pkg@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-3.1.0.tgz#030a9994cc9993d25b4e75a9f1a1923607291ce9" - integrity sha1-AwqZlMyZk9JbTnWp8aGSNgcpHOk= dependencies: sort-keys "^2.0.0" write-json-file "^2.2.0" @@ -15170,14 +13280,12 @@ write-pkg@^3.1.0: write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= dependencies: mkdirp "^0.5.1" ws@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ws/-/ws-3.1.0.tgz#8afafecdeab46d572e5397ee880739367aa2f41c" - integrity sha512-TU4/qKFlyQFqNITNWiqPCUY9GqlAhEotlzfcZcve6VT1YEngQl1dDMqwQQS3eMYruJ5r/UD3lcsWib6iVMDGDw== dependencies: safe-buffer "~5.1.0" ultron "~1.1.0" @@ -15185,39 +13293,32 @@ ws@3.1.0: ws@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.0.tgz#119a9dbf92c54e190ec18d10e871d55c95cf9373" - integrity sha512-H3dGVdGvW2H8bnYpIDc3u3LH8Wue3Qh+Zto6aXXFzvESkTVT6rAfKR6tR/+coaUvxs8yHtmNV0uioBF62ZGSTg== dependencies: async-limiter "~1.0.0" x-is-function@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/x-is-function/-/x-is-function-1.0.4.tgz#5d294dc3d268cbdd062580e0c5df77a391d1fa1e" - integrity sha1-XSlNw9Joy90GJYDgxd93o5HR+h4= x-is-string@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" - integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI= xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" - integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= xml-char-classes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/xml-char-classes/-/xml-char-classes-1.0.0.tgz#64657848a20ffc5df583a42ad8a277b4512bbc4d" - integrity sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0= xml-name-validator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" - integrity sha1-TYuPHszTQZqjYgYb7O9RXh5VljU= xml2js@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== dependencies: sax ">=0.6.0" xmlbuilder "~9.0.1" @@ -15225,73 +13326,60 @@ xml2js@0.4.19: xmlbuilder@8.2.2: version "8.2.2" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773" - integrity sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M= xmlbuilder@^9.0.7, xmlbuilder@~9.0.1: version "9.0.7" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= xmldom@0.1.x: version "0.1.27" resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" - integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk= xregexp@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" - integrity sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg== xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= xtend@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= dependencies: object-keys "~0.4.0" y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" - integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= yargs-parser@^10.0.0: version "10.0.0" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.0.0.tgz#c737c93de2567657750cb1f2c00be639fd19c994" - integrity sha512-+DHejWujTVYeMHLff8U96rLc4uE4Emncoftvn5AjhB1Jw1pWxLzgBUT/WYbPrHmy6YPEBTZQx5myHhVcuuu64g== dependencies: camelcase "^4.1.0" yargs-parser@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" - integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== dependencies: camelcase "^4.1.0" yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= dependencies: camelcase "^3.0.0" lodash.assign "^4.0.6" @@ -15299,21 +13387,18 @@ yargs-parser@^2.4.1: yargs-parser@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= dependencies: camelcase "^3.0.0" yargs-parser@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= dependencies: camelcase "^4.1.0" yargs@11.0.0, yargs@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.0.0.tgz#c052931006c5eee74610e5fc0354bedfd08a201b" - integrity sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw== dependencies: cliui "^4.0.0" decamelize "^1.1.1" @@ -15331,7 +13416,6 @@ yargs@11.0.0, yargs@^11.0.0: yargs@12.0.2, yargs@^12.0.2: version "12.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.2.tgz#fe58234369392af33ecbef53819171eff0f5aadc" - integrity sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ== dependencies: cliui "^4.0.0" decamelize "^2.0.0" @@ -15349,7 +13433,6 @@ yargs@12.0.2, yargs@^12.0.2: yargs@^12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.1.tgz#6432e56123bb4e7c3562115401e98374060261c2" - integrity sha512-B0vRAp1hRX4jgIOWFtjfNjd9OA9RWYZ6tqGA9/I/IrTMsxmKvtWy+ersM+jzpQqbC3YfLzeABPdeTgcJ9eu1qQ== dependencies: cliui "^4.0.0" decamelize "^2.0.0" @@ -15367,7 +13450,6 @@ yargs@^12.0.1: yargs@^4.2.0: version "4.8.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= dependencies: cliui "^3.2.0" decamelize "^1.1.1" @@ -15387,7 +13469,6 @@ yargs@^4.2.0: yargs@^7.0.2: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= dependencies: camelcase "^3.0.0" cliui "^3.2.0" @@ -15406,7 +13487,6 @@ yargs@^7.0.2: yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= dependencies: camelcase "^1.0.2" cliui "^2.1.0" @@ -15416,14 +13496,12 @@ yargs@~3.10.0: yauzl@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" - integrity sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU= dependencies: fd-slicer "~1.0.1" yup@^0.26.6: version "0.26.6" resolved "https://registry.yarnpkg.com/yup/-/yup-0.26.6.tgz#07e216a1424861f17958fef1d4775c64ef985724" - integrity sha512-Lfj8pAtQ/cDu/wsCuXt2ArQ0uUO/9nfr+EwlD9oQrWIErtjURjdSXYTS1ycN7T/Ok+IUTy23Tdo6Wo0f/wMMBw== dependencies: "@babel/runtime" "7.0.0" fn-name "~2.0.1"