commit 5d959e6d6efe7c2afeac21ddfbaf897fee9a4b01 Author: dominik-zeglen Date: Wed Jun 19 16:40:52 2019 +0200 Initial commit diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 000000000..65a8dd271 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,37 @@ +engines: + eslint: + enabled: true + channel: eslint-4 + isort: + enabled: true + channel: beta + pep8: + enabled: true + pylint: + enabled: true + channel: beta + plugins: + - celery + - django + checks: + import-error: + enabled: false + tslint: + enabled: true + config: tslint.json + duplication: + enabled: true + config: + languages: + python: + mass_threshold: 100 + python_version: 3 +exclude_patterns: +- ".*" +- "**/__pycache__/" +- "**/migrations/" +- "node_modules/" +- "tests/" +ratings: + paths: + - saleor/** diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..aa6004261 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +*.py[cod] +.* +!.babelrc +!.circleci +!.codeclimate.yml +!.coveragerc +!.dockerignore +!.eslintrc.json +!.flowconfig +!.gqlconfig +!.github +!.gitignore +!.nvmrc +!.npmrc +!.plop +!.pylintrc +!.travis* +!.tx +*.css +*.log +*.pot +*.pyc +local_settings.py +__pycache__/ +build/ +coverage/ +dist/ +*\.egg* +# data +/docs/_build/ +/media/ +/node_modules/ +/static/ +/saleor/static/assets/ +webpack-bundle.json +/templates/templated_email/compiled/* +!/templates/templated_email/compiled/.gitkeep + +# Exported results file +django-queries-results.html diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..0ecb29384 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +puppeteer_skip_chromium_download = true diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..b66f6e5c3 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,73 @@ +dist: xenial +language: python +sudo: false + +python: + - "3.6" + - "3.7" + +branches: + only: + - master + - /next\/.*/ + +cache: + pip: true + directories: + - node_modules + - $HOME/.cache/pip + +install: + - pip install -U pip setuptools wheel + - pip install tox-travis pytest-django-queries + - git clone https://github.com/NyanKiyoshi/pytest-django-queries-ci-tools.git --depth 1 ../queries-ci-tools + - > + if [ -n "$DJANGO" ]; then + nvm install 10 \ + && npm i \ + && npm run build-assets --production \ + && npm run build-emails + fi + +script: + - > + if [ -n "$DJANGO" ]; then + npm run test + fi + - tox + +env: + global: + - DATABASE_URL="postgres://postgres@localhost:5432/saleor" + - SECRET_KEY="irrelevant" + - DIFF_RESULTS_BASE_URL="http://dhrwmpu5reeyd.cloudfront.net" + - QUERIES_RESULTS_PATH=/tmp/queries-results.json + matrix: + - DJANGO="2.2" + - DJANGO="master" + +matrix: + fast_finish: true + include: + - env: TOXENV=black + python: "3.6" + - env: TOXENV=flake8 + python: "3.6" + - env: TOXENV=check_gql_schema + python: "3.6" + - env: TOXENV=check_migrations + python: "3.6" + allow_failures: + - python: "3.6" + env: DJANGO="master" + - python: "3.7" + env: DJANGO="master" + +services: + - postgresql + +addons: + postgresql: 9.4 + +after_success: + - ../queries-ci-tools/handle-event.sh diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..8c9e2af55 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,517 @@ +# Changelog + +All notable, unreleased changes to this project will be documented in this file. For the released changes, please visit the [Releases](https://github.com/mirumee/saleor/releases) page. + +## [Unreleased Changeset: Attributes] + +- The mutations `attributeCreate` and `attributeUpdate`: + - They no longer crash if no values were passed. - #4260 by @NyanKiyoshi + - They no longer accept the `productType` parameter and no longer return the attribute's `productType` in the root of the response; instead, you should query the attribute's `productType` manually. - #4260 by @NyanKiyoshi + - They now accept an optional `slug` input parameter for setting the internal representation of the attribute instead of always generating it. This allows users to have multiple attributes with the same name but that are different things or set of values. - #4260 by @NyanKiyoshi +- The `Attribute` model: + - They now always unique, instead of being unique only into a given product type. - #4260 by @NyanKiyoshi +- Attributes can now be associated to multiple product types. - #4266 by @NyanKiyoshi +- The `Attribute` model's `product_type` field was renamed to `product_types` (M2M related manager). - #4266 by @NyanKiyoshi +- Added `attributeAssign(...)` and `attributeUnassign(...)` mutations in the GraphQL API. - #4266 by @NyanKiyoshi + +## [Unreleased] + +- Fixed internal error when creating a checkout with a voucher code - #4292 by @NyanKiyoshi +- Add filter tab name as required - #4269 by @benekex2 +- A few unused panels are now disabled by default from the debug toolbar; this should improve loading time when debugging - #4301 by @NyanKiyoshi + +## 2.7.0 + +### API + +- Create order only when payment is successful - #4154 by @NyanKiyoshi +- Order Events containing order lines or fulfillment lines now return the line object in the GraphQL API - #4114 by @NyanKiyoshi +- GraphQL now prints exceptions to stderr as well as returning them or not - #4148 by @NyanKiyoshi +- Refactored API resolvers to static methods with root typing - #4155 by @NyanKiyoshi +- Add phone validation in the GraphQL API to handle the library upgrade - #4156 by @NyanKiyoshi + +### Core + +- Add basic Gift Cards support in the backend - #4025 by @fowczarek +- Add the ability to sort products within a collection - #4123 by @NyanKiyoshi +- Implement customer events - #4094 by @NyanKiyoshi +- Merge "authorize" and "capture" operations - #4098 by @korycins, @NyanKiyoshi +- Separate the Django middlewares from the GraphQL API middlewares - #4102 by @NyanKiyoshi, #4186 by @cmiacz + +### Dashboard 2.0 + +- Add navigation section - #4012 by @dominik-zeglen +- Add filtering on product list - #4193 by @dominik-zeglen +- Add filtering on orders list - #4237 by @dominik-zeglen +- Change input style and improve Storybook stories - #4115 by @dominik-zeglen +- Migrate deprecated fields in Dashboard 2.0 - #4121 by @benekex2 +- Add multiple select checkbox - #4133, #4146 by @benekex2 +- Rename menu items in Dashboard 2.0 - #4172 by @benekex2 +- Category delete modal improvements - #4171 by @benekex2 +- Close modals on click outside - #4236 - by @benekex2 +- Use date localize hook in translations - #4202 by @dominik-zeglen +- Unify search API - #4200 by @dominik-zeglen +- Default default PAGINATE_BY - #4238 by @dominik-zeglen +- Create generic filtering interface - #4221 by @dominik-zeglen +- Add default state to rich text editor = #4281 by @dominik-zeglen +- Fix translation discard button - #4109 by @benekex2 +- Fix draftail options and icons - #4132 by @benekex2 +- Fix typos and messages in Dashboard 2.0 - #4168 by @benekex2 +- Fix view all orders button - #4173 by @benekex2 +- Fix visibility card view - #4198 by @benekex2 +- Fix query refetch after selecting an object in list - #4272 by @dominik-zeglen +- Fix image selection in variants - #4270 by @benekex2 +- Fix collection search - #4267 by @dominik-zeglen +- Fix quantity height in draft order edit - #4273 by @benekex2 +- Fix checkbox clickable area size - #4280 by @dominik-zeglen +- Fix breaking object selection in menu section - #4282 by @dominik-zeglen +- Reset selected items when tab switch - #4268 by @benekex2 +- Add attribute section - #4305 by @dominik-zeglen + +### Other notable changes + +- Add support for Google Cloud Storage - #4127 by @chetabahana +- Adding a nonexistent variant to checkout no longer crashes - #4166 by @NyanKiyoshi +- Disable storage of Celery results - #4169 by @NyanKiyoshi +- Disable polling in Playground - #4188 by @maarcingebala +- Cleanup code for updated function names and unused argument - #4090 by @jxltom +- Users can now add multiple "Add to Cart" forms in a single page - #4165 by @NyanKiyoshi +- Fix incorrect argument in `get_client_token` in Braintree integration - #4182 by @maarcingebala +- Fix resolving attribute values when transforming them to HStore - #4161 by @maarcingebala +- Fix wrong calculation of subtotal in cart page - #4145 by @korycins +- Fix margin calculations when product/variant price is set to zero - #4170 by @MahmoudRizk +- Fix applying discounts in checkout's subtotal calculation in API - #4192 by @maarcingebala +- Fix GATEWAYS_ENUM to always contain all implemented payment gateways - #4108 by @koradon + + +## 2.6.0 + +### API + +- Add unified filtering interface in resolvers - #3952, #4078 by @korycins +- Add mutations for bulk actions - #3935, #3954, #3967, #3969, #3970 by @akjanik +- Add mutation for reordering menu items - #3958 by @NyanKiyoshi +- Optimize queries for single nodes - #3968 @NyanKiyoshi +- Refactor error handling in mutations #3891 by @maarcingebala & @akjanik +- Specify mutation permissions through Meta classes - #3980 by @NyanKiyoshi +- Unify pricing access in products and variants - #3948 by @NyanKiyoshi +- Use only_fields instead of exclude_fields in type definitions - #3940 by @michaljelonek +- Prefetch collections when getting sales of a bunch of products - #3961 by @NyanKiyoshi +- Remove unnecessary dedents from GraphQL schema so new Playground can work - #4045 by @salwator +- Restrict resolving payment by ID - #4009 @NyanKiyoshi +- Require `checkoutId` for updating checkout's shipping and billing address - #4074 by @jxltom +- Handle errors in `TokenVerify` mutation - #3981 by @fowczarek +- Unify argument names in types and resolvers - #3942 by @NyanKiyoshi + +### Core + +- Use Black as the default code formatting tool - #3852 by @krzysztofwolski and @NyanKiyoshi +- Dropped Python 3.5 support - #4028 by @korycins +- Rename Cart to Checkout - #3963 by @michaljelonek +- Use data classes to exchange data with payment gateways - #4028 by @korycins +- Refactor order events - #4018 by @NyanKiyoshi + +### Dashboard 2.0 + +- Add bulk actions - #3955 by @dominik-zeglen +- Add user avatar management - #4030 by @benekex2 +- Add navigation drawer support on mobile devices - #3839 by @benekex2 +- Fix rendering validation errors in product form - #4024 by @benekex2 +- Move dialog windows to query string rather than router paths - #3953 by @dominik-zeglen +- Update order events types - #4089 by @jxltom +- Code cleanup by replacing render props with react hooks - #4010 by @dominik-zeglen + +### Other notable changes + +- Add setting to enable Django Debug Toolbar - #3983 by @koradon +- Use newest GraphQL Playground - #3971 by @salwator +- Ensure adding to quantities in the checkout is respecting the limits - #4005 by @NyanKiyoshi +- Fix country area choices - #4008 by @fowczarek +- Fix price_range_as_dict function - #3999 by @zodiacfireworks +- Fix the product listing not showing in the voucher when there were products selected - #4062 by @NyanKiyoshi +- Fix crash in Dashboard 1.0 when updating an order address's phone number - #4061 by @NyanKiyoshi +- Reduce the time of tests execution by using dummy password hasher - #4083 by @korycins +- Set up explicit **hash** function - #3979 by @akjanik +- Unit tests use none as media root - #3975 by @korycins +- Update file field styles with materializecss template filter - #3998 by @zodiacfireworks +- New translations: + - Albanian + - Colombian Spanish + - Lithuanian + +## 2.5.0 + +### API + +- Add query to fetch draft orders - #3809 by @michaljelonek +- Add bulk delete mutations - #3838 by @michaljelonek +- Add `languageCode` enum to API - #3819 by @michaljelonek, #3854 by @jxltom +- Duplicate address instances in checkout mutations - #3866 by @pawelzar +- Restrict access to `orders` query for unauthorized users - #3861 by @pawelzar +- Support setting address as default in address mutations - #3787 by @jxltom +- Fix phone number validation in GraphQL when country prefix not given - #3905 by @patrys +- Report pretty stack traces in DEBUG mode - #3918 by @patrys + +### Core + +- Drop support for Django 2.1 and Django 1.11 (previous LTS) - #3929 by @patrys +- Fulfillment of digital products - #3868 by @korycins +- Introduce avatars for staff accounts - #3878 by @pawelzar +- Refactor the account avatars path from a relative to absolute - #3938 by @NyanKiyoshi + +### Dashboard 2.0 + +- Add translations section - #3884 by @dominik-zeglen +- Add light/dark theme - #3856 by @dominik-zeglen +- Add customer's address book view - #3826 by @dominik-zeglen +- Add "Add variant" button on the variant details page = #3914 by @dominik-zeglen +- Add back arrows in "Configure" subsections - #3917 by @dominik-zeglen +- Display avatars in staff views - #3922 by @dominik-zeglen +- Prevent user from changing his own status and permissions - #3922 by @dominik-zeglen +- Fix crashing product create view - #3837, #3910 by @dominik-zeglen +- Fix layout in staff members details page - #3857 by @dominik-zeglen +- Fix unfocusing rich text editor - #3902 by @dominik-zeglen +- Improve accessibility - #3856 by @dominik-zeglen + +### Other notable changes + +- Improve user and staff management in dashboard 1.0 - #3781 by @jxltom +- Fix default product tax rate in Dashboard 1.0 - #3880 by @pawelzar +- Fix logo in docs - #3928 by @michaljelonek +- Fix name of logo file - #3867 by @jxltom +- Fix variants for juices in example data - #3926 by @michaljelonek +- Fix alignment of the cart dropdown on new bootstrap version - #3937 by @NyanKiyoshi +- Refactor the account avatars path from a relative to absolute - #3938 by @NyanKiyoshi +- New translations: + - Armenian + - Portuguese + - Swahili + - Thai + +## 2.4.0 + +### API + +- Add model translations support in GraphQL API - #3789 by @michaljelonek +- Add mutations to manage addresses for authenticated customers - #3772 by @Kwaidan00, @maarcingebala +- Add mutation to apply vouchers in checkout - #3739 by @Kwaidan00 +- Add thumbnail field to `OrderLine` type - #3737 by @michaljelonek +- Add a query to fetch order by token - #3740 by @michaljelonek +- Add city choices and city area type to address validator API - #3788 by @jxltom +- Fix access to unpublished objects in API - #3724 by @Kwaidan00 +- Fix bug where errors are not returned when creating fulfillment with a non-existent order line - #3777 by @jxltom +- Fix `productCreate` mutation when no product type was provided - #3804 by @michaljelonek +- Enable database search in products query - #3736 by @michaljelonek +- Use authenticated user's email as default email in creating checkout - #3726 by @jxltom +- Generate voucher code if it wasn't provided in mutation - #3717 by @Kwaidan00 +- Improve limitation of vouchers by country - #3707 by @michaljelonek +- Only include canceled fulfillments for staff in fulfillment API - #3778 by @jxltom +- Support setting address as when creating customer address #3782 by @jxltom +- Fix generating slug from title - #3816 by @maarcingebala +- Add `variant` field to `OrderLine` type - #3820 by @maarcingebala + +### Core + +- Add JSON fields to store rich-text content - #3756 by @michaljelonek +- Add function to recalculate total order weight - #3755 by @Kwaidan00, @maarcingebala +- Unify cart creation logic in API and Django views - #3761, #3790 by @maarcingebala +- Unify payment creation logic in API and Django views - #3715 by @maarcingebala +- Support partially charged and refunded payments - #3735 by @jxltom +- Support partial fulfillment of ordered items - #3754 by @jxltom +- Fix applying discounts when a sale has no end date - #3595 by @cprinos + +### Dashboard 2.0 + +- Add "Discounts" section - #3654 by @dominik-zeglen +- Add "Pages" section; introduce Draftail WYSIWYG editor - #3751 by @dominik-zeglen +- Add "Shipping Methods" section - #3770 by @dominik-zeglen +- Add support for date and datetime components - #3708 by @dominik-zeglen +- Restyle app layout - #3811 by @dominik-zeglen + +### Other notable changes + +- Unify model field names related to models' public access - `publication_date` and `is_published` - #3706 by @michaljelonek +- Improve filter orders by payment status - #3749 @jxltom +- Refactor translations in emails - #3701 by @Kwaidan00 +- Use exact image versions in docker-compose - #3742 by @ashishnitinpatil +- Sort order payment and history in descending order - #3747 by @jxltom +- Disable style-loader in dev mode - #3720 by @jxltom +- Add ordering to shipping method - #3806 by @michaljelonek +- Add missing type definition for dashboard 2.0 - #3776 by @jxltom +- Add header and footer for checkout success pages #3752 by @jxltom +- Add instructions for using local assets in Docker - #3723 by @michaljelonek +- Update S3 deployment documentation to include CORS configuration note - #3743 by @NyanKiyoshi +- Fix missing migrations for is_published field of product and page model - #3757 by @jxltom +- Fix problem with l10n in Braintree payment gateway template - #3691 by @Kwaidan00 +- Fix bug where payment is not filtered from active ones when creating payment - #3732 by @jxltom +- Fix incorrect cart badge location - #3786 by @jxltom +- Fix storefront styles after bootstrap is updated to 4.3.1 - #3753 by @jxltom +- Fix logo size in different browser and devices with different sizes - #3722 by @jxltom +- Rename dumpdata file `db.json` to `populatedb_data.json` - #3810 by @maarcingebala +- Prefetch collections for product availability - #3813 by @michaljelonek +- Bump django-graphql-jwt - #3814 by @michaljelonek +- Fix generating slug from title - #3816 by @maarcingebala +- New translations: + - Estonian + - Indonesian + +## 2.3.1 + +- Fix access to private variant fields in API - #3773 by maarcingebala +- Limit access of quantity and allocated quantity to staff in GraphQL API #3780 by @jxltom + +## 2.3.0 + +### API + +- Return user's last checkout in the `User` type - #3578 by @fowczarek +- Automatically assign checkout to the logged in user - #3587 by @fowczarek +- Expose `chargeTaxesOnShipping` field in the `Shop` type - #3603 by @fowczarek +- Expose list of enabled payment gateways - #3639 by @fowczarek +- Validate uploaded files in a unified way - #3633 by @fowczarek +- Add mutation to trigger fetching tax rates - #3622 by @fowczarek +- Use USERNAME_FIELD instead of hard-code email field when resolving user - #3577 by @jxltom +- Require variant and quantity fields in `CheckoutLineInput` type - #3592 by @jxltom +- Preserve order of nodes in `get_nodes_or_error` function - #3632 by @jxltom +- Add list mutations for `Voucher` and `Sale` models - #3669 by @michaljelonek +- Use proper type for countries in `Voucher` type - #3664 by @michaljelonek +- Require email in when creating checkout in API - #3667 by @michaljelonek +- Unify returning errors in the `tokenCreate` mutation - #3666 by @michaljelonek +- Use `Date` field in Sale/Voucher inputs - #3672 by @michaljelonek +- Refactor checkout mutations - #3610 by @fowczarek +- Refactor `clean_instance`, so it does not returns errors anymore - #3597 by @akjanik +- Handle GraphqQL syntax errors - #3576 by @jxltom + +### Core + +- Refactor payments architecture - #3519 by @michaljelonek +- Improve Docker and `docker-compose` configuration - #3657 by @michaljelonek +- Allow setting payment status manually for dummy gateway in Storefront 1.0 - #3648 by @jxltom +- Infer default transaction kind from operation type - #3646 by @jxltom +- Get correct payment status for order without any payments - #3605 by @jxltom +- Add default ordering by `id` for `CartLine` model - #3593 by @jxltom +- Fix "set password" email sent to customer created in the dashboard - #3688 by @Kwaidan00 + +### Dashboard 2.0 + +- ️Add taxes section - #3622 by @dominik-zeglen +- Add drag'n'drop image upload - #3611 by @dominik-zeglen +- Unify grid handling - #3520 by @dominik-zeglen +- Add component generator - #3670 by @dominik-zeglen +- Throw Typescript errors while snapshotting - #3611 by @dominik-zeglen +- Simplify mutation's error checking - #3589 by @dominik-zeglen +- Fix order cancelling - #3624 by @dominik-zeglen +- Fix logo placement - #3602 by @dominik-zeglen + +### Other notable changes + +- Register Celery task for updating exchange rates - #3599 by @jxltom +- Fix handling different attributes with the same slug - #3626 by @jxltom +- Add missing migrations for tax rate choices - #3629 by @jxltom +- Fix `TypeError` on calling `get_client_token` - #3660 by @michaljelonek +- Make shipping required as default when creating product types - #3655 by @jxltom +- Display payment status on customer's account page in Storefront 1.0 - #3637 by @jxltom +- Make order fields sequence in Dashboard 1.0 same as in Dashboard 2.0 - #3606 by @jxltom +- Fix returning products for homepage for the currently viewing user - #3598 by @jxltom +- Allow filtering payments by status in Dashboard 1.0 - #3608 by @jxltom +- Fix typo in the definition of order status - #3649 by @jxltom +- Add margin for order notes section - #3650 by @jxltom +- Fix logo position - #3609, #3616 by @jxltom +- Storefront visual improvements - #3696 by @piotrgrundas +- Fix product list price filter - #3697 by @Kwaidan00 +- Redirect to success page after successful payment - #3693 by @Kwaidan00 + +## 2.2.0 + +### API + +- Use `PermissionEnum` as input parameter type for `permissions` field - #3434 by @maarcingebala +- Add "authorize" and "charge" mutations for payments - #3426 by @jxltom +- Add alt text to product thumbnails and background images of collections and categories - #3429 by @fowczarek +- Fix passing decimal arguments = #3457 by @fowczarek +- Allow sorting products by the update date - #3470 by @jxltom +- Validate and clear the shipping method in draft order mutations - #3472 by @fowczarek +- Change tax rate field to choice field - #3478 by @fowczarek +- Allow filtering attributes by collections - #3508 by @maarcingebala +- Resolve to `None` when empty object ID was passed as mutation argument - #3497 by @maarcingebala +- Change `errors` field type from [Error] to [Error!] - #3489 by @fowczarek +- Support creating default variant for product types that don't use multiple variants - #3505 by @fowczarek +- Validate SKU when creating a default variant - #3555 by @fowczarek +- Extract enums to separate files - #3523 by @maarcingebala + +### Core + +- Add Stripe payment gateway - #3408 by @jxltom +- Add `first_name` and `last_name` fields to the `User` model - #3101 by @fowczarek +- Improve several payment validations - #3418 by @jxltom +- Optimize payments related database queries - #3455 by @jxltom +- Add publication date to collections - #3369 by @k-brk +- Fix hard-coded site name in order PDFs - #3526 by @NyanKiyoshi +- Update favicons to the new style - #3483 by @dominik-zeglen +- Fix migrations for default currency - #3235 by @bykof +- Remove Elasticsearch from `docker-compose.yml` - #3482 by @maarcingebala +- Resort imports in tests - #3471 by @jxltom +- Fix the no shipping orders payment crash on Stripe - #3550 by @NyanKiyoshi +- Bump backend dependencies - #3557 by @maarcingebala. This PR removes security issue CVE-2019-3498 which was present in Django 2.1.4. Saleor however wasn't vulnerable to this issue as it doesn't use the affected `django.views.defaults.page_not_found()` view. +- Generate random data using the default currency - #3512 by @stephenmoloney +- New translations: + - Catalan + - Serbian + +### Dashboard 2.0 + +- Restyle product selection dialogs - #3499 by @dominik-zeglen, @maarcingebala +- Fix minor visual bugs in Dashboard 2.0 - #3433 by @dominik-zeglen +- Display warning if order draft has missing data - #3431 by @dominik-zeglen +- Add description field to collections - #3435 by @dominik-zeglen +- Add query batching - #3443 by @dominik-zeglen +- Use autocomplete fields in country selection - #3443 by @dominik-zeglen +- Add alt text to categories and collections - #3461 by @dominik-zeglen +- Use first and last name of a customer or staff member in UI - #3247 by @Bonifacy1, @dominik-zeglen +- Show error page if an object was not found - #3463 by @dominik-zeglen +- Fix simple product's inventory data saving bug - #3474 by @dominik-zeglen +- Replace `thumbnailUrl` with `thumbnail { url }` - #3484 by @dominik-zeglen +- Change "Feature on Homepage" switch behavior - #3481 by @dominik-zeglen +- Expand payment section in order view - #3502 by @dominik-zeglen +- Change TypeScript loader to speed up the build process - #3545 by @patrys + +### Bugfixes + +- Do not show `Pay For Order` if order is partly paid since partial payment is not supported - #3398 by @jxltom +- Fix attribute filters in the products category view - #3535 by @fowczarek +- Fix storybook dependencies conflict - #3544 by @dominik-zeglen + +## 2.1.0 + +### API + +- Change selected connection fields to lists - #3307 by @fowczarek +- Require pagination in connections - #3352 by @maarcingebala +- Replace Graphene view with a custom one - #3263 by @patrys +- Change `sortBy` parameter to use enum type - #3345 by @fowczarek +- Add `me` query to fetch data of a logged-in user - #3202, #3316 by @fowczarek +- Add `canFinalize` field to the Order type - #3356 by @fowczarek +- Extract resolvers and mutations to separate files - #3248 by @fowczarek +- Add VAT tax rates field to country - #3392 by @michaljelonek +- Allow creating orders without users - #3396 by @fowczarek + +### Core + +- Add Razorpay payment gatway - #3205 by @NyanKiyoshi +- Use standard tax rate as a default tax rate value - #3340 by @fowczarek +- Add description field to the Collection model - #3275 by @fowczarek +- Enforce the POST method on VAT rates fetching - #3337 by @NyanKiyoshi +- Generate thumbnails for category/collection background images - #3270 by @NyanKiyoshi +- Add warm-up support in product image creation mutation - #3276 by @NyanKiyoshi +- Fix error in the `populatedb` script when running it not from the project root - #3272 by @NyanKiyoshi +- Make Webpack rebuilds fast - #3290 by @patrys +- Skip installing Chromium to make deployment faster - #3227 by @jxltom +- Add default test runner - #3258 by @jxltom +- Add Transifex client to Pipfile - #3321 by @jxltom +- Remove additional pytest arguments in tox - #3338 by @jxltom +- Remove test warnings - #3339 by @jxltom +- Remove runtime warning when product has discount - #3310 by @jxltom +- Remove `django-graphene-jwt` warnings - #3228 by @jxltom +- Disable deprecated warnings - #3229 by @jxltom +- Add `AWS_S3_ENDPOINT_URL` setting to support DigitalOcean spaces. - #3281 by @hairychris +- Add `.gitattributes` file to hide diffs for generated files on Github - #3055 by @NyanKiyoshi +- Add database sequence reset to `populatedb` - #3406 by @michaljelonek +- Get authorized amount from succeeded auth transactions - #3417 by @jxltom +- Resort imports by `isort` - #3412 by @jxltom + +### Dashboard 2.0 + +- Add confirmation modal when leaving view with unsaved changes - #3375 by @dominik-zeglen +- Add dialog loading and error states - #3359 by @dominik-zeglen +- Split paths and urls - #3350 by @dominik-zeglen +- Derive state from props in forms - #3360 by @dominik-zeglen +- Apply debounce to autocomplete fields - #3351 by @dominik-zeglen +- Use Apollo signatures - #3353 by @dominik-zeglen +- Add order note field in the order details view - #3346 by @dominik-zeglen +- Add app-wide progress bar - #3312 by @dominik-zeglen +- Ensure that all queries are built on top of TypedQuery - #3309 by @dominik-zeglen +- Close modal windows automatically - #3296 by @dominik-zeglen +- Move URLs to separate files - #3295 by @dominik-zeglen +- Add basic filters for products and orders list - #3237 by @Bonifacy1 +- Fetch default currency from API - #3280 by @dominik-zeglen +- Add `displayName` property to components - #3238 by @Bonifacy1 +- Add window titles - #3279 by @dominik-zeglen +- Add paginator component - #3265 by @dominik-zeglen +- Update Material UI to 3.6 - #3387 by @patrys +- Upgrade React, Apollo, Webpack and Babel - #3393 by @patrys +- Add pagination for required connections - #3411 by @dominik-zeglen + +### Bugfixes + +- Fix language codes - #3311 by @jxltom +- Fix resolving empty attributes list - #3293 by @maarcingebala +- Fix range filters not being applied - #3385 by @michaljelonek +- Remove timeout for updating image height - #3344 by @jxltom +- Return error if checkout was not found - #3289 by @maarcingebala +- Solve an auto-resize conflict between Materialize and medium-editor - #3367 by @adonig +- Fix calls to `ngettext_lazy` - #3380 by @patrys +- Filter preauthorized order from succeeded transactions - #3399 by @jxltom +- Fix incorrect country code in fixtures - #3349 by @bingimar +- Fix updating background image of a collection - #3362 by @fowczarek & @dominik-zeglen + +### Docs + +- Document settings related to generating thumbnails on demand - #3329 by @NyanKiyoshi +- Improve documentation for Heroku deployment - #3170 by @raybesiga +- Update documentation on Docker deployment - #3326 by @jxltom +- Document payment gateway configuration - #3376 by @NyanKiyoshi + +## 2.0.0 + +### API + +- Add mutation to delete a customer; add `isActive` field in `customerUpdate` mutation - #3177 by @maarcingebala +- Add mutations to manage authorization keys - #3082 by @maarcingebala +- Add queries for dashboard homepage - #3146 by @maarcingebala +- Allows user to unset homepage collection - #3140 by @oldPadavan +- Use enums as permission codes - #3095 by @the-bionic +- Return absolute image URLs - #3182 by @maarcingebala +- Add `backgroundImage` field to `CategoryInput` - #3153 by @oldPadavan +- Add `dateJoined` and `lastLogin` fields in `User` type - #3169 by @maarcingebala +- Separate `parent` input field from `CategoryInput` - #3150 by @akjanik +- Remove duplicated field in Order type - #3180 by @maarcingebala +- Handle empty `backgroundImage` field in API - #3159 by @maarcingebala +- Generate name-based slug in collection mutations - #3145 by @akjanik +- Remove products field from `collectionUpdate` mutation - #3141 by @oldPadavan +- Change `items` field in `Menu` type from connection to list - #3032 by @oldPadavan +- Make `Meta.description` required in `BaseMutation` - #3034 by @oldPadavan +- Apply `textwrap.dedent` to GraphQL descriptions - #3167 by @fowczarek + +### Dashboard 2.0 + +- Add collection management - #3135 by @dominik-zeglen +- Add customer management - #3176 by @dominik-zeglen +- Add homepage view - #3155, #3178 by @Bonifacy1 and @dominik-zeglen +- Add product type management - #3052 by @dominik-zeglen +- Add site settings management - #3071 by @dominik-zeglen +- Escape node IDs in URLs - #3115 by @dominik-zeglen +- Restyle categories section - #3072 by @Bonifacy1 + +### Other + +- Change relation between `ProductType` and `Attribute` models - #3097 by @maarcingebala +- Remove `quantity-allocated` generation in `populatedb` script - #3084 by @MartinSeibert +- Handle `Money` serialization - #3131 by @Pacu2 +- Do not collect unnecessary static files - #3050 by @jxltom +- Remove host mounted volume in `docker-compose` - #3091 by @tiangolo +- Remove custom services names in `docker-compose` - #3092 by @tiangolo +- Replace COUNTRIES with countries.countries - #3079 by @neeraj1909 +- Installing dev packages in docker since tests are needed - #3078 by @jxltom +- Remove comparing string in address-form-panel template - #3074 by @tomcio1205 +- Move updating variant names to a Celery task - #3189 by @fowczarek + +### Bugfixes + +- Fix typo in `clean_input` method - #3100 by @the-bionic +- Fix typo in `ShippingMethod` model - #3099 by @the-bionic +- Remove duplicated variable declaration - #3094 by @the-bionic + +### Docs + +- Add createdb note to getting started for Windows - #3106 by @ajostergaard +- Update docs on pipenv - #3045 by @jxltom diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..4dc14a810 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2010-2018, Mirumee Software +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 000000000..c7e0e30a6 --- /dev/null +++ b/README.md @@ -0,0 +1,143 @@ +![github_saleor_readmew_header_01](https://user-images.githubusercontent.com/5421321/47800694-19bec680-dd2d-11e8-8625-2ed7c690bc13.jpg) + +
+

Saleor

+
+ +
+ E-commerce for the PWA era +
+ +
+ A modular, high performance e-commerce storefront built with GraphQL, Django, and ReactJS. +
+ +
+ +
+ Join our active, engaged community:
+ Website + | + Blog + | + Twitter + | + Gitter + | + Spectrum +
+ +
+ +
+ + Build status + + + Codecov + + + Documentation Status + + + Code style: black + +
+ + +## Table of Contents +- [What makes Saleor special?](#what-makes-saleor-special) +- [Features](#features) +- [Installation](#installation) +- [Demo](#demo) +- [Contributing](#contributing) +- [Translations](#translations) +- [Your feedback](#your-feedback) +- [License](#license) + + +## What makes Saleor special? + +Saleor is a rapidly-growing open source e-commerce platform that has served high-volume companies from branches like publishing and apparel since 2012. Based on Python and Django, the latest major update introduces a modular front end powered by a GraphQL API and written with React and TypeScript. + +## Features +- __PWA__: End users can shop offline for better sales and shopping experiences +- __GraphQL API__: Access all data from any web or mobile client using the latest technology +- __Headless commerce__: Build mobile apps, customize storefronts and externalize processes +- __UX and UI__: Designed for a user experience that rivals even the top commercial platforms +- __Dashboard__: Administrators have total control of users, processes and products +- __Orders__: A comprehensive system for orders, dispatch and refunds +- __Cart__: Advanced payment and tax options, with full control over discounts and promotions +- __Payments__: Flexible API architecture allows integration of any payment method. Comes with Braintree support out of the box. +- __Geo-adaptive__: Automatic localized pricing. Over 20 local languages. Localized checkout experience by country. +- __SEO__: Packed with features that get stores to a wider audience +- __Cloud__: Optimized for deployments using Docker +- __Analytics__: Server-side Google Analytics to report e-commerce metrics without affecting privacy + +Saleor is free and always will be. +Help us out… If you love free stuff and great software, give us a star! 🌟 + +![1 copy 2x](https://user-images.githubusercontent.com/5421321/47798207-30aeea00-dd28-11e8-9398-3d8426836a83.png) +![group 2 2x](https://user-images.githubusercontent.com/5421321/47799917-8afd7a00-dd2b-11e8-88c7-63588e25bcea.png) + + +## Installation + +Saleor requires Python 3.6+, Node.js 10.0+, PostgreSQL and OS-specific dependency tools. + +[See the Saleor docs](https://saleor.readthedocs.io) for step-by-step installation and deployment instructions. + + +## Demo + +Want to see Saleor in action? + +[View Storefront](http://demo.getsaleor.com/) | [View Dashboard (admin area)](http://demo.getsaleor.com/dashboard/) + +Or launch the demo on a free Heroku instance. + +[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) + +Login credentials: `admin@example.com`/`admin` + + +## PWA Storefront +The PWA, single-page storefront lives in a [separate repository](https://github.com/mirumee/saleor-storefront). + +[View PWA Storefront](https://pwa.getsaleor.com/) + + +## Contributing +We love your contributions and do our best to provide you with mentorship and support. If you are looking for an issue to tackle, take a look at issues labelled [`Help Wanted`](https://github.com/mirumee/saleor/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22). + +If nothing grabs your attention, check [our roadmap](https://github.com/mirumee/saleor/projects/6) or come up with your own feature. Just drop us a line or [open an issue](https://github.com/mirumee/saleor/issues/new) and we’ll work out how to handle it. + +Get more details in our [Contributing Guide](https://saleor.readthedocs.io/en/latest/contributing.html). + + +## Translations + +Did you know that Saleor is available in almost 30 languages, translated entirely by our community? + +If you'd like to help us, you can join one of our translation teams on [the localization platform Transifex](https://www.transifex.com/mirumee/saleor-1/languages/). + +The repository gets synchronized weekly with the latest contributions. + + +## Your feedback + +Do you use Saleor as an e-commerce platform? +Fill out this short survey and help us grow. It will take just a minute, but mean a lot! + +[Take a survey](https://mirumee.typeform.com/to/sOIJbJ) + + +## License + +Disclaimer: Everything you see here is open and free to use as long as you comply with the [license](https://github.com/mirumee/saleor/blob/master/LICENSE). There are no hidden charges. We promise to do our best to fix bugs and improve the code. + +Some situations do call for extra code; we can cover exotic use cases or build you a custom e-commerce appliance. + + +#### Crafted with ❤️ by [Mirumee Software](http://mirumee.com) +hello@mirumee.com diff --git a/apollo.config.js b/apollo.config.js new file mode 100644 index 000000000..ecc2a94d7 --- /dev/null +++ b/apollo.config.js @@ -0,0 +1,14 @@ +module.exports = { + client: { + addTypename: true, + includes: [ + 'saleor/static/dashboard-next/**/*.ts', + 'saleor/static/dashboard-next/**/*.tsx' + ], + name: 'storefront', + service: { + localSchemaFile: 'saleor/graphql/schema.graphql', + name: 'saleor' + } + } +}; diff --git a/assets/images/arrow-down-icon.svg b/assets/images/arrow-down-icon.svg new file mode 100644 index 000000000..373987c07 --- /dev/null +++ b/assets/images/arrow-down-icon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/images/arrow-down.svg b/assets/images/arrow-down.svg new file mode 100644 index 000000000..58cc54b36 --- /dev/null +++ b/assets/images/arrow-down.svg @@ -0,0 +1,9 @@ + + + + + diff --git a/assets/images/arrow-left.svg b/assets/images/arrow-left.svg new file mode 100644 index 000000000..214309d65 --- /dev/null +++ b/assets/images/arrow-left.svg @@ -0,0 +1 @@ + diff --git a/assets/images/arrow-select.svg b/assets/images/arrow-select.svg new file mode 100644 index 000000000..cc3e09f51 --- /dev/null +++ b/assets/images/arrow-select.svg @@ -0,0 +1,7 @@ + + + + + Svg Vector Icons : http://www.onlinewebfonts.com/icon + + diff --git a/assets/images/arrow-up-icon.svg b/assets/images/arrow-up-icon.svg new file mode 100644 index 000000000..f9c576d4a --- /dev/null +++ b/assets/images/arrow-up-icon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/images/arrow-up.svg b/assets/images/arrow-up.svg new file mode 100644 index 000000000..9d5a9dad0 --- /dev/null +++ b/assets/images/arrow-up.svg @@ -0,0 +1,9 @@ + + + + + diff --git a/assets/images/avatars/avatar1.png b/assets/images/avatars/avatar1.png new file mode 100644 index 000000000..6fd5af7b3 Binary files /dev/null and b/assets/images/avatars/avatar1.png differ diff --git a/assets/images/avatars/avatar10.png b/assets/images/avatars/avatar10.png new file mode 100644 index 000000000..8f4b8466c Binary files /dev/null and b/assets/images/avatars/avatar10.png differ diff --git a/assets/images/avatars/avatar11.png b/assets/images/avatars/avatar11.png new file mode 100644 index 000000000..d512fcf7d Binary files /dev/null and b/assets/images/avatars/avatar11.png differ diff --git a/assets/images/avatars/avatar12.png b/assets/images/avatars/avatar12.png new file mode 100644 index 000000000..c3b169997 Binary files /dev/null and b/assets/images/avatars/avatar12.png differ diff --git a/assets/images/avatars/avatar2.png b/assets/images/avatars/avatar2.png new file mode 100644 index 000000000..8a09b3b7b Binary files /dev/null and b/assets/images/avatars/avatar2.png differ diff --git a/assets/images/avatars/avatar3.png b/assets/images/avatars/avatar3.png new file mode 100644 index 000000000..5c87d41fb Binary files /dev/null and b/assets/images/avatars/avatar3.png differ diff --git a/assets/images/avatars/avatar4.png b/assets/images/avatars/avatar4.png new file mode 100644 index 000000000..54754d934 Binary files /dev/null and b/assets/images/avatars/avatar4.png differ diff --git a/assets/images/avatars/avatar5.png b/assets/images/avatars/avatar5.png new file mode 100644 index 000000000..a5a36542d Binary files /dev/null and b/assets/images/avatars/avatar5.png differ diff --git a/assets/images/avatars/avatar6.png b/assets/images/avatars/avatar6.png new file mode 100644 index 000000000..b56f56bf2 Binary files /dev/null and b/assets/images/avatars/avatar6.png differ diff --git a/assets/images/avatars/avatar7.png b/assets/images/avatars/avatar7.png new file mode 100644 index 000000000..17ecedc77 Binary files /dev/null and b/assets/images/avatars/avatar7.png differ diff --git a/assets/images/avatars/avatar8.png b/assets/images/avatars/avatar8.png new file mode 100644 index 000000000..e6cc141bf Binary files /dev/null and b/assets/images/avatars/avatar8.png differ diff --git a/assets/images/avatars/avatar9.png b/assets/images/avatars/avatar9.png new file mode 100644 index 000000000..e4cde6c4e Binary files /dev/null and b/assets/images/avatars/avatar9.png differ diff --git a/assets/images/block1.jpg b/assets/images/block1.jpg new file mode 100644 index 000000000..ddb6ece3a Binary files /dev/null and b/assets/images/block1.jpg differ diff --git a/assets/images/block2.jpg b/assets/images/block2.jpg new file mode 100644 index 000000000..4712727da Binary files /dev/null and b/assets/images/block2.jpg differ diff --git a/assets/images/block3.jpg b/assets/images/block3.jpg new file mode 100644 index 000000000..e0726d4c5 Binary files /dev/null and b/assets/images/block3.jpg differ diff --git a/assets/images/checkout-bg.png b/assets/images/checkout-bg.png new file mode 100644 index 000000000..e99bfb687 Binary files /dev/null and b/assets/images/checkout-bg.png differ diff --git a/assets/images/checkout-bg2x.png b/assets/images/checkout-bg2x.png new file mode 100644 index 000000000..87adda555 Binary files /dev/null and b/assets/images/checkout-bg2x.png differ diff --git a/assets/images/checkout.svg b/assets/images/checkout.svg new file mode 100644 index 000000000..580d8bbbb --- /dev/null +++ b/assets/images/checkout.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/chevron-down.svg b/assets/images/chevron-down.svg new file mode 100644 index 000000000..3ae8b304e --- /dev/null +++ b/assets/images/chevron-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/chevron-up.svg b/assets/images/chevron-up.svg new file mode 100644 index 000000000..ff63bd5a7 --- /dev/null +++ b/assets/images/chevron-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/close.svg b/assets/images/close.svg new file mode 100644 index 000000000..9e64a2a42 --- /dev/null +++ b/assets/images/close.svg @@ -0,0 +1 @@ + diff --git a/assets/images/confirm-order-bg.png b/assets/images/confirm-order-bg.png new file mode 100644 index 000000000..72ff27e1f Binary files /dev/null and b/assets/images/confirm-order-bg.png differ diff --git a/assets/images/confirm-order-bg2x.png b/assets/images/confirm-order-bg2x.png new file mode 100644 index 000000000..3348e85e0 Binary files /dev/null and b/assets/images/confirm-order-bg2x.png differ diff --git a/assets/images/delete.svg b/assets/images/delete.svg new file mode 100644 index 000000000..003d4187f --- /dev/null +++ b/assets/images/delete.svg @@ -0,0 +1,13 @@ + + + diff --git a/assets/images/dribbble-logo.svg b/assets/images/dribbble-logo.svg new file mode 100644 index 000000000..89f2ce28b --- /dev/null +++ b/assets/images/dribbble-logo.svg @@ -0,0 +1,97 @@ + + + +image/svg+xml diff --git a/assets/images/edit.svg b/assets/images/edit.svg new file mode 100644 index 000000000..c81d49328 --- /dev/null +++ b/assets/images/edit.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/images/empty-checkout-bg.png b/assets/images/empty-checkout-bg.png new file mode 100644 index 000000000..f9252c0de Binary files /dev/null and b/assets/images/empty-checkout-bg.png differ diff --git a/assets/images/empty-checkout-bg2x.png b/assets/images/empty-checkout-bg2x.png new file mode 100644 index 000000000..7df4c9714 Binary files /dev/null and b/assets/images/empty-checkout-bg2x.png differ diff --git a/assets/images/facebook-logo.svg b/assets/images/facebook-logo.svg new file mode 100644 index 000000000..45c2ee19f --- /dev/null +++ b/assets/images/facebook-logo.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/favicon.svg b/assets/images/favicon.svg new file mode 100644 index 000000000..edda289bb --- /dev/null +++ b/assets/images/favicon.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/filter-icon.svg b/assets/images/filter-icon.svg new file mode 100644 index 000000000..faa47d97a --- /dev/null +++ b/assets/images/filter-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/assets/images/gallery-arrow.svg b/assets/images/gallery-arrow.svg new file mode 100644 index 000000000..3be1a489c --- /dev/null +++ b/assets/images/gallery-arrow.svg @@ -0,0 +1,18 @@ + +Group +Created using Figma + + + + + + + + + + + + + + + diff --git a/assets/images/github-logo.svg b/assets/images/github-logo.svg new file mode 100644 index 000000000..c8a7210be --- /dev/null +++ b/assets/images/github-logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/google-logo.svg b/assets/images/google-logo.svg new file mode 100644 index 000000000..800402771 --- /dev/null +++ b/assets/images/google-logo.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/instagram-logo.svg b/assets/images/instagram-logo.svg new file mode 100644 index 000000000..3f4f4ed61 --- /dev/null +++ b/assets/images/instagram-logo.svg @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/assets/images/linkedin-logo.svg b/assets/images/linkedin-logo.svg new file mode 100644 index 000000000..56f547317 --- /dev/null +++ b/assets/images/linkedin-logo.svg @@ -0,0 +1 @@ +icon-linkedin \ No newline at end of file diff --git a/assets/images/loader.svg b/assets/images/loader.svg new file mode 100644 index 000000000..a2457c3ad --- /dev/null +++ b/assets/images/loader.svg @@ -0,0 +1,46 @@ + + + + + + diff --git a/assets/images/login-background.svg b/assets/images/login-background.svg new file mode 100644 index 000000000..f3489b8b5 --- /dev/null +++ b/assets/images/login-background.svg @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/login-bg.png b/assets/images/login-bg.png new file mode 100644 index 000000000..651dacde1 Binary files /dev/null and b/assets/images/login-bg.png differ diff --git a/assets/images/login-bg2x.png b/assets/images/login-bg2x.png new file mode 100644 index 000000000..41766f7df Binary files /dev/null and b/assets/images/login-bg2x.png differ diff --git a/assets/images/logo-dark.svg b/assets/images/logo-dark.svg new file mode 100644 index 000000000..309d7c895 --- /dev/null +++ b/assets/images/logo-dark.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/logo-light.svg b/assets/images/logo-light.svg new file mode 100644 index 000000000..60f632623 --- /dev/null +++ b/assets/images/logo-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/logo-white.svg b/assets/images/logo-white.svg new file mode 100644 index 000000000..d01d84844 --- /dev/null +++ b/assets/images/logo-white.svg @@ -0,0 +1 @@ + diff --git a/assets/images/meetup-logo.svg b/assets/images/meetup-logo.svg new file mode 100644 index 000000000..8bc2c38b9 --- /dev/null +++ b/assets/images/meetup-logo.svg @@ -0,0 +1,72 @@ + + + + + + image/svg+xml + + + + + + + meetup + Created with Sketch. + + + + + + + diff --git a/assets/images/mobile-menu.svg b/assets/images/mobile-menu.svg new file mode 100644 index 000000000..cf6d6688b --- /dev/null +++ b/assets/images/mobile-menu.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/no-results-bg.svg b/assets/images/no-results-bg.svg new file mode 100644 index 000000000..26f94ff44 --- /dev/null +++ b/assets/images/no-results-bg.svg @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/not-found-404.svg b/assets/images/not-found-404.svg new file mode 100644 index 000000000..3d240f77f --- /dev/null +++ b/assets/images/not-found-404.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/pass-invisible.svg b/assets/images/pass-invisible.svg new file mode 100644 index 000000000..454002a2d --- /dev/null +++ b/assets/images/pass-invisible.svg @@ -0,0 +1,19 @@ + + + + + + diff --git a/assets/images/pass-visible.svg b/assets/images/pass-visible.svg new file mode 100644 index 000000000..7c71d26a5 --- /dev/null +++ b/assets/images/pass-visible.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/assets/images/photo-icon.svg b/assets/images/photo-icon.svg new file mode 100644 index 000000000..57ee59835 --- /dev/null +++ b/assets/images/photo-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/placeholder1080x1080.png b/assets/images/placeholder1080x1080.png new file mode 100644 index 000000000..8fd6bf607 Binary files /dev/null and b/assets/images/placeholder1080x1080.png differ diff --git a/assets/images/placeholder120x120.png b/assets/images/placeholder120x120.png new file mode 100644 index 000000000..9be8593db Binary files /dev/null and b/assets/images/placeholder120x120.png differ diff --git a/assets/images/placeholder255x255.png b/assets/images/placeholder255x255.png new file mode 100644 index 000000000..90451c513 Binary files /dev/null and b/assets/images/placeholder255x255.png differ diff --git a/assets/images/placeholder540x540.png b/assets/images/placeholder540x540.png new file mode 100644 index 000000000..409d9bee0 Binary files /dev/null and b/assets/images/placeholder540x540.png differ diff --git a/assets/images/placeholder60x60.png b/assets/images/placeholder60x60.png new file mode 100644 index 000000000..a2efcc0bf Binary files /dev/null and b/assets/images/placeholder60x60.png differ diff --git a/assets/images/reset-bg.png b/assets/images/reset-bg.png new file mode 100644 index 000000000..3e824a034 Binary files /dev/null and b/assets/images/reset-bg.png differ diff --git a/assets/images/sale-bg.svg b/assets/images/sale-bg.svg new file mode 100644 index 000000000..6fabb7b39 --- /dev/null +++ b/assets/images/sale-bg.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/sample-product.jpg b/assets/images/sample-product.jpg new file mode 100644 index 000000000..1db06734f Binary files /dev/null and b/assets/images/sample-product.jpg differ diff --git a/assets/images/sample-product2.jpg b/assets/images/sample-product2.jpg new file mode 100644 index 000000000..aedf9d12b Binary files /dev/null and b/assets/images/sample-product2.jpg differ diff --git a/assets/images/search.svg b/assets/images/search.svg new file mode 100755 index 000000000..60e676e33 --- /dev/null +++ b/assets/images/search.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/twitter-logo.svg b/assets/images/twitter-logo.svg new file mode 100644 index 000000000..2fa8be814 --- /dev/null +++ b/assets/images/twitter-logo.svg @@ -0,0 +1,2 @@ + + diff --git a/assets/images/what.svg b/assets/images/what.svg new file mode 100644 index 000000000..52ca6ab45 --- /dev/null +++ b/assets/images/what.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..a8fca2178 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,32039 @@ +{ + "name": "saleor", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@apollographql/apollo-tools": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.3.5.tgz", + "integrity": "sha512-5ySiiNT2EIwxGKWyoAOnibCPUXvbxKOVxiPMK4uIXmvF+qbGNleQWP+vekciiAmCCESPmGd5szscRwDm4G/NNg==", + "requires": { + "apollo-env": "0.4.0" + } + }, + "@apollographql/graphql-language-service-interface": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@apollographql/graphql-language-service-interface/-/graphql-language-service-interface-2.0.2.tgz", + "integrity": "sha512-28wePK0hlIVjgmvMXMAUq8qRSjz9O+6lqFp4PzOTHtfJfSsjVe9EfjF98zTpHsTgT3HcOxmbqDZZy8jlXtOqEA==", + "requires": { + "@apollographql/graphql-language-service-parser": "^2.0.0", + "@apollographql/graphql-language-service-types": "^2.0.0", + "@apollographql/graphql-language-service-utils": "^2.0.2" + } + }, + "@apollographql/graphql-language-service-parser": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@apollographql/graphql-language-service-parser/-/graphql-language-service-parser-2.0.2.tgz", + "integrity": "sha512-rpTPrEJu1PMaRQxz5P8BZWsixNNhYloS0H0dwTxNBuE3qctbARvR7o8UCKLsmKgTbo+cz3T3a6IAsWlkHgMWGg==", + "requires": { + "@apollographql/graphql-language-service-types": "^2.0.0" + } + }, + "@apollographql/graphql-language-service-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@apollographql/graphql-language-service-types/-/graphql-language-service-types-2.0.2.tgz", + "integrity": "sha512-vE+Dz8pG+Xa1Z2nMl82LoO66lQ6JqBUjaXqLDvS3eMjvA3N4hf+YUDOWfPdNZ0zjhHhHXzUIIZCkax6bXfFbzQ==" + }, + "@apollographql/graphql-language-service-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@apollographql/graphql-language-service-utils/-/graphql-language-service-utils-2.0.2.tgz", + "integrity": "sha512-fDj5rWlTi/czvUS5t7V7I45Ai6bOO3Z7JARYj21Y2xxfbRGtJi6h8FvLX0N/EbzQgo/fiZc/HAhtfwn+OCjD7A==", + "requires": { + "@apollographql/graphql-language-service-types": "^2.0.0" + } + }, + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.2.0.tgz", + "integrity": "sha512-7pvAdC4B+iKjFFp9Ztj0QgBndJ++qaMeonT185wAqUnhipw8idm9Rv1UMyBuKtYjfl6ORNkgEgcsYLfHX/GpLw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.0", + "@babel/helpers": "^7.2.0", + "@babel/parser": "^7.2.0", + "@babel/template": "^7.1.2", + "@babel/traverse": "^7.1.6", + "@babel/types": "^7.2.0", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.10", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", + "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "dev": true, + "requires": { + "@babel/types": "^7.2.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/traverse": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", + "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.6", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.6", + "@babel/types": "^7.1.6", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", + "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "dev": true, + "requires": { + "@babel/types": "^7.2.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", + "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.1.0", + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-builder-react-jsx": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.0.0.tgz", + "integrity": "sha512-ebJ2JM6NAKW0fQEqN8hOLxK84RbRz9OkUhGS/Xd5u56ejMfVbayJ4+LykERZCOUM6faa6Fp3SZNX3fcT16MKHw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "esutils": "^2.0.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-call-delegate": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz", + "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.0.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", + "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "dev": true, + "requires": { + "@babel/types": "^7.2.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/traverse": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", + "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.6", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.6", + "@babel/types": "^7.1.6", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.2.1.tgz", + "integrity": "sha512-EsEP7XLFmcJHjcuFYBxYD1FkP0irC8C9fsrt2tX/jrAi/eTnFI6DOPgVFb+WREeg1GboF+Ib+nCHbGBodyAXSg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-define-map": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz", + "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.0.0", + "lodash": "^4.17.10" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", + "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", + "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "dev": true, + "requires": { + "@babel/types": "^7.2.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/traverse": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", + "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.6", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.6", + "@babel/types": "^7.1.6", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz", + "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz", + "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-module-transforms": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz", + "integrity": "sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0", + "lodash": "^4.17.10" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0.tgz", + "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", + "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", + "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "dev": true, + "requires": { + "@babel/types": "^7.2.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/traverse": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", + "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.6", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.6", + "@babel/types": "^7.1.6", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-replace-supers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz", + "integrity": "sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", + "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "dev": true, + "requires": { + "@babel/types": "^7.2.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/traverse": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", + "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.6", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.6", + "@babel/types": "^7.1.6", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-simple-access": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", + "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "dev": true, + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helper-wrap-function": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", + "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.2.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", + "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "dev": true, + "requires": { + "@babel/types": "^7.2.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/traverse": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", + "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.6", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.6", + "@babel/types": "^7.1.6", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/helpers": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.2.0.tgz", + "integrity": "sha512-Fr07N+ea0dMcMN8nFpuK6dUIT7/ivt9yKQdEEnjVS83tG2pHwPi03gYmk/tyuwONnZ+sY+GFFPlWGgCtW1hF9A==", + "dev": true, + "requires": { + "@babel/template": "^7.1.2", + "@babel/traverse": "^7.1.5", + "@babel/types": "^7.2.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", + "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "dev": true, + "requires": { + "@babel/types": "^7.2.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/traverse": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", + "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.6", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.6", + "@babel/types": "^7.1.6", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + } + } + }, + "@babel/parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.0.0.tgz", + "integrity": "sha512-RgJhNdRinpO8zibnoHbzTTexNs4c8ROkXFBanNDZTLHjwbdLk8J5cJSKulx/bycWTLYmKVNCkxRtVCoJnqPk+g==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", + "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.2.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.2.1.tgz", + "integrity": "sha512-/4FKFChkQ2Jgb8lBDsvFX496YTi7UWTetVgS8oJUpX1e/DlaoeEK57At27ug8Hu2zI2g8bzkJ+8k9qrHZRPGPA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.2.1", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.2.0.tgz", + "integrity": "sha512-yrDmvCsOMvNPpjCC6HMseiac2rUuQdeNqUyPU+3QbW7gLg/APX0c/7l9i/aulSICJQOkP6/4EHxkcB4d4DqZhg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/plugin-syntax-decorators": "^7.2.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", + "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.2.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-1L5mWLSvR76XYUQJXkd/EEQgjq8HHRP6lQuZTTg0VA4tTGPpGemmCdAfQIz1rzEuWAm+ecP8PyyEm30jC1eQCg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz", + "integrity": "sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.2.0" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", + "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.2.0.tgz", + "integrity": "sha512-UxYaGXYQ7rrKJS/PxIKRkv3exi05oH7rokBAsmCSsCxz1sVPZ7Fu6FzKoGgUvmY+0YgSkYHgUoCh5R5bCNBQlw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-decorators": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.2.0.tgz", + "integrity": "sha512-38QdqVoXdHUQfTpZo3rQwqQdWtCn5tMv4uV6r2RMfTqNBuv4ZBhz79SfaQWKTVmxHjeFv/DnXVC/+agHCklYWA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.0.0.tgz", + "integrity": "sha512-Gt9xNyRrCHCiyX/ZxDGOcBnlJl0I3IWicpZRC4CdC0P5a/I07Ya2OAMEBU+J7GmRFVmIetqEYRko6QYRuKOESw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-flow": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.2.0.tgz", + "integrity": "sha512-r6YMuZDWLtLlu0kqIim5o/3TNRAlWb073HwT3e2nKf9I8IIvOggPrnILYPsrrKilmn/mYEMCf/Z07w3yQJF6dg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", + "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz", + "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + } + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.2.0.tgz", + "integrity": "sha512-WhKr6yu6yGpGcNMVgIBuI9MkredpVc7Y3YR4UzEZmDztHoL6wV56YBHLhWnjO1EvId1B32HrD3DRFc+zSoKI1g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", + "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.2.0.tgz", + "integrity": "sha512-CEHzg4g5UraReozI9D4fblBYABs7IM6UerAVG7EJVrTLC5keh00aEuLUT+O40+mJCEzaXkYfTCUKIyeDfMOFFQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", + "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.2.0.tgz", + "integrity": "sha512-vDTgf19ZEV6mx35yiPJe4fS02mPQUUcBNwWQSZFXSzTSbsJFQvHt7DqyS3LK8oOWALFOsJ+8bbqBgkirZteD5Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.10" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.2.0.tgz", + "integrity": "sha512-aPCEkrhJYebDXcGTAP+cdUENkH7zqOlgbKwLbghjjHpJRJBWM/FSlCjMoPGA8oUdiMfOrk3+8EFPLLb5r7zj2w==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.1.0", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", + "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.2.0.tgz", + "integrity": "sha512-coVO2Ayv7g0qdDbrNiadE4bU7lvCd9H539m2gMknyVjjMdwF/iCOM7R+E8PkntoqLkltO0rk+3axhpp/0v68VQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz", + "integrity": "sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.1.3" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz", + "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", + "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.2.3.tgz", + "integrity": "sha512-xnt7UIk9GYZRitqCnsVMjQK1O2eKZwFB3CvvHjf5SGx6K6vr/MScCKQDnf1DxRaj501e3pXjti+inbSXX2ZUoQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.2.0" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz", + "integrity": "sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz", + "integrity": "sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/plugin-transform-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", + "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz", + "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz", + "integrity": "sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.2.0.tgz", + "integrity": "sha512-aYJwpAhoK9a+1+O625WIjvMY11wkB/ok0WClVwmeo3mCjcNRjt+/8gHWrB5i+00mUju0gWsBkQnPpdvQ7PImmQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", + "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz", + "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz", + "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.2.0.tgz", + "integrity": "sha512-kB9+hhUidIgUoBQ0MsxMewhzr8i60nMa2KgeJKQWYrqQpqcBYtnpR+JgkadZVZoaEZ/eKu9mclFaVwhRpLNSzA==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.1.0", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + }, + "dependencies": { + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@babel/plugin-transform-react-constant-elements": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.2.0.tgz", + "integrity": "sha512-YYQFg6giRFMsZPKUM9v+VcHOdfSQdz9jHCx3akAi3UYgyjndmdYGSXylQ/V+HswQt4fL8IklchD9HTsaOCrWQQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz", + "integrity": "sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + } + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.2.0.tgz", + "integrity": "sha512-h/fZRel5wAfCqcKgq3OhbmYaReo7KkoJBpt8XnvpS7wqaNMqtw5xhxutzcm35iMUWucfAdT/nvGTsWln0JTg2Q==", + "dev": true, + "requires": { + "@babel/helper-builder-react-jsx": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + } + } + }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.2.0.tgz", + "integrity": "sha512-v6S5L/myicZEy+jr6ielB0OR8h+EH/1QFx/YJ7c7Ua+7lqsjj/vW6fD5FR9hB/6y7mGbfT4vAURn3xqBxsUcdg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + } + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.2.0.tgz", + "integrity": "sha512-A32OkKTp4i5U6aE88GwwcuV4HAprUgHcTq0sSafLxjr6AW0QahrCRCjxogkbbcdtpbXkuTOlgpjophCxb6sh5g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + } + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz", + "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==", + "dev": true, + "requires": { + "regenerator-transform": "^0.13.3" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.1.0.tgz", + "integrity": "sha512-WFLMgzu5DLQEah0lKTJzYb14vd6UiES7PTnXcvrPZ1VrwFeJ+mTbvr65fFAsXYMt2bIoOoC0jk76zY1S7HZjUg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "resolve": "^1.8.1", + "semver": "^5.5.1" + }, + "dependencies": { + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "resolve": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", + "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", + "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.0.tgz", + "integrity": "sha512-7TtPIdwjS/i5ZBlNiQePQCovDh9pAhVbp/nGVRBZuUdBiVRThyyLend3OHobc0G+RLCPPAN70+z/MAMhsgJd/A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", + "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz", + "integrity": "sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", + "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.2.0.tgz", + "integrity": "sha512-EnI7i2/gJ7ZNr2MuyvN2Hu+BHJENlxWte5XygPvfj/MbvtOkWor9zcnHpMMQL2YYaaCcqtIvJUyJ7QVfoGs7ew==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-typescript": "^7.2.0" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz", + "integrity": "sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0", + "regexpu-core": "^4.1.3" + } + }, + "@babel/preset-env": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.2.0.tgz", + "integrity": "sha512-haGR38j5vOGVeBatrQPr3l0xHbs14505DcM57cbJy48kgMFvvHHoYEhHuRV+7vi559yyAUAVbTWzbK/B/pzJng==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.2.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.2.0", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.2.0", + "@babel/plugin-transform-block-scoped-functions": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.2.0", + "@babel/plugin-transform-classes": "^7.2.0", + "@babel/plugin-transform-computed-properties": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.2.0", + "@babel/plugin-transform-dotall-regex": "^7.2.0", + "@babel/plugin-transform-duplicate-keys": "^7.2.0", + "@babel/plugin-transform-exponentiation-operator": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.2.0", + "@babel/plugin-transform-function-name": "^7.2.0", + "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-modules-amd": "^7.2.0", + "@babel/plugin-transform-modules-commonjs": "^7.2.0", + "@babel/plugin-transform-modules-systemjs": "^7.2.0", + "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-new-target": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.2.0", + "@babel/plugin-transform-parameters": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.2.0", + "@babel/plugin-transform-spread": "^7.2.0", + "@babel/plugin-transform-sticky-regex": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.2.0", + "@babel/plugin-transform-typeof-symbol": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.2.0", + "browserslist": "^4.3.4", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.3.0" + }, + "dependencies": { + "browserslist": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.5.tgz", + "integrity": "sha512-z9ZhGc3d9e/sJ9dIx5NFXkKoaiQTnrvrMsN3R1fGb1tkWWNSz12UewJn9TNxGo1l7J23h0MRaPmk7jfeTZYs1w==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000912", + "electron-to-chromium": "^1.3.86", + "node-releases": "^1.0.5" + } + }, + "caniuse-lite": { + "version": "1.0.30000914", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000914.tgz", + "integrity": "sha512-qqj0CL1xANgg6iDOybiPTIxtsmAnfIky9mBC35qgWrnK4WwmhqfpmkDYMYgwXJ8LRZ3/2jXlCntulO8mBaAgSg==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.88", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.88.tgz", + "integrity": "sha512-UPV4NuQMKeUh1S0OWRvwg0PI8ASHN9kBC8yDTk1ROXLC85W5GnhTRu/MZu3Teqx3JjlQYuckuHYXSUSgtb3J+A==", + "dev": true + } + } + }, + "@babel/preset-flow": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.0.0.tgz", + "integrity": "sha512-bJOHrYOPqJZCkPVbG1Lot2r5OSsB+iUOaxiHdlOeB1yPWS6evswVHwvkDLZ54WTaTRIk89ds0iHmGZSnxlPejQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0" + } + }, + "@babel/preset-react": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.0.0.tgz", + "integrity": "sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + } + } + }, + "@babel/preset-typescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.1.0.tgz", + "integrity": "sha512-LYveByuF9AOM8WrsNne5+N79k1YxjNB6gmpCQsnuSBAcV8QUeB+ZUxQzL7Rz7HksPbahymKkq2qBR+o36ggFZA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.1.0" + } + }, + "@babel/runtime": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.2.0.tgz", + "integrity": "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg==", + "requires": { + "regenerator-runtime": "^0.12.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" + } + } + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + } + } + }, + "@babel/traverse": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", + "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.6", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.6", + "@babel/types": "^7.1.6", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", + "dev": true + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", + "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "dev": true, + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "@emotion/cache": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-0.8.8.tgz", + "integrity": "sha512-yaQQjNAVkKclMX6D8jTU3rhQKjCnXU1KS+Ok0lgZcarGHI2yydU/kKHyF3PZnQhbTpIFBK5W4+HmLCtCie7ESw==", + "dev": true, + "requires": { + "@emotion/sheet": "^0.8.1", + "@emotion/stylis": "^0.7.1", + "@emotion/utils": "^0.8.2" + } + }, + "@emotion/core": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@emotion/core/-/core-0.13.1.tgz", + "integrity": "sha512-5qzKP6bTe2Ah7Wvh1sgtzgy6ycdpxwgMAjQ/K/VxvqBxveG9PCpq+Z0GdVg7Houb1AwYjTfNtXstjSk4sqi/7g==", + "dev": true, + "requires": { + "@emotion/cache": "^0.8.8", + "@emotion/css": "^0.9.8", + "@emotion/serialize": "^0.9.1", + "@emotion/sheet": "^0.8.1", + "@emotion/utils": "^0.8.2" + } + }, + "@emotion/css": { + "version": "0.9.8", + "resolved": "https://registry.npmjs.org/@emotion/css/-/css-0.9.8.tgz", + "integrity": "sha512-Stov3+9+KWZAte/ED9Hts3r4DVBADd5erDrhrywokM31ctQsRPD3qk8W4d1ca48ry57g/nc0qUHNis/xd1SoFg==", + "dev": true, + "requires": { + "@emotion/serialize": "^0.9.1", + "@emotion/utils": "^0.8.2" + } + }, + "@emotion/hash": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.6.6.tgz", + "integrity": "sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ==", + "dev": true + }, + "@emotion/is-prop-valid": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.6.8.tgz", + "integrity": "sha512-IMSL7ekYhmFlILXcouA6ket3vV7u9BqStlXzbKOF9HBtpUPMMlHU+bBxrLOa2NvleVwNIxeq/zL8LafLbeUXcA==", + "dev": true, + "requires": { + "@emotion/memoize": "^0.6.6" + } + }, + "@emotion/memoize": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.6.6.tgz", + "integrity": "sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ==", + "dev": true + }, + "@emotion/provider": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@emotion/provider/-/provider-0.11.2.tgz", + "integrity": "sha512-y/BRd6cJ9tyxsy4EK8WheD2X1/RfmudMYILpa8sgI3dKCjVWeEZuQM17wXRVEyhrisaRaIp1qT4h0eWUaaqNLg==", + "dev": true, + "requires": { + "@emotion/cache": "^0.8.8", + "@emotion/weak-memoize": "^0.1.3" + } + }, + "@emotion/serialize": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.9.1.tgz", + "integrity": "sha512-zTuAFtyPvCctHBEL8KZ5lJuwBanGSutFEncqLn/m9T1a6a93smBStK+bZzcNPgj4QS8Rkw9VTwJGhRIUVO8zsQ==", + "dev": true, + "requires": { + "@emotion/hash": "^0.6.6", + "@emotion/memoize": "^0.6.6", + "@emotion/unitless": "^0.6.7", + "@emotion/utils": "^0.8.2" + } + }, + "@emotion/sheet": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-0.8.1.tgz", + "integrity": "sha512-p82hFBHbNkPLZ410HOeaRJZMrN1uh9rI7JAaRXIp62PP5evspPXyi3xYtxZc1+sCSlwjnQPuOIa6N88iJNtPXw==", + "dev": true + }, + "@emotion/styled": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-0.10.6.tgz", + "integrity": "sha512-DFNW8jlMjy1aYCj/PKsvBoJVZAQXzjmSCwtKXLs31qZzNPaUEPbTYSIKnMUtIiAOYsu0pUTGXM+l0a+MYNm4lA==", + "dev": true, + "requires": { + "@emotion/styled-base": "^0.10.6" + } + }, + "@emotion/styled-base": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/@emotion/styled-base/-/styled-base-0.10.6.tgz", + "integrity": "sha512-7RfdJm2oEXiy3isFRY63mHRmWWjScFXFoZTFkCJPaL8NhX+H724WwIoQOt3WA1Jd+bb97xkJg31JbYYsSqnEaQ==", + "dev": true, + "requires": { + "@emotion/is-prop-valid": "^0.6.8", + "@emotion/serialize": "^0.9.1", + "@emotion/utils": "^0.8.2" + } + }, + "@emotion/stylis": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.7.1.tgz", + "integrity": "sha512-/SLmSIkN13M//53TtNxgxo57mcJk/UJIDFRKwOiLIBEyBHEcipgR6hNMQ/59Sl4VjCJ0Z/3zeAZyvnSLPG/1HQ==", + "dev": true + }, + "@emotion/unitless": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.6.7.tgz", + "integrity": "sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg==", + "dev": true + }, + "@emotion/utils": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.8.2.tgz", + "integrity": "sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw==", + "dev": true + }, + "@emotion/weak-memoize": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.1.3.tgz", + "integrity": "sha512-QsYGKdhhuDFNq7bjm2r44y0mp5xW3uO3csuTPDWZc0OIiMQv+AIY5Cqwd4mJiC5N8estVl7qlvOx1hbtOuUWbw==", + "dev": true + }, + "@endemolshinegroup/cosmiconfig-typescript-loader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.0.tgz", + "integrity": "sha512-qMbu0alhP2VmxYhO9rwJDAEDhBIa2lN+aRxRTBbvvk1sxuzAj3RZNuvtlKkM8CPBlE9PBAjCV3l5opXP1wPIZw==", + "requires": { + "lodash.get": "^4", + "ts-node": "^7" + } + }, + "@heroku-cli/color": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@heroku-cli/color/-/color-1.1.14.tgz", + "integrity": "sha512-2JYy//YE2YINTe21hpdVMBNc7aYFkgDeY9JUz/BCjFZmYLn0UjGaCc4BpTcMGXNJwuqoUenw2WGOFGHsJqlIDw==", + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "strip-ansi": "^5.0.0", + "supports-color": "^5.5.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + } + } + }, + "@jest/console": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz", + "integrity": "sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg==", + "dev": true, + "requires": { + "@jest/source-map": "^24.3.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "@jest/core": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.7.1.tgz", + "integrity": "sha512-ivlZ8HX/FOASfHcb5DJpSPFps8ydfUYzLZfgFFqjkLijYysnIEOieg72YRhO4ZUB32xu40hsSMmaw+IGYeKONA==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.7.0", + "jest-config": "^24.7.1", + "jest-haste-map": "^24.7.1", + "jest-message-util": "^24.7.1", + "jest-regex-util": "^24.3.0", + "jest-resolve-dependencies": "^24.7.1", + "jest-runner": "^24.7.1", + "jest-runtime": "^24.7.1", + "jest-snapshot": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", + "jest-watcher": "^24.7.1", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-diff": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.7.0.tgz", + "integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.3.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-get-type": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", + "dev": true + }, + "jest-matcher-utils": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz", + "integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.7.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-message-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz", + "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-snapshot": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.7.1.tgz", + "integrity": "sha512-8Xk5O4p+JsZZn4RCNUS3pxA+ORKpEKepE+a5ejIKrId9CwrVN0NY+vkqEkXqlstA5NMBkNahXkR/4qEBy0t5yA==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "expect": "^24.7.1", + "jest-diff": "^24.7.0", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-resolve": "^24.7.1", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.7.0", + "semver": "^5.5.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "pretty-format": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "@jest/environment": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.7.1.tgz", + "integrity": "sha512-wmcTTYc4/KqA+U5h1zQd5FXXynfa7VGP2NfF+c6QeGJ7c+2nStgh65RQWNX62SC716dTtqheTRrZl0j+54oGHw==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.7.1", + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "jest-mock": "^24.7.0" + } + }, + "@jest/fake-timers": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.7.1.tgz", + "integrity": "sha512-4vSQJDKfR2jScOe12L9282uiwuwQv9Lk7mgrCSZHA9evB9efB/qx8i0KJxsAKtp8fgJYBJdYY7ZU6u3F4/pyjA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-mock": "^24.7.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-message-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz", + "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "@jest/reporters": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.7.1.tgz", + "integrity": "sha512-bO+WYNwHLNhrjB9EbPL4kX/mCCG4ZhhfWmO3m4FSpbgr7N83MFejayz30kKjgqr7smLyeaRFCBQMbXpUgnhAJw==", + "dev": true, + "requires": { + "@jest/environment": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-api": "^2.1.1", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-source-maps": "^3.0.1", + "jest-haste-map": "^24.7.1", + "jest-resolve": "^24.7.1", + "jest-runtime": "^24.7.1", + "jest-util": "^24.7.1", + "jest-worker": "^24.6.0", + "node-notifier": "^5.2.1", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + }, + "dependencies": { + "istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz", + "integrity": "sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==", + "dev": true, + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.3", + "semver": "^5.5.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@jest/source-map": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.3.0.tgz", + "integrity": "sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@jest/test-result": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.7.1.tgz", + "integrity": "sha512-3U7wITxstdEc2HMfBX7Yx3JZgiNBubwDqQMh+BXmZXHa3G13YWF3p6cK+5g0hGkN3iufg/vGPl3hLxQXD74Npg==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.7.1.tgz", + "integrity": "sha512-84HQkCpVZI/G1zq53gHJvSmhUer4aMYp9tTaffW28Ih5OxfCg8hGr3nTSbL1OhVDRrFZwvF+/R9gY6JRkDUpUA==", + "dev": true, + "requires": { + "@jest/test-result": "^24.7.1", + "jest-haste-map": "^24.7.1", + "jest-runner": "^24.7.1", + "jest-runtime": "^24.7.1" + } + }, + "@jest/transform": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.7.1.tgz", + "integrity": "sha512-EsOUqP9ULuJ66IkZQhI5LufCHlTbi7hrcllRMUEV/tOgqBVQi93+9qEvkX0n8mYpVXQ8VjwmICeRgg58mrtIEw==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.7.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.7.1", + "jest-regex-util": "^24.3.0", + "jest-util": "^24.7.1", + "micromatch": "^3.1.10", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "babel-plugin-istanbul": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.1.tgz", + "integrity": "sha512-RNNVv2lsHAXJQsEJ5jonQwrJVWK8AcZpG1oxhnjCUaAjL7xahYLANhPUZbzEQHjKy1NMYUwn+0NPKQc8iSY4xQ==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.0.0", + "test-exclude": "^5.0.0" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz", + "integrity": "sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==", + "dev": true, + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.3", + "semver": "^5.5.0" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "test-exclude": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.1.0.tgz", + "integrity": "sha512-gwf0S2fFsANC55fSeSqpb8BYk6w3FDvwZxfNjeF6FRgvFa43r+7wRiA/Q0IxoRU37wB/LE8IQ4221BsNucTaCA==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^1.0.1" + } + } + } + }, + "@jest/types": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.7.0.tgz", + "integrity": "sha512-ipJUa2rFWiKoBqMKP63Myb6h9+iT3FHRTF2M8OR6irxWzItisa8i4dcSg14IbvmXUnBlHBlUQPYUHWyX3UPpYA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/yargs": "^12.0.9" + } + }, + "@material-ui/core": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-3.9.3.tgz", + "integrity": "sha512-REIj62+zEvTgI/C//YL4fZxrCVIySygmpZglsu/Nl5jPqy3CDjZv1F9ubBYorHqmRgeVPh64EghMMWqk4egmfg==", + "requires": { + "@babel/runtime": "^7.2.0", + "@material-ui/system": "^3.0.0-alpha.0", + "@material-ui/utils": "^3.0.0-alpha.2", + "@types/jss": "^9.5.6", + "@types/react-transition-group": "^2.0.8", + "brcast": "^3.0.1", + "classnames": "^2.2.5", + "csstype": "^2.5.2", + "debounce": "^1.1.0", + "deepmerge": "^3.0.0", + "dom-helpers": "^3.2.1", + "hoist-non-react-statics": "^3.2.1", + "is-plain-object": "^2.0.4", + "jss": "^9.8.7", + "jss-camel-case": "^6.0.0", + "jss-default-unit": "^8.0.2", + "jss-global": "^3.0.0", + "jss-nested": "^6.0.1", + "jss-props-sort": "^6.0.0", + "jss-vendor-prefixer": "^7.0.0", + "normalize-scroll-left": "^0.1.2", + "popper.js": "^1.14.1", + "prop-types": "^15.6.0", + "react-event-listener": "^0.6.2", + "react-transition-group": "^2.2.1", + "recompose": "0.28.0 - 0.30.0", + "warning": "^4.0.1" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz", + "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==", + "requires": { + "react-is": "^16.7.0" + } + }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, + "@material-ui/icons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-3.0.1.tgz", + "integrity": "sha512-1kNcxYiIT1x8iDPEAlgmKrfRTIV8UyK6fLVcZ9kMHIKGWft9I451V5mvSrbCjbf7MX1TbLWzZjph0aVCRf9MqQ==", + "requires": { + "@babel/runtime": "7.0.0", + "recompose": "^0.29.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz", + "integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==", + "requires": { + "regenerator-runtime": "^0.12.0" + } + }, + "recompose": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.29.0.tgz", + "integrity": "sha512-J/qLXNU4W+AeHCDR70ajW8eMd1uroqZaECTj6qqDLPMILz3y0EzpYlvrnxKB9DnqcngWrtGwjXY9JeXaW9kS1A==", + "requires": { + "@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" + } + }, + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" + } + } + }, + "@material-ui/styles": { + "version": "3.0.0-alpha.10", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-3.0.0-alpha.10.tgz", + "integrity": "sha512-qJ5eiupBPRCNlMCDZ2G5h8auBtBtm8uT/oCUAJ/FqhO5oC7POLmmvDN1Cq1cgAmqQnaL6uN5mAM1Gc90GpKr9A==", + "requires": { + "@babel/runtime": "^7.2.0", + "@emotion/hash": "^0.7.1", + "@material-ui/utils": "^3.0.0-alpha.2", + "classnames": "^2.2.5", + "deepmerge": "^3.0.0", + "hoist-non-react-statics": "^3.2.1", + "jss": "^10.0.0-alpha.7", + "jss-plugin-camel-case": "^10.0.0-alpha.7", + "jss-plugin-default-unit": "^10.0.0-alpha.7", + "jss-plugin-global": "^10.0.0-alpha.7", + "jss-plugin-nested": "^10.0.0-alpha.7", + "jss-plugin-props-sort": "^10.0.0-alpha.7", + "jss-plugin-rule-value-function": "^10.0.0-alpha.7", + "jss-plugin-vendor-prefixer": "^10.0.0-alpha.7", + "prop-types": "^15.6.0", + "warning": "^4.0.1" + }, + "dependencies": { + "@emotion/hash": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.7.1.tgz", + "integrity": "sha512-OYpa/Sg+2GDX+jibUfpZVn1YqSVRpYmTLF2eyAfrFTIJSbwyIrc+YscayoykvaOME/wV4BV0Sa0yqdMrgse6mA==" + }, + "hoist-non-react-statics": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz", + "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==", + "requires": { + "react-is": "^16.7.0" + } + }, + "jss": { + "version": "10.0.0-alpha.16", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0-alpha.16.tgz", + "integrity": "sha512-HmKNNnr82TR5jkWjBcbrx/uim2ief588pWp7zsf4GQpL125zRkEaWYL1SXv5bR6bBvAoTtvJsTAOxDIlLxUNZg==", + "requires": { + "@babel/runtime": "^7.3.1", + "is-in-browser": "^1.1.3", + "tiny-warning": "^1.0.2" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.5.tgz", + "integrity": "sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + } + } + }, + "regenerator-runtime": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", + "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" + }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, + "@material-ui/system": { + "version": "3.0.0-alpha.2", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-3.0.0-alpha.2.tgz", + "integrity": "sha512-odmxQ0peKpP7RQBQ8koly06YhsPzcoVib1vByVPBH4QhwqBXuYoqlCjt02846fYspAqkrWzjxnWUD311EBbxOA==", + "requires": { + "@babel/runtime": "^7.2.0", + "deepmerge": "^3.0.0", + "prop-types": "^15.6.0", + "warning": "^4.0.1" + }, + "dependencies": { + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, + "@material-ui/utils": { + "version": "3.0.0-alpha.3", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-3.0.0-alpha.3.tgz", + "integrity": "sha512-rwMdMZptX0DivkqBuC+Jdq7BYTXwqKai5G5ejPpuEDKpWzi1Oxp+LygGw329FrKpuKeiqpcymlqJTjmy+quWng==", + "requires": { + "@babel/runtime": "^7.2.0", + "prop-types": "^15.6.0", + "react-is": "^16.6.3" + } + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "@oclif/color": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@oclif/color/-/color-0.0.0.tgz", + "integrity": "sha512-KKd3W7eNwfNF061tr663oUNdt8EMnfuyf5Xv55SGWA1a0rjhWqS/32P7OeB7CbXcJUBdfVrPyR//1afaW12AWw==", + "requires": { + "ansi-styles": "^3.2.1", + "supports-color": "^5.4.0", + "tslib": "^1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + } + } + }, + "@oclif/command": { + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.5.12.tgz", + "integrity": "sha512-D5/Kph9smL92X1z9WPmxFd9zDruFsCk4/LbfCaBmiO2Vyyt7Y9O6kI1YLsC3B0KC9wymSCTH14IK96rf9AFHfQ==", + "requires": { + "@oclif/errors": "^1.2.2", + "@oclif/parser": "^3.7.3", + "debug": "^4.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + } + } + }, + "@oclif/config": { + "version": "1.12.12", + "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.12.12.tgz", + "integrity": "sha512-0vlX5VYvOfF9QbkCqMyPSzH9GMp6at4Mbqn8CxCskxhKvNZoPD5ocda2ku0zEnoqxGAQ4VfQP7NCqJthuiStfg==", + "requires": { + "debug": "^4.1.1", + "tslib": "^1.9.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + } + } + }, + "@oclif/errors": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@oclif/errors/-/errors-1.2.2.tgz", + "integrity": "sha512-Eq8BFuJUQcbAPVofDxwdE0bL14inIiwt5EaKRVY9ZDIG11jwdXZqiQEECJx0VfnLyUZdYfRd/znDI/MytdJoKg==", + "requires": { + "clean-stack": "^1.3.0", + "fs-extra": "^7.0.0", + "indent-string": "^3.2.0", + "strip-ansi": "^5.0.0", + "wrap-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz", + "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + } + } + }, + "@oclif/linewrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz", + "integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==" + }, + "@oclif/parser": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.7.3.tgz", + "integrity": "sha512-yfYpDzVn9ipo4HZtYLfMtd3j3ArpTQlRbQfy9pNnHFd4VedE2PNYQTRWYYMuu1FxEOoknlMZbzsewVvl41TvKg==", + "requires": { + "@oclif/linewrap": "^1.0.0", + "chalk": "^2.4.1", + "tslib": "^1.9.3" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + } + } + }, + "@oclif/plugin-autocomplete": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@oclif/plugin-autocomplete/-/plugin-autocomplete-0.1.0.tgz", + "integrity": "sha512-Dz2dGyBoOUcv6/gqr9qaG7KTIkYxILL0MvMVwlhkS0f6UqCsh8fC3adYTr8BeIPQmUqWkACtC7bYp9DyQ8m2Jw==", + "requires": { + "@oclif/command": "^1.4.31", + "@oclif/config": "^1.6.22", + "@types/fs-extra": "^5.0.2", + "chalk": "^2.4.1", + "cli-ux": "^4.4.0", + "debug": "^3.1.0", + "fs-extra": "^6.0.1", + "moment": "^2.22.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "fs-extra": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "@oclif/plugin-help": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-2.1.6.tgz", + "integrity": "sha512-M4kTERpPWNSM1Mga7K/zo9DWHLCVf2FRaIeXPoytmTPd+0kSvG3TR0Vc1bwx9/cxXoYyYGgEejwNlrfayr8FZw==", + "requires": { + "@oclif/command": "^1.5.8", + "chalk": "^2.4.1", + "indent-string": "^3.2.0", + "lodash.template": "^4.4.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0", + "widest-line": "^2.0.1", + "wrap-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "requires": { + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "wrap-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz", + "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + } + } + }, + "@oclif/plugin-not-found": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-1.2.2.tgz", + "integrity": "sha512-SPlmiJFmTFltQT/owdzQwKgq6eq5AEKVwVK31JqbzK48bRWvEL1Ye60cgztXyZ4bpPn2Fl+KeL3FWFQX41qJuA==", + "requires": { + "@oclif/color": "^0.0.0", + "@oclif/command": "^1.5.3", + "cli-ux": "^4.9.0", + "fast-levenshtein": "^2.0.6", + "lodash": "^4.17.11" + } + }, + "@oclif/plugin-plugins": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-1.7.8.tgz", + "integrity": "sha512-GxLxaf8Lk1RqHVAIBZyA7hmhU7u5oV97i/OsWgFPdjPaT+BmWlWXR8IpmtA8giNo6atR+JpfgDmYndMU75zYUQ==", + "requires": { + "@oclif/color": "^0.0.0", + "@oclif/command": "^1.5.12", + "chalk": "^2.4.2", + "cli-ux": "^5.2.1", + "debug": "^4.1.0", + "fs-extra": "^7.0.1", + "http-call": "^5.2.2", + "load-json-file": "^5.2.0", + "npm-run-path": "^3.0.0", + "semver": "^5.6.0", + "tslib": "^1.9.3", + "yarn": "^1.15.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "clean-stack": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.1.0.tgz", + "integrity": "sha512-uQWrpRm+iZZUCAp7ZZJQbd4Za9I3AjR/3YTjmcnAtkauaIm/T5CT6U8zVI6e60T6OANqBFAzuR9/HB3NzuZCRA==" + }, + "cli-ux": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.2.1.tgz", + "integrity": "sha512-zG1012o7U4ZsCuIST1t2yrHPADv16J81RAGYjY9X1yABEFK40oyjRchD5ffVZaG44BjizmLvu677zbVIypRuxw==", + "requires": { + "@oclif/command": "^1.5.1", + "@oclif/errors": "^1.2.1", + "@oclif/linewrap": "^1.0.0", + "@oclif/screen": "^1.0.3", + "ansi-escapes": "^3.1.0", + "ansi-styles": "^3.2.1", + "cardinal": "^2.1.1", + "chalk": "^2.4.1", + "clean-stack": "^2.0.0", + "extract-stack": "^1.0.0", + "fs-extra": "^7.0.1", + "hyperlinker": "^1.0.0", + "indent-string": "^3.2.0", + "is-wsl": "^1.1.0", + "lodash": "^4.17.11", + "natural-orderby": "^2.0.1", + "password-prompt": "^1.1.2", + "semver": "^5.6.0", + "string-width": "^3.1.0", + "strip-ansi": "^5.1.0", + "supports-color": "^5.5.0", + "supports-hyperlinks": "^1.0.1", + "treeify": "^1.1.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "npm-run-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", + "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==", + "requires": { + "path-key": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-key": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.0.tgz", + "integrity": "sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg==" + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + } + } + }, + "@oclif/plugin-warn-if-update-available": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-1.7.0.tgz", + "integrity": "sha512-Nwyz3BJ8RhsfQ+OmFSsJSPIfn5YJqMrCzPh72Zgo2jqIjKIBWD8N9vTTe4kZlpeUUn77SyXFfwlBQbNCL5OEuQ==", + "requires": { + "@oclif/command": "^1.5.10", + "@oclif/config": "^1.12.8", + "@oclif/errors": "^1.2.2", + "chalk": "^2.4.1", + "debug": "^4.1.0", + "fs-extra": "^7.0.0", + "http-call": "^5.2.2", + "lodash.template": "^4.4.0", + "semver": "^5.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + } + } + }, + "@oclif/screen": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@oclif/screen/-/screen-1.0.4.tgz", + "integrity": "sha512-60CHpq+eqnTxLZQ4PGHYNwUX572hgpMHGPtTWMjdTMsAvlm69lZV/4ly6O3sAYkomo4NggGcomrDpBe34rxUqw==" + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "requires": { + "any-observable": "^0.3.0" + } + }, + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + }, + "@storybook/addon-storyshots": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@storybook/addon-storyshots/-/addon-storyshots-4.1.4.tgz", + "integrity": "sha512-AQk7lYpYqDmBG6rFm0PSffW3mKOSogLci1CQ+vNFBhwvf2INLj4JHU/G7cSKK1NvtZlp9kvl4E8jVzXGNo610A==", + "dev": true, + "requires": { + "@storybook/addons": "4.1.4", + "core-js": "^2.5.7", + "glob": "^7.1.3", + "global": "^4.3.2", + "jest-specific-snapshot": "^1.0.0", + "read-pkg-up": "^4.0.0", + "regenerator-runtime": "^0.12.1" + }, + "dependencies": { + "core-js": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz", + "integrity": "sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "@storybook/addons": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-4.1.4.tgz", + "integrity": "sha512-h91OXr9eFx3ilST+4rpXpPB3Y6gnJ/ZBps84cgZ69coffTeYfzNHPB1Fu2RVsB1skdSFTF/TnB1bAEzYNZ2cDQ==", + "dev": true, + "requires": { + "@storybook/channels": "4.1.4", + "@storybook/components": "4.1.4", + "global": "^4.3.2", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/channel-postmessage": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-4.1.6.tgz", + "integrity": "sha512-CUFcnzZE5y24AUZqArt9/95wLdk0phsrOzDU8Q/WNWpzYCzTaaNzd82DDG4AWWHd7awtbgGGueKDCoAXU99t5A==", + "dev": true, + "requires": { + "@storybook/channels": "4.1.6", + "global": "^4.3.2", + "json-stringify-safe": "^5.0.1" + }, + "dependencies": { + "@storybook/channels": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-4.1.6.tgz", + "integrity": "sha512-8MqGYypdaPmZR7eORXdxtJijGOz5UMHXoMskVtodvKi26tmltFKX+okXFNh/teKe3+8s0QWkpzM95VI+Z+0qFA==", + "dev": true + } + } + }, + "@storybook/channels": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-4.1.4.tgz", + "integrity": "sha512-tXKSz58p4o1CiRL9VNUfgMuNeuyUkLLyBfK0tAY0Co370BTfUvMq7clG65+nPj+rdb7foYQQKpnwGYdMVzuzsg==", + "dev": true + }, + "@storybook/client-logger": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-4.1.6.tgz", + "integrity": "sha512-P65Pw3m2FRW7QDIU51zj3ANzo7twL7/9nQKoyMJKy/1rgqk1RMa/boHERPRhfATzqYPf5hh2G0PBTMKBEG4A8w==", + "dev": true + }, + "@storybook/components": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-4.1.4.tgz", + "integrity": "sha512-H0SMPt/zF1zfyCqUTwx0RcaRbviiz9vdxXWO4jURfgULhGpP+mQRXz0KUn2k7s/RMerTtpB4/DKNKm0zDylcNQ==", + "dev": true, + "requires": { + "@emotion/core": "^0.13.1", + "@emotion/provider": "^0.11.2", + "@emotion/styled": "^0.10.6", + "global": "^4.3.2", + "lodash": "^4.17.11", + "prop-types": "^15.6.2", + "react-inspector": "^2.3.0", + "react-split-pane": "^0.1.84", + "react-textarea-autosize": "^7.0.4", + "render-fragment": "^0.1.1" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + } + } + }, + "@storybook/core": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-4.1.6.tgz", + "integrity": "sha512-0T4mDt3Wzyg8UIrF0kPvP5kA+S+fGhaZI/vWGUPvmxsYuVQHGhvna1ZiayIW8R9TdHx1g+uSYkUxb8wVVUmwQA==", + "dev": true, + "requires": { + "@babel/plugin-proposal-class-properties": "^7.2.0", + "@babel/preset-env": "^7.2.0", + "@emotion/core": "^0.13.1", + "@emotion/provider": "^0.11.2", + "@emotion/styled": "^0.10.6", + "@storybook/addons": "4.1.6", + "@storybook/channel-postmessage": "4.1.6", + "@storybook/client-logger": "4.1.6", + "@storybook/core-events": "4.1.6", + "@storybook/node-logger": "4.1.6", + "@storybook/ui": "4.1.6", + "airbnb-js-shims": "^1 || ^2", + "autoprefixer": "^9.3.1", + "babel-plugin-macros": "^2.4.2", + "babel-preset-minify": "^0.5.0 || 0.6.0-alpha.5", + "boxen": "^2.0.0", + "case-sensitive-paths-webpack-plugin": "^2.1.2", + "chalk": "^2.4.1", + "child-process-promise": "^2.2.1", + "cli-table3": "0.5.1", + "commander": "^2.19.0", + "common-tags": "^1.8.0", + "core-js": "^2.5.7", + "css-loader": "^1.0.1", + "detect-port": "^1.2.3", + "dotenv-webpack": "^1.5.7", + "ejs": "^2.6.1", + "eventemitter3": "^3.1.0", + "express": "^4.16.3", + "file-loader": "^2.0.0", + "file-system-cache": "^1.0.5", + "find-cache-dir": "^2.0.0", + "fs-extra": "^7.0.1", + "global": "^4.3.2", + "html-webpack-plugin": "^4.0.0-beta.2", + "inquirer": "^6.2.0", + "interpret": "^1.1.0", + "ip": "^1.1.5", + "json5": "^2.1.0", + "lazy-universal-dotenv": "^2.0.0", + "node-fetch": "^2.2.0", + "opn": "^5.4.0", + "postcss-flexbugs-fixes": "^4.1.0", + "postcss-loader": "^3.0.0", + "pretty-hrtime": "^1.0.3", + "prop-types": "^15.6.2", + "qs": "^6.5.2", + "raw-loader": "^0.5.1", + "react-dev-utils": "^6.1.0", + "redux": "^4.0.1", + "regenerator-runtime": "^0.12.1", + "resolve": "^1.8.1", + "resolve-from": "^4.0.0", + "semver": "^5.6.0", + "serve-favicon": "^2.5.0", + "shelljs": "^0.8.2", + "spawn-promise": "^0.1.8", + "style-loader": "^0.23.1", + "svg-url-loader": "^2.3.2", + "terser-webpack-plugin": "^1.1.0", + "url-loader": "^1.1.2", + "webpack": "^4.23.1", + "webpack-dev-middleware": "^3.4.0", + "webpack-hot-middleware": "^2.24.3" + }, + "dependencies": { + "@storybook/addons": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-4.1.6.tgz", + "integrity": "sha512-5dG0adChzNRbRLS/YD/5mEoWLTk3uaJpzbRSJVKe6HQKBPDXmuEMYYPiHI83o15YBJjGHx68+PkHBI08oRsuhQ==", + "dev": true, + "requires": { + "@storybook/channels": "4.1.6", + "@storybook/components": "4.1.6", + "global": "^4.3.2", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/channels": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-4.1.6.tgz", + "integrity": "sha512-8MqGYypdaPmZR7eORXdxtJijGOz5UMHXoMskVtodvKi26tmltFKX+okXFNh/teKe3+8s0QWkpzM95VI+Z+0qFA==", + "dev": true + }, + "@storybook/components": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-4.1.6.tgz", + "integrity": "sha512-kWIUiexzFurNwW8NaJEhlFWD1kohnvNlOxgph7oSoXo/yCBodkEYpIuNbznQnNSH2xIjqh1dvbniJNSJZyEbTQ==", + "dev": true, + "requires": { + "@emotion/core": "^0.13.1", + "@emotion/provider": "^0.11.2", + "@emotion/styled": "^0.10.6", + "global": "^4.3.2", + "lodash": "^4.17.11", + "prop-types": "^15.6.2", + "react-inspector": "^2.3.0", + "react-split-pane": "^0.1.84", + "react-textarea-autosize": "^7.0.4", + "render-fragment": "^0.1.1" + } + }, + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "autoprefixer": { + "version": "9.4.5", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.4.5.tgz", + "integrity": "sha512-M602C0ZxzFpJKqD4V6eq2j+K5CkzlhekCrcQupJmAOrPEZjWJyj/wSeo6qRSNoN6M3/9mtLPQqTTrABfReytQg==", + "dev": true, + "requires": { + "browserslist": "^4.4.0", + "caniuse-lite": "^1.0.30000928", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.11", + "postcss-value-parser": "^3.3.1" + } + }, + "browserslist": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.0.tgz", + "integrity": "sha512-tQkHS8VVxWbrjnNDXgt7/+SuPJ7qDvD0Y2e6bLtoQluR2SPvlmPUcfcU75L1KAalhqULlIFJlJ6BDfnYyJxJsw==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000928", + "electron-to-chromium": "^1.3.100", + "node-releases": "^1.1.3" + } + }, + "caniuse-lite": { + "version": "1.0.30000929", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000929.tgz", + "integrity": "sha512-n2w1gPQSsYyorSVYqPMqbSaz1w7o9ZC8VhOEGI9T5MfGDzp7sbopQxG6GaQmYsaq13Xfx/mkxJUWC1Dz3oZfzw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true + }, + "core-js": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.2.tgz", + "integrity": "sha512-NdBPF/RVwPW6jr0NCILuyN9RiqLo2b1mddWHkUL+VnvcB7dzlnBJ1bXYntjpTGOgkZiiLWj2JxmOr7eGE3qK6g==", + "dev": true + }, + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" + } + }, + "css-loader": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz", + "integrity": "sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "css-selector-tokenizer": "^0.7.0", + "icss-utils": "^2.1.0", + "loader-utils": "^1.0.2", + "lodash": "^4.17.11", + "postcss": "^6.0.23", + "postcss-modules-extract-imports": "^1.2.0", + "postcss-modules-local-by-default": "^1.2.0", + "postcss-modules-scope": "^1.1.0", + "postcss-modules-values": "^1.3.0", + "postcss-value-parser": "^3.3.0", + "source-list-map": "^2.0.0" + }, + "dependencies": { + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "electron-to-chromium": { + "version": "1.3.103", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.103.tgz", + "integrity": "sha512-tObPqGmY9X8MUM8i3MEimYmbnLLf05/QV5gPlkR8MQ3Uj8G8B2govE1U4cQcBYtv3ymck9Y8cIOu4waoiykMZQ==", + "dev": true + }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "file-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-2.0.0.tgz", + "integrity": "sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^1.0.0" + } + }, + "find-cache-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", + "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "html-webpack-plugin": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.5.tgz", + "integrity": "sha512-y5l4lGxOW3pz3xBTFdfB9rnnrWRPVxlAhX6nrBYIcW+2k2zC3mSp/3DxlWVCMBfnO6UAnoF8OcFn0IMy6kaKAQ==", + "dev": true, + "requires": { + "html-minifier": "^3.5.20", + "loader-utils": "^1.1.0", + "lodash": "^4.17.11", + "pretty-error": "^2.1.1", + "tapable": "^1.1.0", + "util.promisify": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inquirer": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.1.tgz", + "integrity": "sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.0", + "figures": "^2.0.0", + "lodash": "^4.17.10", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.1.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.0.0", + "through": "^2.3.6" + } + }, + "js-yaml": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "node-fetch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", + "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==", + "dev": true + }, + "node-releases": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.3.tgz", + "integrity": "sha512-6VrvH7z6jqqNFY200kdB6HdzkgM96Oaj9v3dqGfgp6mF+cHmU4wyQKZ2/WPDRVoR0Jz9KqbamaBN0ZhdUaysUQ==", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "postcss": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.13.tgz", + "integrity": "sha512-h8SY6kQTd1wISHWjz+E6cswdhMuyBZRb16pSTv3W4zYZ3/YbyWeJdNUeOXB5IdZqE1U76OUEjjjqsC3z2f3hVg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "postcss-load-config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", + "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", + "dev": true, + "requires": { + "cosmiconfig": "^4.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", + "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + } + } + }, + "@storybook/core-events": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-4.1.6.tgz", + "integrity": "sha512-07ki5+VuruWQv7B1ZBlsNYEVSC3dQwIZKjEFL4aKFO57ruaNijkZTF1QHkSGJapyBPa7+LLM2fXqnBkputoEZw==", + "dev": true + }, + "@storybook/mantra-core": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@storybook/mantra-core/-/mantra-core-1.7.2.tgz", + "integrity": "sha512-GD4OYJ8GsayVhIg306sfgcKDk9j8YfuSKIAWvdB/g7IDlw0pDgueONALVEEE2XWJtCwcsUyDtCYzXFgCBWLEjA==", + "dev": true, + "requires": { + "@storybook/react-komposer": "^2.0.1", + "@storybook/react-simple-di": "^1.2.1", + "babel-runtime": "6.x.x" + } + }, + "@storybook/node-logger": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-4.1.6.tgz", + "integrity": "sha512-3mLcNp0eTjwQKHJ0vWpZLlayPOUaZJR/Umc6kWzdMn1K398/k7FU0fBK4FJ7VmnI0z1sYTlqaTqjqN0U3XaxjA==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "core-js": "^2.5.7", + "npmlog": "^4.1.2", + "pretty-hrtime": "^1.0.3", + "regenerator-runtime": "^0.12.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "core-js": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.2.tgz", + "integrity": "sha512-NdBPF/RVwPW6jr0NCILuyN9RiqLo2b1mddWHkUL+VnvcB7dzlnBJ1bXYntjpTGOgkZiiLWj2JxmOr7eGE3qK6g==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", + "dev": true + } + } + }, + "@storybook/podda": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@storybook/podda/-/podda-1.2.3.tgz", + "integrity": "sha512-g7dsdsn50AhlGZ8iIDKdF8bi7Am++iFOq+QN+hNKz3FvgLuf8Dz+mpC/BFl90eE9bEYxXqXKeMf87399Ec5Qhw==", + "dev": true, + "requires": { + "babel-runtime": "^6.11.6", + "immutable": "^3.8.1" + } + }, + "@storybook/react": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-4.1.6.tgz", + "integrity": "sha512-JavzdoIrLQprLlt/0Bm0QMKMOzqweL7gjXKSl8W5p38hhDpyxRt989t0yfZnwF6K0iGWeU88mAb9OoRkn7o8tA==", + "dev": true, + "requires": { + "@babel/plugin-transform-react-constant-elements": "^7.2.0", + "@babel/preset-flow": "^7.0.0", + "@babel/preset-react": "^7.0.0", + "@emotion/styled": "^0.10.6", + "@storybook/core": "4.1.6", + "@storybook/node-logger": "4.1.6", + "@svgr/webpack": "^4.0.3", + "babel-plugin-named-asset-import": "^0.2.3", + "babel-plugin-react-docgen": "^2.0.0", + "babel-preset-react-app": "^6.1.0", + "common-tags": "^1.8.0", + "core-js": "^2.5.7", + "global": "^4.3.2", + "lodash": "^4.17.11", + "mini-css-extract-plugin": "^0.4.4", + "prop-types": "^15.6.2", + "react-dev-utils": "^6.1.0", + "regenerator-runtime": "^0.12.1", + "semver": "^5.6.0", + "webpack": "^4.23.1" + }, + "dependencies": { + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true + }, + "core-js": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.2.tgz", + "integrity": "sha512-NdBPF/RVwPW6jr0NCILuyN9RiqLo2b1mddWHkUL+VnvcB7dzlnBJ1bXYntjpTGOgkZiiLWj2JxmOr7eGE3qK6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "mini-css-extract-plugin": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.5.tgz", + "integrity": "sha512-dqBanNfktnp2hwL2YguV9Jh91PFX7gu7nRLs4TGsbAfAG6WOtlynFRYzwDwmmeSb5uIwHo9nx1ta0f7vAZVp2w==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + } + }, + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + } + } + }, + "@storybook/react-komposer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@storybook/react-komposer/-/react-komposer-2.0.5.tgz", + "integrity": "sha512-zX5UITgAh37tmD0MWnUFR29S5YM8URMHc/9iwczX/P1f3tM4nPn8VAzxG/UWQecg1xZVphmqkZoux+SDrtTZOQ==", + "dev": true, + "requires": { + "@storybook/react-stubber": "^1.0.0", + "babel-runtime": "^6.11.6", + "hoist-non-react-statics": "^1.2.0", + "lodash": "^4.17.11", + "shallowequal": "^1.1.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz", + "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=", + "dev": true + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } + } + }, + "@storybook/react-simple-di": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@storybook/react-simple-di/-/react-simple-di-1.3.0.tgz", + "integrity": "sha512-RH6gPQaYMs/VzQX2dgbZU8DQMKFXVOv1ruohHjjNPys4q+YdqMFMDe5jOP1AUE3j9g01x0eW7bVjRawSpl++Ew==", + "dev": true, + "requires": { + "babel-runtime": "6.x.x", + "create-react-class": "^15.6.2", + "hoist-non-react-statics": "1.x.x", + "prop-types": "^15.6.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz", + "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=", + "dev": true + } + } + }, + "@storybook/react-stubber": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@storybook/react-stubber/-/react-stubber-1.0.1.tgz", + "integrity": "sha512-k+CHH+vA8bQfCmzBTtJsPkITFgD+C/w19KuByZ9WeEvNUFtnDaCqfP+Vp3/OR+3IAfAXYYOWolqPLxNPcEqEjw==", + "dev": true, + "requires": { + "babel-runtime": "^6.5.0" + } + }, + "@storybook/ui": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-4.1.6.tgz", + "integrity": "sha512-MXod0JMu/P2sTYlN6DM6yuwvizUKjwFn4lOf+F9hNe4lxZEXw74KogCv0CN32VUrWUP++ZY9DybQr4SMRFVVww==", + "dev": true, + "requires": { + "@emotion/core": "^0.13.1", + "@emotion/provider": "^0.11.2", + "@emotion/styled": "^0.10.6", + "@storybook/components": "4.1.6", + "@storybook/core-events": "4.1.6", + "@storybook/mantra-core": "^1.7.2", + "@storybook/podda": "^1.2.3", + "@storybook/react-komposer": "^2.0.5", + "deep-equal": "^1.0.1", + "eventemitter3": "^3.1.0", + "fuse.js": "^3.3.0", + "global": "^4.3.2", + "keycode": "^2.2.0", + "lodash": "^4.17.11", + "prop-types": "^15.6.2", + "qs": "^6.5.2", + "react": "^16.7.0", + "react-dom": "^16.7.0", + "react-fuzzy": "^0.5.2", + "react-lifecycles-compat": "^3.0.4", + "react-modal": "^3.6.1", + "react-treebeard": "^3.1.0" + }, + "dependencies": { + "@storybook/components": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-4.1.6.tgz", + "integrity": "sha512-kWIUiexzFurNwW8NaJEhlFWD1kohnvNlOxgph7oSoXo/yCBodkEYpIuNbznQnNSH2xIjqh1dvbniJNSJZyEbTQ==", + "dev": true, + "requires": { + "@emotion/core": "^0.13.1", + "@emotion/provider": "^0.11.2", + "@emotion/styled": "^0.10.6", + "global": "^4.3.2", + "lodash": "^4.17.11", + "prop-types": "^15.6.2", + "react-inspector": "^2.3.0", + "react-split-pane": "^0.1.84", + "react-textarea-autosize": "^7.0.4", + "render-fragment": "^0.1.1" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "react": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.7.0.tgz", + "integrity": "sha512-StCz3QY8lxTb5cl2HJxjwLFOXPIFQp+p+hxQfc8WE0QiLfCtIlKj8/+5tjjKm8uSTlAW+fCPaavGFS06V9Ar3A==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.12.0" + } + }, + "react-dom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.7.0.tgz", + "integrity": "sha512-D0Ufv1ExCAmF38P2Uh1lwpminZFRXEINJe53zRAbm4KPwSyd6DY/uDoS0Blj9jvPpn1+wivKpZYc8aAAN/nAkg==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.12.0" + } + }, + "scheduler": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.12.0.tgz", + "integrity": "sha512-t7MBR28Akcp4Jm+QoR63XgAi9YgCUmgvDHqf5otgAj4QvdoBE4ImCX0ffehefePPG+aitiYHp0g/mW6s4Tp+dw==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.0.0.tgz", + "integrity": "sha512-PDvHV2WhSGCSExp+eIMEKxYd1Q0SBvXLb4gAOXbdh0dswHFFgXWzxGjCmx5aln4qGrhkuN81khzYzR/44DYaMA==", + "dev": true + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-4.0.3.tgz", + "integrity": "sha512-fpG7AzzJxz1tc8ITYS1jCAt1cq4ydK2R+sx//BMTJgvOjfk91M5GiqFolP8aYTzLcum92IGNAVFS3zEcucOQEA==", + "dev": true + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-4.0.0.tgz", + "integrity": "sha512-nBGVl6LzXTdk1c6w3rMWcjq3mYGz+syWc5b3CdqAiEeY/nswYDoW/cnGUKKC8ofD6/LaG+G/IUnfv3jKoHz43A==", + "dev": true + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-4.0.0.tgz", + "integrity": "sha512-ejQqpTfORy6TT5w1x/2IQkscgfbtNFjitcFDu63GRz7qfhVTYhMdiJvJ1+Aw9hmv9bO4tXThGQDr1IF5lIvgew==", + "dev": true + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.0.0.tgz", + "integrity": "sha512-OE6GT9WRKWqd0Dk6NJ5TYXTF5OxAyn74+c/D+gTLbCXnK2A0luEXuwMbe5zR5Px4A/jow2OeEBboTENl4vtuQg==", + "dev": true + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-4.0.0.tgz", + "integrity": "sha512-QeDRGHXfjYEBTXxV0TsjWmepsL9Up5BOOlMFD557x2JrSiVGUn2myNxHIrHiVW0+nnWnaDcrkjg/jUvbJ5nKCg==", + "dev": true + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-4.0.0.tgz", + "integrity": "sha512-c6eE6ovs14k6dmHKoy26h7iRFhjWNnwYVrDWIPfouVm/gcLIeMw/ME4i91O5LEfaDHs6kTRCcVpbAVbNULZOtw==", + "dev": true + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-4.1.0.tgz", + "integrity": "sha512-uulxdx2p3nrM2BkrtADQHK8IhEzCxdUILfC/ddvFC8tlFWuKiA3ych8C6q0ulyQHq34/3hzz+3rmUbhWF9redg==", + "dev": true + }, + "@svgr/babel-preset": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-4.1.0.tgz", + "integrity": "sha512-Nat5aJ3VO3LE8KfMyIbd3sGWnaWPiFCeWIdEV+lalga0To/tpmzsnPDdnrR9fNYhvSSLJbwhU/lrLYt9wXY0ZQ==", + "dev": true, + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^4.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^4.0.3", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^4.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^4.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "^4.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "^4.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "^4.0.0", + "@svgr/babel-plugin-transform-svg-component": "^4.1.0" + } + }, + "@svgr/core": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-4.1.0.tgz", + "integrity": "sha512-ahv3lvOKuUAcs0KbQ4Jr5fT5pGHhye4ew8jZVS4lw8IQdWrbG/o3rkpgxCPREBk7PShmEoGQpteeXVwp2yExuQ==", + "dev": true, + "requires": { + "@svgr/plugin-jsx": "^4.1.0", + "camelcase": "^5.0.0", + "cosmiconfig": "^5.0.7" + }, + "dependencies": { + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "dev": true + }, + "cosmiconfig": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz", + "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0" + } + }, + "js-yaml": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-4.1.0.tgz", + "integrity": "sha512-tdkEZHmigYYiVhIEzycAMKN5aUSpddUnjr6v7bPwaNTFuSyqGUrpCg1JlIGi7PUaaJVHbn6whGQMGUpKOwT5nw==", + "dev": true, + "requires": { + "@babel/types": "^7.1.6" + } + }, + "@svgr/plugin-jsx": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-4.1.0.tgz", + "integrity": "sha512-xwu+9TGziuN7cu7p+vhCw2EJIfv8iDNMzn2dR0C7fBYc8q+SRtYTcg4Uyn8ZWh6DM+IZOlVrS02VEMT0FQzXSA==", + "dev": true, + "requires": { + "@babel/core": "^7.1.6", + "@svgr/babel-preset": "^4.1.0", + "@svgr/hast-util-to-babel-ast": "^4.1.0", + "rehype-parse": "^6.0.0", + "unified": "^7.0.2", + "vfile": "^3.0.1" + } + }, + "@svgr/plugin-svgo": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-4.0.3.tgz", + "integrity": "sha512-MgL1CrlxvNe+1tQjPUc2bIJtsdJOIE5arbHlPgW+XVWGjMZTUcyNNP8R7/IjM2Iyrc98UJY+WYiiWHrinnY9ZQ==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.7", + "merge-deep": "^3.0.2", + "svgo": "^1.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + } + }, + "cosmiconfig": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz", + "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0" + } + }, + "css-select": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz", + "integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^2.1.2", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-what": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz", + "integrity": "sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ==", + "dev": true + }, + "csso": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz", + "integrity": "sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==", + "dev": true, + "requires": { + "css-tree": "1.0.0-alpha.29" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.29", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz", + "integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==", + "dev": true, + "requires": { + "mdn-data": "~1.1.0", + "source-map": "^0.5.3" + } + } + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "js-yaml": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "svgo": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.1.1.tgz", + "integrity": "sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g==", + "dev": true, + "requires": { + "coa": "~2.0.1", + "colors": "~1.1.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "~0.1.0", + "css-tree": "1.0.0-alpha.28", + "css-url-regex": "^1.1.0", + "csso": "^3.5.0", + "js-yaml": "^3.12.0", + "mkdirp": "~0.5.1", + "object.values": "^1.0.4", + "sax": "~1.2.4", + "stable": "~0.1.6", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + } + } + }, + "@svgr/webpack": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-4.1.0.tgz", + "integrity": "sha512-d09ehQWqLMywP/PT/5JvXwPskPK9QCXUjiSkAHehreB381qExXf5JFCBWhfEyNonRbkIneCeYM99w+Ud48YIQQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.6", + "@babel/plugin-transform-react-constant-elements": "^7.0.0", + "@babel/preset-env": "^7.1.6", + "@babel/preset-react": "^7.0.0", + "@svgr/core": "^4.1.0", + "@svgr/plugin-jsx": "^4.1.0", + "@svgr/plugin-svgo": "^4.0.3", + "loader-utils": "^1.1.0" + } + }, + "@types/async": { + "version": "2.0.50", + "resolved": "https://registry.npmjs.org/@types/async/-/async-2.0.50.tgz", + "integrity": "sha512-VMhZMMQgV1zsR+lX/0IBfAk+8Eb7dPVMWiQGFAt3qjo5x7Ml6b77jUo0e1C3ToD+XRDXqtrfw+6AB0uUsPEr3Q==", + "optional": true + }, + "@types/babel__core": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.0.tgz", + "integrity": "sha512-wJTeJRt7BToFx3USrCDs2BhEi4ijBInTQjOIukj6a/5tEkwpFMVZ+1ppgmE+Q/FQyc5P/VWUbx7I9NELrKruHA==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + }, + "dependencies": { + "@babel/parser": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.3.tgz", + "integrity": "sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==", + "dev": true + } + } + }, + "@types/babel__generator": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.0.2.tgz", + "integrity": "sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + }, + "dependencies": { + "@babel/parser": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.3.tgz", + "integrity": "sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==", + "dev": true + } + } + }, + "@types/babel__traverse": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.6.tgz", + "integrity": "sha512-XYVgHF2sQ0YblLRMLNPB3CkFMewzFmlDsH/TneZFHUXDlABQgh88uOxuez7ZcXxayLFrqLwtDH1t+FmlFwNZxw==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", + "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@types/cheerio": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.10.tgz", + "integrity": "sha512-fOM/Jhv51iyugY7KOBZz2ThfT1gwvsGCfWxpLpZDgkGjpEO4Le9cld07OdskikLjDUQJ43dzDaVRSFwQlpdqVg==" + }, + "@types/classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-XHcYvVdbtAxVstjKxuULYqYaWIzHR15yr1pZj4fnGChuBVJlIAp9StJna0ZJNSgxPh4Nac2FL4JM3M11Tm6fqQ==" + }, + "@types/draft-js": { + "version": "0.10.28", + "resolved": "https://registry.npmjs.org/@types/draft-js/-/draft-js-0.10.28.tgz", + "integrity": "sha512-mShgWAYAduZ2Rwzpo52cToq+q8SIZ2O6Byl2F9wphB0QFjuNtUMyvAzGGg4kYGWPLZKELMWlEA/wv+AdPlkclw==", + "dev": true, + "requires": { + "@types/react": "*", + "immutable": "^3.8.1" + } + }, + "@types/enzyme": { + "version": "3.1.15", + "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.1.15.tgz", + "integrity": "sha512-6b4JWgV+FNec1c4+8HauGbXg5gRc1oQK93t2+4W+bHjG/PzO+iPvagY6d6bXAZ+t+ps51Zb2F9LQ4vl0S0Epog==", + "requires": { + "@types/cheerio": "*", + "@types/react": "*" + } + }, + "@types/events": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" + }, + "@types/fs-extra": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.5.tgz", + "integrity": "sha512-w7iqhDH9mN8eLClQOYTkhdYUOSpp25eXxfc6VbFOGtzxW34JcvctH2bKjj4jD4++z4R5iO5D+pg48W2e03I65A==", + "requires": { + "@types/node": "*" + } + }, + "@types/fuzzaldrin": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/fuzzaldrin/-/fuzzaldrin-2.1.1.tgz", + "integrity": "sha512-KHKQApfuxY67bNVCvRYXEJA/8krvf27T4aA5dTQV8GBx19FKOhcvznbHBVqR7pFJhXZk/yYMWiPEPJ/JVdQ0jQ==" + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/history": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.6.2.tgz", + "integrity": "sha512-eVAb52MJ4lfPLiO9VvTgv8KaZDEIqCwhv+lXOMLlt4C1YHTShgmMULEg0RrCbnqfYd6QKfHsMp0MiX0vWISpSw==", + "dev": true + }, + "@types/i18next": { + "version": "8.4.3", + "resolved": "https://registry.npmjs.org/@types/i18next/-/i18next-8.4.3.tgz", + "integrity": "sha512-ayqHEU+i9H7/Fkefnhyvml1ChKEZXcDwmVqo3jmrxy7PoAtTSY1t4/hr58Xz8hkXLPoCGS1hTc6bLJOUaOAjfQ==", + "dev": true + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz", + "integrity": "sha512-eAtOAFZefEnfJiRFQBGw1eYqa5GTLCZ1y86N0XSI/D6EB+E8z6VPV/UL7Gi5UEclFqoQk+6NRqEDsfmDLXn8sg==", + "dev": true + }, + "@types/jest": { + "version": "23.3.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.1.tgz", + "integrity": "sha512-/UMY+2GkOZ27Vrc51pqC5J8SPd39FKt7kkoGAtWJ8s4msj0b15KehDWIiJpWY3/7tLxBQLLzJhIBhnEsXdzpgw==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "@types/jss": { + "version": "9.5.8", + "resolved": "https://registry.npmjs.org/@types/jss/-/jss-9.5.8.tgz", + "integrity": "sha512-bBbHvjhm42UKki+wZpR89j73ykSXg99/bhuKuYYePtpma3ZAnmeGnl0WxXiZhPGsIfzKwCUkpPC0jlrVMBfRxA==", + "requires": { + "csstype": "^2.0.0", + "indefinite-observable": "^1.0.1" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/moment-timezone": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@types/moment-timezone/-/moment-timezone-0.5.9.tgz", + "integrity": "sha512-tBf1QR8xAayQfI1xD+SMSNDMxi+aCYKEhjgVXTZt3sgxS2XusNX3jM6jJbFoY/ar1CK/PaYJoPkWs/mwcwgOqw==", + "requires": { + "moment": ">=2.14.0" + } + }, + "@types/node": { + "version": "9.4.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.4.6.tgz", + "integrity": "sha512-CTUtLb6WqCCgp6P59QintjHWqzf4VL1uPA27bipLAPxFqrtK1gEYllePzTICGqQ8rYsCbpnsNypXjjDzGAAjEQ==" + }, + "@types/prop-types": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.0.tgz", + "integrity": "sha512-eItQyV43bj4rR3JPV0Skpl1SncRCdziTEK9/v8VwXmV6d/qOUO8/EuWeHBbCZcsfSHfzI5UyMJLCSXtxxznyZg==" + }, + "@types/puppeteer": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-1.5.0.tgz", + "integrity": "sha512-KNQzIbHKn/yOlCH3BXOBA+3OUTZRmLkeCMQOHSid1ytrCKNks8ut6Oj0eeUeiOdOoRcW264qNh5kjH6LIoxeCA==", + "requires": { + "@types/events": "*", + "@types/node": "*" + } + }, + "@types/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.1.tgz", + "integrity": "sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA==", + "dev": true + }, + "@types/react": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.6.tgz", + "integrity": "sha512-bN9qDjEMltmHrl0PZRI4IF2AbB7V5UlRfG+OOduckVnRQ4VzXVSzy/1eLAh778IEqhTnW0mmgL9yShfinNverA==", + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "@types/react-dom": { + "version": "16.8.2", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.8.2.tgz", + "integrity": "sha512-MX7n1wq3G/De15RGAAqnmidzhr2Y9O/ClxPxyqaNg96pGyeXUYPSvujgzEVpLo9oIP4Wn1UETl+rxTN02KEpBw==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-dropzone": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/react-dropzone/-/react-dropzone-4.2.2.tgz", + "integrity": "sha512-okO6HY+w7V0uHoy6JpLY6BwY/s/oObtXZmUQdX0ycjPeLhK8Af/xf79CFkLA1fM6oVp16n1d962ejdkEXk375Q==", + "requires": { + "@types/react": "*" + } + }, + "@types/react-helmet": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-5.0.7.tgz", + "integrity": "sha512-FbDibfkcGsD/N+3k47bfLcr5uAzSi64LJ2OOILz/P5vtBwT5A92KZAU5H9/7OjhUN6au5k+BbNplhVfp6IXDcQ==", + "requires": { + "@types/react": "*" + } + }, + "@types/react-infinite-scroller": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/react-infinite-scroller/-/react-infinite-scroller-1.2.0.tgz", + "integrity": "sha512-5TiqZoj3bn+lOctSra4+02T2ma12drNvQOjFicLL3iPWhNREbA9gb/XG9jCDR7f5Bl8k17pbm0nGFa5olnt9rA==", + "requires": { + "@types/react": "*" + } + }, + "@types/react-router": { + "version": "4.0.26", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-4.0.26.tgz", + "integrity": "sha512-BBL/Dk/sXAlC0Ee4zJrgYp8AsM5ubITRz8kX2a+4BBkDh9E5YE+4ZqzrS6L+ec6cXb4yRHL983fEN5AsobOIHg==", + "dev": true, + "requires": { + "@types/history": "*", + "@types/react": "*" + } + }, + "@types/react-router-dom": { + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-4.2.7.tgz", + "integrity": "sha512-6sIP3dIj6xquvcAuYDaxpbeLjr9954OuhCXnniMhnDgykAw2tVji9b0jKHofPJGUoHEMBsWzO83tjnk7vfzozA==", + "dev": true, + "requires": { + "@types/history": "*", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "@types/react-sortable-tree": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@types/react-sortable-tree/-/react-sortable-tree-0.3.6.tgz", + "integrity": "sha512-zNqhO7Rv9dJ8AfrLOrjOjMKsKsiXrWa6YbMakp+6bhYQojkNQ4Hs8g12gTO2+5Rerj3iU9hJb+XncI0G2X3W3Q==", + "requires": { + "@types/react": "*", + "@types/react-virtualized": "*", + "react-dnd": "5 || 6 || 7" + } + }, + "@types/react-test-renderer": { + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.8.1.tgz", + "integrity": "sha512-8gU69ELfJGxzVWVYj4MTtuHxz9nO+d175XeQ1XrXXxesUBsB4KK6OCfzVhEX6leZWWBDVtMJXp/rUjhClzL7gw==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-transition-group": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-2.9.1.tgz", + "integrity": "sha512-1usq4DRUVBFnxc9KGJAlJO9EpQrLZGDDEC8wDOn2+2ODSyudYo8FiIzPDRaX/hfQjHqGeeoNaNdA2bj0l35hZQ==", + "requires": { + "@types/react": "*" + } + }, + "@types/react-virtualized": { + "version": "9.21.1", + "resolved": "https://registry.npmjs.org/@types/react-virtualized/-/react-virtualized-9.21.1.tgz", + "integrity": "sha512-BwWXk6Vy+YuWbc2jZsmm0fn8bglPUpqUWPH/JUUBfvfKfL2nDvvmCiauyxMCWrxZMVBbkxaUuP82SviaDv0wGw==", + "requires": { + "@types/prop-types": "*", + "@types/react": "*" + } + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "@types/storybook__addon-storyshots": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/storybook__addon-storyshots/-/storybook__addon-storyshots-3.4.3.tgz", + "integrity": "sha512-xn8V+3heUFbpMeVkkhG97CB0UaiWdr7QklmhZ7OftH4uS7VgposNybp+2/iwduoKQyfB7tLSxth9t5rOvDHWMA==", + "requires": { + "@types/puppeteer": "*", + "@types/react": "*" + } + }, + "@types/storybook__react": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/storybook__react/-/storybook__react-4.0.0.tgz", + "integrity": "sha512-Iq3RX953fqZRwWN3jywm8pUx1/Atev+x/9tF7/2CNA+Ii55sGSJJRWMRthUKQXTa3zOexcvfksfVYdUaIZY91w==", + "dev": true, + "requires": { + "@types/react": "*", + "@types/webpack-env": "*" + } + }, + "@types/string-similarity": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/string-similarity/-/string-similarity-1.2.0.tgz", + "integrity": "sha512-zrUNNlpw29TES8RF5EbdjlyLQduy9rh0b+xgx3RuPl0Qb6KMcQ3CI+cNKejpU3TEbLEfq6l627WxDIXS+Ebj/Q==" + }, + "@types/unist": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.2.tgz", + "integrity": "sha512-iHI60IbyfQilNubmxsq4zqSjdynlmc2Q/QvH9kjzg9+CCYVVzq1O6tc7VBzSygIwnmOt07w80IG6HDQvjv3Liw==", + "dev": true + }, + "@types/url-join": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@types/url-join/-/url-join-0.8.2.tgz", + "integrity": "sha1-EYHsvh2XtwNODqHjXmLobMJrQi0=" + }, + "@types/vfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz", + "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/unist": "*", + "@types/vfile-message": "*" + } + }, + "@types/vfile-message": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-1.0.1.tgz", + "integrity": "sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/unist": "*" + } + }, + "@types/webpack-env": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.13.6.tgz", + "integrity": "sha512-5Th3OsZ4gTRdr9Mho83BQ23cex4sRhOR4XTG+m+cJc0FhtUBK9Vn62hBJ+pnQYnSxoPOsKoAPOx6FcphxBC8ng==", + "dev": true + }, + "@types/yargs": { + "version": "12.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.12.tgz", + "integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==", + "dev": true + }, + "@types/zen-observable": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.0.tgz", + "integrity": "sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg==" + }, + "@webassemblyjs/ast": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", + "integrity": "sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz", + "integrity": "sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz", + "integrity": "sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz", + "integrity": "sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz", + "integrity": "sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.7.11" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz", + "integrity": "sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz", + "integrity": "sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz", + "integrity": "sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz", + "integrity": "sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz", + "integrity": "sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz", + "integrity": "sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.1" + } + }, + "@webassemblyjs/utf8": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz", + "integrity": "sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz", + "integrity": "sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/helper-wasm-section": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-opt": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "@webassemblyjs/wast-printer": "1.7.11" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz", + "integrity": "sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz", + "integrity": "sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz", + "integrity": "sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz", + "integrity": "sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/floating-point-hex-parser": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-code-frame": "1.7.11", + "@webassemblyjs/helper-fsm": "1.7.11", + "@xtuc/long": "4.2.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz", + "integrity": "sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11", + "@xtuc/long": "4.2.1" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", + "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", + "dev": true + }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "dev": true + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "~1.33.0" + } + } + } + }, + "acorn": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.6.0.tgz", + "integrity": "sha512-QatFQ4C0n+PLqemyC6zXEv04tSqRR0hRqe+uGKPEVgKe2G8kl8wJvHzRYWwz6vqqEqt6idPVMFojZ4P1zlyAzQ==", + "dev": true + }, + "acorn-dynamic-import": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", + "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", + "dev": true, + "requires": { + "acorn": "^5.0.0" + } + }, + "acorn-globals": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", + "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "dev": true + }, + "address": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz", + "integrity": "sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg==", + "dev": true + }, + "airbnb-js-shims": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/airbnb-js-shims/-/airbnb-js-shims-2.1.1.tgz", + "integrity": "sha512-h8UtyB/TCdOwWoEPQJGHgsWwSnTqPrRZbhyZYjAwY9/AbjdjfkKy9L/T3fIFS6MKX8YrpWFRm6xqFSgU+2DRGw==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "array.prototype.flatmap": "^1.2.1", + "es5-shim": "^4.5.10", + "es6-shim": "^0.35.3", + "function.prototype.name": "^1.1.0", + "object.entries": "^1.0.4", + "object.fromentries": "^1.0.0", + "object.getownpropertydescriptors": "^2.0.3", + "object.values": "^1.0.4", + "promise.prototype.finally": "^3.1.0", + "string.prototype.matchall": "^3.0.0", + "string.prototype.padend": "^3.0.0", + "string.prototype.padstart": "^3.0.0", + "symbol.prototype.description": "^1.0.0" + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ajv-errors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz", + "integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=", + "dev": true + }, + "ajv-keywords": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", + "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", + "dev": true + }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "requires": { + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "string-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.0.0.tgz", + "integrity": "sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } + } + }, + "ansi-colors": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.2.tgz", + "integrity": "sha512-kJmcp4PrviBBEx95fC3dYRiC/QSN3EBd0GU1XoNEk/IuUa92rsB6o90zP3w5VAyNznR38Vkc9i8vk5zK6T7TxA==", + "dev": true + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==" + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "apollo": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/apollo/-/apollo-2.8.1.tgz", + "integrity": "sha512-8zU8Dr4fk39oMmdGXGwSFDtWF6LaIGXL6saqL5bNAhbzgPOon9IYtTE09o4qSlqULMtcm2TOdMZ+ffLH+ft6Iw==", + "requires": { + "@apollographql/apollo-tools": "0.3.5", + "@oclif/command": "1.5.12", + "@oclif/config": "1.12.12", + "@oclif/errors": "1.2.2", + "@oclif/plugin-autocomplete": "0.1.0", + "@oclif/plugin-help": "2.1.6", + "@oclif/plugin-not-found": "1.2.2", + "@oclif/plugin-plugins": "1.7.8", + "@oclif/plugin-warn-if-update-available": "1.7.0", + "apollo-codegen-core": "0.33.2", + "apollo-codegen-flow": "0.33.2", + "apollo-codegen-scala": "0.34.2", + "apollo-codegen-swift": "0.33.2", + "apollo-codegen-typescript": "0.33.2", + "apollo-env": "0.4.0", + "apollo-graphql": "0.2.0", + "apollo-language-server": "1.6.2", + "chalk": "2.4.2", + "cli-ux": "4.9.3", + "env-ci": "3.2.0", + "gaze": "1.1.3", + "git-parse": "1.0.3", + "git-rev-sync": "1.12.0", + "glob": "7.1.3", + "graphql": "^14.0.2", + "graphql-tag": "2.10.1", + "heroku-cli-util": "8.0.11", + "listr": "0.14.3", + "lodash": "4.17.11", + "tty": "1.0.1", + "vscode-uri": "1.0.6" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graphql-tag": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.1.tgz", + "integrity": "sha512-jApXqWBzNXQ8jYa/HLkZJaVw9jgwNqZkywa2zfFn16Iv1Zb7ELNHkJaXHR7Quvd5SIGsy6Ny7SUKATgnu05uEg==" + } + } + }, + "apollo-cache": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.1.21.tgz", + "integrity": "sha512-5ErNb78KHtrJNimkDBTEigcvHkIqUmS7QJIk4lpZZ+XLVVgvk2fD+GhD1PLP+s8vHfAKVbO6vdbRxCCjGGrh5w==", + "requires": { + "apollo-utilities": "^1.0.26" + }, + "dependencies": { + "apollo-utilities": { + "version": "1.0.26", + "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.26.tgz", + "integrity": "sha512-URw7o3phymliqYCYatcird2YRPUU2eWCNvip64U9gQrX56mEfK4m99yBIDCMTpmcvOFsKLii1sIEZsHIs/bvnw==", + "requires": { + "fast-json-stable-stringify": "^2.0.0" + } + } + } + }, + "apollo-cache-inmemory": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/apollo-cache-inmemory/-/apollo-cache-inmemory-1.3.11.tgz", + "integrity": "sha512-fSoyjBV5RV57J3i/VHDDB74ZgXc0PFiogheNFHEhC0mL6rg5e/DjTx0Vg+csIBk23gvlzTvV+eypx7Q2NJ+dYg==", + "requires": { + "apollo-cache": "^1.1.21", + "apollo-utilities": "^1.0.26", + "optimism": "^0.6.6" + }, + "dependencies": { + "apollo-utilities": { + "version": "1.0.26", + "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.26.tgz", + "integrity": "sha512-URw7o3phymliqYCYatcird2YRPUU2eWCNvip64U9gQrX56mEfK4m99yBIDCMTpmcvOFsKLii1sIEZsHIs/bvnw==", + "requires": { + "fast-json-stable-stringify": "^2.0.0" + } + } + } + }, + "apollo-client": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-2.4.7.tgz", + "integrity": "sha512-6aAm+16AFBYZhJF8eKxrup6AbYni01InDiwTfZhMMTP2xaXQWjsQnfaHbI2oE+hd3+AZFy1drkse8RZKghR/WQ==", + "requires": { + "@types/async": "2.0.50", + "@types/zen-observable": "^0.8.0", + "apollo-cache": "1.1.21", + "apollo-link": "^1.0.0", + "apollo-link-dedup": "^1.0.0", + "apollo-utilities": "1.0.26", + "symbol-observable": "^1.0.2", + "zen-observable": "^0.8.0" + }, + "dependencies": { + "apollo-cache": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.1.21.tgz", + "integrity": "sha512-5ErNb78KHtrJNimkDBTEigcvHkIqUmS7QJIk4lpZZ+XLVVgvk2fD+GhD1PLP+s8vHfAKVbO6vdbRxCCjGGrh5w==", + "requires": { + "apollo-utilities": "^1.0.26" + } + }, + "apollo-utilities": { + "version": "1.0.26", + "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.26.tgz", + "integrity": "sha512-URw7o3phymliqYCYatcird2YRPUU2eWCNvip64U9gQrX56mEfK4m99yBIDCMTpmcvOFsKLii1sIEZsHIs/bvnw==", + "requires": { + "fast-json-stable-stringify": "^2.0.0" + } + }, + "zen-observable": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.11.tgz", + "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==" + } + } + }, + "apollo-client-preset": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/apollo-client-preset/-/apollo-client-preset-1.0.8.tgz", + "integrity": "sha512-vRrdBfoOBkSboUmkec/zDWK9dT22GoZ2NgTKxfPXaTRh82HGDejDAblMr7BuDtZQ6zxMUiD9kghmO+3HXsHKdQ==", + "requires": { + "apollo-cache-inmemory": "^1.1.7", + "apollo-client": "^2.2.2", + "apollo-link": "^1.0.6", + "apollo-link-http": "^1.3.1", + "graphql-tag": "^2.4.2" + } + }, + "apollo-codegen-core": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/apollo-codegen-core/-/apollo-codegen-core-0.33.2.tgz", + "integrity": "sha512-KRXUvJuV6PsO3ktImlTWcISmaQbG4rsCSltRgh/XiIPYr9pv4j61+7Q/J78/o+wgfRiKUhOytfuyVLNbSCFR1Q==", + "requires": { + "@babel/generator": "7.4.0", + "@babel/parser": "^7.1.3", + "@babel/types": "7.4.0", + "apollo-env": "0.4.0", + "apollo-language-server": "1.6.2", + "ast-types": "^0.12.0", + "common-tags": "^1.5.1", + "recast": "^0.17.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.0.tgz", + "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==", + "requires": { + "@babel/types": "^7.4.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/parser": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.3.tgz", + "integrity": "sha512-gxpEUhTS1sGA63EGQGuA+WESPR/6tz6ng7tSHFCmaTJK/cGK8y37cBTspX+U2xCAue2IQVvF6Z0oigmjwD8YGQ==" + }, + "@babel/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", + "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "ast-types": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.12.3.tgz", + "integrity": "sha512-wJUcAfrdW+IgDoMGNz5MmcvahKgB7BwIbLupdKVVHxHNYt+HVR2k35swdYNv9aZpF8nvlkjbnkp2rrNwxGckZA==" + }, + "recast": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.17.5.tgz", + "integrity": "sha512-K+DgfAMIyEjNKjaFSWgg9TTu7wFgU/4KTyw4E9vl6M5QPDuUYbyt49Yzb0EIDbZks+6lXk/UZ9eTuE4jlLyf2A==", + "requires": { + "ast-types": "0.12.3", + "esprima": "~4.0.0", + "private": "^0.1.8", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + } + } + }, + "apollo-codegen-flow": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/apollo-codegen-flow/-/apollo-codegen-flow-0.33.2.tgz", + "integrity": "sha512-s0Q7Mh2uWgZJM1y9jJs3bunInZrr4OISLGFOJL0PAiTURHtKoAWtgITY+Fiz3HdkIcyNgyb6cw+KnOTizyzm7A==", + "requires": { + "@babel/generator": "7.4.0", + "@babel/types": "7.4.0", + "apollo-codegen-core": "0.33.2", + "apollo-env": "0.4.0", + "change-case": "^3.0.1", + "common-tags": "^1.5.1", + "inflected": "^2.0.3" + }, + "dependencies": { + "@babel/generator": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.0.tgz", + "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==", + "requires": { + "@babel/types": "^7.4.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", + "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + } + } + }, + "apollo-codegen-scala": { + "version": "0.34.2", + "resolved": "https://registry.npmjs.org/apollo-codegen-scala/-/apollo-codegen-scala-0.34.2.tgz", + "integrity": "sha512-MDSS8aWFziw/+pvpswIOPdRwZpdSw/f5Hixu8PxYJG088UlQ8odVCa9bNqfmkGd+IPK6bRwAR0vv1HvIITzhsw==", + "requires": { + "apollo-codegen-core": "0.33.2", + "apollo-env": "0.4.0", + "change-case": "^3.0.1", + "common-tags": "^1.5.1", + "inflected": "^2.0.3" + } + }, + "apollo-codegen-swift": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/apollo-codegen-swift/-/apollo-codegen-swift-0.33.2.tgz", + "integrity": "sha512-+ZD9Deh04d+Iv8nU2R94ZnGj5sjxfAF+NNZoRAR9A7EqEKMNB8tUvwzKQlLnMN3v1J/Rs64Jlk84VbKMpbPgWQ==", + "requires": { + "apollo-codegen-core": "0.33.2", + "apollo-env": "0.4.0", + "change-case": "^3.0.1", + "common-tags": "^1.5.1", + "inflected": "^2.0.3" + } + }, + "apollo-codegen-typescript": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/apollo-codegen-typescript/-/apollo-codegen-typescript-0.33.2.tgz", + "integrity": "sha512-jE0sSbt1GXUjRVCgqMQqgbyDjc/HKD2UN55PG4K6wOfPQIzUkx6ZLFBhXJONrnXggQthZyT9h7LcGgvL4EEa1Q==", + "requires": { + "@babel/generator": "7.4.0", + "@babel/types": "7.4.0", + "apollo-codegen-core": "0.33.2", + "apollo-env": "0.4.0", + "change-case": "^3.0.1", + "common-tags": "^1.5.1", + "inflected": "^2.0.3" + }, + "dependencies": { + "@babel/generator": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.0.tgz", + "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==", + "requires": { + "@babel/types": "^7.4.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", + "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + } + } + }, + "apollo-datasource": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.3.1.tgz", + "integrity": "sha512-qdEUeonc9pPZvYwXK36h2NZoT7Pddmy0HYOzdV0ON5pcG1YtNmUyyYi83Q60V5wTWjuaCjyJ9hOY6wr0BMvQuA==", + "requires": { + "apollo-server-caching": "0.3.1", + "apollo-server-env": "2.2.0" + } + }, + "apollo-env": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/apollo-env/-/apollo-env-0.4.0.tgz", + "integrity": "sha512-TZpk59RTbXd8cEqwmI0KHFoRrgBRplvPAP4bbRrX4uDSxXvoiY0Y6tQYUlJ35zi398Hob45mXfrZxeRDzoFMkQ==", + "requires": { + "core-js": "3.0.0-beta.13", + "node-fetch": "^2.2.0", + "sha.js": "^2.4.11" + }, + "dependencies": { + "core-js": { + "version": "3.0.0-beta.13", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.0-beta.13.tgz", + "integrity": "sha512-16Q43c/3LT9NyePUJKL8nRIQgYWjcBhjJSMWg96PVSxoS0PeE0NHitPI3opBrs9MGGHjte1KoEVr9W63YKlTXQ==" + }, + "node-fetch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", + "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==" + } + } + }, + "apollo-graphql": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.2.0.tgz", + "integrity": "sha512-wwKynD31Yw1L93IAtnEyhSxBhK4X7NXqkY6wBKWRQ4xph5uJKGgmcQmq3sPieKJT91BGL4AQBv+cwGD3blbLNA==", + "requires": { + "apollo-env": "0.4.0", + "lodash.sortby": "^4.7.0" + } + }, + "apollo-language-server": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/apollo-language-server/-/apollo-language-server-1.6.2.tgz", + "integrity": "sha512-t3jjvyZtLr/PG6R4vtF6AD3eLu75npWIjUikh6KA8YT8c35IHEf55tNpYCDAJCVWszn6HGokKVtmFr6u5J+6Gg==", + "requires": { + "@apollographql/apollo-tools": "0.3.5", + "@apollographql/graphql-language-service-interface": "^2.0.2", + "@endemolshinegroup/cosmiconfig-typescript-loader": "^1.0.0", + "apollo-datasource": "^0.3.0", + "apollo-env": "0.4.0", + "apollo-link": "^1.2.3", + "apollo-link-context": "^1.0.9", + "apollo-link-error": "^1.1.1", + "apollo-link-http": "^1.5.5", + "apollo-link-ws": "^1.0.9", + "apollo-server-errors": "^2.0.2", + "await-to-js": "^2.0.1", + "core-js": "3.0.0-beta.13", + "cosmiconfig": "^5.0.6", + "dotenv": "^7.0.0", + "glob": "^7.1.3", + "graphql": "^14.0.2", + "graphql-tag": "^2.10.1", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "minimist": "^1.2.0", + "moment": "^2.22.2", + "recursive-readdir": "^2.2.2", + "subscriptions-transport-ws": "^0.9.15", + "vscode-languageserver": "^5.1.0", + "vscode-uri": "^1.0.6", + "ws": "^6.1.0" + }, + "dependencies": { + "core-js": { + "version": "3.0.0-beta.13", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.0-beta.13.tgz", + "integrity": "sha512-16Q43c/3LT9NyePUJKL8nRIQgYWjcBhjJSMWg96PVSxoS0PeE0NHitPI3opBrs9MGGHjte1KoEVr9W63YKlTXQ==" + }, + "cosmiconfig": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.0.tgz", + "integrity": "sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g==", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.0", + "parse-json": "^4.0.0" + } + }, + "dotenv": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", + "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==" + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graphql-tag": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.1.tgz", + "integrity": "sha512-jApXqWBzNXQ8jYa/HLkZJaVw9jgwNqZkywa2zfFn16Iv1Zb7ELNHkJaXHR7Quvd5SIGsy6Ny7SUKATgnu05uEg==" + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "apollo-link": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.5.tgz", + "integrity": "sha512-GJHEE4B06oEB58mpRRwW6ISyvgX2aCqCLjpcE3M/6/4e+ZVeX7fRGpMJJDq2zZ8n7qWdrEuY315JfxzpsJmUhA==", + "requires": { + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.12" + } + }, + "apollo-link-batch": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/apollo-link-batch/-/apollo-link-batch-1.1.6.tgz", + "integrity": "sha512-jmNy15zMe3jwT27vyNhC8PqHC8hvHarZ2ui/lvZH77J58+5qBR5X9GmNyGZ1srtuBVynrMnrzBJWlvORmkO54Q==", + "requires": { + "apollo-link": "^1.2.5" + }, + "dependencies": { + "apollo-link": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.5.tgz", + "integrity": "sha512-GJHEE4B06oEB58mpRRwW6ISyvgX2aCqCLjpcE3M/6/4e+ZVeX7fRGpMJJDq2zZ8n7qWdrEuY315JfxzpsJmUhA==", + "requires": { + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.12" + } + }, + "zen-observable": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.11.tgz", + "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==" + }, + "zen-observable-ts": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.12.tgz", + "integrity": "sha512-wwqbD6K6CqDd1T67UFg4hgDqnu2YAnFJDCPYmwN/N6Yfa+2QgoSp+nJomh+FWUdOc1A+553/ElvfoW8Vc/vsLg==", + "requires": { + "zen-observable": "^0.8.0" + } + } + } + }, + "apollo-link-batch-http": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/apollo-link-batch-http/-/apollo-link-batch-http-1.2.5.tgz", + "integrity": "sha512-dU8DcH7aKY/mus4apii7FQolAal6nKN5TmOWCU+se/rsykFkQTpvU+hdF2EZvAgqSnNGpKdtgLetoM/GyrNk4A==", + "requires": { + "apollo-link": "^1.2.5", + "apollo-link-batch": "^1.1.6", + "apollo-link-http-common": "^0.2.7" + }, + "dependencies": { + "apollo-link": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.5.tgz", + "integrity": "sha512-GJHEE4B06oEB58mpRRwW6ISyvgX2aCqCLjpcE3M/6/4e+ZVeX7fRGpMJJDq2zZ8n7qWdrEuY315JfxzpsJmUhA==", + "requires": { + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.12" + } + }, + "apollo-link-http-common": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.7.tgz", + "integrity": "sha512-rnn6BWDnd7DR8Xskpicw2dPV2bkXN4cD6VhikdWK982ovmLi7gP67ZXA+Hclox4aEUEhRLJnuprBwzSU3bRtEQ==", + "requires": { + "apollo-link": "^1.2.5" + } + }, + "zen-observable": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.11.tgz", + "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==" + }, + "zen-observable-ts": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.12.tgz", + "integrity": "sha512-wwqbD6K6CqDd1T67UFg4hgDqnu2YAnFJDCPYmwN/N6Yfa+2QgoSp+nJomh+FWUdOc1A+553/ElvfoW8Vc/vsLg==", + "requires": { + "zen-observable": "^0.8.0" + } + } + } + }, + "apollo-link-context": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/apollo-link-context/-/apollo-link-context-1.0.10.tgz", + "integrity": "sha512-HX3BEmkANs2A8AcYCy92SFJrW+0SbGrhDTSHV6ZwKIJ9ZrsOtly8cMrRLzEw1emjHIz5SP7XJEn3ko7BwhBBSw==", + "requires": { + "apollo-link": "^1.2.4" + }, + "dependencies": { + "apollo-link": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.4.tgz", + "integrity": "sha512-B1z+9H2nTyWEhMXRFSnoZ1vSuAYP+V/EdUJvRx9uZ8yuIBZMm6reyVtr1n0BWlKeSFyPieKJy2RLzmITAAQAMQ==", + "requires": { + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.11" + } + }, + "zen-observable": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.11.tgz", + "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==" + }, + "zen-observable-ts": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.11.tgz", + "integrity": "sha512-8bs7rgGV4kz5iTb9isudkuQjtWwPnQ8lXq6/T76vrepYZVMsDEv6BXaEA+DHdJSK3KVLduagi9jSpSAJ5NgKHw==", + "requires": { + "zen-observable": "^0.8.0" + } + } + } + }, + "apollo-link-dedup": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/apollo-link-dedup/-/apollo-link-dedup-1.0.11.tgz", + "integrity": "sha512-RcvkXR0CNbQcsw6LdrPksGa+9YjZ1ghk0k2PKal6rSBCyyqzokcBawXOtoMN8q+0FLR1dGs5GnAQVeucQuY28g==", + "requires": { + "apollo-link": "^1.2.4" + }, + "dependencies": { + "apollo-link": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.4.tgz", + "integrity": "sha512-B1z+9H2nTyWEhMXRFSnoZ1vSuAYP+V/EdUJvRx9uZ8yuIBZMm6reyVtr1n0BWlKeSFyPieKJy2RLzmITAAQAMQ==", + "requires": { + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.11" + } + }, + "zen-observable": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.11.tgz", + "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==" + }, + "zen-observable-ts": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.11.tgz", + "integrity": "sha512-8bs7rgGV4kz5iTb9isudkuQjtWwPnQ8lXq6/T76vrepYZVMsDEv6BXaEA+DHdJSK3KVLduagi9jSpSAJ5NgKHw==", + "requires": { + "zen-observable": "^0.8.0" + } + } + } + }, + "apollo-link-error": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/apollo-link-error/-/apollo-link-error-1.1.2.tgz", + "integrity": "sha512-zlEZiqQ42E49+BeX3mIKPkMTSlOPrYNEwzSi1MubUiP/Bi6QRP7tzdJXNBnUpkW6MjZJQpfSNZNxK/xwvPiJIw==", + "requires": { + "apollo-link": "^1.2.4" + }, + "dependencies": { + "apollo-link": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.4.tgz", + "integrity": "sha512-B1z+9H2nTyWEhMXRFSnoZ1vSuAYP+V/EdUJvRx9uZ8yuIBZMm6reyVtr1n0BWlKeSFyPieKJy2RLzmITAAQAMQ==", + "requires": { + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.11" + } + }, + "zen-observable": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.11.tgz", + "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==" + }, + "zen-observable-ts": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.11.tgz", + "integrity": "sha512-8bs7rgGV4kz5iTb9isudkuQjtWwPnQ8lXq6/T76vrepYZVMsDEv6BXaEA+DHdJSK3KVLduagi9jSpSAJ5NgKHw==", + "requires": { + "zen-observable": "^0.8.0" + } + } + } + }, + "apollo-link-http": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.7.tgz", + "integrity": "sha512-EZ9nynHjwYCpGYP5IsRrZGTWidUVpshk7MuSG4joqGtJMwpFCgMQz+y3BHdUhowHtfAd9z60XmeOTG9FJolb8A==", + "requires": { + "apollo-link": "^1.2.4", + "apollo-link-http-common": "^0.2.6" + }, + "dependencies": { + "apollo-link": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.4.tgz", + "integrity": "sha512-B1z+9H2nTyWEhMXRFSnoZ1vSuAYP+V/EdUJvRx9uZ8yuIBZMm6reyVtr1n0BWlKeSFyPieKJy2RLzmITAAQAMQ==", + "requires": { + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.11" + } + }, + "apollo-link-http-common": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.6.tgz", + "integrity": "sha512-LUOMWvrZuBP1hyWLBXyaW0KyFeKo79j+k3N+Q4HSkXKbLibnllXQ+JxxoSKGhm0bhREygiLtJAG9JnGlhxGO/Q==", + "requires": { + "apollo-link": "^1.2.4" + } + }, + "zen-observable": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.11.tgz", + "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==" + }, + "zen-observable-ts": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.11.tgz", + "integrity": "sha512-8bs7rgGV4kz5iTb9isudkuQjtWwPnQ8lXq6/T76vrepYZVMsDEv6BXaEA+DHdJSK3KVLduagi9jSpSAJ5NgKHw==", + "requires": { + "zen-observable": "^0.8.0" + } + } + } + }, + "apollo-link-http-common": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.6.tgz", + "integrity": "sha512-LUOMWvrZuBP1hyWLBXyaW0KyFeKo79j+k3N+Q4HSkXKbLibnllXQ+JxxoSKGhm0bhREygiLtJAG9JnGlhxGO/Q==", + "requires": { + "apollo-link": "^1.2.4" + }, + "dependencies": { + "apollo-link": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.4.tgz", + "integrity": "sha512-B1z+9H2nTyWEhMXRFSnoZ1vSuAYP+V/EdUJvRx9uZ8yuIBZMm6reyVtr1n0BWlKeSFyPieKJy2RLzmITAAQAMQ==", + "requires": { + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.11" + } + }, + "zen-observable": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.11.tgz", + "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==" + }, + "zen-observable-ts": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.11.tgz", + "integrity": "sha512-8bs7rgGV4kz5iTb9isudkuQjtWwPnQ8lXq6/T76vrepYZVMsDEv6BXaEA+DHdJSK3KVLduagi9jSpSAJ5NgKHw==", + "requires": { + "zen-observable": "^0.8.0" + } + } + } + }, + "apollo-link-ws": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/apollo-link-ws/-/apollo-link-ws-1.0.17.tgz", + "integrity": "sha512-0PKgahM2BOcUiI3QSJMYXOoUylWKzar5NTZLgMLEW4K/CczOTzC4CTXvKMjh/cx57Jto/U2xzKRy9BEoNfnK5Q==", + "requires": { + "apollo-link": "^1.2.11", + "tslib": "^1.9.3" + }, + "dependencies": { + "apollo-link": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.11.tgz", + "integrity": "sha512-PQvRCg13VduLy3X/0L79M6uOpTh5iHdxnxYuo8yL7sJlWybKRJwsv4IcRBJpMFbChOOaHY7Og9wgPo6DLKDKDA==", + "requires": { + "apollo-utilities": "^1.2.1", + "ts-invariant": "^0.3.2", + "tslib": "^1.9.3", + "zen-observable-ts": "^0.8.18" + } + }, + "apollo-utilities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.2.1.tgz", + "integrity": "sha512-Zv8Udp9XTSFiN8oyXOjf6PMHepD4yxxReLsl6dPUy5Ths7jti3nmlBzZUOxuTWRwZn0MoclqL7RQ5UEJN8MAxg==", + "requires": { + "fast-json-stable-stringify": "^2.0.0", + "ts-invariant": "^0.2.1", + "tslib": "^1.9.3" + }, + "dependencies": { + "ts-invariant": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.2.1.tgz", + "integrity": "sha512-Z/JSxzVmhTo50I+LKagEISFJW3pvPCqsMWLamCTX8Kr3N5aMrnGOqcflbe5hLUzwjvgPfnLzQtHZv0yWQ+FIHg==", + "requires": { + "tslib": "^1.9.3" + } + } + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "zen-observable-ts": { + "version": "0.8.18", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.18.tgz", + "integrity": "sha512-q7d05s75Rn1j39U5Oapg3HI2wzriVwERVo4N7uFGpIYuHB9ff02P/E92P9B8T7QVC93jCMHpbXH7X0eVR5LA7A==", + "requires": { + "tslib": "^1.9.3", + "zen-observable": "^0.8.0" + } + } + } + }, + "apollo-server-caching": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.3.1.tgz", + "integrity": "sha512-mfxzikYXbB/OoEms77AGYwRh7FF3Oim5v5XWAL+VL49FrkbZt5lopVa4bABi7Mz8Nt3Htl9EBJN8765s/yh8IA==", + "requires": { + "lru-cache": "^5.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + } + } + }, + "apollo-server-env": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.2.0.tgz", + "integrity": "sha512-wjJiI5nQWPBpNmpiLP389Ezpstp71szS6DHAeTgYLb/ulCw3CTuuA+0/E1bsThVWiQaDeHZE0sE3yI8q2zrYiA==", + "requires": { + "node-fetch": "^2.1.2", + "util.promisify": "^1.0.0" + }, + "dependencies": { + "node-fetch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", + "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==" + } + } + }, + "apollo-server-errors": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.2.1.tgz", + "integrity": "sha512-wY/YE3iJVMYC+WYIf8QODBjIP4jhI+oc7kiYo9mrz7LdYPKAgxr/he+NteGcqn/0Ea9K5/ZFTGJDbEstSMeP8g==" + }, + "apollo-upload-client": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-9.1.0.tgz", + "integrity": "sha512-ZN5gsbBjImEZTWWTUHpCEGDasnoBGbaODpznQ5EawyNHceuFYSNJbbft+ZZ841vZAcj9XZdKUKoaLBlMZ/r7nw==", + "requires": { + "apollo-link": "^1.2.3", + "apollo-link-http-common": "^0.2.5", + "extract-files": "^4.0.0" + }, + "dependencies": { + "apollo-link": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.4.tgz", + "integrity": "sha512-B1z+9H2nTyWEhMXRFSnoZ1vSuAYP+V/EdUJvRx9uZ8yuIBZMm6reyVtr1n0BWlKeSFyPieKJy2RLzmITAAQAMQ==", + "requires": { + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.11" + } + }, + "zen-observable": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.11.tgz", + "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==" + }, + "zen-observable-ts": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.11.tgz", + "integrity": "sha512-8bs7rgGV4kz5iTb9isudkuQjtWwPnQ8lXq6/T76vrepYZVMsDEv6BXaEA+DHdJSK3KVLduagi9jSpSAJ5NgKHw==", + "requires": { + "zen-observable": "^0.8.0" + } + } + } + }, + "apollo-utilities": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.8.tgz", + "integrity": "sha512-EvqRJCw5xy2gWeH37toUimbEkmUxronCosBNE4tOCJvZUMLLGB8CuTQ5RsBhKJm+rZ6kwGxV+2uszk14f/P/rA==" + }, + "app-root-dir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", + "integrity": "sha1-OBh+wt6nV3//Az/8sSFyaS/24Rg=", + "dev": true + }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "requires": { + "default-require-extensions": "^2.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "array.prototype.flat": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz", + "integrity": "sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.10.0", + "function-bind": "^1.1.1" + } + }, + "array.prototype.flatmap": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.1.tgz", + "integrity": "sha512-i18e2APdsiezkcqDyZor78Pbfjfds3S94dG6dgIV2ZASJaUf1N0dz2tGdrmwrmlZuNUgxH+wz6Z0zYVH2c5xzQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.10.0", + "function-bind": "^1.1.1" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.7.tgz", + "integrity": "sha512-2mP3TwtkY/aTv5X3ZsMpNAbOnyoC/aMJwJSoaELPkHId0nSQgFcnU4dRW3isxiz7+zBexk0ym3WNVjMiQBnJSw==", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "^4.14.0" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", + "dev": true + }, + "attr-accept": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-1.1.3.tgz", + "integrity": "sha512-iT40nudw8zmCweivz6j58g+RT33I4KbaIvRUhjNmDwO2WmsQUxFEZZYZ5w3vXe5x5MX9D7mfvA/XaLOZYFR9EQ==", + "requires": { + "core-js": "^2.5.0" + } + }, + "await-to-js": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-2.1.1.tgz", + "integrity": "sha512-CHBC6gQGCIzjZ09tJ+XmpQoZOn4GdWePB4qUweCaKNJ0D3f115YdhmYVTZ4rMVpiJ3cFzZcTYK1VMYEICV4YXw==" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + } + } + }, + "babel-helper-evaluate-path": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz", + "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==", + "dev": true + }, + "babel-helper-flip-expressions": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz", + "integrity": "sha1-NpZzahKKwYvCUlS19AoizrPB0/0=", + "dev": true + }, + "babel-helper-is-nodes-equiv": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", + "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", + "dev": true + }, + "babel-helper-is-void-0": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz", + "integrity": "sha1-fZwBtFYee5Xb2g9u7kj1tg5nMT4=", + "dev": true + }, + "babel-helper-mark-eval-scopes": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz", + "integrity": "sha1-0kSjvvmESHJgP/tG4izorN9VFWI=", + "dev": true + }, + "babel-helper-remove-or-void": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz", + "integrity": "sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA=", + "dev": true + }, + "babel-helper-to-multiple-sequence-expressions": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz", + "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==", + "dev": true + }, + "babel-jest": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-23.6.0.tgz", + "integrity": "sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==", + "dev": true, + "requires": { + "babel-plugin-istanbul": "^4.1.6", + "babel-preset-jest": "^23.2.0" + } + }, + "babel-loader": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.4.tgz", + "integrity": "sha512-fhBhNkUToJcW9nV46v8w87AJOwAJDz84c1CL57n3Stj73FANM/b9TbCUK4YhdOwEyZ+OxhYpdeZDNzSI29Firw==", + "dev": true, + "requires": { + "find-cache-dir": "^1.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1", + "util.promisify": "^1.0.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.2.0.tgz", + "integrity": "sha512-fP899ELUnTaBcIzmrW7nniyqqdYWrWuJUyPWHxFa/c7r7hS6KC8FscNfLlBNIoPSc55kYMGEEKjPjJGCLbE1qA==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-istanbul": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", + "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.13.0", + "find-up": "^2.1.0", + "istanbul-lib-instrument": "^1.10.1", + "test-exclude": "^4.2.1" + } + }, + "babel-plugin-jest-hoist": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz", + "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=", + "dev": true + }, + "babel-plugin-macros": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.4.5.tgz", + "integrity": "sha512-+/9yteNQw3yuZ3krQUfjAeoT/f4EAdn3ELwhFfDj0rTMIaoHfIdrcLePOfIaL0qmFLpIcgPIL2Lzm58h+CGWaw==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.5", + "resolve": "^1.8.1" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz", + "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0" + } + }, + "js-yaml": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "resolve": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", + "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "babel-plugin-minify-builtins": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz", + "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==", + "dev": true + }, + "babel-plugin-minify-constant-folding": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz", + "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "babel-plugin-minify-dead-code-elimination": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.0.tgz", + "integrity": "sha512-XQteBGXlgEoAKc/BhO6oafUdT4LBa7ARi55mxoyhLHNuA+RlzRmeMAfc31pb/UqU01wBzRc36YqHQzopnkd/6Q==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-mark-eval-scopes": "^0.4.3", + "babel-helper-remove-or-void": "^0.4.3", + "lodash.some": "^4.6.0" + } + }, + "babel-plugin-minify-flip-comparisons": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz", + "integrity": "sha1-AMqHDLjxO0XAOLPB68DyJyk8llo=", + "dev": true, + "requires": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "babel-plugin-minify-guarded-expressions": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.3.tgz", + "integrity": "sha1-zHCbRFP9IbHzAod0RMifiEJ845c=", + "dev": true, + "requires": { + "babel-helper-flip-expressions": "^0.4.3" + } + }, + "babel-plugin-minify-infinity": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz", + "integrity": "sha1-37h2obCKBldjhO8/kuZTumB7Oco=", + "dev": true + }, + "babel-plugin-minify-mangle-names": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.0.tgz", + "integrity": "sha512-3jdNv6hCAw6fsX1p2wBGPfWuK69sfOjfd3zjUXkbq8McbohWy23tpXfy5RnToYWggvqzuMOwlId1PhyHOfgnGw==", + "dev": true, + "requires": { + "babel-helper-mark-eval-scopes": "^0.4.3" + } + }, + "babel-plugin-minify-numeric-literals": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz", + "integrity": "sha1-jk/VYcefeAEob/YOjF/Z3u6TwLw=", + "dev": true + }, + "babel-plugin-minify-replace": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz", + "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==", + "dev": true + }, + "babel-plugin-minify-simplify": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.0.tgz", + "integrity": "sha512-TM01J/YcKZ8XIQd1Z3nF2AdWHoDsarjtZ5fWPDksYZNsoOjQ2UO2EWm824Ym6sp127m44gPlLFiO5KFxU8pA5Q==", + "dev": true, + "requires": { + "babel-helper-flip-expressions": "^0.4.3", + "babel-helper-is-nodes-equiv": "^0.0.1", + "babel-helper-to-multiple-sequence-expressions": "^0.5.0" + } + }, + "babel-plugin-minify-type-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz", + "integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA=", + "dev": true, + "requires": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "babel-plugin-named-asset-import": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.2.3.tgz", + "integrity": "sha512-9mx2Z9M4EGbutvXxoLV7aUBCY6ps3sqLFl094FeA2tFQzQffIh0XSsmwwQRxiSfpg3rnb5x/o46qRLxS/OzFTg==", + "dev": true + }, + "babel-plugin-react-docgen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-react-docgen/-/babel-plugin-react-docgen-2.0.0.tgz", + "integrity": "sha512-AaA6IPxCF1EkzpFG41GkVh/VGdoBejPF6oIub2K8E6AD3kwnTZ0DIKG7f20a7zmqBEeO8GkFWdM7tYd9Owkc+Q==", + "dev": true, + "requires": { + "lodash": "^4.17.10", + "react-docgen": "^3.0.0-rc.1" + } + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-transform-inline-consecutive-adds": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz", + "integrity": "sha1-Mj1Ho+pjqDp6w8gRro5pQfrysNE=", + "dev": true + }, + "babel-plugin-transform-member-expression-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz", + "integrity": "sha1-NwOcmgwzE6OUlfqsL/OmtbnQOL8=", + "dev": true + }, + "babel-plugin-transform-merge-sibling-variables": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.4.tgz", + "integrity": "sha1-hbQi/DN3tEnJ0c3kQIcgNTJAHa4=", + "dev": true + }, + "babel-plugin-transform-minify-booleans": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz", + "integrity": "sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg=", + "dev": true + }, + "babel-plugin-transform-property-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz", + "integrity": "sha1-mMHSHiVXNlc/k+zlRFn2ziSYXTk=", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.18.tgz", + "integrity": "sha512-azed2nHo8vmOy7EY26KH+om5oOcWRs0r1U8wOmhwta+SBMMnmJ4H6yaBZRCcHBtMeWp9AVhvBTL/lpR1kEx+Xw==", + "dev": true + }, + "babel-plugin-transform-regexp-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz", + "integrity": "sha1-WLd3W2OvzzMyj66aX4j71PsLSWU=", + "dev": true + }, + "babel-plugin-transform-remove-console": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz", + "integrity": "sha1-uYA2DAZzhOJLNXpYjYB9PINSd4A=", + "dev": true + }, + "babel-plugin-transform-remove-debugger": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz", + "integrity": "sha1-QrcnYxyXl44estGZp67IShgznvI=", + "dev": true + }, + "babel-plugin-transform-remove-undefined": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz", + "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "babel-plugin-transform-simplify-comparison-operators": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz", + "integrity": "sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk=", + "dev": true + }, + "babel-plugin-transform-undefined-to-void": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz", + "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=", + "dev": true + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + } + } + }, + "babel-preset-jest": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz", + "integrity": "sha1-jsegOhOPABoaj7HoETZSvxpV2kY=", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^23.2.0", + "babel-plugin-syntax-object-rest-spread": "^6.13.0" + } + }, + "babel-preset-minify": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.0.tgz", + "integrity": "sha512-xj1s9Mon+RFubH569vrGCayA9Fm2GMsCgDRm1Jb8SgctOB7KFcrVc2o8K3YHUyMz+SWP8aea75BoS8YfsXXuiA==", + "dev": true, + "requires": { + "babel-plugin-minify-builtins": "^0.5.0", + "babel-plugin-minify-constant-folding": "^0.5.0", + "babel-plugin-minify-dead-code-elimination": "^0.5.0", + "babel-plugin-minify-flip-comparisons": "^0.4.3", + "babel-plugin-minify-guarded-expressions": "^0.4.3", + "babel-plugin-minify-infinity": "^0.4.3", + "babel-plugin-minify-mangle-names": "^0.5.0", + "babel-plugin-minify-numeric-literals": "^0.4.3", + "babel-plugin-minify-replace": "^0.5.0", + "babel-plugin-minify-simplify": "^0.5.0", + "babel-plugin-minify-type-constructors": "^0.4.3", + "babel-plugin-transform-inline-consecutive-adds": "^0.4.3", + "babel-plugin-transform-member-expression-literals": "^6.9.4", + "babel-plugin-transform-merge-sibling-variables": "^6.9.4", + "babel-plugin-transform-minify-booleans": "^6.9.4", + "babel-plugin-transform-property-literals": "^6.9.4", + "babel-plugin-transform-regexp-constructors": "^0.4.3", + "babel-plugin-transform-remove-console": "^6.9.4", + "babel-plugin-transform-remove-debugger": "^6.9.4", + "babel-plugin-transform-remove-undefined": "^0.5.0", + "babel-plugin-transform-simplify-comparison-operators": "^6.9.4", + "babel-plugin-transform-undefined-to-void": "^6.9.4", + "lodash.isplainobject": "^4.0.6" + } + }, + "babel-preset-react-app": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-6.1.0.tgz", + "integrity": "sha512-8PJ4N+acfYsjhDK4gMWkqJMVRMjDKb93D+nz7lWlNe73Jcv38FNu37i5K/dVQnFDdRYHbe1SjII+Y0mCgink9A==", + "dev": true, + "requires": { + "@babel/core": "7.1.0", + "@babel/plugin-proposal-class-properties": "7.1.0", + "@babel/plugin-proposal-decorators": "7.1.2", + "@babel/plugin-proposal-object-rest-spread": "7.0.0", + "@babel/plugin-syntax-dynamic-import": "7.0.0", + "@babel/plugin-transform-classes": "7.1.0", + "@babel/plugin-transform-destructuring": "7.0.0", + "@babel/plugin-transform-flow-strip-types": "7.0.0", + "@babel/plugin-transform-react-constant-elements": "7.0.0", + "@babel/plugin-transform-react-display-name": "7.0.0", + "@babel/plugin-transform-runtime": "7.1.0", + "@babel/preset-env": "7.1.0", + "@babel/preset-react": "7.0.0", + "@babel/preset-typescript": "7.1.0", + "@babel/runtime": "7.0.0", + "babel-loader": "8.0.4", + "babel-plugin-dynamic-import-node": "2.2.0", + "babel-plugin-macros": "2.4.2", + "babel-plugin-transform-react-remove-prop-types": "0.4.18" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.1.0.tgz", + "integrity": "sha512-9EWmD0cQAbcXSc+31RIoYgEHx3KQ2CCSMDBhnXrShWvo45TMw+3/55KVxlhkG53kw9tl87DqINgHDgFVhZJV/Q==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.0.0", + "@babel/helpers": "^7.1.0", + "@babel/parser": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0", + "convert-source-map": "^1.1.0", + "debug": "^3.1.0", + "json5": "^0.5.0", + "lodash": "^4.17.10", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz", + "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", + "dev": true + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.1.0.tgz", + "integrity": "sha512-/PCJWN+CKt5v1xcGn4vnuu13QDoV+P7NcICP44BoonAJoPSGwVkgrXihFIQGiEjjPlUDBIw1cM7wYFLARS2/hw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-member-expression-to-functions": "^7.0.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0", + "@babel/plugin-syntax-class-properties": "^7.0.0" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.1.2.tgz", + "integrity": "sha512-YooynBO6PmBgHvAd0fl5e5Tq/a0pEC6RqF62ouafme8FzdIVH41Mz/u1dn8fFVm4jzEJ+g/MsOxouwybJPuP8Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/plugin-syntax-decorators": "^7.1.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz", + "integrity": "sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.1.0.tgz", + "integrity": "sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.1.0", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.0.0.tgz", + "integrity": "sha512-Fr2GtF8YJSXGTyFPakPFB4ODaEKGU04bPsAllAIabwoXdFrPxL0LVXQX5dQWoxOjjgozarJcC9eWGsj0fD6Zsg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.0.0.tgz", + "integrity": "sha512-WhXUNb4It5a19RsgKKbQPrjmy4yWOY1KynpEbNw7bnd1QTcrT/EIl3MJvnGgpgvrKyKbqX7nUNOJfkpLOnoDKA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.0.0" + } + }, + "@babel/plugin-transform-react-constant-elements": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.0.0.tgz", + "integrity": "sha512-z8yrW4KCVcqPYr0r9dHXe7fu3daLzn0r6TQEFoGbXahdrzEwT1d1ux+/EnFcqIHv9uPilUlnRnPIUf7GMO0ehg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.0.0.tgz", + "integrity": "sha512-BX8xKuQTO0HzINxT6j/GiCwoJB0AOMs0HmLbEnAvcte8U8rSkNa/eSCAY+l1OA4JnCVq2jw2p6U8QQryy2fTPg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/preset-env": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.1.0.tgz", + "integrity": "sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.1.0", + "@babel/plugin-proposal-json-strings": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.0.0", + "@babel/plugin-syntax-async-generators": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.1.0", + "@babel/plugin-transform-block-scoped-functions": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.1.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-dotall-regex": "^7.0.0", + "@babel/plugin-transform-duplicate-keys": "^7.0.0", + "@babel/plugin-transform-exponentiation-operator": "^7.1.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.1.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-amd": "^7.1.0", + "@babel/plugin-transform-modules-commonjs": "^7.1.0", + "@babel/plugin-transform-modules-systemjs": "^7.0.0", + "@babel/plugin-transform-modules-umd": "^7.1.0", + "@babel/plugin-transform-new-target": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.1.0", + "@babel/plugin-transform-parameters": "^7.1.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "@babel/plugin-transform-typeof-symbol": "^7.0.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "browserslist": "^4.1.0", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.3.0" + } + }, + "@babel/runtime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz", + "integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.12.0" + } + }, + "babel-plugin-macros": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.4.2.tgz", + "integrity": "sha512-NBVpEWN4OQ/bHnu1fyDaAaTPAjnhXCEPqr1RwqxrU7b6tZ2hypp+zX4hlNfmVGfClD5c3Sl6Hfj5TJNF5VG5aA==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.5", + "resolve": "^1.8.1" + }, + "dependencies": { + "resolve": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", + "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "browserslist": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.0.tgz", + "integrity": "sha512-tQkHS8VVxWbrjnNDXgt7/+SuPJ7qDvD0Y2e6bLtoQluR2SPvlmPUcfcU75L1KAalhqULlIFJlJ6BDfnYyJxJsw==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000928", + "electron-to-chromium": "^1.3.100", + "node-releases": "^1.1.3" + } + }, + "caniuse-lite": { + "version": "1.0.30000929", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000929.tgz", + "integrity": "sha512-n2w1gPQSsYyorSVYqPMqbSaz1w7o9ZC8VhOEGI9T5MfGDzp7sbopQxG6GaQmYsaq13Xfx/mkxJUWC1Dz3oZfzw==", + "dev": true + }, + "cosmiconfig": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz", + "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0" + } + }, + "electron-to-chromium": { + "version": "1.3.103", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.103.tgz", + "integrity": "sha512-tObPqGmY9X8MUM8i3MEimYmbnLLf05/QV5gPlkR8MQ3Uj8G8B2govE1U4cQcBYtv3ymck9Y8cIOu4waoiykMZQ==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "node-releases": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.3.tgz", + "integrity": "sha512-6VrvH7z6jqqNFY200kdB6HdzkgM96Oaj9v3dqGfgp6mF+cHmU4wyQKZ2/WPDRVoR0Jz9KqbamaBN0ZhdUaysUQ==", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", + "dev": true + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + } + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + } + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, + "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, + "bail": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", + "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.1", + "http-errors": "~1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "~2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "~1.6.15" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "boxen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-2.1.0.tgz", + "integrity": "sha512-luq3RQOt2U5sUX+fiu+qnT+wWnHDcATLpEe63jvge6GUZO99AKbVRfp97d2jgLvq1iQa0ORzaAm4lGVG52ZSlw==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.0.0", + "chalk": "^2.4.1", + "cli-boxes": "^1.0.0", + "string-width": "^3.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "string-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.0.0.tgz", + "integrity": "sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + } + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brcast": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/brcast/-/brcast-3.0.1.tgz", + "integrity": "sha512-eI3yqf9YEqyGl9PCNTR46MGvDylGtaHjalcz6Q3fAPnP/PhpKkkve52vFdfGpwp4VUvK6LUr4TQN+2stCrEwTg==" + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", + "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "byline": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", + "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "requires": { + "is-plain-obj": "^1.0.0" + } + } + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=" + } + } + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "requires": { + "rsvp": "^4.8.4" + } + }, + "cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "requires": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + } + }, + "case-sensitive-paths-webpack-plugin": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.1.2.tgz", + "integrity": "sha512-oEZgAFfEvKtjSRCu6VgYkuGxwrWXMnQzyBmlLPP7r6PWQVtHxP5Z5N6XsuJvtoVax78am/r7lr46bwo3IVEBOg==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "ccount": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", + "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", + "dev": true + }, + "chain-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.0.tgz", + "integrity": "sha1-DUqzfn4Y6tC9xHuSB2QRjOWHM9w=" + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.2.0" + } + }, + "change-case": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-3.0.2.tgz", + "integrity": "sha512-Mww+SLF6MZ0U6kdg11algyKd5BARbyM4TbFBepwowYSR5ClfQGCGtxNXgykpN0uF/bstWeaGDT4JWaDh8zWAHA==", + "requires": { + "camel-case": "^3.0.0", + "constant-case": "^2.0.0", + "dot-case": "^2.1.0", + "header-case": "^1.0.0", + "is-lower-case": "^1.1.0", + "is-upper-case": "^1.1.0", + "lower-case": "^1.1.1", + "lower-case-first": "^1.0.0", + "no-case": "^2.3.2", + "param-case": "^2.1.0", + "pascal-case": "^2.0.0", + "path-case": "^2.1.0", + "sentence-case": "^2.1.0", + "snake-case": "^2.1.0", + "swap-case": "^1.1.0", + "title-case": "^2.1.0", + "upper-case": "^1.1.1", + "upper-case-first": "^1.1.0" + } + }, + "change-emitter": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz", + "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU=" + }, + "child-process-promise": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/child-process-promise/-/child-process-promise-2.2.1.tgz", + "integrity": "sha1-RzChHvYQ+tRQuPIjx50x172tgHQ=", + "dev": true, + "requires": { + "cross-spawn": "^4.0.2", + "node-version": "^1.0.0", + "promise-polyfill": "^6.0.1" + }, + "dependencies": { + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + } + } + }, + "chokidar": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", + "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true + } + } + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "upath": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", + "dev": true + } + } + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", + "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, + "clean-css": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", + "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "clean-stack": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-1.3.0.tgz", + "integrity": "sha1-noIVAa6XmYbEax1m0tQy2y/UrjE=" + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "dev": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "cli-ux": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-4.9.3.tgz", + "integrity": "sha512-/1owvF0SZ5Gn54cgrikJ0QskgTzeg30HGjkmjFoaHDJzAqFpuX1DBpFR8aLvsE1J5s9MgeYRENQK4BFwOag5VA==", + "requires": { + "@oclif/errors": "^1.2.2", + "@oclif/linewrap": "^1.0.0", + "@oclif/screen": "^1.0.3", + "ansi-escapes": "^3.1.0", + "ansi-styles": "^3.2.1", + "cardinal": "^2.1.1", + "chalk": "^2.4.1", + "clean-stack": "^2.0.0", + "extract-stack": "^1.0.0", + "fs-extra": "^7.0.0", + "hyperlinker": "^1.0.0", + "indent-string": "^3.2.0", + "is-wsl": "^1.1.0", + "lodash": "^4.17.11", + "password-prompt": "^1.0.7", + "semver": "^5.6.0", + "strip-ansi": "^5.0.0", + "supports-color": "^5.5.0", + "supports-hyperlinks": "^1.0.1", + "treeify": "^1.1.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "clean-stack": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.1.0.tgz", + "integrity": "sha512-uQWrpRm+iZZUCAp7ZZJQbd4Za9I3AjR/3YTjmcnAtkauaIm/T5CT6U8zVI6e60T6OANqBFAzuR9/HB3NzuZCRA==" + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + } + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "clsx": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.0.4.tgz", + "integrity": "sha512-1mQ557MIZTrL/140j+JVdRM6e31/OA4vTYxXgqIIZlndyfjHpyawKZia1Im05Vp9BWmImkcNrNtFYQMyFcgJDg==" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "requires": { + "color-name": "^1.1.1" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "comma-separated-tokens": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz", + "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==", + "dev": true, + "requires": { + "trim": "0.0.1" + } + }, + "commander": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", + "dev": true + }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "compare-versions": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.4.0.tgz", + "integrity": "sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "compressible": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", + "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==", + "dev": true, + "requires": { + "mime-db": ">= 1.40.0 < 2" + }, + "dependencies": { + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + } + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "constant-case": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz", + "integrity": "sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=", + "requires": { + "snake-case": "^2.1.0", + "upper-case": "^1.1.1" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "create-react-class": { + "version": "15.6.3", + "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz", + "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==", + "dev": true, + "requires": { + "fbjs": "^0.8.9", + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "create-react-context": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.3.tgz", + "integrity": "sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==", + "requires": { + "fbjs": "^0.8.0", + "gud": "^1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "css-selector-tokenizer": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", + "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", + "dev": true, + "requires": { + "cssesc": "^0.1.0", + "fastparse": "^1.1.1", + "regexpu-core": "^1.0.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + } + } + }, + "css-tree": { + "version": "1.0.0-alpha.28", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.28.tgz", + "integrity": "sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w==", + "dev": true, + "requires": { + "mdn-data": "~1.1.0", + "source-map": "^0.5.3" + } + }, + "css-url-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz", + "integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w=", + "dev": true + }, + "css-vendor": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-0.3.8.tgz", + "integrity": "sha1-ZCHP0wNM5mT+dnOXL9ARn8KJQfo=", + "requires": { + "is-in-browser": "^1.0.2" + } + }, + "css-what": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true + }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, + "cssom": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", + "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==", + "dev": true + }, + "cssstyle": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.2.tgz", + "integrity": "sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "csstype": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.5.3.tgz", + "integrity": "sha512-G5HnoK8nOiAq3DXIEoY2n/8Vb7Lgrms+jGJl8E4EJpQEeVONEnPFJSl8IK505wPBoxxtrtHhrRm4WX2GgdqarA==" + }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "debounce": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", + "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==" + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "deepmerge": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.2.0.tgz", + "integrity": "sha512-6+LuZGU7QCNUnAJyX8cIrlzoEgggTM6B7mm+znKOX4t5ltluT9KLjN6g61ECMS0LTsLW7yDpNoxhix5FZcrIow==" + }, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true, + "requires": { + "strip-bom": "^3.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "requires": { + "foreach": "^2.0.5", + "object-keys": "^1.0.8" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "is-path-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.1.0.tgz", + "integrity": "sha512-Sc5j3/YnM8tDeyCsVeKlm/0p95075DyLmDEIkSgQ7mXkrOX+uTCtmQFm0CYzVyJwcCCmO3k8qfJt17SxQwB5Zw==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "detect-port": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", + "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", + "dev": true, + "requires": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "diff": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==" + }, + "diff-sequences": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.3.0.tgz", + "integrity": "sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dir-glob": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.1.tgz", + "integrity": "sha512-UN6X6XwRjllabfRhBdkVSo63uurJ8nSvMGrwl94EYVz6g+exhTV+yVSYk5VC/xl3MBFBTtC0J20uFKce4Brrng==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", + "dev": true + }, + "dnd-core": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-7.4.4.tgz", + "integrity": "sha512-xR8SINDCJG9AmKSjXUMJ1PEl8ih1+xSHH8x4DgBtzScXnEtpCnV1ibDZNV0uyps9VgkXTTbYYzJdF04y0v0e3Q==", + "requires": { + "asap": "^2.0.6", + "invariant": "^2.2.4", + "redux": "^4.0.1" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + } + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-helpers": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.3.1.tgz", + "integrity": "sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg==" + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "~1.1.1", + "entities": "~1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=", + "dev": true + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz", + "integrity": "sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4=", + "requires": { + "no-case": "^2.2.0" + } + }, + "dotenv": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz", + "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==", + "dev": true + }, + "dotenv-expand": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-4.2.0.tgz", + "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU=", + "dev": true + }, + "dotenv-webpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-1.6.0.tgz", + "integrity": "sha512-jTbHXmcVw3KMVhTdgthYNLWWHRGtucrADpZWwVCdiP+pCvuWvxLcUadwEnmz8Wqv/d2UAJxJhp1jrxGlMYCetg==", + "dev": true, + "requires": { + "dotenv": "^5.0.1", + "dotenv-expand": "^4.0.1" + } + }, + "downshift": { + "version": "1.31.14", + "resolved": "https://registry.npmjs.org/downshift/-/downshift-1.31.14.tgz", + "integrity": "sha512-KguEqOCAykRVkBG8kB1YMOf4RWolupoUMW3cv6VLVBQw+yOB1BrROX4MbUoCqDaj9vBZS7DNqz7VBqfM4x3dsg==" + }, + "draft-js": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.10.5.tgz", + "integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==", + "requires": { + "fbjs": "^0.8.15", + "immutable": "~3.7.4", + "object-assign": "^4.1.0" + }, + "dependencies": { + "immutable": { + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", + "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=" + } + } + }, + "draftail": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/draftail/-/draftail-1.1.0.tgz", + "integrity": "sha512-wELmjR4cDBgXRZr31PhB2RTR34OO79+kgAG8kdWC17aV6zziKgY/LMjz3OJPvQzSOP41U9GIx0qFESw9O5Yxgg==", + "requires": { + "draftjs-conductor": "^0.4.1", + "draftjs-filters": "^2.2.3" + } + }, + "draftjs-conductor": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/draftjs-conductor/-/draftjs-conductor-0.4.1.tgz", + "integrity": "sha512-5BcJLdYLNIA/TNp/9xwIeD1quWsWEoi0ZI81TiW3vLecBEQgWKVxuKZaLdaXHYpW4/kdQvAJz2KcOBTpJkYBxg==" + }, + "draftjs-filters": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/draftjs-filters/-/draftjs-filters-2.2.3.tgz", + "integrity": "sha512-xbpXgjTtFzaMp9P9xlaqmf3NpP4yYM3OT3HbodUQpI4t2kO9ltJTo0+3H+1PlsUPKoc7jPthiE0MYN/VMrsuNw==" + }, + "draftjs-to-html": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/draftjs-to-html/-/draftjs-to-html-0.8.4.tgz", + "integrity": "sha512-+4hekxc8dTJvKk6usiEsFX9O1uOD9vLZZOs9ZI3RhTe89yNmtazYII/ILDXfbMPfzNaYfX7Gf3zjRm6UUFxqyg==" + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "duplexify": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "~0.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", + "dev": true + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz", + "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + }, + "env-ci": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-3.2.0.tgz", + "integrity": "sha512-TFjNiDlXrL8/pfHswdvJGEZzJcq3aBPb8Eka83hlGLwuNw9F9BC9S9ETlkfkItLRT9k5JgpGgeP+rL6/3cEbcw==", + "requires": { + "execa": "^1.0.0", + "java-properties": "^0.2.9" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "enzyme": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.7.0.tgz", + "integrity": "sha512-QLWx+krGK6iDNyR1KlH5YPZqxZCQaVF6ike1eDJAOg0HvSkSCVImPsdWaNw6v+VrnK92Kg8jIOYhuOSS9sBpyg==", + "dev": true, + "requires": { + "array.prototype.flat": "^1.2.1", + "cheerio": "^1.0.0-rc.2", + "function.prototype.name": "^1.1.0", + "has": "^1.0.3", + "is-boolean-object": "^1.0.0", + "is-callable": "^1.1.4", + "is-number-object": "^1.0.3", + "is-string": "^1.0.4", + "is-subset": "^0.1.1", + "lodash.escape": "^4.0.1", + "lodash.isequal": "^4.5.0", + "object-inspect": "^1.6.0", + "object-is": "^1.0.1", + "object.assign": "^4.1.0", + "object.entries": "^1.0.4", + "object.values": "^1.0.4", + "raf": "^3.4.0", + "rst-selector-parser": "^2.2.3", + "string.prototype.trim": "^1.1.2" + }, + "dependencies": { + "cheerio": { + "version": "1.0.0-rc.2", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", + "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "dev": true, + "requires": { + "@types/node": "*" + } + } + } + }, + "enzyme-adapter-react-16": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.7.0.tgz", + "integrity": "sha512-rDr0xlnnFPffAPYrvG97QYJaRl9unVDslKee33wTStsBEwZTkESX1H7VHGT5eUc6ifNzPgOJGvSh2zpHT4gXjA==", + "dev": true, + "requires": { + "enzyme-adapter-utils": "^1.9.0", + "function.prototype.name": "^1.1.0", + "object.assign": "^4.1.0", + "object.values": "^1.0.4", + "prop-types": "^15.6.2", + "react-is": "^16.6.1", + "react-test-renderer": "^16.0.0-0" + }, + "dependencies": { + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "react-is": { + "version": "16.6.3", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.3.tgz", + "integrity": "sha512-u7FDWtthB4rWibG/+mFbVd5FvdI20yde86qKGx4lVUTWmPlSWQ4QxbBIrrs+HnXGbxOUlUzTAP/VDmvCwaP2yA==", + "dev": true + } + } + }, + "enzyme-adapter-utils": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.9.0.tgz", + "integrity": "sha512-uMe4xw4l/Iloh2Fz+EO23XUYMEQXj5k/5ioLUXCNOUCI8Dml5XQMO9+QwUq962hBsY5qftfHHns+d990byWHvg==", + "dev": true, + "requires": { + "function.prototype.name": "^1.1.0", + "object.assign": "^4.1.0", + "prop-types": "^15.6.2", + "semver": "^5.6.0" + }, + "dependencies": { + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + } + } + }, + "enzyme-to-json": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.3.5.tgz", + "integrity": "sha512-DmH1wJ68HyPqKSYXdQqB33ZotwfUhwQZW3IGXaNXgR69Iodaoj8TF/D9RjLdz4pEhGq2Tx2zwNUIjBuqoZeTgA==", + "dev": true, + "requires": { + "lodash": "^4.17.4" + } + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", + "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "requires": { + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "requires": { + "is-callable": "^1.1.1", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.1" + } + }, + "es5-shim": { + "version": "4.5.12", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.12.tgz", + "integrity": "sha512-MjoCAHE6P2Dirme70Cxd9i2Ng8rhXiaVSsxDWdSwimfLERJL/ypR2ed2rTYkeeYrMk8gq281dzKLiGcdrmc8qg==", + "dev": true + }, + "es6-shim": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.4.tgz", + "integrity": "sha512-oJidbXjN/VWXZJs41E9JEqWzcFbjt43JupimIoVX82Thzt5qy1CiYezdhRmWkj3KOuwJ106IG/ZZrcFC6fgIUQ==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==" + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "eventsource": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", + "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", + "dev": true, + "requires": { + "original": ">=0.0.5" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exec-sh": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", + "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==", + "dev": true + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=" + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "expect": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.7.1.tgz", + "integrity": "sha512-mGfvMTPduksV3xoI0xur56pQsg2vJjNf5+a+bXOjqCkiCBbmCayrBbHS/75y9K430cfqyocPr2ZjiNiRx4SRKw==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.3.0", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-regex-util": "^24.3.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-diff": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.7.0.tgz", + "integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.3.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-get-type": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", + "dev": true + }, + "jest-matcher-utils": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz", + "integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.7.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-message-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz", + "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "pretty-format": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "express": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.3", + "qs": "6.5.1", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "extract-files": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-4.1.0.tgz", + "integrity": "sha512-2gjdb3dVzr1ie9+K8pupPTnsNkK4qmzbTFOIxghiWoh6nCTajGCGC72ZNYX0nBWy5IOq1FXfRVgvkkLqqE4sdw==" + }, + "extract-stack": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-1.0.0.tgz", + "integrity": "sha1-uXrK+UQe6iMyUpYktzL8WhyBZfo=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-array-diff": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/fast-array-diff/-/fast-array-diff-0.2.0.tgz", + "integrity": "sha1-9T6JEQl0/+lgP2LnpePvcfCvU3k=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-glob": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.6.tgz", + "integrity": "sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "fastparse": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", + "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "dev": true, + "requires": { + "bser": "^2.0.0" + } + }, + "fbjs": { + "version": "0.8.16", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz", + "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=", + "requires": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.9" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + } + } + }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-loader": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^0.4.5" + } + }, + "file-system-cache": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-1.0.5.tgz", + "integrity": "sha1-hCWbNqK7uNPW6xAh0xMv/mTP/08=", + "dev": true, + "requires": { + "bluebird": "^3.3.5", + "fs-extra": "^0.30.0", + "ramda": "^0.21.0" + }, + "dependencies": { + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + } + } + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true, + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } + }, + "filesize": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", + "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "fined": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz", + "integrity": "sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } + }, + "follow-redirects": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", + "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", + "dev": true, + "requires": { + "debug": "^3.2.6" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "fork-ts-checker-webpack-plugin": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-0.5.2.tgz", + "integrity": "sha512-a5IG+xXyKnpruI0CP/anyRLAoxWtp3lzdG6flxicANnoSzz64b12dJ7ASAVRrI2OaWwZR2JyBaMHFQqInhWhIw==", + "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "chalk": "^2.4.1", + "chokidar": "^2.0.4", + "micromatch": "^3.1.10", + "minimatch": "^3.0.4", + "tapable": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + }, + "dependencies": { + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true + } + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + } + } + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + } + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "frontend-collective-react-dnd-scrollzone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/frontend-collective-react-dnd-scrollzone/-/frontend-collective-react-dnd-scrollzone-1.0.2.tgz", + "integrity": "sha512-me/D9PZJq9j/sjEjs/OPmm6V6nbaHbhgeQiwrWu0t35lhwAOKWc+QBzzKKcZQeboYTkgE8UvCD9el+5ANp+g5Q==", + "requires": { + "hoist-non-react-statics": "^3.1.0", + "lodash.throttle": "^4.0.1", + "prop-types": "^15.5.9", + "raf": "^3.2.0", + "react": "^16.3.0", + "react-display-name": "^0.2.0", + "react-dom": "^16.3.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz", + "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==", + "requires": { + "react-is": "^16.7.0" + } + } + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz", + "integrity": "sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "is-callable": "^1.1.3" + } + }, + "fuse.js": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.3.0.tgz", + "integrity": "sha512-ESBRkGLWMuVkapqYCcNO1uqMg5qbCKkgb+VS6wsy17Rix0/cMS9kSOZoYkjH8Ko//pgJ/EEGu0GTjk2mjX2LGQ==", + "dev": true + }, + "fuzzaldrin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz", + "integrity": "sha1-kCBMPi/appQbso0WZF1BgGOpDps=" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "requires": { + "globule": "^1.0.0" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "git-parse": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-parse/-/git-parse-1.0.3.tgz", + "integrity": "sha512-LlGDePBQ9Lr/jsL3ULrnV8SQL8sk3cdScyc+vAk6jVLkHBOxdIj3JosNWemH2o9pNnGtcqukl+ym1Nl6k5jw0Q==", + "requires": { + "babel-polyfill": "6.26.0", + "byline": "5.0.0", + "util.promisify": "1.0.0" + } + }, + "git-rev-sync": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/git-rev-sync/-/git-rev-sync-1.12.0.tgz", + "integrity": "sha1-RGhAbH5sO6TPRYeZnhrbKNnRr1U=", + "requires": { + "escape-string-regexp": "1.0.5", + "graceful-fs": "4.1.11", + "shelljs": "0.7.7" + }, + "dependencies": { + "shelljs": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.7.tgz", + "integrity": "sha1-svXHfvlxSPS09uImguELuoZnz/E=", + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "dev": true, + "requires": { + "min-document": "^2.19.0", + "process": "~0.5.1" + }, + "dependencies": { + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", + "dev": true + } + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-modules-path": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.1.tgz", + "integrity": "sha512-y+shkf4InI7mPRHSo2b/k6ix6+NLDtyccYv86whhxrSGX9wjPX1VMITmrDbE1eh7zkzhiWtW2sHklJYoQ62Cxg==", + "dev": true + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.5.0.tgz", + "integrity": "sha512-hYyf+kI8dm3nORsiiXUQigOU62hDLfJ9G01uyGMxhc6BKsircrUhC4uJPQPUSuq2GrTmiiEt7ewxlMdBewfmKQ==", + "dev": true + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graphql": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz", + "integrity": "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==", + "requires": { + "iterall": "^1.2.2" + } + }, + "graphql-tag": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.0.tgz", + "integrity": "sha512-9FD6cw976TLLf9WYIUPCaaTpniawIjHWZSwIRZSjrfufJamcXbVVYfN2TWvJYbw0Xf2JjYbl1/f2+wDnBVw3/w==" + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, + "gud": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", + "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" + }, + "gzip-size": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.0.0.tgz", + "integrity": "sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "handle-thing": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", + "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", + "dev": true + }, + "handlebars": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", + "integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "^5.1.0", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "requires": { + "function-bind": "^1.0.2" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", + "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hast-util-from-parse5": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.0.tgz", + "integrity": "sha512-A7ev5OseS/J15214cvDdcI62uwovJO2PB60Xhnq7kaxvvQRFDEccuqbkrFXU03GPBGopdPqlpQBRqIcDS/Fjbg==", + "dev": true, + "requires": { + "ccount": "^1.0.3", + "hastscript": "^5.0.0", + "property-information": "^5.0.0", + "web-namespaces": "^1.1.2", + "xtend": "^4.0.1" + } + }, + "hast-util-parse-selector": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.1.tgz", + "integrity": "sha512-Xyh0v+nHmQvrOqop2Jqd8gOdyQtE8sIP9IQf7mlVDqp924W4w/8Liuguk2L2qei9hARnQSG2m+wAOCxM7npJVw==", + "dev": true + }, + "hastscript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.0.0.tgz", + "integrity": "sha512-xJtuJ8D42Xtq5yJrnDg/KAIxl2cXBXKoiIJwmWX9XMf8113qHTGl/Bf7jEsxmENJ4w6q4Tfl8s/Y6mEZo8x8qw==", + "dev": true, + "requires": { + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.2.0", + "property-information": "^5.0.1", + "space-separated-tokens": "^1.0.0" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "header-case": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz", + "integrity": "sha1-lTWXMZfBRLCWE81l0xfvGZY70C0=", + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.3" + } + }, + "heroku-cli-util": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/heroku-cli-util/-/heroku-cli-util-8.0.11.tgz", + "integrity": "sha512-cApMBbrfAhFTKs/loXm7zkWRC4kOH1VHoqU5WNgzs2TGKJqQI3QYvxITKE+8iC1Gb1xAy0BCqdGgzx8t7EoeWQ==", + "requires": { + "@heroku-cli/color": "^1.1.3", + "ansi-escapes": "^3.1.0", + "ansi-styles": "^3.2.1", + "cardinal": "^2.0.1", + "chalk": "^2.4.1", + "co": "^4.6.0", + "got": "^8.3.1", + "heroku-client": "^3.0.7", + "lodash": "^4.17.10", + "netrc-parser": "^3.1.4", + "opn": "^3.0.3", + "strip-ansi": "^4.0.0", + "supports-color": "^5.4.0", + "tslib": "^1.9.0", + "tunnel-agent": "^0.6.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "opn": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/opn/-/opn-3.0.3.tgz", + "integrity": "sha1-ttmec5n3jWXDuq/+8fsojpuFJDo=", + "requires": { + "object-assign": "^4.0.1" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "heroku-client": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/heroku-client/-/heroku-client-3.0.7.tgz", + "integrity": "sha512-wL8d3ufIWGzL8B2U7oPzN+SdcMt6LPqA/x4nb9pDG45IXpr8KO+N4dvX4Vycgn0WrJVDfQnQ1juctJsUwuoeww==", + "requires": { + "is-retry-allowed": "^1.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "history": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/history/-/history-4.9.0.tgz", + "integrity": "sha512-H2DkjCjXf0Op9OAr6nJ56fcRkTSNrUiv41vNJ6IswJjif6wlpZK0BTfFbi7qK9dXLSYZxkq5lBsj3vUjlYBYZA==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^2.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^0.4.0" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz", + "integrity": "sha512-6Bl6XsDT1ntE0lHbIhr4Kp2PGcleGZ66qu5Jqk8lc0Xc/IeG6gVLmwUGs/K0Us+L8VWoKgj0uWdPMataOsm31w==" + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "dev": true + }, + "html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "dev": true, + "requires": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + } + } + }, + "html-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", + "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", + "dev": true, + "requires": { + "html-minifier": "^3.2.3", + "loader-utils": "^0.2.16", + "lodash": "^4.17.3", + "pretty-error": "^2.0.2", + "tapable": "^1.0.0", + "toposort": "^1.0.0", + "util.promisify": "1.0.0" + }, + "dependencies": { + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + } + } + }, + "htmlparser2": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, + "http-call": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/http-call/-/http-call-5.2.3.tgz", + "integrity": "sha512-IkwGruHVHATmnonLKMGX5tkpM0KSn/C240o8/OfBsESRaJacykSia+akhD0d3fljQ5rQPXtBvSrVShAsj+EOUQ==", + "requires": { + "content-type": "^1.0.4", + "debug": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "is-stream": "^1.1.0", + "tunnel-agent": "^0.6.0" + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": ">= 1.3.1 < 2" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + } + } + }, + "http-parser-js": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", + "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=", + "dev": true + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "httpplease": { + "version": "0.16.4", + "resolved": "https://registry.npmjs.org/httpplease/-/httpplease-0.16.4.tgz", + "integrity": "sha1-04Lr4jDvUHkIC06f/r8xap51wNo=", + "requires": { + "urllite": "~0.5.0", + "xmlhttprequest": "*", + "xtend": "~3.0.0" + }, + "dependencies": { + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=" + } + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "hyperlinker": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hyperlinker/-/hyperlinker-1.0.0.tgz", + "integrity": "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==" + }, + "hyphenate-style-name": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz", + "integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es=" + }, + "i18next": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-11.2.2.tgz", + "integrity": "sha512-Rld/aWCZUut44b1VdfUCp1n5fDWf9/7hseF7hCl/W3s6zQeWuTT7354JnosYyMbFNbbduv32fte0JBeyMIoM1Q==" + }, + "i18next-browser-languagedetector": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-2.2.0.tgz", + "integrity": "sha512-fKhsaJzXY2anqAPxn9bgxc5NrTcu1GnYiIwGfNFPkpfFneutHnuReb4x4suOVNMf9RTuiCxfR+UAF8aHhv89SQ==" + }, + "i18next-xhr-backend": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/i18next-xhr-backend/-/i18next-xhr-backend-1.5.1.tgz", + "integrity": "sha512-9OLdC/9YxDvTFcgsH5t2BHCODHEotHCa6h7Ly0EUlUC7Y2GS09UeoHOGj3gWKQ3HCqXz8NlH4gOrK3NNc9vPuw==" + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "icss-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "dev": true, + "requires": { + "postcss": "^6.0.1" + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz", + "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", + "dev": true + }, + "immer": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/immer/-/immer-1.7.2.tgz", + "integrity": "sha512-4Urocwu9+XLDJw4Tc6ZCg7APVjjLInCFvO4TwGsAYV5zT6YYSor14dsZR0+0tHlDIN92cFUOq+i7fC00G5vTxA==", + "dev": true + }, + "immutable": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", + "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=", + "dev": true + }, + "immutable-tuple": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/immutable-tuple/-/immutable-tuple-0.4.9.tgz", + "integrity": "sha512-LWbJPZnidF8eczu7XmcnLBsumuyRBkpwIRPCZxlojouhBo5jEBO4toj6n7hMy6IxHU/c+MqDSWkvaTpPlMQcyA==" + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "requires": { + "import-from": "^2.1.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "dependencies": { + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + } + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indefinite-observable": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-1.0.2.tgz", + "integrity": "sha512-Mps0898zEduHyPhb7UCgNmfzlqNZknVmaFz5qzr0mm04YQ5FGLhAyK/dJ+NaRxGyR6juQXIxh5Ev0xx+qq0nYA==", + "requires": { + "symbol-observable": "1.2.0" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflected": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inflected/-/inflected-2.0.4.tgz", + "integrity": "sha512-HQPzFLTTUvwfeUH6RAGjD8cHS069mBqXG5n4qaxX7sJXBhVQrsGgF+0ZJGkSuN6a8pcUWB/GXStta11kKi/WvA==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "dev": true + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" + }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "requires": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-boolean-object": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.0.tgz", + "integrity": "sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=" + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" + }, + "is-dom": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/is-dom/-/is-dom-1.0.9.tgz", + "integrity": "sha1-SDgy1SlyBz3hK5/j9gMghw2oNw0=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-in-browser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", + "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=" + }, + "is-lower-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz", + "integrity": "sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=", + "requires": { + "lower-case": "^1.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-number-object": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.3.tgz", + "integrity": "sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=", + "dev": true + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "requires": { + "symbol-observable": "^1.1.0" + } + }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "^1.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.0.0.tgz", + "integrity": "sha512-F/pJIk8QD6OX5DNhRB7hWamLsUilmkDGho48KbgZ6xg/lmAZXHxzXQ91jzB3yRSw5kdQGGGc4yz8HYhTYIMWPg==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-string": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz", + "integrity": "sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ=", + "dev": true + }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", + "dev": true + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-upper-case": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz", + "integrity": "sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=", + "requires": { + "upper-case": "^1.1.0" + } + }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-api": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.1.tgz", + "integrity": "sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw==", + "dev": true, + "requires": { + "async": "^2.6.1", + "compare-versions": "^3.2.1", + "fileset": "^2.0.3", + "istanbul-lib-coverage": "^2.0.3", + "istanbul-lib-hook": "^2.0.3", + "istanbul-lib-instrument": "^3.1.0", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.2", + "istanbul-reports": "^2.1.1", + "js-yaml": "^3.12.0", + "make-dir": "^1.3.0", + "minimatch": "^3.0.4", + "once": "^1.4.0" + }, + "dependencies": { + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz", + "integrity": "sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==", + "dev": true, + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.3", + "semver": "^5.5.0" + } + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "istanbul-lib-coverage": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz", + "integrity": "sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA==", + "dev": true, + "requires": { + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", + "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.0", + "semver": "^5.3.0" + }, + "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz", + "integrity": "sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "supports-color": "^6.0.0" + }, + "dependencies": { + "istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", + "dev": true + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz", + "integrity": "sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "rimraf": "^2.6.2", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", + "dev": true + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.1.1.tgz", + "integrity": "sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw==", + "dev": true, + "requires": { + "handlebars": "^4.1.0" + }, + "dependencies": { + "handlebars": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", + "integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + } + }, + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, + "iterall": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz", + "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==" + }, + "java-properties": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-0.2.10.tgz", + "integrity": "sha512-CpKJh9VRNhS+XqZtg1UMejETGEiqwCGDC/uwPEEQwc2nfdbSm73SIE29TplG2gLYuBOOTNDqxzG6A9NtEPLt0w==" + }, + "jest": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.7.1.tgz", + "integrity": "sha512-AbvRar5r++izmqo5gdbAjTeA6uNRGoNRuj5vHB0OnDXo2DXWZJVuaObiGgtlvhKb+cWy2oYbQSfxv7Q7GjnAtA==", + "dev": true, + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.7.1" + }, + "dependencies": { + "jest-cli": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.7.1.tgz", + "integrity": "sha512-32OBoSCVPzcTslGFl6yVCMzB2SqX3IrWwZCY5mZYkb0D2WsogmU3eV2o8z7+gRQa4o4sZPX/k7GU+II7CxM6WQ==", + "dev": true, + "requires": { + "@jest/core": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^12.0.2" + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + } + } + }, + "jest-changed-files": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.7.0.tgz", + "integrity": "sha512-33BgewurnwSfJrW7T5/ZAXGE44o7swLslwh8aUckzq2e17/2Os1V0QU506ZNik3hjs8MgnEMKNkcud442NCDTw==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "jest-config": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.7.1.tgz", + "integrity": "sha512-8FlJNLI+X+MU37j7j8RE4DnJkvAghXmBWdArVzypW6WxfGuxiL/CCkzBg0gHtXhD2rxla3IMOSUAHylSKYJ83g==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.7.1", + "@jest/types": "^24.7.0", + "babel-jest": "^24.7.1", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.7.1", + "jest-environment-node": "^24.7.1", + "jest-get-type": "^24.3.0", + "jest-jasmine2": "^24.7.1", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.7.0", + "realpath-native": "^1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "babel-jest": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.7.1.tgz", + "integrity": "sha512-GPnLqfk8Mtt0i4OemjWkChi73A3ALs4w2/QbG64uAj8b5mmwzxc7jbJVRZt8NJkxi6FopVHog9S3xX6UJKb2qg==", + "dev": true, + "requires": { + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.6.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "babel-plugin-istanbul": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.1.tgz", + "integrity": "sha512-RNNVv2lsHAXJQsEJ5jonQwrJVWK8AcZpG1oxhnjCUaAjL7xahYLANhPUZbzEQHjKy1NMYUwn+0NPKQc8iSY4xQ==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.0.0", + "test-exclude": "^5.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.6.0.tgz", + "integrity": "sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz", + "integrity": "sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.6.0" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz", + "integrity": "sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==", + "dev": true, + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.3", + "semver": "^5.5.0" + } + }, + "jest-get-type": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pretty-format": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "test-exclude": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.1.0.tgz", + "integrity": "sha512-gwf0S2fFsANC55fSeSqpb8BYk6w3FDvwZxfNjeF6FRgvFa43r+7wRiA/Q0IxoRU37wB/LE8IQ4221BsNucTaCA==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^1.0.1" + } + } + } + }, + "jest-diff": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.7.0.tgz", + "integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.3.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-docblock": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.3.0.tgz", + "integrity": "sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg==", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.7.1.tgz", + "integrity": "sha512-4fsS8fEfLa3lfnI1Jw6NxjhyRTgfpuOVTeUZZFyVYqeTa4hPhr2YkToUhouuLTrL2eMGOfpbdMyRx0GQ/VooKA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.3.0", + "jest-util": "^24.7.1", + "pretty-format": "^24.7.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "jest-get-type": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", + "dev": true + }, + "pretty-format": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + } + } + }, + "jest-environment-jsdom": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.7.1.tgz", + "integrity": "sha512-Gnhb+RqE2JuQGb3kJsLF8vfqjt3PHKSstq4Xc8ic+ax7QKo4Z0RWGucU3YV+DwKR3T9SYc+3YCUQEJs8r7+Jxg==", + "dev": true, + "requires": { + "@jest/environment": "^24.7.1", + "@jest/fake-timers": "^24.7.1", + "@jest/types": "^24.7.0", + "jest-mock": "^24.7.0", + "jest-util": "^24.7.1", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.7.1.tgz", + "integrity": "sha512-GJJQt1p9/C6aj6yNZMvovZuxTUd+BEJprETdvTKSb4kHcw4mFj8777USQV0FJoJ4V3djpOwA5eWyPwfq//PFBA==", + "dev": true, + "requires": { + "@jest/environment": "^24.7.1", + "@jest/fake-timers": "^24.7.1", + "@jest/types": "^24.7.0", + "jest-mock": "^24.7.0", + "jest-util": "^24.7.1" + } + }, + "jest-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jest-file/-/jest-file-1.0.0.tgz", + "integrity": "sha1-jFmWeL/TrtDTvp9+pgUES/3wFYw=", + "dev": true + }, + "jest-get-type": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", + "dev": true + }, + "jest-haste-map": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.7.1.tgz", + "integrity": "sha512-g0tWkzjpHD2qa03mTKhlydbmmYiA2KdcJe762SbfFo/7NIMgBWAA0XqQlApPwkWOF7Cxoi/gUqL0i6DIoLpMBw==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.4.0", + "jest-util": "^24.7.1", + "jest-worker": "^24.6.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "jest-jasmine2": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.7.1.tgz", + "integrity": "sha512-Y/9AOJDV1XS44wNwCaThq4Pw3gBPiOv/s6NcbOAkVRRUEPu+36L2xoPsqQXsDrxoBerqeyslpn2TpCI8Zr6J2w==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.7.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.7.1", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-runtime": "^24.7.1", + "jest-snapshot": "^24.7.1", + "jest-util": "^24.7.1", + "pretty-format": "^24.7.0", + "throat": "^4.0.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-diff": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.7.0.tgz", + "integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.3.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-get-type": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", + "dev": true + }, + "jest-matcher-utils": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz", + "integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.7.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-message-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz", + "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-snapshot": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.7.1.tgz", + "integrity": "sha512-8Xk5O4p+JsZZn4RCNUS3pxA+ORKpEKepE+a5ejIKrId9CwrVN0NY+vkqEkXqlstA5NMBkNahXkR/4qEBy0t5yA==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "expect": "^24.7.1", + "jest-diff": "^24.7.0", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-resolve": "^24.7.1", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.7.0", + "semver": "^5.5.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "pretty-format": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "jest-leak-detector": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.7.0.tgz", + "integrity": "sha512-zV0qHKZGXtmPVVzT99CVEcHE9XDf+8LwiE0Ob7jjezERiGVljmqKFWpV2IkG+rkFIEUHFEkMiICu7wnoPM/RoQ==", + "dev": true, + "requires": { + "pretty-format": "^24.7.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "pretty-format": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + } + } + }, + "jest-matcher-utils": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz", + "integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.7.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-message-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz", + "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "jest-mock": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.7.0.tgz", + "integrity": "sha512-6taW4B4WUcEiT2V9BbOmwyGuwuAFT2G8yghF7nyNW1/2gq5+6aTqSPcS9lS6ArvEkX55vbPAS/Jarx5LSm4Fng==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "dev": true + }, + "jest-regex-util": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.3.0.tgz", + "integrity": "sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg==", + "dev": true + }, + "jest-resolve": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.7.1.tgz", + "integrity": "sha512-Bgrc+/UUZpGJ4323sQyj85hV9d+ANyPNu6XfRDUcyFNX1QrZpSoM0kE4Mb2vZMAYTJZsBFzYe8X1UaOkOELSbw==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + }, + "dependencies": { + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + } + } + }, + "jest-resolve-dependencies": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.7.1.tgz", + "integrity": "sha512-2Eyh5LJB2liNzfk4eo7bD1ZyBbqEJIyyrFtZG555cSWW9xVHxII2NuOkSl1yUYTAYCAmM2f2aIT5A7HzNmubyg==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.7.1" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-diff": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.7.0.tgz", + "integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.3.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-get-type": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", + "dev": true + }, + "jest-matcher-utils": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz", + "integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.7.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-message-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz", + "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-snapshot": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.7.1.tgz", + "integrity": "sha512-8Xk5O4p+JsZZn4RCNUS3pxA+ORKpEKepE+a5ejIKrId9CwrVN0NY+vkqEkXqlstA5NMBkNahXkR/4qEBy0t5yA==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "expect": "^24.7.1", + "jest-diff": "^24.7.0", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-resolve": "^24.7.1", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.7.0", + "semver": "^5.5.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "pretty-format": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "jest-runner": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.7.1.tgz", + "integrity": "sha512-aNFc9liWU/xt+G9pobdKZ4qTeG/wnJrJna3VqunziDNsWT3EBpmxXZRBMKCsNMyfy+A/XHiV+tsMLufdsNdgCw==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.7.1", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.7.1", + "jest-jasmine2": "^24.7.1", + "jest-leak-detector": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-resolve": "^24.7.1", + "jest-runtime": "^24.7.1", + "jest-util": "^24.7.1", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-message-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz", + "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "jest-runtime": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.7.1.tgz", + "integrity": "sha512-0VAbyBy7tll3R+82IPJpf6QZkokzXPIS71aDeqh+WzPRXRCNz6StQ45otFariPdJ4FmXpDiArdhZrzNAC3sj6A==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.7.1", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/yargs": "^12.0.2", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.7.1", + "jest-haste-map": "^24.7.1", + "jest-message-util": "^24.7.1", + "jest-mock": "^24.7.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.7.1", + "jest-snapshot": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^12.0.2" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-diff": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.7.0.tgz", + "integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.3.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-get-type": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", + "dev": true + }, + "jest-matcher-utils": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz", + "integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.7.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" + } + }, + "jest-message-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz", + "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-snapshot": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.7.1.tgz", + "integrity": "sha512-8Xk5O4p+JsZZn4RCNUS3pxA+ORKpEKepE+a5ejIKrId9CwrVN0NY+vkqEkXqlstA5NMBkNahXkR/4qEBy0t5yA==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "expect": "^24.7.1", + "jest-diff": "^24.7.0", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-resolve": "^24.7.1", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.7.0", + "semver": "^5.5.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "pretty-format": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "jest-serializer": { + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.4.0.tgz", + "integrity": "sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q==", + "dev": true + }, + "jest-snapshot": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.7.1.tgz", + "integrity": "sha512-8Xk5O4p+JsZZn4RCNUS3pxA+ORKpEKepE+a5ejIKrId9CwrVN0NY+vkqEkXqlstA5NMBkNahXkR/4qEBy0t5yA==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", + "expect": "^24.7.1", + "jest-diff": "^24.7.0", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-resolve": "^24.7.1", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.7.0", + "semver": "^5.5.0" + } + }, + "jest-specific-snapshot": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jest-specific-snapshot/-/jest-specific-snapshot-1.0.0.tgz", + "integrity": "sha512-EjCK8Ob8eneeQCdBuO06J1v1C1jklKK7VvCOG/iwQx+8byZ7iCY8+d9M7xlUJiu76ubycXtSkIrPrL+nqjJsjA==", + "dev": true, + "requires": { + "jest-snapshot": ">=20.0.3" + } + }, + "jest-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.7.1.tgz", + "integrity": "sha512-/KilOue2n2rZ5AnEBYoxOXkeTu6vi7cjgQ8MXEkih0oeAXT6JkS3fr7/j8+engCjciOU1Nq5loMSKe0A1oeX0A==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/fake-timers": "^24.7.1", + "@jest/source-map": "^24.3.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "jest-validate": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.7.0.tgz", + "integrity": "sha512-cgai/gts9B2chz1rqVdmLhzYxQbgQurh1PEQSvSgPZ8KGa1AqXsqC45W5wKEwzxKrWqypuQrQxnF4+G9VejJJA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "camelcase": "^5.0.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.3.0", + "leven": "^2.1.0", + "pretty-format": "^24.7.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "jest-get-type": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", + "dev": true + }, + "pretty-format": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + } + } + }, + "jest-watcher": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.7.1.tgz", + "integrity": "sha512-Wd6TepHLRHVKLNPacEsBwlp9raeBIO+01xrN24Dek4ggTS8HHnOzYSFnvp+6MtkkJ3KfMzy220KTi95e2rRkrw==", + "dev": true, + "requires": { + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/yargs": "^12.0.9", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.7.1", + "string-length": "^2.0.0" + } + }, + "jest-worker": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.6.0.tgz", + "integrity": "sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==", + "dev": true, + "requires": { + "merge-stream": "^1.0.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.4.tgz", + "integrity": "sha512-PxfGzSs0ztShKrUYPIn5r0MtyAhYcCwmndozzpz8YObbPnD1jFxzlBGbRnX2mIu6Z13xN6+PTu05TQFnZFlzow==", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, + "jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=" + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jss": { + "version": "9.8.7", + "resolved": "https://registry.npmjs.org/jss/-/jss-9.8.7.tgz", + "integrity": "sha512-awj3XRZYxbrmmrx9LUSj5pXSUfm12m8xzi/VKeqI1ZwWBtQ0kVPTs3vYs32t4rFw83CgFDukA8wKzOE9sMQnoQ==", + "requires": { + "is-in-browser": "^1.1.3", + "symbol-observable": "^1.1.0", + "warning": "^3.0.0" + } + }, + "jss-camel-case": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jss-camel-case/-/jss-camel-case-6.1.0.tgz", + "integrity": "sha512-HPF2Q7wmNW1t79mCqSeU2vdd/vFFGpkazwvfHMOhPlMgXrJDzdj9viA2SaHk9ZbD5pfL63a8ylp4++irYbbzMQ==", + "requires": { + "hyphenate-style-name": "^1.0.2" + } + }, + "jss-compose": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/jss-compose/-/jss-compose-5.0.0.tgz", + "integrity": "sha512-YofRYuiA0+VbeOw0VjgkyO380sA4+TWDrW52nSluD9n+1FWOlDzNbgpZ/Sb3Y46+DcAbOS21W5jo6SAqUEiuwA==", + "requires": { + "warning": "^3.0.0" + } + }, + "jss-default-unit": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/jss-default-unit/-/jss-default-unit-8.0.2.tgz", + "integrity": "sha512-WxNHrF/18CdoAGw2H0FqOEvJdREXVXLazn7PQYU7V6/BWkCV0GkmWsppNiExdw8dP4TU1ma1dT9zBNJ95feLmg==" + }, + "jss-expand": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/jss-expand/-/jss-expand-5.3.0.tgz", + "integrity": "sha512-NiM4TbDVE0ykXSAw6dfFmB1LIqXP/jdd0ZMnlvlGgEMkMt+weJIl8Ynq1DsuBY9WwkNyzWktdqcEW2VN0RAtQg==" + }, + "jss-extend": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jss-extend/-/jss-extend-6.2.0.tgz", + "integrity": "sha512-YszrmcB6o9HOsKPszK7NeDBNNjVyiW864jfoiHoMlgMIg2qlxKw70axZHqgczXHDcoyi/0/ikP1XaHDPRvYtEA==", + "requires": { + "warning": "^3.0.0" + } + }, + "jss-global": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jss-global/-/jss-global-3.0.0.tgz", + "integrity": "sha512-wxYn7vL+TImyQYGAfdplg7yaxnPQ9RaXY/cIA8hawaVnmmWxDHzBK32u1y+RAvWboa3lW83ya3nVZ/C+jyjZ5Q==" + }, + "jss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jss-nested/-/jss-nested-6.0.1.tgz", + "integrity": "sha512-rn964TralHOZxoyEgeq3hXY8hyuCElnvQoVrQwKHVmu55VRDd6IqExAx9be5HgK0yN/+hQdgAXQl/GUrBbbSTA==", + "requires": { + "warning": "^3.0.0" + } + }, + "jss-plugin-camel-case": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.0.0-alpha.7.tgz", + "integrity": "sha512-Bwrav1ZB0XywdJW6TaEuFhKe1ZpZvUlESh3jsFOvebA9aFTYNCkmHMEqjA5+u9VMxksl3u77nnZHtukpxkzrBA==", + "requires": { + "@babel/runtime": "^7.0.0", + "hyphenate-style-name": "^1.0.2" + } + }, + "jss-plugin-default-unit": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.0.0-alpha.7.tgz", + "integrity": "sha512-auuJUbQaWMxoHOVFPrfZNZpZm9ab8PZeDyvey8nMt2lbokkmZ53UyAnM/1kNsg5BdAXTItcLDxDB3I4gwNU84g==", + "requires": { + "@babel/runtime": "^7.0.0" + } + }, + "jss-plugin-global": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.0.0-alpha.7.tgz", + "integrity": "sha512-OWeoW4szLDgRUKviST+xfilqa8O5uXJCW+O3YonheCRTRJg6rRzlE/b5pfYPoU9UtwvY9n7JvwBX5r3c1lMsEQ==", + "requires": { + "@babel/runtime": "^7.0.0" + } + }, + "jss-plugin-nested": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.0.0-alpha.7.tgz", + "integrity": "sha512-wsRzuIZXAc6WMjc61mREW9cUrDxgSI7dK/fx5c7a06IDUfSn+83NJ30J/RB4oBnbQW9SijV/muujz7IJqpn9Gw==", + "requires": { + "@babel/runtime": "^7.0.0", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-props-sort": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.0.0-alpha.7.tgz", + "integrity": "sha512-KXOCaHUk1+KXqE0z3q66/w1fDoy+VsZvI77gLxOqTsTrvIKFLX0jarwXogW3CDlaPQQFTZ6JykJJXtPRTBlstA==", + "requires": { + "@babel/runtime": "^7.0.0" + } + }, + "jss-plugin-rule-value-function": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.0.0-alpha.7.tgz", + "integrity": "sha512-ett83hvIM69/LknmrWndrrdiDlfLfP+rneU5qP7gTOWJ7g1P9GuEL1Tc4CWdZUWBX+T58tgIBP0V1pzWCkP0QA==", + "requires": { + "@babel/runtime": "^7.0.0" + } + }, + "jss-plugin-vendor-prefixer": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.0.0-alpha.7.tgz", + "integrity": "sha512-YbIVgqq+dLimOBOEYggho1Iuc0roz4PJSZYyaok9n8JnXVIqPnxYJbr8+bMbvzJ5CL3eeJij/e7L2IPCceRKrA==", + "requires": { + "@babel/runtime": "^7.0.0", + "css-vendor": "^1.1.0" + }, + "dependencies": { + "css-vendor": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-1.2.1.tgz", + "integrity": "sha512-ZpwiWxn5jWNJ7NF3DAb/Dc/+c2lRu+fnovej/adCv3VJsULJSjdXEpUwRcq4fnpAAh98Hi7b0GDnlyoNFcdv1g==", + "requires": { + "@babel/runtime": "^7.3.1", + "is-in-browser": "^1.0.2" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.5.tgz", + "integrity": "sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + } + } + }, + "regenerator-runtime": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", + "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" + } + } + }, + "jss-preset-default": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/jss-preset-default/-/jss-preset-default-4.5.0.tgz", + "integrity": "sha512-qZbpRVtHT7hBPpZEBPFfafZKWmq3tA/An5RNqywDsZQGrlinIF/mGD9lmj6jGqu8GrED2SMHZ3pPKLmjCZoiaQ==", + "requires": { + "jss-camel-case": "^6.1.0", + "jss-compose": "^5.0.0", + "jss-default-unit": "^8.0.2", + "jss-expand": "^5.3.0", + "jss-extend": "^6.2.0", + "jss-global": "^3.0.0", + "jss-nested": "^6.0.1", + "jss-props-sort": "^6.0.0", + "jss-template": "^1.0.1", + "jss-vendor-prefixer": "^7.0.0" + } + }, + "jss-props-sort": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/jss-props-sort/-/jss-props-sort-6.0.0.tgz", + "integrity": "sha512-E89UDcrphmI0LzmvYk25Hp4aE5ZBsXqMWlkFXS0EtPkunJkRr+WXdCNYbXbksIPnKlBenGB9OxzQY+mVc70S+g==" + }, + "jss-template": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jss-template/-/jss-template-1.0.1.tgz", + "integrity": "sha512-m5BqEWha17fmIVXm1z8xbJhY6GFJxNB9H68GVnCWPyGYfxiAgY9WTQyvDAVj+pYRgrXSOfN5V1T4+SzN1sJTeg==", + "requires": { + "warning": "^3.0.0" + } + }, + "jss-vendor-prefixer": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/jss-vendor-prefixer/-/jss-vendor-prefixer-7.0.0.tgz", + "integrity": "sha512-Agd+FKmvsI0HLcYXkvy8GYOw3AAASBUpsmIRvVQheps+JWaN892uFOInTr0DRydwaD91vSSUCU4NssschvF7MA==", + "requires": { + "css-vendor": "^0.3.8" + } + }, + "keycode": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz", + "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ=" + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lazy-universal-dotenv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-2.0.0.tgz", + "integrity": "sha512-1Wi0zgZMfRLaRAK21g3odYuU+HE1d85Loe2tb44YhcNwIzhmD49mTPR9aKckpB9Q9Q9mA+hUMLI2xlkcCAe3yw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.0.0", + "app-root-dir": "^1.0.2", + "core-js": "^2.5.7", + "dotenv": "^6.0.0", + "dotenv-expand": "^4.2.0" + }, + "dependencies": { + "core-js": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.2.tgz", + "integrity": "sha512-NdBPF/RVwPW6jr0NCILuyN9RiqLo2b1mddWHkUL+VnvcB7dzlnBJ1bXYntjpTGOgkZiiLWj2JxmOr7eGE3qK6g==", + "dev": true + }, + "dotenv": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", + "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==", + "dev": true + } + } + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, + "linear-layout-vector": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/linear-layout-vector/-/linear-layout-vector-0.0.1.tgz", + "integrity": "sha1-OYEU1zA7bsx/1rJzr3uEAdi6nHA=" + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=" + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "^1.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "lodash.escape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", + "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", + "dev": true + }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "requires": { + "lodash._reinterpolate": "~3.0.0" + } + }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + } + } + }, + "loglevel": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.3.tgz", + "integrity": "sha512-LoEDv5pgpvWgPF4kNYuIp0qqSJVWak/dML0RY74xlzMZiT9w77teNAwKYKWBTYjlokMirg+o3jBwp+vlLrcfAA==", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "requires": { + "js-tokens": "^3.0.0" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" + }, + "lower-case-first": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz", + "integrity": "sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=", + "requires": { + "lower-case": "^1.1.2" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", + "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==" + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.x" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "mdn-data": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz", + "integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-deep": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.2.tgz", + "integrity": "sha512-T7qC8kg4Zoti1cFd8Cr0M+qaZfOwjlPDEdZIIPPB2JZctjaPM4fX+i7HOId69tAti2fvO6X5ldfYUONDODsrkA==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "clone-deep": "^0.2.4", + "kind-of": "^3.0.2" + }, + "dependencies": { + "clone-deep": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", + "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", + "dev": true, + "requires": { + "for-own": "^0.1.3", + "is-plain-object": "^2.0.1", + "kind-of": "^3.0.2", + "lazy-cache": "^1.0.3", + "shallow-clone": "^0.1.2" + } + }, + "shallow-clone": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", + "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", + "dev": true, + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^2.0.1", + "lazy-cache": "^0.2.3", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", + "dev": true, + "requires": { + "is-buffer": "^1.0.2" + } + }, + "lazy-cache": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", + "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=", + "dev": true + } + } + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "merge2": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", + "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "~1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dev": true, + "requires": { + "dom-walk": "^0.1.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "dev": true, + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", + "dev": true + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "moment": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz", + "integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==" + }, + "moment-timezone": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.21.tgz", + "integrity": "sha512-j96bAh4otsgj3lKydm3K7kdtA3iKf2m6MY2iSYCzCm5a1zmHo1g+aK3068dDEeocLZQIS9kU8bsdQHLqEvgW0A==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "moo": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.4.3.tgz", + "integrity": "sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==", + "dev": true + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.9.2.tgz", + "integrity": "sha512-ltW65co7f3PQWBDbqVvaU1WtFJUsNW7sWWm4HINhbMQIyVyzIeyZ8toX5TC5eeooE6piZoaEh4cZkueSKG3KYw==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-odd": "^2.0.0", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "natural-orderby": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.2.tgz", + "integrity": "sha512-ehKWiU0ZoYJw6JRlxcW3PPNW8xUpomrak7bXLyGzkx4f9eQVs7VpxEFMpGITdgrPuAWd5/9bD1MQha5w3z3v6A==" + }, + "nearley": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.15.1.tgz", + "integrity": "sha512-8IUY/rUrKz2mIynUGh8k+tul1awMKEjeHHC5G3FHvvyAW6oq4mQfNp2c0BMea+sYZJvYcrrM6GmZVIle/GRXGw==", + "dev": true, + "requires": { + "moo": "^0.4.3", + "nomnom": "~1.6.2", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6", + "semver": "^5.4.1" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, + "neo-async": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.2.tgz", + "integrity": "sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw==", + "dev": true + }, + "netrc-parser": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/netrc-parser/-/netrc-parser-3.1.6.tgz", + "integrity": "sha512-lY+fmkqSwntAAjfP63jB4z5p5WbuZwyMCD3pInT7dpHU/Gc6Vv90SAC6A0aNiqaRGHiuZFBtiwu+pu8W/Eyotw==", + "requires": { + "debug": "^3.1.0", + "execa": "^0.10.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", + "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + } + } + }, + "nice-try": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "requires": { + "lower-case": "^1.1.1" + } + }, + "node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU=", + "dev": true, + "requires": { + "minimatch": "^3.0.2" + } + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "node-forge": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", + "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", + "dev": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.0", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + } + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, + "node-notifier": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.0.tgz", + "integrity": "sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + } + }, + "node-plop": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/node-plop/-/node-plop-0.17.3.tgz", + "integrity": "sha512-oITDOxms/0tW0FQIorc/WcK8QxXxW78I6hRSxn7jTSO08KTsfWHsh8J4fGmT4V3GDextl9gyX3juqFl4j1A02A==", + "dev": true, + "requires": { + "change-case": "^3.0.1", + "co": "^4.6.0", + "core-js": "^2.4.1", + "del": "^3.0.0", + "globby": "^8.0.0", + "handlebars": "^4.0.5", + "inquirer": "^6.0.0", + "isbinaryfile": "^3.0.2", + "lodash.get": "^4.4.2", + "mkdirp": "^0.5.1", + "pify": "^4.0.0", + "resolve": "^1.2.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "^6.1.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "path-type": "^3.0.0" + } + }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "globby": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", + "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "2.0.0", + "fast-glob": "^2.0.2", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inquirer": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", + "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.11", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.0.0", + "through": "^2.3.6" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "strip-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "dev": true, + "requires": { + "ansi-regex": "^4.0.0" + } + } + } + }, + "node-releases": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.5.tgz", + "integrity": "sha512-Ky7q0BO1BBkG/rQz6PkEZ59rwo+aSfhczHP1wwq8IowoVdN/FpiP7qp0XW0P2+BVCWe5fQUBozdbVd54q1RbCQ==", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, + "node-version": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/node-version/-/node-version-1.2.0.tgz", + "integrity": "sha512-ma6oU4Sk0qOoKEAymVoTvk8EdXEobdS7m/mAGhDJ8Rouugho48crHBORAmy5BoOcv8wraPM6xumapQp5hl4iIQ==", + "dev": true + }, + "nomnom": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", + "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=", + "dev": true, + "requires": { + "colors": "0.5.x", + "underscore": "~1.4.4" + }, + "dependencies": { + "colors": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=", + "dev": true + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-scroll-left": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-scroll-left/-/normalize-scroll-left-0.1.2.tgz", + "integrity": "sha512-F9YMRls0zCF6BFIE2YnXDRpHPpfd91nOIaNdDgrx5YMoPLo8Wqj+6jNXHQsYBavJeXP4ww8HCt0xQAKc5qk2Fg==" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "nwsapi": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.3.tgz", + "integrity": "sha512-RowAaJGEgYXEZfQ7tvvdtAQUKPyTR6T6wNu0fwlNsGQYr/h3yQc6oI8WnVZh3Y/Sylwc+dtAlvPqfFZjhTyk3A==", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-is": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", + "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", + "dev": true + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.entries": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", + "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.6.1", + "function-bind": "^1.1.0", + "has": "^1.0.1" + } + }, + "object.fromentries": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-1.0.0.tgz", + "integrity": "sha512-F7XUm84lg0uNXNzrRAC5q8KJe0yYaxgLU9hTSqWYM6Rfnh0YjP24EG3xq7ncj2Wu1AdfueNHKCOlamIonG4UHQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.11.0", + "function-bind": "^1.1.1", + "has": "^1.0.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + }, + "dependencies": { + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + } + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + } + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.values": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", + "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.6.1", + "function-bind": "^1.1.0", + "has": "^1.0.1" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "opn": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", + "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optimism": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.6.8.tgz", + "integrity": "sha512-bN5n1KCxSqwBDnmgDnzMtQTHdL+uea2HYFx1smvtE+w2AMl0Uy31g0aXnP/Nt85OINnMJPRpJyfRQLTCqn5Weg==", + "requires": { + "immutable-tuple": "^0.4.9" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "original": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.1.tgz", + "integrity": "sha512-IEvtB5vM5ULvwnqMxWBLxkS13JIEXbakizMSo3yoPNPCIWzg8TG3Usn/UhXoZFM/m+FuEA20KdzPSFq/0rS+UA==", + "dev": true, + "requires": { + "url-parse": "~1.4.0" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" + }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "requires": { + "p-finally": "^1.0.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "requires": { + "no-case": "^2.2.0" + } + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascal-case": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz", + "integrity": "sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=", + "requires": { + "camel-case": "^3.0.0", + "upper-case-first": "^1.1.0" + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "password-prompt": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/password-prompt/-/password-prompt-1.1.2.tgz", + "integrity": "sha512-bpuBhROdrhuN3E7G/koAju0WjVw9/uQOG5Co5mokNj0MiOSBVZS1JTwM4zl55hu0WFmIEFvO9cU9sJQiBIYeIA==", + "requires": { + "ansi-escapes": "^3.1.0", + "cross-spawn": "^6.0.5" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-2.1.1.tgz", + "integrity": "sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=", + "requires": { + "no-case": "^2.2.0" + } + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "plop": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/plop/-/plop-2.2.0.tgz", + "integrity": "sha512-qt4pCQPL76AzEYX+OPoWsvT+WUbyU15Zkwb3DQa9n5QQcd6np6l6Rh+7oufmxo93olMVScKBaZ1JDy3zyIsaQg==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "interpret": "^1.0.0", + "liftoff": "^2.2.0", + "minimist": "^1.2.0", + "node-plop": "=0.17.3", + "ora": "^3.0.0", + "v8flags": "^2.0.10" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cli-spinners": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz", + "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ora": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.0.0.tgz", + "integrity": "sha512-LBS97LFe2RV6GJmXBi6OKcETKyklHNMV0xw7BtsVn2MlsgsydyZetSCbCANr+PFLmDyv4KV88nn0eCKza665Mg==", + "dev": true, + "requires": { + "chalk": "^2.3.1", + "cli-cursor": "^2.1.0", + "cli-spinners": "^1.1.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^4.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "popper.js": { + "version": "1.14.6", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.6.tgz", + "integrity": "sha512-AGwHGQBKumlk/MDfrSOf0JHhJCImdDMcGNoqKmKkU+68GFazv3CQ6q9r7Ja1sKDZmYWTckY/uLyEznheTDycnA==" + }, + "portfinder": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz", + "integrity": "sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw==", + "dev": true, + "requires": { + "async": "^1.5.2", + "debug": "^2.2.0", + "mkdirp": "0.5.x" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "6.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", + "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", + "dev": true, + "requires": { + "chalk": "^2.3.2", + "source-map": "^0.6.1", + "supports-color": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-flexbugs-fixes": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.1.0.tgz", + "integrity": "sha512-jr1LHxQvStNNAHlgco6PzY308zvLklh7SJVYuWUwyUQncofaAlD2l+P/gxKHOdqWKe7xJSkVLFF/2Tp+JqMSZA==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.13.tgz", + "integrity": "sha512-h8SY6kQTd1wISHWjz+E6cswdhMuyBZRb16pSTv3W4zYZ3/YbyWeJdNUeOXB5IdZqE1U76OUEjjjqsC3z2f3hVg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz", + "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=", + "dev": true, + "requires": { + "postcss": "^6.0.1" + } + }, + "postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + } + }, + "postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + } + }, + "postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "dev": true, + "requires": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^6.0.1" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "dev": true, + "requires": { + "renderkid": "^2.0.1", + "utila": "~0.4" + } + }, + "pretty-format": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + } + } + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==" + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "promise-polyfill": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-6.1.0.tgz", + "integrity": "sha1-36lpQ+qcEh/KTem1hoyznTRy4Fc=", + "dev": true + }, + "promise.prototype.finally": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.0.tgz", + "integrity": "sha512-7p/K2f6dI+dM8yjRQEGrTQs5hTQixUAdOGpMEA3+pVxpX5oHKRSKAXyLw9Q9HUWDTdwtoo39dSHGQtN90HcEwQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.9.0", + "function-bind": "^1.1.1" + } + }, + "prompts": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.0.4.tgz", + "integrity": "sha512-HTzM3UWp/99A0gk51gAegwo1QRYA7xjcZufMNe33rCclFszUYAuHe1fIN/3ZmiHeGPkUsNaRyQm1hHOfM0PKxA==", + "dev": true, + "requires": { + "kleur": "^3.0.2", + "sisteransi": "^1.0.0" + } + }, + "prop-types": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", + "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", + "requires": { + "fbjs": "^0.8.16", + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "property-information": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.0.1.tgz", + "integrity": "sha512-nAtBDVeSwFM3Ot/YxT7s4NqZmqXI7lLzf46BThvotEtYf2uk2yH0ACYuWQkJ7gxKs49PPtKVY0UlDGkyN9aJlw==", + "dev": true, + "requires": { + "xtend": "^4.0.1" + } + }, + "proxy-addr": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.6.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", + "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", + "dev": true + }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "requires": { + "performance-now": "^2.1.0" + } + }, + "railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", + "dev": true + }, + "ramda": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz", + "integrity": "sha1-oAGr7bP/YQd9T/HVd9RN536NCjU=", + "dev": true + }, + "randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dev": true, + "requires": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": ">= 1.3.1 < 2" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + } + } + }, + "raw-loader": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", + "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=", + "dev": true + }, + "react": { + "version": "16.8.4", + "resolved": "https://registry.npmjs.org/react/-/react-16.8.4.tgz", + "integrity": "sha512-0GQ6gFXfUH7aZcjGVymlPOASTuSjlQL4ZtVC5YKH+3JL6bBLCVO21DknzmaPlI90LN253ojj02nsapy+j7wIjg==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.13.4" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + }, + "dependencies": { + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + } + } + }, + "react-is": { + "version": "16.8.4", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz", + "integrity": "sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA==" + }, + "scheduler": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.4.tgz", + "integrity": "sha512-cvSOlRPxOHs5dAhP9yiS/6IDmVAVxmk33f0CtTJRkmUWcb1Us+t7b1wqdzoC0REw2muC9V5f1L/w5R5uKGaepA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, + "react-apollo": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/react-apollo/-/react-apollo-2.5.2.tgz", + "integrity": "sha512-lmglhG6NQ+lfAUDzx8ZgelWKUbvxBhhy1l7Z2ksgtQ8+FVqwX7i6p5O3zicAZZlIdKzdq82V0kqq5WkxEsffrA==", + "requires": { + "apollo-utilities": "^1.2.1", + "hoist-non-react-statics": "^3.0.0", + "lodash.isequal": "^4.5.0", + "prop-types": "^15.6.0", + "ts-invariant": "^0.3.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "apollo-utilities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.2.1.tgz", + "integrity": "sha512-Zv8Udp9XTSFiN8oyXOjf6PMHepD4yxxReLsl6dPUy5Ths7jti3nmlBzZUOxuTWRwZn0MoclqL7RQ5UEJN8MAxg==", + "requires": { + "fast-json-stable-stringify": "^2.0.0", + "ts-invariant": "^0.2.1", + "tslib": "^1.9.3" + }, + "dependencies": { + "ts-invariant": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.2.1.tgz", + "integrity": "sha512-Z/JSxzVmhTo50I+LKagEISFJW3pvPCqsMWLamCTX8Kr3N5aMrnGOqcflbe5hLUzwjvgPfnLzQtHZv0yWQ+FIHg==", + "requires": { + "tslib": "^1.9.3" + } + } + } + }, + "hoist-non-react-statics": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz", + "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==", + "requires": { + "react-is": "^16.7.0" + } + }, + "react-is": { + "version": "16.8.4", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz", + "integrity": "sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA==" + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + } + } + }, + "react-dev-utils": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-6.1.1.tgz", + "integrity": "sha512-ThbJ86coVd6wV/QiTo8klDTvdAJ1WsFCGQN07+UkN+QN9CtCSsl/+YuDJToKGeG8X4j9HMGXNKbk2QhPAZr43w==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0", + "address": "1.0.3", + "browserslist": "4.1.1", + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "detect-port-alt": "1.1.6", + "escape-string-regexp": "1.0.5", + "filesize": "3.6.1", + "find-up": "3.0.0", + "global-modules": "1.0.0", + "globby": "8.0.1", + "gzip-size": "5.0.0", + "immer": "1.7.2", + "inquirer": "6.2.0", + "is-root": "2.0.0", + "loader-utils": "1.1.0", + "opn": "5.4.0", + "pkg-up": "2.0.0", + "react-error-overlay": "^5.1.0", + "recursive-readdir": "2.2.2", + "shell-quote": "1.6.1", + "sockjs-client": "1.1.5", + "strip-ansi": "4.0.0", + "text-table": "0.2.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "browserslist": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.1.1.tgz", + "integrity": "sha512-VBorw+tgpOtZ1BYhrVSVTzTt/3+vSE3eFUh0N2GCFK1HffceOaf32YS/bs6WiFhjDAblAFrx85jMy3BG9fBK2Q==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000884", + "electron-to-chromium": "^1.3.62", + "node-releases": "^1.0.0-alpha.11" + } + }, + "caniuse-lite": { + "version": "1.0.30000929", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000929.tgz", + "integrity": "sha512-n2w1gPQSsYyorSVYqPMqbSaz1w7o9ZC8VhOEGI9T5MfGDzp7sbopQxG6GaQmYsaq13Xfx/mkxJUWC1Dz3oZfzw==", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "dev": true, + "requires": { + "address": "^1.0.1", + "debug": "^2.6.0" + } + }, + "electron-to-chromium": { + "version": "1.3.103", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.103.tgz", + "integrity": "sha512-tObPqGmY9X8MUM8i3MEimYmbnLLf05/QV5gPlkR8MQ3Uj8G8B2govE1U4cQcBYtv3ymck9Y8cIOu4waoiykMZQ==", + "dev": true + }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "globby": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", + "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "fast-glob": "^2.0.2", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inquirer": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", + "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.0", + "figures": "^2.0.0", + "lodash": "^4.17.10", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.1.0", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "react-display-name": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/react-display-name/-/react-display-name-0.2.4.tgz", + "integrity": "sha512-zvU6iouW+SWwHTyThwxGICjJYCMZFk/6r/+jmOdC7ntQoPlS/Pqb81MkxaMf2bHTSq9TN3K3zX2/ayMW/jCtyA==" + }, + "react-dnd": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-7.4.5.tgz", + "integrity": "sha512-/689FECqmfNxHZJymC0Ge0Vt5A2oxXwcpVpFjM7O21ifzSh3YtZl83rre6Cosdc4Sx9ucrMq3sRxKMH9p/ekCg==", + "requires": { + "dnd-core": "^7.4.4", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.1.0", + "shallowequal": "^1.1.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz", + "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==", + "requires": { + "react-is": "^16.7.0" + } + } + } + }, + "react-dnd-html5-backend": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-7.4.4.tgz", + "integrity": "sha512-X/lP92ateY0glHan8mU0JzjBuZL6VHv2Gc/H9OBBxaf/ZCN1oC16MLKdesqG4x1f/NWFTNtuG3W4B99r5gPVog==", + "requires": { + "dnd-core": "^7.4.4" + } + }, + "react-docgen": { + "version": "3.0.0-rc.2", + "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-3.0.0-rc.2.tgz", + "integrity": "sha512-tXbIvq7Hxdc92jW570rztqsz0adtWEM5FX8bShJYozT2Y6L/LeHvBMQcED6mSqJ72niiNMPV8fi3S37OHrGMEw==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.3", + "@babel/runtime": "^7.0.0", + "async": "^2.1.4", + "commander": "^2.19.0", + "doctrine": "^2.0.0", + "node-dir": "^0.1.10", + "recast": "^0.16.0" + }, + "dependencies": { + "@babel/parser": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz", + "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", + "dev": true + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + } + } + }, + "react-dom": { + "version": "16.8.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.4.tgz", + "integrity": "sha512-Ob2wK7XG2tUDt7ps7LtLzGYYB6DXMCLj0G5fO6WeEICtT4/HdpOi7W/xLzZnR6RCG1tYza60nMdqtxzA8FaPJQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.13.4" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + }, + "dependencies": { + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + } + } + }, + "react-is": { + "version": "16.8.4", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz", + "integrity": "sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA==" + }, + "scheduler": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.4.tgz", + "integrity": "sha512-cvSOlRPxOHs5dAhP9yiS/6IDmVAVxmk33f0CtTJRkmUWcb1Us+t7b1wqdzoC0REw2muC9V5f1L/w5R5uKGaepA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, + "react-dropzone": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-8.0.3.tgz", + "integrity": "sha512-3zvEH4szxTHjpNIbuSXY3aIByv6fUao8ZYOqtYucmgduRR+r0c94xMJvrPKyAj9hgWZTJ/0I//PMq+SDZp3MCw==", + "requires": { + "attr-accept": "^1.1.3", + "prop-types": "^15.6.2" + }, + "dependencies": { + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + } + } + }, + "react-error-overlay": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-5.1.2.tgz", + "integrity": "sha512-7kEBKwU9R8fKnZJBRa5RSIfay4KJwnYvKB6gODGicUmDSAhQJ7Tdnll5S0RLtYrzRfMVXlqYw61rzrSpP4ThLQ==", + "dev": true + }, + "react-event-listener": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/react-event-listener/-/react-event-listener-0.6.6.tgz", + "integrity": "sha512-+hCNqfy7o9wvO6UgjqFmBzARJS7qrNoda0VqzvOuioEpoEXKutiKuv92dSz6kP7rYLmyHPyYNLesi5t/aH1gfw==", + "requires": { + "@babel/runtime": "^7.2.0", + "prop-types": "^15.6.0", + "warning": "^4.0.1" + }, + "dependencies": { + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, + "react-fuzzy": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/react-fuzzy/-/react-fuzzy-0.5.2.tgz", + "integrity": "sha512-qIZZxaCheb/HhcBi5fABbiCFg85+K5r1TCps1D4uaL0LAMMD/1zm/x1/kNR130Tx7nnY9V7mbFyY0DquPYeLAw==", + "dev": true, + "requires": { + "babel-runtime": "^6.23.0", + "classnames": "^2.2.5", + "fuse.js": "^3.0.1", + "prop-types": "^15.5.9" + } + }, + "react-helmet": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-5.2.0.tgz", + "integrity": "sha1-qBgR3yExOm1VxfBYxK66XW89l6c=", + "requires": { + "deep-equal": "^1.0.1", + "object-assign": "^4.1.1", + "prop-types": "^15.5.4", + "react-side-effect": "^1.1.0" + } + }, + "react-infinite-scroller": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/react-infinite-scroller/-/react-infinite-scroller-1.2.4.tgz", + "integrity": "sha512-/oOa0QhZjXPqaD6sictN2edFMsd3kkMiE19Vcz5JDgHpzEJVqYcmq+V3mkwO88087kvKGe1URNksHEOt839Ubw==", + "requires": { + "prop-types": "^15.5.8" + } + }, + "react-inlinesvg": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/react-inlinesvg/-/react-inlinesvg-0.8.1.tgz", + "integrity": "sha512-rdeqawsT17tKvY3B9rfHsNUpZ9RpDP7URNLCrv4NifWcIoPcBxAc7Vel1pK7hyAYKgv6DDMaf8x9PB3jyWjW4A==", + "requires": { + "httpplease": "^0.16.4", + "once": "^1.4.0" + } + }, + "react-inspector": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-2.3.1.tgz", + "integrity": "sha512-tUUK7t3KWgZEIUktOYko5Ic/oYwvjEvQUFAGC1UeMeDaQ5za2yZFtItJa2RTwBJB//NxPr000WQK6sEbqC6y0Q==", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "is-dom": "^1.0.9", + "prop-types": "^15.6.1" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" + }, + "react-jss": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.4.0.tgz", + "integrity": "sha512-yIi4udcTIIh5u4KJ47wsL3UZYMuSrp5xR1YBvPeRNshpCdRoJxt5BWmCu1RA3LIa+//dnRsAtAQmMAYeg1W9oQ==", + "requires": { + "hoist-non-react-statics": "^2.3.1", + "jss": "^9.7.0", + "jss-preset-default": "^4.3.0", + "prop-types": "^15.6.0", + "theming": "^1.3.0" + } + }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-modal": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.8.1.tgz", + "integrity": "sha512-aLKeZM9pgXpIKVwopRHMuvqKWiBajkqisDA8UzocdCF6S4fyKVfLWmZR5G1Q0ODBxxxxf2XIwiCP8G/11GJAuw==", + "dev": true, + "requires": { + "exenv": "^1.2.0", + "prop-types": "^15.5.10", + "react-lifecycles-compat": "^3.0.0", + "warning": "^3.0.0" + } + }, + "react-moment": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/react-moment/-/react-moment-0.7.7.tgz", + "integrity": "sha512-ARzgdPQV7NA1s2U8ZZ/y8KFc9MM4zMx+TY9TLxKybKZU55PbLFoiYD9u4XdNeguu47TNgzuTKW5lAZJuIY632g==" + }, + "react-router": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.0.0.tgz", + "integrity": "sha512-6EQDakGdLG/it2x9EaCt9ZpEEPxnd0OCLBHQ1AcITAAx7nCnyvnzf76jKWG1s2/oJ7SSviUgfWHofdYljFexsA==", + "requires": { + "@babel/runtime": "^7.1.2", + "create-react-context": "^0.2.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz", + "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==", + "requires": { + "react-is": "^16.7.0" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + }, + "dependencies": { + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + } + } + }, + "react-is": { + "version": "16.8.4", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz", + "integrity": "sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA==" + } + } + }, + "react-router-dom": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.0.0.tgz", + "integrity": "sha512-wSpja5g9kh5dIteZT3tUoggjnsa+TPFHSMrpHXMpFsaHhQkm/JNVGh2jiF9Dkh4+duj4MKCkwO6H08u6inZYgQ==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + }, + "dependencies": { + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + } + } + }, + "react-is": { + "version": "16.8.4", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz", + "integrity": "sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA==" + } + } + }, + "react-router-navigation-prompt": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/react-router-navigation-prompt/-/react-router-navigation-prompt-1.8.2.tgz", + "integrity": "sha512-jUdoU4Ri3ONhdoAqMW4knCiO4Ql9wy3IRu62BugORFMW5L2Fb3VyE4QHj0puPzVZ5lEeLCddU2vQDZwXiVUZ+g==" + }, + "react-side-effect": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-1.1.5.tgz", + "integrity": "sha512-Z2ZJE4p/jIfvUpiUMRydEVpQRf2f8GMHczT6qLcARmX7QRb28JDBTpnM2g/i5y/p7ZDEXYGHWg0RbhikE+hJRw==", + "requires": { + "exenv": "^1.2.1", + "shallowequal": "^1.0.1" + }, + "dependencies": { + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + } + } + }, + "react-sortable-hoc": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-0.6.8.tgz", + "integrity": "sha512-sUUAtNdV84AKZ2o+F5lVOOFWcyWG6aGDkNFgHoieB1zFLeWLWENkix06asPS4/GhigfuRh06aZix1j3Qx8+NSQ==", + "requires": { + "babel-runtime": "^6.11.6", + "invariant": "^2.2.1", + "lodash": "^4.12.0", + "prop-types": "^15.5.7" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + } + } + }, + "react-sortable-tree": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/react-sortable-tree/-/react-sortable-tree-2.6.2.tgz", + "integrity": "sha512-mYX6ByTs7fywPqTEWpEUMgtvLDVyVrkm1Tw/pOPteiLwwMnOqh1LxBwJPUJBmhU2E0P2Zvw3dhnBFL14Fe4EkA==", + "requires": { + "frontend-collective-react-dnd-scrollzone": "^1.0.2", + "lodash.isequal": "^4.5.0", + "prop-types": "^15.6.1", + "react-dnd": "^7.3.0", + "react-dnd-html5-backend": "^7.0.1", + "react-lifecycles-compat": "^3.0.4", + "react-sortable-tree": "^2.6.0", + "react-virtualized": "^9.19.1" + } + }, + "react-split-pane": { + "version": "0.1.85", + "resolved": "https://registry.npmjs.org/react-split-pane/-/react-split-pane-0.1.85.tgz", + "integrity": "sha512-3GhaYs6+eVNrewgN4eQKJoNMQ4pcegNMTMhR5bO/NFO91K6/98qdD1sCuWPpsefCjzxNTjkvVYWQC0bMaC45mA==", + "dev": true, + "requires": { + "prop-types": "^15.5.10", + "react": "^16.6.3", + "react-dom": "^16.6.3", + "react-lifecycles-compat": "^3.0.4", + "react-style-proptype": "^3.0.0" + } + }, + "react-style-proptype": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-style-proptype/-/react-style-proptype-3.2.2.tgz", + "integrity": "sha512-ywYLSjNkxKHiZOqNlso9PZByNEY+FTyh3C+7uuziK0xFXu9xzdyfHwg4S9iyiRRoPCR4k2LqaBBsWVmSBwCWYQ==", + "dev": true, + "requires": { + "prop-types": "^15.5.4" + } + }, + "react-svg": { + "version": "2.2.18", + "resolved": "https://registry.npmjs.org/react-svg/-/react-svg-2.2.18.tgz", + "integrity": "sha512-Hm+PJYxfZ4FIWyI3xypvyrrt+qbhCaDHKPiYv3Aen57xMjhtESKYQArkGVmn2O7W+lROLCjFfp+NnivULBtxxw==", + "requires": { + "svg-injector": "^1.1.3" + } + }, + "react-test-renderer": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.8.6.tgz", + "integrity": "sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "react-is": "^16.8.6", + "scheduler": "^0.13.6" + }, + "dependencies": { + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } + } + }, + "react-textarea-autosize": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-7.1.0.tgz", + "integrity": "sha512-c2FlR/fP0qbxmlrW96SdrbgP/v0XZMTupqB90zybvmDVDutytUgPl7beU35klwcTeMepUIQEpQUn3P3bdshGPg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.1.2", + "prop-types": "^15.6.0" + } + }, + "react-transition-group": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.2.1.tgz", + "integrity": "sha512-q54UBM22bs/CekG8r3+vi9TugSqh0t7qcEVycaRc9M0p0aCEu+h6rp/RFiW7fHfgd1IKpd9oILFTl5QK+FpiPA==", + "requires": { + "chain-function": "^1.0.0", + "classnames": "^2.2.5", + "dom-helpers": "^3.2.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.5.8", + "warning": "^3.0.0" + } + }, + "react-treebeard": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/react-treebeard/-/react-treebeard-3.1.0.tgz", + "integrity": "sha512-u4OEzwZk1Xcxp2s55Ny/Ofp8fHRwlabKOAeGbzQ7XUE9YXFbPj8ajl0FInbXEP4Ys9+E1vHCtgqJ6VBsgbCPVg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.0.0", + "@emotion/core": "^0.13.1", + "@emotion/styled": "^0.10.6", + "deep-equal": "^1.0.1", + "prop-types": "^15.6.2", + "shallowequal": "^1.1.0", + "velocity-react": "^1.4.1" + }, + "dependencies": { + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + } + } + }, + "react-virtualized": { + "version": "9.21.1", + "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.21.1.tgz", + "integrity": "sha512-E53vFjRRMCyUTEKuDLuGH1ld/9TFzjf/fFW816PE4HFXWZorESbSTYtiZz1oAjra0MminaUU1EnvUxoGuEFFPA==", + "requires": { + "babel-runtime": "^6.26.0", + "clsx": "^1.0.1", + "dom-helpers": "^2.4.0 || ^3.0.0", + "linear-layout-vector": "0.0.1", + "loose-envify": "^1.3.0", + "prop-types": "^15.6.0", + "react-lifecycles-compat": "^3.0.4" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + } + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "recast": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.16.2.tgz", + "integrity": "sha512-O/7qXi51DPjRVdbrpNzoBQH5dnAPQNbfoOFyRiUwreTMJfIHYOEBzwuH+c0+/BTSJ3CQyKs6ILSWXhESH6Op3A==", + "dev": true, + "requires": { + "ast-types": "0.11.7", + "esprima": "~4.0.0", + "private": "~0.1.5", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "^1.1.6" + } + }, + "recompose": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.30.0.tgz", + "integrity": "sha512-ZTrzzUDa9AqUIhRk4KmVFihH0rapdCSMFXjhHbNrjAWxBuUD/guYlyysMnuHjlZC/KRiOKRtB4jf96yYSkKE8w==", + "requires": { + "@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": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", + "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "requires": { + "minimatch": "3.0.4" + } + }, + "redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "requires": { + "esprima": "~4.0.0" + } + }, + "redux": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.1.tgz", + "integrity": "sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + }, + "dependencies": { + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + } + } + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz", + "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + }, + "dependencies": { + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + } + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regenerator-transform": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz", + "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==", + "dev": true, + "requires": { + "private": "^0.1.6" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", + "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2" + } + }, + "regexpu-core": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", + "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^7.0.0", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.0.2" + }, + "dependencies": { + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + } + } + }, + "regjsgen": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", + "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", + "dev": true + }, + "regjsparser": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "rehype-parse": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.0.tgz", + "integrity": "sha512-V2OjMD0xcSt39G4uRdMTqDXXm6HwkUbLMDayYKA/d037j8/OtVSQ+tqKwYWOuyBeoCs/3clXRe30VUjeMDTBSA==", + "dev": true, + "requires": { + "hast-util-from-parse5": "^5.0.0", + "parse5": "^5.0.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "dev": true + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "render-fragment": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/render-fragment/-/render-fragment-0.1.1.tgz", + "integrity": "sha512-+DnAcalJYR8GE5VRuQGGu78Q0GDe8EXnkuk4DF8gbAhIeS6LRt4j+aaggLLj4PtQVfXNC61McXvXI58WqmRleQ==", + "dev": true + }, + "renderkid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.3.tgz", + "integrity": "sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA==", + "dev": true, + "requires": { + "css-select": "^1.1.0", + "dom-converter": "^0.2", + "htmlparser2": "^3.3.0", + "strip-ansi": "^3.0.0", + "utila": "^0.4.0" + } + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "request": { + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" + } + }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "request-promise-native": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", + "dev": true, + "requires": { + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-pathname": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz", + "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rst-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", + "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=", + "dev": true, + "requires": { + "lodash.flattendeep": "^4.4.0", + "nearley": "^2.7.10" + } + }, + "rsvp": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.4.tgz", + "integrity": "sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==", + "dev": true + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "dev": true, + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "scheduler": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", + "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", + "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + }, + "dependencies": { + "ajv": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.0.tgz", + "integrity": "sha1-r6wpW7qgFSRJ5SJ0LkVHwa6TKNI=", + "dev": true, + "requires": { + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + } + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz", + "integrity": "sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw==", + "dev": true, + "requires": { + "node-forge": "0.7.5" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "sentence-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.1.tgz", + "integrity": "sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ=", + "requires": { + "no-case": "^2.2.0", + "upper-case-first": "^1.1.2" + } + }, + "serialize-javascript": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", + "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", + "dev": true + }, + "serve-favicon": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", + "integrity": "sha1-k10kDN/g9YBTB/3+ln2IlCosvPA=", + "dev": true, + "requires": { + "etag": "~1.8.1", + "fresh": "0.5.2", + "ms": "2.1.1", + "parseurl": "~1.3.2", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } + }, + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "sisteransi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.0.tgz", + "integrity": "sha512-N+z4pHB4AmUv0SjveWRd6q1Nj5w62m5jodv+GD8lvmbY/83T/rpbJGZOnK5T149OldDj4Db07BSv9xY4K6NTPQ==", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slugify": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.3.4.tgz", + "integrity": "sha512-KP0ZYk5hJNBS8/eIjGkFDCzGQIoZ1mnfQRYS5WM3273z+fxGWXeN0fkwf2ebEweydv9tioZIHGZKoF21U07/nw==" + }, + "snake-case": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz", + "integrity": "sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=", + "requires": { + "no-case": "^2.2.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + } + }, + "sockjs": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "dev": true, + "requires": { + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" + } + }, + "sockjs-client": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.5.tgz", + "integrity": "sha1-G7fA9yIsQPQq3xT0RCy9Eml3GoM=", + "dev": true, + "requires": { + "debug": "^2.6.6", + "eventsource": "0.1.6", + "faye-websocket": "~0.11.0", + "inherits": "^2.0.1", + "json3": "^3.3.2", + "url-parse": "^1.1.8" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + } + } + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "space-separated-tokens": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz", + "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==", + "dev": true, + "requires": { + "trim": "0.0.1" + } + }, + "spawn-promise": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/spawn-promise/-/spawn-promise-0.1.8.tgz", + "integrity": "sha512-pTkEOFxvYLq9SaI1d8bwepj0yD9Yyz65+4e979YZLv/L3oYPxZpDTabcm6e+KIZniGK9mQ+LGrwB5s1v2z67nQ==", + "dev": true, + "requires": { + "co": "^4.6.0" + } + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "dev": true + }, + "spdy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", + "integrity": "sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "tweetnacl": "~0.14.0" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha1-1PM6tU6OOHeLDKXP07OvsS22hiA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string-similarity": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-1.2.0.tgz", + "integrity": "sha1-11FTyzg4RjGLejmo2SkrtNtOnDA=", + "requires": { + "lodash": "^4.13.1" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string.prototype.matchall": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-3.0.1.tgz", + "integrity": "sha512-NSiU0ILQr9PQ1SZmM1X327U5LsM+KfDTassJfqN1al1+0iNpKzmQ4BfXOJwRnTEqv8nKJ67mFpqRoPaGWwvy5A==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "regexp.prototype.flags": "^1.2.0" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + } + } + }, + "string.prototype.padend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", + "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.4.3", + "function-bind": "^1.0.2" + } + }, + "string.prototype.padstart": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.padstart/-/string.prototype.padstart-3.0.0.tgz", + "integrity": "sha1-W8+tOfRkm7LQMSkuGbzwtRDUskI=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.4.3", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "style-loader": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", + "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "subscriptions-transport-ws": { + "version": "0.9.16", + "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.16.tgz", + "integrity": "sha512-pQdoU7nC+EpStXnCfh/+ho0zE0Z+ma+i7xvj7bkXKb1dvYHSZxgRPaU6spRP+Bjzow67c/rRDoix5RT0uU9omw==", + "requires": { + "backo2": "^1.0.2", + "eventemitter3": "^3.1.0", + "iterall": "^1.2.1", + "symbol-observable": "^1.0.4", + "ws": "^5.2.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-hyperlinks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz", + "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==", + "requires": { + "has-flag": "^2.0.0", + "supports-color": "^5.0.0" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + } + } + }, + "svg-injector": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/svg-injector/-/svg-injector-1.1.3.tgz", + "integrity": "sha1-j7oY10GeX4GOcSxPgtg+41dhDmE=" + }, + "svg-url-loader": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/svg-url-loader/-/svg-url-loader-2.3.2.tgz", + "integrity": "sha1-3YaybBn+O5FPBOoQ7zlZTq3gRGQ=", + "dev": true, + "requires": { + "file-loader": "1.1.11", + "loader-utils": "1.1.0" + } + }, + "swap-case": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz", + "integrity": "sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=", + "requires": { + "lower-case": "^1.1.1", + "upper-case": "^1.1.1" + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, + "symbol-tree": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", + "dev": true + }, + "symbol.prototype.description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/symbol.prototype.description/-/symbol.prototype.description-1.0.0.tgz", + "integrity": "sha512-I9mrbZ5M96s7QeJDv95toF1svkUjeBybe8ydhY7foPaBmr0SPJMFupArmMkDrOKTTj0sJVr+nvQNxWLziQ7nDQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "tapable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", + "dev": true + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + } + }, + "terser": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.11.0.tgz", + "integrity": "sha512-5iLMdhEPIq3zFWskpmbzmKwMQixKmTYwY3Ox9pjtSklBLnHiuQ0GKJLhL1HSYtyffHM3/lDIFBnb82m9D7ewwQ==", + "dev": true, + "requires": { + "commander": "~2.17.1", + "source-map": "~0.6.1", + "source-map-support": "~0.5.6" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.1.0.tgz", + "integrity": "sha512-61lV0DSxMAZ8AyZG7/A4a3UPlrbOBo8NIQ4tJzLPAdGOQ+yoNC7l5ijEow27lBAL2humer01KLS6bGIMYQxKoA==", + "dev": true, + "requires": { + "cacache": "^11.0.2", + "find-cache-dir": "^2.0.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "terser": "^3.8.1", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" + }, + "dependencies": { + "ajv": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", + "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "cacache": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.1.tgz", + "integrity": "sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "figgy-pudding": "^3.1.0", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.3", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^6.0.0", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "find-cache-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", + "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "p-limit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", + "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + } + } + }, + "test-exclude": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.1.tgz", + "integrity": "sha512-qpqlP/8Zl+sosLxBcVKl9vYy26T9NPalxSzzCP/OY6K7j938ui2oKgo+kRZYfxAeIpLqpbVnsHq1tyV70E4lWQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "micromatch": "^3.1.8", + "object-assign": "^4.1.0", + "read-pkg-up": "^1.0.1", + "require-main-filename": "^1.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "theming": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/theming/-/theming-1.3.0.tgz", + "integrity": "sha512-ya5Ef7XDGbTPBv5ENTwrwkPUexrlPeiAg/EI9kdlUAZhNlRbCdhMKRgjNX1IcmsmiPcqDQZE6BpSaH+cr31FKw==", + "requires": { + "brcast": "^3.0.1", + "is-function": "^1.0.1", + "is-plain-object": "^2.0.1", + "prop-types": "^15.5.8" + } + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", + "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", + "dev": true + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tiny-invariant": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.0.3.tgz", + "integrity": "sha512-ytQx8T4DL8PjlX53yYzcIC0WhIZbpR0p1qcYjw2pHu3w6UtgWwFJQ/02cnhOnBBhlFx/edUIfcagCaQSe3KMWg==" + }, + "tiny-warning": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.2.tgz", + "integrity": "sha512-rru86D9CpQRLvsFG5XFdy0KdLAvjdQDyZCsRcuu60WtzFylDM3eAWSxEVz5kzL2Gp544XiUvPbVKtOA/txLi9Q==" + }, + "title-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz", + "integrity": "sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o=", + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.0.3" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "^1.4.1" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "treeify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", + "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==" + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + }, + "trough": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz", + "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==", + "dev": true + }, + "ts-invariant": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.3.2.tgz", + "integrity": "sha512-QsY8BCaRnHiB5T6iE4DPlJMAKEG3gzMiUco9FEt1jUXQf0XP6zi0idT0i0rMTu8A326JqNSDsmlkA9dRSh1TRg==", + "requires": { + "tslib": "^1.9.3" + }, + "dependencies": { + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + } + } + }, + "ts-jest": { + "version": "23.10.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-23.10.5.tgz", + "integrity": "sha512-MRCs9qnGoyKgFc8adDEntAOP64fWK1vZKnOYU1o2HxaqjdJvGqmkLCPCnVq1/If4zkUmEjKPnCiUisTrlX2p2A==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "json5": "2.x", + "make-error": "1.x", + "mkdirp": "0.x", + "resolve": "1.x", + "semver": "^5.5", + "yargs-parser": "10.x" + }, + "dependencies": { + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "ts-loader": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.3.2.tgz", + "integrity": "sha512-TPeXFkdPjOrVEawY4xUgRnzlHEmKQF1DclJghPGq67jKnroVvs6mEGHWYtbUczgeWTvTaqUjSSaMmp1k5do4vw==", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.0.2", + "micromatch": "^3.1.4", + "semver": "^5.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "requires": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "tsconfig-paths": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.8.0.tgz", + "integrity": "sha512-zZEYFo4sjORK8W58ENkRn9s+HmQFkkwydDG7My5s/fnfr2YYCaiyXe/HBUcIgU8epEKOXwiahOO+KZYjiXlWyQ==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "deepmerge": "^2.0.1", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "tsconfig-paths-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-S/gOOPOkV8rIL4LurZ1vUdYCVgo15iX9ZMJ6wx6w2OgcpT/G4wMyHB6WM+xheSqGMrWKuxFul+aXpCju3wmj/g==", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "tsconfig-paths": "^3.4.0" + } + }, + "tslib": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.2.tgz", + "integrity": "sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw==" + }, + "tslint": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", + "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", + "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.27.2" + } + }, + "tslint-config-prettier": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.15.0.tgz", + "integrity": "sha512-06CgrHJxJmNYVgsmeMoa1KXzQRoOdvfkqnJth6XUkNeOz707qxN0WfxfhYwhL5kXHHbYJRby2bqAPKwThlZPhw==", + "dev": true + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tty": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tty/-/tty-1.0.1.tgz", + "integrity": "sha1-5ECayYsN0cULWf846G6sPwdk7kU=" + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.0.tgz", + "integrity": "sha512-fg3sfdDdJDtdHLUpeGsf/fLyG1aapk6zgFiYG5+MDUPybGrJemH4SLk5tP7hGRe8ntxjg0q5LYW53b6YpJIQ9Q==" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "~1.33.0" + } + } + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", + "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==" + }, + "ua-parser-js": { + "version": "0.7.17", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", + "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==" + }, + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "dev": true, + "requires": { + "commander": "~2.17.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "underscore": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", + "dev": true + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz", + "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", + "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==", + "dev": true + }, + "unified": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz", + "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "@types/vfile": "^3.0.0", + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^3.0.0", + "x-is-string": "^0.1.0" + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unique-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unist-util-stringify-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==", + "dev": true + }, + "universal-cookie": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-2.1.2.tgz", + "integrity": "sha512-F/rsGtceIw9hR5cHCckluI2wO2CmEe4hb3jGC+EJ+1feeFmc5byaenW/1Cg/bUggJ11qNFSTVqnocP5Y0HwNeg==", + "requires": { + "cookie": "^0.3.1", + "object-assign": "^4.1.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" + }, + "upper-case-first": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz", + "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=", + "requires": { + "upper-case": "^1.1.1" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-join": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", + "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=" + }, + "url-loader": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", + "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "url-parse": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz", + "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==", + "dev": true, + "requires": { + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "^2.0.0" + }, + "dependencies": { + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + } + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, + "urllite": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/urllite/-/urllite-0.5.0.tgz", + "integrity": "sha1-G3u5yj+w25Ug3hE0ZrvPfMNBRRo=", + "requires": { + "xtend": "~4.0.0" + } + }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "use-force-update": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/use-force-update/-/use-force-update-1.0.4.tgz", + "integrity": "sha512-/tF1kH4p4KwuJeA9De0hzPXi48JTk9fEwlBnZ8fUOTcDYwKuLiMPVOFrN0RzbcKLgcVog/74kTRCiHfu93ju+g==" + }, + "use-react-router": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/use-react-router/-/use-react-router-1.0.4.tgz", + "integrity": "sha512-KYtW6OxvdqQYO2jINUHH0f8ax4dHTbLj7sqFlUPQosG64tVhmFvjEsLC1p91g7/L6nKQ4R+tslc9X+WKCDULdA==", + "requires": { + "use-force-update": "^1.0.4" + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", + "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "^1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "value-equal": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz", + "integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "velocity-animate": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/velocity-animate/-/velocity-animate-1.5.2.tgz", + "integrity": "sha512-m6EXlCAMetKztO1ppBhGU1/1MR3IiEevO6ESq6rcrSQ3Q77xYSW13jkfXW88o4xMrkXJhy/U7j4wFR/twMB0Eg==", + "dev": true + }, + "velocity-react": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/velocity-react/-/velocity-react-1.4.1.tgz", + "integrity": "sha512-ZyXBm+9C/6kNUNyc+aeNKEhtTu/Mn+OfpsNBGuTxU8S2DUcis/KQL0rTN6jWL+7ygdOrun18qhheNZTA7YERmg==", + "dev": true, + "requires": { + "lodash": "^4.17.5", + "prop-types": "^15.5.8", + "react-transition-group": "^2.0.0", + "velocity-animate": "^1.4.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz", + "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==", + "dev": true, + "requires": { + "is-buffer": "^2.0.0", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + } + } + }, + "vfile-message": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", + "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", + "dev": true, + "requires": { + "unist-util-stringify-position": "^1.1.1" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "vscode-jsonrpc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz", + "integrity": "sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==" + }, + "vscode-languageserver": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-5.2.1.tgz", + "integrity": "sha512-GuayqdKZqAwwaCUjDvMTAVRPJOp/SLON3mJ07eGsx/Iq9HjRymhKWztX41rISqDKhHVVyFM+IywICyZDla6U3A==", + "requires": { + "vscode-languageserver-protocol": "3.14.1", + "vscode-uri": "^1.0.6" + } + }, + "vscode-languageserver-protocol": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz", + "integrity": "sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==", + "requires": { + "vscode-jsonrpc": "^4.0.0", + "vscode-languageserver-types": "3.14.0" + } + }, + "vscode-languageserver-types": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz", + "integrity": "sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A==" + }, + "vscode-uri": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.6.tgz", + "integrity": "sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww==" + }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.x" + } + }, + "warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + }, + "dependencies": { + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true + } + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + } + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "web-namespaces": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.2.tgz", + "integrity": "sha512-II+n2ms4mPxK+RnIxRPOw3zwF2jRscdJIUE9BfkKHm4FYEg9+biIoTMnaZF5MpemE3T+VhMLrhbyD4ilkPCSbg==", + "dev": true + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "webpack": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.27.0.tgz", + "integrity": "sha512-y77EQNIlsB9fUGgpLv/ZzmH+Yd9DgyIF9omX9RFavR5ZFM6HxFm6sqkbBXYxpjbKej9K6hD+Y8qEVg2rWdI2gg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/wasm-edit": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "acorn": "^5.6.2", + "acorn-dynamic-import": "^3.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^1.0.0", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.0", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", + "mkdirp": "~0.5.0", + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^0.4.4", + "tapable": "^1.1.0", + "terser-webpack-plugin": "^1.1.0", + "watchpack": "^1.5.0", + "webpack-sources": "^1.3.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "ajv": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", + "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "tapable": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", + "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==", + "dev": true + }, + "webpack-sources": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "webpack-bundle-tracker": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/webpack-bundle-tracker/-/webpack-bundle-tracker-0.3.0.tgz", + "integrity": "sha512-I0Gwkug8QX8xZS14SvmfWin1AmZDoZp/0AGvlgKqNxyw20DgkFkq1jTQ/Ml73YgjFTmQ5bATyQM7TjtYMP1nFA==", + "dev": true, + "requires": { + "deep-extend": "^0.4.1", + "mkdirp": "^0.5.1", + "strip-ansi": "^2.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=", + "dev": true + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "strip-ansi": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", + "dev": true, + "requires": { + "ansi-regex": "^1.0.0" + } + } + } + }, + "webpack-cli": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.1.2.tgz", + "integrity": "sha512-Cnqo7CeqeSvC6PTdts+dywNi5CRlIPbLx1AoUPK2T6vC1YAugMG3IOoO9DmEscd+Dghw7uRlnzV1KwOe5IrtgQ==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.0", + "global-modules-path": "^2.3.0", + "import-local": "^2.0.0", + "interpret": "^1.1.0", + "loader-utils": "^1.1.0", + "supports-color": "^5.5.0", + "v8-compile-cache": "^2.0.2", + "yargs": "^12.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", + "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz", + "integrity": "sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==", + "dev": true, + "requires": { + "memory-fs": "~0.4.1", + "mime": "^2.3.1", + "range-parser": "^1.0.3", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + } + } + }, + "webpack-dev-server": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.7.2.tgz", + "integrity": "sha512-mjWtrKJW2T9SsjJ4/dxDC2fkFVUw8jlpemDERqV0ZJIkjjjamR2AbQlr3oz+j4JLhYCHImHnXZK5H06P2wvUew==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.6", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.2.1", + "http-proxy-middleware": "^0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "killable": "^1.0.1", + "loglevel": "^1.6.3", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.20", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.4", + "semver": "^6.1.1", + "serve-index": "^1.9.1", + "sockjs": "0.3.19", + "sockjs-client": "1.3.0", + "spdy": "^4.0.0", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.0", + "webpack-log": "^2.0.0", + "yargs": "12.0.5" + }, + "dependencies": { + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "dev": true, + "requires": { + "original": "^1.0.0" + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ipaddr.js": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, + "requires": { + "mime-db": "1.40.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "proxy-addr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", + "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", + "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==", + "dev": true + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "sockjs-client": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", + "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==", + "dev": true, + "requires": { + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "webpack-dev-middleware": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz", + "integrity": "sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.2", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "dev": true + } + } + } + } + }, + "webpack-hot-middleware": { + "version": "2.24.3", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.24.3.tgz", + "integrity": "sha512-pPlmcdoR2Fn6UhYjAhp1g/IJy1Yc9hD+T6O9mjRcWV2pFbBjIFoJXhP0CoD0xPOhWJuWXuZXGBga9ybbOdzXpg==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "html-entities": "^1.2.0", + "querystring": "^0.2.0", + "strip-ansi": "^3.0.0" + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + } + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "whatwg-fetch": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", + "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=" + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "requires": { + "string-width": "^1.0.2" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "widest-line": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz", + "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", + "dev": true, + "requires": { + "string-width": "^2.1.1" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "worker-farm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=", + "dev": true + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", + "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", + "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^1.1.0" + } + }, + "os-locale": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", + "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", + "dev": true, + "requires": { + "execa": "^0.10.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", + "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", + "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "dev": true + } + } + }, + "yarn": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.15.2.tgz", + "integrity": "sha512-DhqaGe2FcYKduO42d2hByXk7y8k2k42H3uzYdWBMTvcNcgWKx7xCkJWsVAQikXvaEQN2GyJNrz8CboqUmaBRrw==" + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=" + }, + "zen-observable": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.11.tgz", + "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==" + }, + "zen-observable-ts": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.12.tgz", + "integrity": "sha512-wwqbD6K6CqDd1T67UFg4hgDqnu2YAnFJDCPYmwN/N6Yfa+2QgoSp+nJomh+FWUdOc1A+553/ElvfoW8Vc/vsLg==", + "requires": { + "zen-observable": "^0.8.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..3ed7dec43 --- /dev/null +++ b/package.json @@ -0,0 +1,177 @@ +{ + "name": "saleor", + "version": "0.0.0", + "main": "Gruntfile.js", + "repository": { + "type": "git", + "url": "git://github.com/mirumee/saleor-dashboard.git" + }, + "author": "Mirumee Software", + "license": "BSD-3-Clause", + "bugs": { + "url": "https://github.com/mirumee/saleor-dashboard/issues" + }, + "homepage": "http://getsaleor.com/", + "engines": { + "node": ">=10.6.0", + "npm": ">=6.1.0" + }, + "dependencies": { + "@material-ui/core": "^3.9.3", + "@material-ui/icons": "^3.0.1", + "@material-ui/styles": "^3.0.0-alpha.10", + "@types/classnames": "^2.2.6", + "@types/enzyme": "^3.1.15", + "@types/fuzzaldrin": "^2.1.1", + "@types/moment-timezone": "^0.5.9", + "@types/react-dropzone": "^4.2.2", + "@types/react-helmet": "^5.0.7", + "@types/react-infinite-scroller": "^1.2.0", + "@types/react-sortable-tree": "^0.3.6", + "@types/storybook__addon-storyshots": "^3.4.3", + "@types/string-similarity": "^1.2.0", + "@types/url-join": "^0.8.2", + "apollo": "^2.8.1", + "apollo-cache-inmemory": "^1.3.11", + "apollo-client": "^2.4.7", + "apollo-client-preset": "^1.0.6", + "apollo-link": "^1.2.5", + "apollo-link-batch-http": "^1.2.5", + "apollo-link-context": "^1.0.10", + "apollo-link-error": "^1.1.2", + "apollo-upload-client": "^9.1.0", + "classnames": "^2.2.6", + "crc-32": "^1.2.0", + "downshift": "^1.31.14", + "draft-js": "^0.10.5", + "draftail": "^1.1.0", + "draftjs-to-html": "^0.8.4", + "fast-array-diff": "^0.2.0", + "fuzzaldrin": "^2.1.0", + "graphql": "^14.0.2", + "graphql-tag": "^2.10.0", + "i18next": "^11.2.2", + "i18next-browser-languagedetector": "^2.2.0", + "i18next-xhr-backend": "^1.5.1", + "is-url": "^1.2.4", + "keycode": "^2.2.0", + "lodash": "^4.17.11", + "moment-timezone": "^0.5.21", + "qs": "^6.5.2", + "react": "^16.8.3", + "react-apollo": "^2.5.1", + "react-dom": "^16.8.3", + "react-dropzone": "^8.0.3", + "react-helmet": "^5.2.0", + "react-infinite-scroller": "^1.2.4", + "react-inlinesvg": "^0.8.1", + "react-jss": "^8.4.0", + "react-moment": "^0.7.7", + "react-router": "^5.0.0", + "react-router-dom": "^5.0.0", + "react-router-navigation-prompt": "^1.8.2", + "react-sortable-hoc": "^0.6.8", + "react-sortable-tree": "^2.6.2", + "react-svg": "^2.2.11", + "slugify": "^1.3.4", + "string-similarity": "^1.2.0", + "typescript": "^3.2.2", + "universal-cookie": "^2.1.2", + "url-join": "^4.0.0", + "use-react-router": "^1.0.4" + }, + "devDependencies": { + "@babel/core": "^7.2.0", + "@babel/plugin-proposal-class-properties": "^7.2.1", + "@babel/plugin-proposal-decorators": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.2.0", + "@babel/preset-env": "^7.2.0", + "@babel/preset-react": "^7.0.0", + "@babel/runtime": "^7.2.0", + "@storybook/addon-storyshots": "^4.1.4", + "@storybook/react": "^4.1.4", + "@types/draft-js": "^0.10.27", + "@types/i18next": "^8.4.3", + "@types/jest": "^23.3.1", + "@types/react": "^16.8.6", + "@types/react-dom": "^16.8.2", + "@types/react-router-dom": "^4.2.6", + "@types/react-test-renderer": "^16.8.1", + "@types/storybook__react": "^4.0.0", + "babel-core": "^7.0.0-bridge.0", + "babel-jest": "^23.6.0", + "babel-loader": "^8.0.4", + "enzyme": "^3.7.0", + "enzyme-adapter-react-16": "^1.7.0", + "enzyme-to-json": "^3.3.5", + "file-loader": "^1.1.11", + "fork-ts-checker-webpack-plugin": "^0.5.2", + "fsevents": "^1.2.9", + "html-webpack-plugin": "^3.2.0", + "jest": "^24.7.1", + "jest-file": "^1.0.0", + "plop": "^2.2.0", + "react-test-renderer": "^16.8.6", + "regenerator-runtime": "^0.11.1", + "ts-jest": "^23.10.5", + "ts-loader": "^5.3.2", + "tsconfig-paths-webpack-plugin": "^3.2.0", + "tslint": "^5.11.0", + "tslint-config-prettier": "^1.15.0", + "webpack": "^4.27.0", + "webpack-bundle-tracker": "^0.3.0", + "webpack-cli": "^3.1.2", + "webpack-dev-server": "^3.7.2" + }, + "babel": { + "presets": [ + "@babel/preset-env", + "@babel/preset-react" + ], + "plugins": [ + "@babel/plugin-proposal-class-properties", + [ + "@babel/plugin-proposal-decorators", + { + "decoratorsBeforeExport": true + } + ], + "@babel/plugin-proposal-object-rest-spread" + ] + }, + "jest": { + "globals": { + "ts-jest": { + "tsConfig": "tsconfig.json" + } + }, + "transform": { + "^.+\\.tsx?$": "ts-jest", + "^.+\\.(png|svg|jpe?g)$": "jest-file" + }, + "testRegex": ".*\\.test\\.tsx?$", + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "jsx", + "json", + "node" + ], + "moduleNameMapper": { + "@assets(.*)$": "/assets/$1", + "@saleor(.*)$": "/src/$1" + } + }, + "scripts": { + "build": "webpack -p", + "build-types": "apollo client:codegen --target=typescript types --globalTypesFile=src/types/globalTypes.ts", + "generate-component": "plop --plopfile .plop/plopfile.js", + "lint": "tslint 'src/**/*.{ts,tsx}'", + "lint-fix": "tslint 'src/**/*.{ts,tsx}' --fix", + "start": "webpack-dev-server --open", + "storybook": "start-storybook -p 3000 -c src/storybook/", + "build-storybook": "build-storybook -c src/storybook/ -o storybook", + "test": "jest src/" + } +} diff --git a/src/Baseline.tsx b/src/Baseline.tsx new file mode 100644 index 000000000..5babc7ade --- /dev/null +++ b/src/Baseline.tsx @@ -0,0 +1,16 @@ +import CssBaseline from "@material-ui/core/CssBaseline"; +import { createStyles, withStyles } from "@material-ui/core/styles"; +import * as React from "react"; + +const styles = createStyles({ + "@global": { + "@import": "url('https://rsms.me/inter/inter.css')" + } +}); + +const Baseline = withStyles(styles, { + name: "Baseline" +})(() => ); +Baseline.displayName = "Baseline"; + +export default Baseline; diff --git a/src/NotFound.tsx b/src/NotFound.tsx new file mode 100644 index 000000000..075e7d4d7 --- /dev/null +++ b/src/NotFound.tsx @@ -0,0 +1,11 @@ +import * as React from "react"; + +import NotFoundPage from "./components/NotFoundPage"; +import useNavigator from "./hooks/useNavigator"; + +export const NotFound: React.StatelessComponent = () => { + const navigate = useNavigator(); + + return navigate("/")} />; +}; +export default NotFound; diff --git a/src/auth/AuthProvider.tsx b/src/auth/AuthProvider.tsx new file mode 100644 index 000000000..64da58a5c --- /dev/null +++ b/src/auth/AuthProvider.tsx @@ -0,0 +1,135 @@ +import * as React from "react"; + +import { getMutationProviderData } from "../misc"; +import { PartialMutationProviderOutput } from "../types"; +import { getAuthToken, removeAuthToken, setAuthToken, UserContext } from "./"; +import { TypedTokenAuthMutation, TypedVerifyTokenMutation } from "./mutations"; +import { TokenAuth, TokenAuthVariables } from "./types/TokenAuth"; +import { User } from "./types/User"; +import { VerifyToken, VerifyTokenVariables } from "./types/VerifyToken"; + +interface AuthProviderOperationsProps { + children: ( + props: { + hasToken: boolean; + isAuthenticated: boolean; + tokenAuthLoading: boolean; + tokenVerifyLoading: boolean; + user: User; + } + ) => React.ReactNode; +} +const AuthProviderOperations: React.StatelessComponent< + AuthProviderOperationsProps +> = ({ children }) => { + return ( + + {(...tokenAuth) => ( + + {(...tokenVerify) => ( + + {children} + + )} + + )} + + ); +}; + +interface AuthProviderProps { + children: ( + props: { + hasToken: boolean; + isAuthenticated: boolean; + tokenAuthLoading: boolean; + tokenVerifyLoading: boolean; + user: User; + } + ) => React.ReactNode; + tokenAuth: PartialMutationProviderOutput; + tokenVerify: PartialMutationProviderOutput; +} + +interface AuthProviderState { + user: User; + persistToken: boolean; +} + +class AuthProvider extends React.Component< + AuthProviderProps, + AuthProviderState +> { + constructor(props) { + super(props); + this.state = { user: undefined, persistToken: false }; + } + + componentWillReceiveProps(props: AuthProviderProps) { + const { tokenAuth, tokenVerify } = props; + if (tokenAuth.opts.error || tokenVerify.opts.error) { + this.logout(); + } + if (tokenAuth.opts.data) { + const user = tokenAuth.opts.data.tokenCreate.user; + // FIXME: Now we set state also when auth fails and returned user is + // `null`, because the LoginView uses this `null` to display error. + this.setState({ user }); + if (user) { + setAuthToken( + tokenAuth.opts.data.tokenCreate.token, + this.state.persistToken + ); + } + } else { + if (tokenVerify.opts.data && tokenVerify.opts.data.tokenVerify.user) { + const user = tokenVerify.opts.data.tokenVerify.user; + this.setState({ user }); + } + } + } + + componentDidMount() { + const { user } = this.state; + const { tokenVerify } = this.props; + const token = getAuthToken(); + if (!!token && !user) { + tokenVerify.mutate({ token }); + } + } + + login = (email: string, password: string, persistToken: boolean) => { + const { tokenAuth } = this.props; + this.setState({ persistToken }); + tokenAuth.mutate({ email, password }); + }; + + logout = () => { + this.setState({ user: undefined }); + removeAuthToken(); + }; + + render() { + const { children, tokenAuth, tokenVerify } = this.props; + const { user } = this.state; + const isAuthenticated = !!user; + return ( + + {children({ + hasToken: !!getAuthToken(), + isAuthenticated, + tokenAuthLoading: tokenAuth.opts.loading, + tokenVerifyLoading: tokenVerify.opts.loading, + user + })} + + ); + } +} + +export default AuthProviderOperations; diff --git a/src/auth/components/LoginLoading/LoginLoading.tsx b/src/auth/components/LoginLoading/LoginLoading.tsx new file mode 100644 index 000000000..99ad30b76 --- /dev/null +++ b/src/auth/components/LoginLoading/LoginLoading.tsx @@ -0,0 +1,21 @@ +import CircularProgress from "@material-ui/core/CircularProgress"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import * as React from "react"; + +const styles = createStyles({ + root: { + alignItems: "center", + display: "flex", + height: "100vh", + justifyContent: "center" + } +}); +const LoginLoading = withStyles(styles, { name: "LoginLoading" })( + ({ classes }: WithStyles) => ( +
+ +
+ ) +); +LoginLoading.displayName = "LoginLoading"; +export default LoginLoading; diff --git a/src/auth/components/LoginLoading/index.ts b/src/auth/components/LoginLoading/index.ts new file mode 100644 index 000000000..eaeb4c412 --- /dev/null +++ b/src/auth/components/LoginLoading/index.ts @@ -0,0 +1,2 @@ +export { default } from "./LoginLoading"; +export * from "./LoginLoading"; diff --git a/src/auth/components/LoginPage/LoginPage.tsx b/src/auth/components/LoginPage/LoginPage.tsx new file mode 100644 index 000000000..42860b4ea --- /dev/null +++ b/src/auth/components/LoginPage/LoginPage.tsx @@ -0,0 +1,201 @@ +import Button from "@material-ui/core/Button"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; +import SVG from "react-inlinesvg"; + +import * as backgroundArt from "@assets/images/login-background.svg"; +import * as saleorDarkLogo from "@assets/images/logo-dark.svg"; +import * as saleorLightLogo from "@assets/images/logo-light.svg"; +import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; +import Form from "@saleor/components/Form"; +import { FormSpacer } from "@saleor/components/FormSpacer"; +import useTheme from "@saleor/hooks/useTheme"; +import i18n from "../../../i18n"; + +export interface FormData { + email: string; + loading: boolean; + password: string; + rememberMe: boolean; +} + +const styles = (theme: Theme) => + createStyles({ + buttonContainer: { + display: "flex", + justifyContent: "space-between" + }, + link: { + color: theme.palette.primary.main, + cursor: "pointer", + textAlign: "center" + }, + loginButton: { + width: 140 + }, + logo: { + "& svg": { + display: "block", + height: 40, + marginBottom: theme.spacing.unit * 4 + } + }, + mainPanel: { + [theme.breakpoints.down("sm")]: { + padding: theme.spacing.unit * 2 + }, + background: theme.palette.background.paper, + display: "flex", + flexDirection: "column", + height: "100vh", + justifyContent: "center", + padding: theme.spacing.unit * 6, + width: "100%" + }, + mainPanelContent: { + [theme.breakpoints.up("xs")]: { + width: "100%" + }, + [theme.breakpoints.up("sm")]: { + width: 328 + }, + "@media (min-width: 1440px)": { + width: 464 + }, + margin: "auto", + width: "100%" + }, + panel: { + "& span": { + color: theme.palette.error.contrastText + }, + background: theme.palette.error.main, + borderRadius: theme.spacing.unit, + marginBottom: theme.spacing.unit * 3, + padding: theme.spacing.unit * 1.5 + }, + root: { + [theme.breakpoints.up("lg")]: { + gridTemplateColumns: "376px 1fr" + }, + "@media (min-width: 1440px)": { + gridTemplateColumns: "520px 1fr" + }, + display: "grid", + gridTemplateColumns: "1fr", + height: "100vh", + overflow: "hidden", + width: "100vw" + }, + sidebar: { + [theme.breakpoints.up("lg")]: { + display: "block" + }, + display: "none" + }, + sidebarArt: { + "& svg": { + width: "100%" + } + } + }); + +export interface LoginCardProps extends WithStyles { + error: boolean; + disableLoginButton: boolean; + onPasswordRecovery: () => void; + onSubmit?(event: FormData); +} + +const LoginCard = withStyles(styles, { name: "LoginCard" })( + ({ classes, error, disableLoginButton, onSubmit }: LoginCardProps) => { + const { isDark } = useTheme(); + + return ( +
+ {({ change: handleChange, data, submit: handleSubmit }) => ( +
+
+ +
+
+
+ + {error && ( +
+ Please try again." + ) + }} + /> +
+ )} + + + + +
+ + + +
+ {/* + + {i18n.t("Reset your password")} + */} +
+
+
+ )} +
+ ); + } +); +LoginCard.displayName = "LoginCard"; +export default LoginCard; diff --git a/src/auth/components/LoginPage/index.ts b/src/auth/components/LoginPage/index.ts new file mode 100644 index 000000000..358f81bd4 --- /dev/null +++ b/src/auth/components/LoginPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./LoginPage"; +export * from "./LoginPage"; diff --git a/src/auth/components/SectionRoute.tsx b/src/auth/components/SectionRoute.tsx new file mode 100644 index 000000000..c5c97d315 --- /dev/null +++ b/src/auth/components/SectionRoute.tsx @@ -0,0 +1,34 @@ +import * as React from "react"; +import { Route, RouteProps } from "react-router-dom"; + +import AppLayout from "@saleor/components/AppLayout"; +import { UserContext } from ".."; +import NotFound from "../../NotFound"; +import { PermissionEnum } from "../../types/globalTypes"; +import { hasPermission } from "../misc"; + +interface SectionRouteProps extends RouteProps { + permissions?: PermissionEnum[]; +} + +export const SectionRoute: React.StatelessComponent = ({ + permissions, + ...props +}) => ( + + {({ user }) => + !permissions || + permissions + .map(permission => hasPermission(permission, user)) + .reduce((prev, curr) => prev && curr) ? ( + + + + ) : ( + + ) + } + +); +SectionRoute.displayName = "Route"; +export default SectionRoute; diff --git a/src/auth/index.tsx b/src/auth/index.tsx new file mode 100644 index 000000000..a38347d30 --- /dev/null +++ b/src/auth/index.tsx @@ -0,0 +1,30 @@ +import * as React from "react"; + +import { User } from "./types/User"; + +const TOKEN_STORAGE_KEY = "dashboardAuth"; + +interface UserContext { + login: (username: string, password: string, persist: boolean) => void; + logout: () => void; + user?: User; +} + +export const UserContext = React.createContext({ + login: undefined, + logout: undefined +}); + +export const getAuthToken = () => + localStorage.getItem(TOKEN_STORAGE_KEY) || + sessionStorage.getItem(TOKEN_STORAGE_KEY); + +export const setAuthToken = (token: string, persist: boolean) => + persist + ? localStorage.setItem(TOKEN_STORAGE_KEY, token) + : sessionStorage.setItem(TOKEN_STORAGE_KEY, token); + +export const removeAuthToken = () => { + localStorage.removeItem(TOKEN_STORAGE_KEY); + sessionStorage.removeItem(TOKEN_STORAGE_KEY); +}; diff --git a/src/auth/misc.ts b/src/auth/misc.ts new file mode 100644 index 000000000..497d8a650 --- /dev/null +++ b/src/auth/misc.ts @@ -0,0 +1,5 @@ +import { PermissionEnum } from '../types/globalTypes' +import { User } from "./types/User"; + +export const hasPermission = (permission: PermissionEnum, user: User) => + user.permissions.map(perm => perm.code).includes(permission); diff --git a/src/auth/mutations.ts b/src/auth/mutations.ts new file mode 100644 index 000000000..8d4007ba7 --- /dev/null +++ b/src/auth/mutations.ts @@ -0,0 +1,58 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { TokenAuth, TokenAuthVariables } from "./types/TokenAuth"; +import { VerifyToken, VerifyTokenVariables } from "./types/VerifyToken"; + +export const fragmentUser = gql` + fragment User on User { + id + email + firstName + lastName + isStaff + note + permissions { + code + name + } + } +`; + +export const tokenAuthMutation = gql` + ${fragmentUser} + mutation TokenAuth($email: String!, $password: String!) { + tokenCreate(email: $email, password: $password) { + token + errors { + field + message + } + user { + ...User + } + } + } +`; + +export const TypedTokenAuthMutation = TypedMutation< + TokenAuth, + TokenAuthVariables +>(tokenAuthMutation); + +export const tokenVerifyMutation = gql` + ${fragmentUser} + mutation VerifyToken($token: String!) { + tokenVerify(token: $token) { + payload + user { + ...User + } + } + } +`; + +export const TypedVerifyTokenMutation = TypedMutation< + VerifyToken, + VerifyTokenVariables +>(tokenVerifyMutation); diff --git a/src/auth/types/TokenAuth.ts b/src/auth/types/TokenAuth.ts new file mode 100644 index 000000000..a282edc47 --- /dev/null +++ b/src/auth/types/TokenAuth.ts @@ -0,0 +1,48 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: TokenAuth +// ==================================================== + +export interface TokenAuth_tokenCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface TokenAuth_tokenCreate_user_permissions { + __typename: "PermissionDisplay"; + code: PermissionEnum; + name: string; +} + +export interface TokenAuth_tokenCreate_user { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + isStaff: boolean; + note: string | null; + permissions: (TokenAuth_tokenCreate_user_permissions | null)[] | null; +} + +export interface TokenAuth_tokenCreate { + __typename: "CreateToken"; + token: string | null; + errors: (TokenAuth_tokenCreate_errors | null)[]; + user: TokenAuth_tokenCreate_user | null; +} + +export interface TokenAuth { + tokenCreate: TokenAuth_tokenCreate | null; +} + +export interface TokenAuthVariables { + email: string; + password: string; +} diff --git a/src/auth/types/User.ts b/src/auth/types/User.ts new file mode 100644 index 000000000..6027f7f82 --- /dev/null +++ b/src/auth/types/User.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: User +// ==================================================== + +export interface User_permissions { + __typename: "PermissionDisplay"; + code: PermissionEnum; + name: string; +} + +export interface User { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + isStaff: boolean; + note: string | null; + permissions: (User_permissions | null)[] | null; +} diff --git a/src/auth/types/VerifyToken.ts b/src/auth/types/VerifyToken.ts new file mode 100644 index 000000000..52dc496a4 --- /dev/null +++ b/src/auth/types/VerifyToken.ts @@ -0,0 +1,40 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: VerifyToken +// ==================================================== + +export interface VerifyToken_tokenVerify_user_permissions { + __typename: "PermissionDisplay"; + code: PermissionEnum; + name: string; +} + +export interface VerifyToken_tokenVerify_user { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + isStaff: boolean; + note: string | null; + permissions: (VerifyToken_tokenVerify_user_permissions | null)[] | null; +} + +export interface VerifyToken_tokenVerify { + __typename: "VerifyToken"; + payload: any | null; + user: VerifyToken_tokenVerify_user | null; +} + +export interface VerifyToken { + tokenVerify: VerifyToken_tokenVerify | null; +} + +export interface VerifyTokenVariables { + token: string; +} diff --git a/src/auth/views/Login.tsx b/src/auth/views/Login.tsx new file mode 100644 index 000000000..508f4e8c9 --- /dev/null +++ b/src/auth/views/Login.tsx @@ -0,0 +1,27 @@ +import * as React from "react"; + +import LoginPage, { FormData } from "../components/LoginPage"; +import { UserContext } from "../index"; + +interface LoginViewProps { + loading: boolean; +} + +const LoginView: React.StatelessComponent = ({ loading }) => ( + + {({ login, user }) => { + const handleSubmit = (data: FormData) => + login(data.email, data.password, data.rememberMe); + return ( + + ); + }} + +); +LoginView.displayName = "LoginView"; +export default LoginView; diff --git a/src/categories/components/CategoryBackground/CategoryBackground.tsx b/src/categories/components/CategoryBackground/CategoryBackground.tsx new file mode 100644 index 000000000..a90674bdc --- /dev/null +++ b/src/categories/components/CategoryBackground/CategoryBackground.tsx @@ -0,0 +1,133 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import CardTitle from "@saleor/components/CardTitle"; +import Hr from "@saleor/components/Hr"; +import ImageTile from "@saleor/components/ImageTile"; +import ImageUpload from "@saleor/components/ImageUpload"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { CategoryDetails_category_backgroundImage } from "../../types/CategoryDetails"; +import { FormData } from "../CategoryUpdatePage"; + +const styles = (theme: Theme) => + createStyles({ + fileField: { + display: "none" + }, + image: { + height: "100%", + objectFit: "contain", + userSelect: "none", + width: "100%" + }, + imageContainer: { + background: "#ffffff", + border: "1px solid #eaeaea", + borderRadius: theme.spacing.unit, + height: 148, + justifySelf: "start", + overflow: "hidden", + padding: theme.spacing.unit * 2, + position: "relative", + width: 148 + } + }); + +export interface CategoryBackgroundProps extends WithStyles { + data: FormData; + image: CategoryDetails_category_backgroundImage; + onChange: (event: React.ChangeEvent) => void; + onImageDelete: () => void; + onImageUpload: (file: File) => void; +} + +export const CategoryBackground = withStyles(styles)( + class CategoryBackgroundComponent extends React.Component< + CategoryBackgroundProps, + {} + > { + imgInputAnchor = React.createRef(); + + clickImgInput = () => this.imgInputAnchor.current.click(); + + render() { + const { + classes, + data, + onImageUpload, + image, + onChange, + onImageDelete + } = this.props; + return ( + + + + onImageUpload(event.target.files[0])} + type="file" + ref={this.imgInputAnchor} + /> + + } + /> + {image === undefined ? ( + +
+
+ +
+
+
+ ) : image === null ? ( + + ) : ( + + + + )} + + {image && ( + <> +
+ + + + + )} +
+ ); + } + } +); +CategoryBackground.displayName = "CategoryBackground"; +export default CategoryBackground; diff --git a/src/categories/components/CategoryBackground/index.ts b/src/categories/components/CategoryBackground/index.ts new file mode 100644 index 000000000..f5a59d0a3 --- /dev/null +++ b/src/categories/components/CategoryBackground/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CategoryBackground"; +export * from "./CategoryBackground"; diff --git a/src/categories/components/CategoryCreatePage/CategoryCreatePage.tsx b/src/categories/components/CategoryCreatePage/CategoryCreatePage.tsx new file mode 100644 index 000000000..0177f68e2 --- /dev/null +++ b/src/categories/components/CategoryCreatePage/CategoryCreatePage.tsx @@ -0,0 +1,92 @@ +import { ContentState, convertToRaw, RawDraftContentState } from "draft-js"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import { CardSpacer } from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import SeoForm from "@saleor/components/SeoForm"; +import i18n from "../../../i18n"; +import { UserError } from "../../../types"; +import CategoryDetailsForm from "../../components/CategoryDetailsForm"; + +interface FormData { + description: RawDraftContentState; + name: string; + seoTitle: string; + seoDescription: string; +} + +const initialData: FormData = { + description: convertToRaw(ContentState.createFromText("")), + name: "", + seoDescription: "", + seoTitle: "" +}; + +export interface CategoryCreatePageProps { + errors: UserError[]; + disabled: boolean; + saveButtonBarState: ConfirmButtonTransitionState; + onSubmit(data: FormData); + onBack(); +} + +export const CategoryCreatePage: React.StatelessComponent< + CategoryCreatePageProps +> = ({ + disabled, + onSubmit, + onBack, + errors: userErrors, + saveButtonBarState +}) => ( +
+ {({ data, change, errors, submit, hasChanged }) => ( + + {i18n.t("Categories")} + +
+ + + + +
+
+ )} +
+); +CategoryCreatePage.displayName = "CategoryCreatePage"; +export default CategoryCreatePage; diff --git a/src/categories/components/CategoryCreatePage/index.ts b/src/categories/components/CategoryCreatePage/index.ts new file mode 100644 index 000000000..1624a6ddb --- /dev/null +++ b/src/categories/components/CategoryCreatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CategoryCreatePage"; +export * from "./CategoryCreatePage"; diff --git a/src/categories/components/CategoryDeleteDialog/CategoryDeleteDialog.tsx b/src/categories/components/CategoryDeleteDialog/CategoryDeleteDialog.tsx new file mode 100644 index 000000000..0dd8a1e29 --- /dev/null +++ b/src/categories/components/CategoryDeleteDialog/CategoryDeleteDialog.tsx @@ -0,0 +1,65 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import i18n from "../../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + deleteButton: { + "&:hover": { + backgroundColor: theme.palette.error.main + }, + backgroundColor: theme.palette.error.main, + color: theme.palette.error.contrastText + } + }); + +export interface CategoryDeleteDialogProps extends WithStyles { + open: boolean; + name: string; + onClose(); + onConfirm(); +} + +const CategoryDeleteDialog = withStyles(styles, { + name: "CategoryDeleteDialog" +})(({ classes, name, open, onConfirm, onClose }: CategoryDeleteDialogProps) => ( + + {i18n.t("Delete category", { context: "title" })} + + {{name}}?", + { name } + ) + }} + /> + + + + + + +)); +CategoryDeleteDialog.displayName = "CategoryDeleteDialog"; +export default CategoryDeleteDialog; diff --git a/src/categories/components/CategoryDeleteDialog/index.ts b/src/categories/components/CategoryDeleteDialog/index.ts new file mode 100644 index 000000000..31957694a --- /dev/null +++ b/src/categories/components/CategoryDeleteDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CategoryDeleteDialog"; +export * from "./CategoryDeleteDialog"; diff --git a/src/categories/components/CategoryDetailsForm/CategoryDetailsForm.tsx b/src/categories/components/CategoryDetailsForm/CategoryDetailsForm.tsx new file mode 100644 index 000000000..74e41a6c3 --- /dev/null +++ b/src/categories/components/CategoryDetailsForm/CategoryDetailsForm.tsx @@ -0,0 +1,77 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import { RawDraftContentState } from "draft-js"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import FormSpacer from "@saleor/components/FormSpacer"; +import RichTextEditor from "@saleor/components/RichTextEditor"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { CategoryDetails_category } from "../../types/CategoryDetails"; + +const styles = createStyles({ + root: { + width: "50%" + } +}); + +interface CategoryDetailsFormProps extends WithStyles { + category?: CategoryDetails_category; + data: { + name: string; + description: RawDraftContentState; + }; + disabled: boolean; + errors: { [key: string]: string }; + onChange: (event: React.ChangeEvent) => void; +} + +export const CategoryDetailsForm = withStyles(styles, { + name: "CategoryDetailsForm" +})( + ({ + category, + classes, + disabled, + data, + onChange, + errors + }: CategoryDetailsFormProps) => { + return ( + + + + <> +
+ +
+ + JSON.parse(category.descriptionJson))} + name="description" + onChange={onChange} + /> + +
+
+ ); + } +); +CategoryDetailsForm.displayName = "CategoryDetailsForm"; +export default CategoryDetailsForm; diff --git a/src/categories/components/CategoryDetailsForm/index.ts b/src/categories/components/CategoryDetailsForm/index.ts new file mode 100644 index 000000000..33c5482ba --- /dev/null +++ b/src/categories/components/CategoryDetailsForm/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CategoryDetailsForm"; +export * from "./CategoryDetailsForm"; diff --git a/src/categories/components/CategoryList/CategoryList.tsx b/src/categories/components/CategoryList/CategoryList.tsx new file mode 100644 index 000000000..232509160 --- /dev/null +++ b/src/categories/components/CategoryList/CategoryList.tsx @@ -0,0 +1,190 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Checkbox from "@saleor/components/Checkbox"; +import Skeleton from "@saleor/components/Skeleton"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { renderCollection } from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colName: { + width: 840 + }, + colProducts: { + width: 160 + }, + colSubcategories: { + width: 160 + } + }, + colName: { + paddingLeft: "0 !important" + }, + colProducts: { + textAlign: "center" + }, + colSubcategories: { + textAlign: "center" + }, + tableRow: { + cursor: "pointer" + } + }); + +interface CategoryListProps + extends ListProps, + ListActions, + WithStyles { + categories?: Array<{ + id: string; + name: string; + children: { + totalCount: number; + }; + products: { + totalCount: number; + }; + }>; + isRoot: boolean; + onAdd?(); +} + +const CategoryList = withStyles(styles, { name: "CategoryList" })( + ({ + categories, + classes, + disabled, + isRoot, + pageInfo, + isChecked, + selected, + toggle, + toggleAll, + toolbar, + onAdd, + onNextPage, + onPreviousPage, + onRowClick + }: CategoryListProps) => ( + + {!isRoot && ( + + {i18n.t("Add subcategory")} + + } + /> + )} + + + + {i18n.t("Category Name", { context: "object" })} + + + {i18n.t("Subcategories", { context: "object" })} + + + {i18n.t("No. Products", { context: "object" }).replace(" ", "\xa0")} + + + + + + + + + {renderCollection( + categories, + category => { + const isSelected = category ? isChecked(category.id) : false; + + return ( + + + toggle(category.id)} + /> + + + {category && category.name ? category.name : } + + + {category && + category.children && + category.children.totalCount !== undefined ? ( + category.children.totalCount + ) : ( + + )} + + + {category && + category.products && + category.products.totalCount !== undefined ? ( + category.products.totalCount + ) : ( + + )} + + + ); + }, + () => ( + + + {isRoot + ? i18n.t("No categories found") + : i18n.t("No subcategories found")} + + + ) + )} + +
+
+ ) +); +CategoryList.displayName = "CategoryList"; +export default CategoryList; diff --git a/src/categories/components/CategoryList/index.ts b/src/categories/components/CategoryList/index.ts new file mode 100644 index 000000000..52c4017ff --- /dev/null +++ b/src/categories/components/CategoryList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CategoryList"; +export * from "./CategoryList"; diff --git a/src/categories/components/CategoryListPage/CategoryListPage.tsx b/src/categories/components/CategoryListPage/CategoryListPage.tsx new file mode 100644 index 000000000..38acf31eb --- /dev/null +++ b/src/categories/components/CategoryListPage/CategoryListPage.tsx @@ -0,0 +1,62 @@ +import Button from "@material-ui/core/Button"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { ListActions, PageListProps } from "../../../types"; +import CategoryList from "../CategoryList"; + +export interface CategoryTableProps extends PageListProps, ListActions { + categories: Array<{ + id: string; + name: string; + children: { + totalCount: number; + }; + products: { + totalCount: number; + }; + }>; +} + +export const CategoryListPage: React.StatelessComponent = ({ + categories, + disabled, + onAdd, + onNextPage, + onPreviousPage, + onRowClick, + pageInfo, + isChecked, + selected, + toggle, + toggleAll, + toolbar +}) => ( + + + + + + +); +CategoryListPage.displayName = "CategoryListPage"; +export default CategoryListPage; diff --git a/src/categories/components/CategoryListPage/index.ts b/src/categories/components/CategoryListPage/index.ts new file mode 100644 index 000000000..8f685bd64 --- /dev/null +++ b/src/categories/components/CategoryListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CategoryListPage"; +export * from "./CategoryListPage"; diff --git a/src/categories/components/CategoryProducts/CategoryProducts.tsx b/src/categories/components/CategoryProducts/CategoryProducts.tsx new file mode 100644 index 000000000..5f41d6f53 --- /dev/null +++ b/src/categories/components/CategoryProducts/CategoryProducts.tsx @@ -0,0 +1,136 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; + +const styles = (theme: Theme) => + createStyles({ + link: { + color: theme.palette.primary.main, + cursor: "pointer" + }, + textLeft: { + textAlign: "left" + } + }); + +interface ProductListProps extends WithStyles { + hasNextPage?: boolean; + hasPreviousPage?: boolean; + products?: Array<{ + id: string; + name: string; + productType: { + name: string; + }; + thumbnail: { + url: string; + }; + }>; + onAddProduct?(); + onNextPage?(); + onPreviousPage?(); + onRowClick?(id: string): () => void; +} + +export const ProductList = withStyles(styles, { name: "ProductList" })( + ({ + classes, + hasNextPage, + hasPreviousPage, + products, + onAddProduct, + onNextPage, + onPreviousPage, + onRowClick + }: ProductListProps) => ( + + + {i18n.t("Add product")} + + } + /> + + + + {(products === undefined || products.length > 0) && } + + {i18n.t("Name", { context: "object" })} + + {i18n.t("Type", { context: "object" })} + + + + + + + + + {renderCollection( + products, + product => ( + + product.thumbnail.url)} + /> + + {product ? ( + + {product.name} + + ) : ( + + )} + + + {product && product.productType ? ( + product.productType.name + ) : ( + + )} + + + ), + () => ( + + {i18n.t("No products found")} + + ) + )} + +
+
+ ) +); +ProductList.displayName = "CategoryProductList"; +export default ProductList; diff --git a/src/categories/components/CategoryProducts/index.ts b/src/categories/components/CategoryProducts/index.ts new file mode 100644 index 000000000..12cece4a6 --- /dev/null +++ b/src/categories/components/CategoryProducts/index.ts @@ -0,0 +1 @@ +export { default } from "./CategoryProducts"; diff --git a/src/categories/components/CategoryProductsCard/CategoryProductsCard.tsx b/src/categories/components/CategoryProductsCard/CategoryProductsCard.tsx new file mode 100644 index 000000000..ca0017123 --- /dev/null +++ b/src/categories/components/CategoryProductsCard/CategoryProductsCard.tsx @@ -0,0 +1,59 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import ProductList from "@saleor/components/ProductList"; +import i18n from "../../../i18n"; +import { ListActions, PageListProps } from "../../../types"; +import { CategoryDetails_category_products_edges_node } from "../../types/CategoryDetails"; + +interface CategoryProductsCardProps extends PageListProps, ListActions { + products: CategoryDetails_category_products_edges_node[]; + categoryName: string; +} + +export const CategoryProductsCard: React.StatelessComponent< + CategoryProductsCardProps +> = ({ + products, + disabled, + pageInfo, + onAdd, + onNextPage, + onPreviousPage, + onRowClick, + categoryName, + isChecked, + selected, + toggle, + toggleAll, + toolbar +}) => ( + + + {i18n.t("Add product")} + + } + /> + + +); + +CategoryProductsCard.displayName = "CategoryProductsCard"; +export default CategoryProductsCard; diff --git a/src/categories/components/CategoryProductsCard/index.ts b/src/categories/components/CategoryProductsCard/index.ts new file mode 100644 index 000000000..741d2b708 --- /dev/null +++ b/src/categories/components/CategoryProductsCard/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CategoryProductsCard"; +export * from "./CategoryProductsCard"; diff --git a/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx b/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx new file mode 100644 index 000000000..03d242a9f --- /dev/null +++ b/src/categories/components/CategoryUpdatePage/CategoryUpdatePage.tsx @@ -0,0 +1,219 @@ +import { RawDraftContentState } from "draft-js"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import { CardSpacer } from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import SeoForm from "@saleor/components/SeoForm"; +import { Tab, TabContainer } from "@saleor/components/Tab"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { TabListActions, UserError } from "../../../types"; +import CategoryDetailsForm from "../../components/CategoryDetailsForm"; +import CategoryList from "../../components/CategoryList"; +import { + CategoryDetails_category, + CategoryDetails_category_children_edges_node, + CategoryDetails_category_products_edges_node +} from "../../types/CategoryDetails"; +import CategoryBackground from "../CategoryBackground"; +import CategoryProductsCard from "../CategoryProductsCard"; + +export interface FormData { + backgroundImageAlt: string; + description: RawDraftContentState; + name: string; + seoTitle: string; + seoDescription: string; +} + +export enum CategoryPageTab { + categories = "categories", + products = "products" +} + +export interface CategoryUpdatePageProps + extends TabListActions<"productListToolbar" | "subcategoryListToolbar"> { + changeTab: (index: CategoryPageTab) => void; + currentTab: CategoryPageTab; + errors: UserError[]; + disabled: boolean; + category: CategoryDetails_category; + products: CategoryDetails_category_products_edges_node[]; + subcategories: CategoryDetails_category_children_edges_node[]; + pageInfo: { + hasNextPage: boolean; + hasPreviousPage: boolean; + }; + saveButtonBarState: ConfirmButtonTransitionState; + onImageDelete: () => void; + onSubmit: (data: FormData) => void; + onImageUpload(file: File); + onNextPage(); + onPreviousPage(); + onProductClick(id: string): () => void; + onAddProduct(); + onBack(); + onDelete(); + onAddCategory(); + onCategoryClick(id: string): () => void; +} + +const CategoriesTab = Tab(CategoryPageTab.categories); +const ProductsTab = Tab(CategoryPageTab.products); + +export const CategoryUpdatePage: React.StatelessComponent< + CategoryUpdatePageProps +> = ({ + changeTab, + currentTab, + category, + disabled, + errors: userErrors, + pageInfo, + products, + saveButtonBarState, + subcategories, + onAddCategory, + onAddProduct, + onBack, + onCategoryClick, + onDelete, + onNextPage, + onPreviousPage, + onProductClick, + onSubmit, + onImageDelete, + onImageUpload, + isChecked, + productListToolbar, + selected, + subcategoryListToolbar, + toggle, + toggleAll +}: CategoryUpdatePageProps) => { + const initialData: FormData = category + ? { + backgroundImageAlt: maybe(() => category.backgroundImage.alt, ""), + description: maybe(() => JSON.parse(category.descriptionJson)), + name: category.name || "", + seoDescription: category.seoDescription || "", + seoTitle: category.seoTitle || "" + } + : { + backgroundImageAlt: "", + description: "", + name: "", + seoDescription: "", + seoTitle: "" + }; + return ( +
+ {({ data, change, errors, submit, hasChanged }) => ( + + {i18n.t("Categories")} + + + + category.backgroundImage)} + onChange={change} + /> + + + + + + {i18n.t("Subcategories")} + + + {i18n.t("Products")} + + + + {currentTab === CategoryPageTab.categories && ( + + )} + {currentTab === CategoryPageTab.products && ( + category.name)} + products={products} + disabled={disabled} + pageInfo={pageInfo} + onNextPage={onNextPage} + onPreviousPage={onPreviousPage} + onRowClick={onProductClick} + onAdd={onAddProduct} + toggle={toggle} + toggleAll={toggleAll} + selected={selected} + isChecked={isChecked} + toolbar={productListToolbar} + /> + )} + + + )} +
+ ); +}; +CategoryUpdatePage.displayName = "CategoryUpdatePage"; +export default CategoryUpdatePage; diff --git a/src/categories/components/CategoryUpdatePage/index.ts b/src/categories/components/CategoryUpdatePage/index.ts new file mode 100644 index 000000000..0b5755ef7 --- /dev/null +++ b/src/categories/components/CategoryUpdatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CategoryUpdatePage"; +export * from "./CategoryUpdatePage"; diff --git a/src/categories/fixtures.ts b/src/categories/fixtures.ts new file mode 100644 index 000000000..f7621bfa9 --- /dev/null +++ b/src/categories/fixtures.ts @@ -0,0 +1,316 @@ +import { content } from "../storybook/stories/components/RichTextEditor"; +import { CategoryDetails_category } from "./types/CategoryDetails"; + +export const categories = [ + { + children: { + totalCount: 2 + }, + id: "123123", + name: "Lorem ipsum dolor", + products: { + totalCount: 4 + } + }, + { + children: { + totalCount: 54 + }, + id: "876752", + name: "Mauris vehicula tortor vulputate", + products: { + totalCount: 3 + } + }, + { + children: { + totalCount: 2 + }, + id: "876542", + name: "Excepteur sint occaecat cupidatat non proident", + products: { + totalCount: 6 + } + }, + { + children: { + totalCount: 6 + }, + id: "875352", + name: "Ut enim ad minim veniam", + products: { + totalCount: 12 + } + }, + { + children: { + totalCount: 76 + }, + id: "865752", + name: "Duis aute irure dolor in reprehenderit", + products: { + totalCount: 43 + } + }, + { + children: { + totalCount: 11 + }, + id: "878752", + name: "Neque porro quisquam est", + products: { + totalCount: 21 + } + } +]; +export const category: ( + placeholderImage: string +) => CategoryDetails_category = (placeholderImage: string) => ({ + __typename: "Category", + backgroundImage: { + __typename: "Image", + alt: "Alt text", + url: placeholderImage + }, + children: { + __typename: "CategoryCountableConnection", + edges: [] + }, + descriptionJson: JSON.stringify(content), + id: "Q2F0ZWdvcnk6NA==", + name: "Coffees", + parent: { + __typename: "Category", + id: "Q2F0ZWdvcnk6Mw==" + }, + products: { + __typename: "ProductCountableConnection", + edges: [ + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjA=", + node: { + __typename: "Product", + basePrice: { + __typename: "Money", + amount: 83.3, + currency: "USD" + }, + id: "UHJvZHVjdDoyMQ==", + isAvailable: true, + name: "Gardner-Schultz", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjE=", + node: { + __typename: "Product", + basePrice: { + __typename: "Money", + amount: 68.27, + currency: "USD" + }, + id: "UHJvZHVjdDoyMg==", + isAvailable: true, + name: "James, Martinez and Murray", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjI=", + node: { + __typename: "Product", + basePrice: { + __typename: "Money", + amount: 21.43, + currency: "USD" + }, + id: "UHJvZHVjdDoyMw==", + isAvailable: true, + name: "Curtis, Joyce and Turner", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjM=", + node: { + __typename: "Product", + basePrice: { + __typename: "Money", + amount: 62.76, + currency: "USD" + }, + id: "UHJvZHVjdDoyNA==", + isAvailable: true, + name: "Davis, Brown and Ray", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjQ=", + node: { + __typename: "Product", + basePrice: { + __typename: "Money", + amount: 7.13, + currency: "USD" + }, + id: "UHJvZHVjdDoyNQ==", + isAvailable: true, + name: "Gallegos Ltd", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjU=", + node: { + __typename: "Product", + basePrice: { + __typename: "Money", + amount: 48.82, + currency: "USD" + }, + id: "UHJvZHVjdDoyNg==", + isAvailable: true, + name: "Franklin Inc", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjY=", + node: { + __typename: "Product", + basePrice: { + __typename: "Money", + amount: 27.34, + currency: "USD" + }, + id: "UHJvZHVjdDoyNw==", + isAvailable: true, + name: "Williams-Taylor", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjc=", + node: { + __typename: "Product", + basePrice: { + __typename: "Money", + amount: 75.42, + currency: "USD" + }, + id: "UHJvZHVjdDoyOA==", + isAvailable: true, + name: "Riddle, Evans and Hicks", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjg=", + node: { + __typename: "Product", + basePrice: { + __typename: "Money", + amount: 86.62, + currency: "USD" + }, + id: "UHJvZHVjdDoyOQ==", + isAvailable: true, + name: "Hebert-Sherman", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjk=", + node: { + __typename: "Product", + basePrice: { + __typename: "Money", + amount: 48.66, + currency: "USD" + }, + id: "UHJvZHVjdDozMA==", + isAvailable: true, + name: "Carter and Sons", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + } + ], + pageInfo: { + __typename: "PageInfo", + endCursor: "YXJyYXljb25uZWN0aW9uOjk=", + hasNextPage: false, + hasPreviousPage: false, + startCursor: "YXJyYXljb25uZWN0aW9uOjA=" + } + }, + seoDescription: null, + seoTitle: null +}); +export const errors = [ + { + field: "name", + message: "To pole jest wymagane." + } +]; diff --git a/src/categories/index.tsx b/src/categories/index.tsx new file mode 100644 index 000000000..12af20f0a --- /dev/null +++ b/src/categories/index.tsx @@ -0,0 +1,71 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; +import { WindowTitle } from "../components/WindowTitle"; +import i18n from "../i18n"; +import { + categoryAddPath, + categoryListPath, + CategoryListUrlQueryParams, + categoryPath, + CategoryUrlQueryParams +} from "./urls"; +import { CategoryCreateView } from "./views/CategoryCreate"; +import CategoryDetailsView, { getActiveTab } from "./views/CategoryDetails"; +import CategoryListComponent from "./views/CategoryList"; + +interface CategoryDetailsRouteParams { + id: string; +} +const CategoryDetails: React.StatelessComponent< + RouteComponentProps +> = ({ location, match }) => { + const qs = parseQs(location.search.substr(1)); + const params: CategoryUrlQueryParams = { + ...qs, + activeTab: getActiveTab(qs.activeTab) + }; + return ( + + ); +}; + +interface CategoryCreateRouteParams { + id: string; +} +const CategoryCreate: React.StatelessComponent< + RouteComponentProps +> = ({ match }) => { + return ( + + ); +}; + +const CategoryList: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: CategoryListUrlQueryParams = qs; + return ; +}; + +const Component = () => ( + <> + + + + + + + + +); + +export default Component; diff --git a/src/categories/mutations.ts b/src/categories/mutations.ts new file mode 100644 index 000000000..715aa4bbf --- /dev/null +++ b/src/categories/mutations.ts @@ -0,0 +1,88 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { categoryDetailsFragment } from "./queries"; +import { + CategoryBulkDelete, + CategoryBulkDeleteVariables +} from "./types/CategoryBulkDelete"; +import { + CategoryCreate, + CategoryCreateVariables +} from "./types/CategoryCreate"; +import { + CategoryDelete, + CategoryDeleteVariables +} from "./types/CategoryDelete"; +import { + CategoryUpdate, + CategoryUpdateVariables +} from "./types/CategoryUpdate"; + +export const categoryDeleteMutation = gql` + mutation CategoryDelete($id: ID!) { + categoryDelete(id: $id) { + errors { + field + message + } + } + } +`; +export const TypedCategoryDeleteMutation = TypedMutation< + CategoryDelete, + CategoryDeleteVariables +>(categoryDeleteMutation); + +export const categoryCreateMutation = gql` + ${categoryDetailsFragment} + mutation CategoryCreate($parent: ID, $input: CategoryInput!) { + categoryCreate(parent: $parent, input: $input) { + errors { + field + message + } + category { + ...CategoryDetailsFragment + } + } + } +`; +export const TypedCategoryCreateMutation = TypedMutation< + CategoryCreate, + CategoryCreateVariables +>(categoryCreateMutation); + +export const categoryUpdateMutation = gql` + ${categoryDetailsFragment} + mutation CategoryUpdate($id: ID!, $input: CategoryInput!) { + categoryUpdate(id: $id, input: $input) { + errors { + field + message + } + category { + ...CategoryDetailsFragment + } + } + } +`; +export const TypedCategoryUpdateMutation = TypedMutation< + CategoryUpdate, + CategoryUpdateVariables +>(categoryUpdateMutation); + +export const categoryBulkDeleteMutation = gql` + mutation CategoryBulkDelete($ids: [ID]!) { + categoryBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedCategoryBulkDeleteMutation = TypedMutation< + CategoryBulkDelete, + CategoryBulkDeleteVariables +>(categoryBulkDeleteMutation); diff --git a/src/categories/queries.ts b/src/categories/queries.ts new file mode 100644 index 000000000..273ff7dc2 --- /dev/null +++ b/src/categories/queries.ts @@ -0,0 +1,124 @@ +import gql from "graphql-tag"; + +import { TypedQuery } from "../queries"; +import { + CategoryDetails, + CategoryDetailsVariables +} from "./types/CategoryDetails"; +import { RootCategories } from "./types/RootCategories"; + +export const categoryDetailsFragment = gql` + fragment CategoryDetailsFragment on Category { + id + backgroundImage { + alt + url + } + name + descriptionJson + seoDescription + seoTitle + parent { + id + } + } +`; + +export const rootCategories = gql` + query RootCategories( + $first: Int + $after: String + $last: Int + $before: String + ) { + categories( + level: 0 + first: $first + after: $after + last: $last + before: $before + ) { + edges { + node { + id + name + children { + totalCount + } + products { + totalCount + } + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + } +`; +export const TypedRootCategoriesQuery = TypedQuery( + rootCategories +); + +export const categoryDetails = gql` + ${categoryDetailsFragment} + query CategoryDetails( + $id: ID! + $first: Int + $after: String + $last: Int + $before: String + ) { + category(id: $id) { + ...CategoryDetailsFragment + children(first: 20) { + edges { + node { + id + name + children { + totalCount + } + products { + totalCount + } + } + } + } + products(first: $first, after: $after, last: $last, before: $before) { + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + edges { + cursor + node { + id + name + basePrice { + amount + currency + } + isAvailable + thumbnail { + url + } + productType { + id + name + } + } + } + } + } + } +`; +export const TypedCategoryDetailsQuery = TypedQuery< + CategoryDetails, + CategoryDetailsVariables +>(categoryDetails); diff --git a/src/categories/types/CategoryBulkDelete.ts b/src/categories/types/CategoryBulkDelete.ts new file mode 100644 index 000000000..7824cbe3f --- /dev/null +++ b/src/categories/types/CategoryBulkDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: CategoryBulkDelete +// ==================================================== + +export interface CategoryBulkDelete_categoryBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CategoryBulkDelete_categoryBulkDelete { + __typename: "CategoryBulkDelete"; + errors: CategoryBulkDelete_categoryBulkDelete_errors[] | null; +} + +export interface CategoryBulkDelete { + categoryBulkDelete: CategoryBulkDelete_categoryBulkDelete | null; +} + +export interface CategoryBulkDeleteVariables { + ids: (string | null)[]; +} diff --git a/src/categories/types/CategoryCreate.ts b/src/categories/types/CategoryCreate.ts new file mode 100644 index 000000000..0bd794be3 --- /dev/null +++ b/src/categories/types/CategoryCreate.ts @@ -0,0 +1,52 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { CategoryInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: CategoryCreate +// ==================================================== + +export interface CategoryCreate_categoryCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CategoryCreate_categoryCreate_category_backgroundImage { + __typename: "Image"; + alt: string | null; + url: string; +} + +export interface CategoryCreate_categoryCreate_category_parent { + __typename: "Category"; + id: string; +} + +export interface CategoryCreate_categoryCreate_category { + __typename: "Category"; + id: string; + backgroundImage: CategoryCreate_categoryCreate_category_backgroundImage | null; + name: string; + descriptionJson: any; + seoDescription: string | null; + seoTitle: string | null; + parent: CategoryCreate_categoryCreate_category_parent | null; +} + +export interface CategoryCreate_categoryCreate { + __typename: "CategoryCreate"; + errors: CategoryCreate_categoryCreate_errors[] | null; + category: CategoryCreate_categoryCreate_category | null; +} + +export interface CategoryCreate { + categoryCreate: CategoryCreate_categoryCreate | null; +} + +export interface CategoryCreateVariables { + parent?: string | null; + input: CategoryInput; +} diff --git a/src/categories/types/CategoryDelete.ts b/src/categories/types/CategoryDelete.ts new file mode 100644 index 000000000..e68ff91b8 --- /dev/null +++ b/src/categories/types/CategoryDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: CategoryDelete +// ==================================================== + +export interface CategoryDelete_categoryDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CategoryDelete_categoryDelete { + __typename: "CategoryDelete"; + errors: CategoryDelete_categoryDelete_errors[] | null; +} + +export interface CategoryDelete { + categoryDelete: CategoryDelete_categoryDelete | null; +} + +export interface CategoryDeleteVariables { + id: string; +} diff --git a/src/categories/types/CategoryDetails.ts b/src/categories/types/CategoryDetails.ts new file mode 100644 index 000000000..5168b4606 --- /dev/null +++ b/src/categories/types/CategoryDetails.ts @@ -0,0 +1,118 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: CategoryDetails +// ==================================================== + +export interface CategoryDetails_category_backgroundImage { + __typename: "Image"; + alt: string | null; + url: string; +} + +export interface CategoryDetails_category_parent { + __typename: "Category"; + id: string; +} + +export interface CategoryDetails_category_children_edges_node_children { + __typename: "CategoryCountableConnection"; + totalCount: number | null; +} + +export interface CategoryDetails_category_children_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface CategoryDetails_category_children_edges_node { + __typename: "Category"; + id: string; + name: string; + children: CategoryDetails_category_children_edges_node_children | null; + products: CategoryDetails_category_children_edges_node_products | null; +} + +export interface CategoryDetails_category_children_edges { + __typename: "CategoryCountableEdge"; + node: CategoryDetails_category_children_edges_node; +} + +export interface CategoryDetails_category_children { + __typename: "CategoryCountableConnection"; + edges: CategoryDetails_category_children_edges[]; +} + +export interface CategoryDetails_category_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface CategoryDetails_category_products_edges_node_basePrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface CategoryDetails_category_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface CategoryDetails_category_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface CategoryDetails_category_products_edges_node { + __typename: "Product"; + id: string; + name: string; + basePrice: CategoryDetails_category_products_edges_node_basePrice | null; + isAvailable: boolean | null; + thumbnail: CategoryDetails_category_products_edges_node_thumbnail | null; + productType: CategoryDetails_category_products_edges_node_productType; +} + +export interface CategoryDetails_category_products_edges { + __typename: "ProductCountableEdge"; + cursor: string; + node: CategoryDetails_category_products_edges_node; +} + +export interface CategoryDetails_category_products { + __typename: "ProductCountableConnection"; + pageInfo: CategoryDetails_category_products_pageInfo; + edges: CategoryDetails_category_products_edges[]; +} + +export interface CategoryDetails_category { + __typename: "Category"; + id: string; + backgroundImage: CategoryDetails_category_backgroundImage | null; + name: string; + descriptionJson: any; + seoDescription: string | null; + seoTitle: string | null; + parent: CategoryDetails_category_parent | null; + children: CategoryDetails_category_children | null; + products: CategoryDetails_category_products | null; +} + +export interface CategoryDetails { + category: CategoryDetails_category | null; +} + +export interface CategoryDetailsVariables { + id: string; + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/categories/types/CategoryDetailsFragment.ts b/src/categories/types/CategoryDetailsFragment.ts new file mode 100644 index 000000000..111a0e6c2 --- /dev/null +++ b/src/categories/types/CategoryDetailsFragment.ts @@ -0,0 +1,29 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: CategoryDetailsFragment +// ==================================================== + +export interface CategoryDetailsFragment_backgroundImage { + __typename: "Image"; + alt: string | null; + url: string; +} + +export interface CategoryDetailsFragment_parent { + __typename: "Category"; + id: string; +} + +export interface CategoryDetailsFragment { + __typename: "Category"; + id: string; + backgroundImage: CategoryDetailsFragment_backgroundImage | null; + name: string; + descriptionJson: any; + seoDescription: string | null; + seoTitle: string | null; + parent: CategoryDetailsFragment_parent | null; +} diff --git a/src/categories/types/CategoryProperties.ts b/src/categories/types/CategoryProperties.ts new file mode 100644 index 000000000..3ff2be8c5 --- /dev/null +++ b/src/categories/types/CategoryProperties.ts @@ -0,0 +1,95 @@ +/* tslint:disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: CategoryProperties +// ==================================================== + +export interface CategoryProperties_category_parent { + __typename: "Category"; + id: string; +} + +export interface CategoryProperties_category_children_edges_node_children { + __typename: "CategoryCountableConnection"; + totalCount: number | null; +} + +export interface CategoryProperties_category_children_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface CategoryProperties_category_children_edges_node { + __typename: "Category"; + id: string; + name: string; + children: CategoryProperties_category_children_edges_node_children | null; + products: CategoryProperties_category_children_edges_node_products | null; +} + +export interface CategoryProperties_category_children_edges { + __typename: "CategoryCountableEdge"; + node: CategoryProperties_category_children_edges_node; +} + +export interface CategoryProperties_category_children { + __typename: "CategoryCountableConnection"; + edges: CategoryProperties_category_children_edges[]; +} + +export interface CategoryProperties_category_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface CategoryProperties_category_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface CategoryProperties_category_products_edges_node { + __typename: "Product"; + id: string; + name: string; + thumbnailUrl: string | null; + productType: CategoryProperties_category_products_edges_node_productType; +} + +export interface CategoryProperties_category_products_edges { + __typename: "ProductCountableEdge"; + cursor: string; + node: CategoryProperties_category_products_edges_node; +} + +export interface CategoryProperties_category_products { + __typename: "ProductCountableConnection"; + pageInfo: CategoryProperties_category_products_pageInfo; + edges: CategoryProperties_category_products_edges[]; +} + +export interface CategoryProperties_category { + __typename: "Category"; + id: string; + name: string; + description: string; + parent: CategoryProperties_category_parent | null; + children: CategoryProperties_category_children | null; + products: CategoryProperties_category_products | null; +} + +export interface CategoryProperties { + category: CategoryProperties_category | null; +} + +export interface CategoryPropertiesVariables { + id: string; + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/categories/types/CategoryUpdate.ts b/src/categories/types/CategoryUpdate.ts new file mode 100644 index 000000000..c7d6e36ce --- /dev/null +++ b/src/categories/types/CategoryUpdate.ts @@ -0,0 +1,52 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { CategoryInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: CategoryUpdate +// ==================================================== + +export interface CategoryUpdate_categoryUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CategoryUpdate_categoryUpdate_category_backgroundImage { + __typename: "Image"; + alt: string | null; + url: string; +} + +export interface CategoryUpdate_categoryUpdate_category_parent { + __typename: "Category"; + id: string; +} + +export interface CategoryUpdate_categoryUpdate_category { + __typename: "Category"; + id: string; + backgroundImage: CategoryUpdate_categoryUpdate_category_backgroundImage | null; + name: string; + descriptionJson: any; + seoDescription: string | null; + seoTitle: string | null; + parent: CategoryUpdate_categoryUpdate_category_parent | null; +} + +export interface CategoryUpdate_categoryUpdate { + __typename: "CategoryUpdate"; + errors: CategoryUpdate_categoryUpdate_errors[] | null; + category: CategoryUpdate_categoryUpdate_category | null; +} + +export interface CategoryUpdate { + categoryUpdate: CategoryUpdate_categoryUpdate | null; +} + +export interface CategoryUpdateVariables { + id: string; + input: CategoryInput; +} diff --git a/src/categories/types/RootCategories.ts b/src/categories/types/RootCategories.ts new file mode 100644 index 000000000..0c55c71df --- /dev/null +++ b/src/categories/types/RootCategories.ts @@ -0,0 +1,55 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: RootCategories +// ==================================================== + +export interface RootCategories_categories_edges_node_children { + __typename: "CategoryCountableConnection"; + totalCount: number | null; +} + +export interface RootCategories_categories_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface RootCategories_categories_edges_node { + __typename: "Category"; + id: string; + name: string; + children: RootCategories_categories_edges_node_children | null; + products: RootCategories_categories_edges_node_products | null; +} + +export interface RootCategories_categories_edges { + __typename: "CategoryCountableEdge"; + node: RootCategories_categories_edges_node; +} + +export interface RootCategories_categories_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface RootCategories_categories { + __typename: "CategoryCountableConnection"; + edges: RootCategories_categories_edges[]; + pageInfo: RootCategories_categories_pageInfo; +} + +export interface RootCategories { + categories: RootCategories_categories | null; +} + +export interface RootCategoriesVariables { + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/categories/types/RootCategoryChildren.ts b/src/categories/types/RootCategoryChildren.ts new file mode 100644 index 000000000..71f75ba20 --- /dev/null +++ b/src/categories/types/RootCategoryChildren.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: RootCategoryChildren +// ==================================================== + +export interface RootCategoryChildren_categories_edges_node_children { + __typename: "CategoryCountableConnection"; + totalCount: number | null; +} + +export interface RootCategoryChildren_categories_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface RootCategoryChildren_categories_edges_node { + __typename: "Category"; + id: string; + name: string; + children: RootCategoryChildren_categories_edges_node_children | null; + products: RootCategoryChildren_categories_edges_node_products | null; +} + +export interface RootCategoryChildren_categories_edges { + __typename: "CategoryCountableEdge"; + cursor: string; + node: RootCategoryChildren_categories_edges_node; +} + +export interface RootCategoryChildren_categories { + __typename: "CategoryCountableConnection"; + edges: RootCategoryChildren_categories_edges[]; +} + +export interface RootCategoryChildren { + categories: RootCategoryChildren_categories | null; +} diff --git a/src/categories/urls.ts b/src/categories/urls.ts new file mode 100644 index 000000000..09c92f9d2 --- /dev/null +++ b/src/categories/urls.ts @@ -0,0 +1,36 @@ +import { stringify as stringifyQs } from "qs"; +import * as urlJoin from "url-join"; + +import { ActiveTab, BulkAction, Dialog, Pagination } from "../types"; +import { CategoryPageTab } from "./components/CategoryUpdatePage"; + +const categorySectionUrl = "/categories/"; + +export const categoryListPath = categorySectionUrl; +export type CategoryListUrlDialog = "delete"; +export type CategoryListUrlQueryParams = BulkAction & + Dialog & + Pagination; +export const categoryListUrl = (params?: CategoryListUrlQueryParams) => + categorySectionUrl + "?" + stringifyQs(params); + +export const categoryPath = (id: string) => urlJoin(categorySectionUrl, id); +export type CategoryUrlDialog = + | "delete" + | "delete-categories" + | "delete-products"; +export type CategoryUrlQueryParams = BulkAction & + Dialog & + Pagination & + ActiveTab; +export const categoryUrl = (id: string, params?: CategoryUrlQueryParams) => + categoryPath(encodeURIComponent(id)) + "?" + stringifyQs(params); + +export const categoryAddPath = (parentId?: string) => { + if (parentId) { + return urlJoin(categoryPath(parentId), "add"); + } + return urlJoin(categorySectionUrl, "add"); +}; +export const categoryAddUrl = (parentId?: string) => + categoryAddPath(parentId ? encodeURIComponent(parentId) : undefined); diff --git a/src/categories/views/CategoryCreate.tsx b/src/categories/views/CategoryCreate.tsx new file mode 100644 index 000000000..903bd7050 --- /dev/null +++ b/src/categories/views/CategoryCreate.tsx @@ -0,0 +1,75 @@ +import * as React from "react"; + +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import CategoryCreatePage from "../components/CategoryCreatePage"; +import { TypedCategoryCreateMutation } from "../mutations"; +import { CategoryCreate } from "../types/CategoryCreate"; +import { categoryListUrl, categoryUrl } from "../urls"; + +interface CategoryCreateViewProps { + parentId: string; +} + +export const CategoryCreateView: React.StatelessComponent< + CategoryCreateViewProps +> = ({ parentId }) => { + const navigate = useNavigator(); + const notify = useNotifier(); + + const handleSuccess = (data: CategoryCreate) => { + if (data.categoryCreate.errors.length === 0) { + notify({ text: i18n.t("Category created") }); + navigate(categoryUrl(data.categoryCreate.category.id)); + } + }; + return ( + + {(createCategory, createCategoryResult) => { + const errors = maybe( + () => createCategoryResult.data.categoryCreate.errors, + [] + ); + + const formTransitionState = getMutationState( + createCategoryResult.called, + createCategoryResult.loading, + errors + ); + + return ( + <> + + + navigate(parentId ? categoryUrl(parentId) : categoryListUrl()) + } + onSubmit={formData => + createCategory({ + variables: { + input: { + descriptionJson: JSON.stringify(formData.description), + name: formData.name, + seo: { + description: formData.seoDescription, + title: formData.seoTitle + } + }, + parent: parentId || null + } + }) + } + /> + + ); + }} + + ); +}; +export default CategoryCreateView; diff --git a/src/categories/views/CategoryDetails.tsx b/src/categories/views/CategoryDetails.tsx new file mode 100644 index 000000000..07e927fca --- /dev/null +++ b/src/categories/views/CategoryDetails.tsx @@ -0,0 +1,426 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { PAGINATE_BY } from "../../config"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import { TypedProductBulkDeleteMutation } from "../../products/mutations"; +import { productBulkDelete } from "../../products/types/productBulkDelete"; +import { productAddUrl, productUrl } from "../../products/urls"; +import { CategoryInput } from "../../types/globalTypes"; +import { + CategoryPageTab, + CategoryUpdatePage +} from "../components/CategoryUpdatePage/CategoryUpdatePage"; +import { + TypedCategoryBulkDeleteMutation, + TypedCategoryDeleteMutation, + TypedCategoryUpdateMutation +} from "../mutations"; +import { TypedCategoryDetailsQuery } from "../queries"; +import { CategoryBulkDelete } from "../types/CategoryBulkDelete"; +import { CategoryDelete } from "../types/CategoryDelete"; +import { CategoryUpdate } from "../types/CategoryUpdate"; +import { + categoryAddUrl, + categoryListUrl, + categoryUrl, + CategoryUrlDialog, + CategoryUrlQueryParams +} from "../urls"; + +export interface CategoryDetailsProps { + params: CategoryUrlQueryParams; + id: string; +} + +export function getActiveTab(tabName: string): CategoryPageTab { + return tabName === CategoryPageTab.products + ? CategoryPageTab.products + : CategoryPageTab.categories; +} + +export const CategoryDetails: React.StatelessComponent< + CategoryDetailsProps +> = ({ id, params }) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const handleCategoryDelete = (data: CategoryDelete) => { + if (data.categoryDelete.errors.length === 0) { + notify({ + text: i18n.t("Category deleted", { + context: "notification" + }) + }); + navigate(categoryListUrl()); + } + }; + const handleCategoryUpdate = (data: CategoryUpdate) => { + if (data.categoryUpdate.errors.length > 0) { + const backgroundImageError = data.categoryUpdate.errors.find( + error => error.field === ("backgroundImage" as keyof CategoryInput) + ); + if (backgroundImageError) { + notify({ + text: backgroundImageError.message + }); + } + } + }; + + const changeTab = (tabName: CategoryPageTab) => { + reset(); + navigate( + categoryUrl(id, { + activeTab: tabName + }) + ); + }; + + const closeModal = () => + navigate( + categoryUrl(id, { + ...params, + action: undefined, + ids: undefined + }), + true + ); + + const openModal = (action: CategoryUrlDialog, ids?: string[]) => + navigate( + categoryUrl(id, { + ...params, + action, + ids + }) + ); + + return ( + + {(deleteCategory, deleteResult) => ( + + {(updateCategory, updateResult) => { + const paginationState = createPaginationState(PAGINATE_BY, params); + const formTransitionState = getMutationState( + updateResult.called, + updateResult.loading, + maybe(() => updateResult.data.categoryUpdate.errors) + ); + const removeDialogTransitionState = getMutationState( + deleteResult.called, + deleteResult.loading, + maybe(() => deleteResult.data.categoryDelete.errors) + ); + return ( + + {({ data, loading, refetch }) => { + const handleBulkCategoryDelete = ( + data: CategoryBulkDelete + ) => { + if (data.categoryBulkDelete.errors.length === 0) { + closeModal(); + notify({ + text: i18n.t("Categories removed") + }); + refetch(); + reset(); + } + }; + + const handleBulkProductDelete = (data: productBulkDelete) => { + if (data.productBulkDelete.errors.length === 0) { + closeModal(); + notify({ + text: i18n.t("Products removed") + }); + refetch(); + reset(); + } + }; + + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.category.products.pageInfo), + paginationState, + params + ); + + return ( + <> + data.category.name)} /> + + {(categoryBulkDelete, categoryBulkDeleteOpts) => ( + + {(productBulkDelete, productBulkDeleteOpts) => { + const categoryBulkDeleteMutationState = getMutationState( + categoryBulkDeleteOpts.called, + categoryBulkDeleteOpts.loading, + maybe( + () => + categoryBulkDeleteOpts.data + .categoryBulkDelete.errors + ) + ); + const productBulkDeleteMutationState = getMutationState( + productBulkDeleteOpts.called, + productBulkDeleteOpts.loading, + maybe( + () => + productBulkDeleteOpts.data.productBulkDelete + .errors + ) + ); + + return ( + <> + data.category)} + disabled={loading} + errors={maybe( + () => + updateResult.data.categoryUpdate.errors + )} + onAddCategory={() => + navigate(categoryAddUrl(id)) + } + onAddProduct={() => navigate(productAddUrl)} + onBack={() => + navigate( + maybe( + () => + categoryUrl( + data.category.parent.id + ), + categoryListUrl() + ) + ) + } + onCategoryClick={id => () => + navigate(categoryUrl(id))} + onDelete={() => openModal("delete")} + onImageDelete={() => + updateCategory({ + variables: { + id, + input: { + backgroundImage: null + } + } + }) + } + onImageUpload={file => + updateCategory({ + variables: { + id, + input: { + backgroundImage: file + } + } + }) + } + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + pageInfo={pageInfo} + onProductClick={id => () => + navigate(productUrl(id))} + onSubmit={formData => + updateCategory({ + variables: { + id, + input: { + backgroundImageAlt: + formData.backgroundImageAlt, + descriptionJson: JSON.stringify( + formData.description + ), + name: formData.name, + seo: { + description: + formData.seoDescription, + title: formData.seoTitle + } + } + } + }) + } + products={maybe(() => + data.category.products.edges.map( + edge => edge.node + ) + )} + saveButtonBarState={formTransitionState} + subcategories={maybe(() => + data.category.children.edges.map( + edge => edge.node + ) + )} + subcategoryListToolbar={ + + openModal( + "delete-categories", + listElements + ) + } + > + + + } + productListToolbar={ + + openModal( + "delete-products", + listElements + ) + } + > + + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + /> + + deleteCategory({ variables: { id } }) + } + open={params.action === "delete"} + title={i18n.t("Delete category", { + context: "modal title" + })} + variant="delete" + > + {{ categoryName }}?
", + { + categoryName: maybe( + () => data.category.name + ), + context: "modal message" + } + ) + }} + /> + + {i18n.t( + "Remember that this will also remove all products assigned to this category." + )} + +
+ + categoryBulkDelete({ + variables: { ids: params.ids } + }) + } + title={i18n.t("Remove categories")} + variant="delete" + > + {{ number }} categories?", + { + number: maybe( + () => + params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + {i18n.t( + "Remember that this will also remove all products assigned to this category." + )} + + + + productBulkDelete({ + variables: { ids: params.ids } + }) + } + title={i18n.t("Remove products")} + variant="delete" + > + {{ number }} products?", + { + number: maybe( + () => + params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + ); + }} +
+ )} +
+ + ); + }} +
+ ); + }} +
+ )} +
+ ); +}; +export default CategoryDetails; diff --git a/src/categories/views/CategoryList.tsx b/src/categories/views/CategoryList.tsx new file mode 100644 index 000000000..943476702 --- /dev/null +++ b/src/categories/views/CategoryList.tsx @@ -0,0 +1,153 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { PAGINATE_BY } from "../../config"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import { CategoryListPage } from "../components/CategoryListPage/CategoryListPage"; +import { TypedCategoryBulkDeleteMutation } from "../mutations"; +import { TypedRootCategoriesQuery } from "../queries"; +import { CategoryBulkDelete } from "../types/CategoryBulkDelete"; +import { + categoryAddUrl, + categoryListUrl, + CategoryListUrlQueryParams, + categoryUrl +} from "../urls"; + +interface CategoryListProps { + params: CategoryListUrlQueryParams; +} + +export const CategoryList: React.StatelessComponent = ({ + params +}) => { + const navigate = useNavigator(); + const paginate = usePaginator(); + const { isSelected, listElements, toggle, toggleAll, reset } = useBulkActions( + params.ids + ); + + const paginationState = createPaginationState(PAGINATE_BY, params); + return ( + + {({ data, loading, refetch }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.categories.pageInfo), + paginationState, + params + ); + + const handleCategoryBulkDelete = (data: CategoryBulkDelete) => { + if (data.categoryBulkDelete.errors.length === 0) { + navigate(categoryListUrl(), true); + refetch(); + reset(); + } + }; + return ( + + {(categoryBulkDelete, categoryBulkDeleteOpts) => { + const bulkDeleteState = getMutationState( + categoryBulkDeleteOpts.called, + categoryBulkDeleteOpts.loading, + maybe( + () => categoryBulkDeleteOpts.data.categoryBulkDelete.errors + ) + ); + + return ( + <> + data.categories.edges.map(edge => edge.node), + [] + )} + onAdd={() => navigate(categoryAddUrl())} + onRowClick={id => () => navigate(categoryUrl(id))} + disabled={loading} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + pageInfo={pageInfo} + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + toolbar={ + + navigate( + categoryListUrl({ + ...params, + action: "delete", + ids: listElements + }) + ) + } + > + + + } + /> + + navigate( + categoryListUrl({ + ...params, + action: undefined, + ids: undefined + }) + ) + } + onConfirm={() => + categoryBulkDelete({ + variables: { + ids: params.ids + } + }) + } + open={params.action === "delete"} + title={i18n.t("Remove categories")} + variant="delete" + > + {{ number }} categories?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + {i18n.t( + "Remember that this will also remove all products assigned to this category." + )} + + + + ); + }} + + ); + }} + + ); +}; +export default CategoryList; diff --git a/src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx b/src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx new file mode 100644 index 000000000..46cc82bf0 --- /dev/null +++ b/src/collections/components/CollectionCreatePage/CollectionCreatePage.tsx @@ -0,0 +1,167 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { ContentState, convertToRaw, RawDraftContentState } from "draft-js"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import { CardSpacer } from "@saleor/components/CardSpacer"; +import CardTitle from "@saleor/components/CardTitle"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import { Container } from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import SeoForm from "@saleor/components/SeoForm"; +import VisibilityCard from "@saleor/components/VisibilityCard"; +import i18n from "../../../i18n"; +import { UserError } from "../../../types"; +import CollectionDetails from "../CollectionDetails/CollectionDetails"; +import { CollectionImage } from "../CollectionImage/CollectionImage"; + +export interface CollectionCreatePageFormData { + backgroundImage: { + url: string; + value: string; + }; + backgroundImageAlt: string; + description: RawDraftContentState; + name: string; + publicationDate: string; + isPublished: boolean; + seoDescription: string; + seoTitle: string; +} + +export interface CollectionCreatePageProps { + disabled: boolean; + errors: UserError[]; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onSubmit: (data: CollectionCreatePageFormData) => void; +} + +const initialForm: CollectionCreatePageFormData = { + backgroundImage: { + url: null, + value: null + }, + backgroundImageAlt: "", + description: convertToRaw(ContentState.createFromText("")), + isPublished: false, + name: "", + publicationDate: "", + seoDescription: "", + seoTitle: "" +}; + +const CollectionCreatePage: React.StatelessComponent< + CollectionCreatePageProps +> = ({ + disabled, + errors, + saveButtonBarState, + onBack, + onSubmit +}: CollectionCreatePageProps) => ( +
+ {({ change, data, errors: formErrors, hasChanged, submit }) => ( + + {i18n.t("Collections")} + + +
+ + + + change({ + target: { + name: "backgroundImage", + value: { + url: null, + value: null + } + } + } as any) + } + onImageUpload={file => + change({ + target: { + name: "backgroundImage", + value: { + url: URL.createObjectURL(file), + value: file + } + } + } as any) + } + onChange={change} + data={data} + /> + + +
+
+
+ + + + + + +
+
+
+ +
+ )} +
+); +CollectionCreatePage.displayName = "CollectionCreatePage"; +export default CollectionCreatePage; diff --git a/src/collections/components/CollectionCreatePage/index.ts b/src/collections/components/CollectionCreatePage/index.ts new file mode 100644 index 000000000..0ab3d5aa7 --- /dev/null +++ b/src/collections/components/CollectionCreatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CollectionCreatePage"; +export * from "./CollectionCreatePage"; diff --git a/src/collections/components/CollectionDetails/CollectionDetails.tsx b/src/collections/components/CollectionDetails/CollectionDetails.tsx new file mode 100644 index 000000000..180342c9f --- /dev/null +++ b/src/collections/components/CollectionDetails/CollectionDetails.tsx @@ -0,0 +1,70 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import { RawDraftContentState } from "draft-js"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import FormSpacer from "@saleor/components/FormSpacer"; +import RichTextEditor from "@saleor/components/RichTextEditor"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { FormErrors } from "../../../types"; +import { CollectionDetails_collection } from "../../types/CollectionDetails"; + +const styles = createStyles({ + name: { + width: "80%" + } +}); + +export interface CollectionDetailsProps extends WithStyles { + collection?: CollectionDetails_collection; + data: { + description: RawDraftContentState; + name: string; + }; + disabled: boolean; + errors: FormErrors<"descriptionJson" | "name">; + onChange: (event: React.ChangeEvent) => void; +} + +const CollectionDetails = withStyles(styles, { name: "CollectionDetails" })( + ({ + classes, + collection, + disabled, + data, + onChange, + errors + }: CollectionDetailsProps) => ( + + + + + + JSON.parse(collection.descriptionJson))} + label={i18n.t("Description")} + name="description" + disabled={disabled} + onChange={onChange} + /> + + + ) +); +CollectionDetails.displayName = "CollectionDetails"; +export default CollectionDetails; diff --git a/src/collections/components/CollectionDetails/index.ts b/src/collections/components/CollectionDetails/index.ts new file mode 100644 index 000000000..5f4e124e7 --- /dev/null +++ b/src/collections/components/CollectionDetails/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CollectionDetails"; +export * from "./CollectionDetails"; diff --git a/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx b/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx new file mode 100644 index 000000000..a974ae6ad --- /dev/null +++ b/src/collections/components/CollectionDetailsPage/CollectionDetailsPage.tsx @@ -0,0 +1,152 @@ +import { RawDraftContentState } from "draft-js"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import { CardSpacer } from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import { Container } from "@saleor/components/Container"; +import { ControlledSwitch } from "@saleor/components/ControlledSwitch"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import SeoForm from "@saleor/components/SeoForm"; +import VisibilityCard from "@saleor/components/VisibilityCard"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { ListActions, PageListProps } from "../../../types"; +import { CollectionDetails_collection } from "../../types/CollectionDetails"; +import CollectionDetails from "../CollectionDetails/CollectionDetails"; +import { CollectionImage } from "../CollectionImage/CollectionImage"; +import CollectionProducts from "../CollectionProducts/CollectionProducts"; + +export interface CollectionDetailsPageFormData { + backgroundImageAlt: string; + description: RawDraftContentState; + name: string; + publicationDate: string; + seoDescription: string; + seoTitle: string; + isFeatured: boolean; + isPublished: boolean; +} + +export interface CollectionDetailsPageProps extends PageListProps, ListActions { + collection: CollectionDetails_collection; + isFeatured: boolean; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onCollectionRemove: () => void; + onImageDelete: () => void; + onImageUpload: (file: File) => void; + onProductUnassign: (id: string, event: React.MouseEvent) => void; + onSubmit: (data: CollectionDetailsPageFormData) => void; +} + +const CollectionDetailsPage: React.StatelessComponent< + CollectionDetailsPageProps +> = ({ + collection, + disabled, + isFeatured, + saveButtonBarState, + onBack, + onCollectionRemove, + onImageDelete, + onImageUpload, + onSubmit, + ...collectionProductsProps +}: CollectionDetailsPageProps) => { + return ( +
collection.backgroundImage.alt, ""), + description: maybe(() => JSON.parse(collection.descriptionJson)), + isFeatured, + isPublished: maybe(() => collection.isPublished, false), + name: maybe(() => collection.name, ""), + publicationDate: maybe(() => collection.publicationDate, ""), + seoDescription: maybe(() => collection.seoDescription, ""), + seoTitle: maybe(() => collection.seoTitle, "") + }} + onSubmit={onSubmit} + confirmLeave + > + {({ change, data, errors: formErrors, hasChanged, submit }) => ( + + {i18n.t("Collections")} + collection.name)} /> + +
+ + + collection.backgroundImage)} + onImageDelete={onImageDelete} + onImageUpload={onImageUpload} + onChange={change} + /> + + + + collection.name)} + onChange={change} + /> +
+
+
+ + + +
+
+
+ +
+ )} +
+ ); +}; +CollectionDetailsPage.displayName = "CollectionDetailsPage"; +export default CollectionDetailsPage; diff --git a/src/collections/components/CollectionDetailsPage/index.ts b/src/collections/components/CollectionDetailsPage/index.ts new file mode 100644 index 000000000..641c72a74 --- /dev/null +++ b/src/collections/components/CollectionDetailsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CollectionDetailsPage"; +export * from "./CollectionDetailsPage"; diff --git a/src/collections/components/CollectionImage/CollectionImage.tsx b/src/collections/components/CollectionImage/CollectionImage.tsx new file mode 100644 index 000000000..f2866483f --- /dev/null +++ b/src/collections/components/CollectionImage/CollectionImage.tsx @@ -0,0 +1,142 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import CardTitle from "@saleor/components/CardTitle"; +import Hr from "@saleor/components/Hr"; +import ImageTile from "@saleor/components/ImageTile"; +import ImageUpload from "@saleor/components/ImageUpload"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { CollectionDetails_collection_backgroundImage } from "../../types/CollectionDetails"; + +const styles = (theme: Theme) => + createStyles({ + PhotosIcon: { + height: "64px", + margin: "0 auto", + width: "64px" + }, + PhotosIconContainer: { + margin: `${theme.spacing.unit * 5}px 0`, + textAlign: "center" + }, + fileField: { + display: "none" + }, + image: { + height: "100%", + objectFit: "contain", + userSelect: "none", + width: "100%" + }, + imageContainer: { + background: "#ffffff", + border: "1px solid #eaeaea", + borderRadius: theme.spacing.unit, + height: 148, + justifySelf: "start", + overflow: "hidden", + padding: theme.spacing.unit * 2, + position: "relative", + width: 148 + } + }); + +export interface CollectionImageProps extends WithStyles { + data: { + backgroundImageAlt: string; + }; + image: CollectionDetails_collection_backgroundImage; + onChange: (event: React.ChangeEvent) => void; + onImageDelete: () => void; + onImageUpload: (file: File) => void; +} + +export const CollectionImage = withStyles(styles)( + class CollectionImageComponent extends React.Component< + CollectionImageProps, + {} + > { + imgInputAnchor = React.createRef(); + + clickImgInput = () => this.imgInputAnchor.current.click(); + + render() { + const { + classes, + data, + onImageUpload, + image, + onChange, + onImageDelete + } = this.props; + return ( + + + + onImageUpload(event.target.files[0])} + type="file" + ref={this.imgInputAnchor} + /> + + } + /> + {image === undefined ? ( + +
+
+ +
+
+
+ ) : image === null ? ( + + ) : ( + + + + )} + {image && ( + <> +
+ + + + + )} +
+ ); + } + } +); +CollectionImage.displayName = "CollectionImage"; +export default CollectionImage; diff --git a/src/collections/components/CollectionImage/index.ts b/src/collections/components/CollectionImage/index.ts new file mode 100644 index 000000000..1d18c66cc --- /dev/null +++ b/src/collections/components/CollectionImage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CollectionImage"; +export * from "./CollectionImage"; diff --git a/src/collections/components/CollectionList/CollectionList.tsx b/src/collections/components/CollectionList/CollectionList.tsx new file mode 100644 index 000000000..ce8b61550 --- /dev/null +++ b/src/collections/components/CollectionList/CollectionList.tsx @@ -0,0 +1,166 @@ +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import Checkbox from "@saleor/components/Checkbox"; +import Skeleton from "@saleor/components/Skeleton"; +import StatusLabel from "@saleor/components/StatusLabel"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { CollectionList_collections_edges_node } from "../../types/CollectionList"; + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colAvailability: { + width: 240 + }, + colName: {}, + colProducts: { + width: 240 + } + }, + colAvailability: {}, + colName: {}, + colProducts: { + textAlign: "center" + }, + tableRow: { + cursor: "pointer" as "pointer" + } + }); + +interface CollectionListProps + extends ListProps, + ListActions, + WithStyles { + collections: CollectionList_collections_edges_node[]; +} + +const CollectionList = withStyles(styles, { name: "CollectionList" })( + ({ + classes, + collections, + disabled, + onNextPage, + onPreviousPage, + onRowClick, + pageInfo, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: CollectionListProps) => ( + + + + + {i18n.t("Category Name", { context: "table cell" })} + + + {i18n + .t("No. Products", { context: "table cell" }) + .replace(" ", "\xa0")} + + + {i18n.t("Availability", { context: "table cell" })} + + + + + + + + + {renderCollection( + collections, + collection => { + const isSelected = collection ? isChecked(collection.id) : false; + return ( + + + toggle(collection.id)} + /> + + + {maybe( + () => collection.name, + + )} + + + {maybe( + () => collection.products.totalCount, + + )} + + + {maybe( + () => ( + + ), + + )} + + + ); + }, + () => ( + + + {i18n.t("No collections found")} + + + ) + )} + +
+
+ ) +); +CollectionList.displayName = "CollectionList"; +export default CollectionList; diff --git a/src/collections/components/CollectionList/index.ts b/src/collections/components/CollectionList/index.ts new file mode 100644 index 000000000..4f5db2333 --- /dev/null +++ b/src/collections/components/CollectionList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CollectionList"; +export * from "./CollectionList"; diff --git a/src/collections/components/CollectionListPage/CollectionListPage.tsx b/src/collections/components/CollectionListPage/CollectionListPage.tsx new file mode 100644 index 000000000..4fd39fe3c --- /dev/null +++ b/src/collections/components/CollectionListPage/CollectionListPage.tsx @@ -0,0 +1,37 @@ +import Button from "@material-ui/core/Button"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import { Container } from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { ListActions, PageListProps } from "../../../types"; +import { CollectionList_collections_edges_node } from "../../types/CollectionList"; +import CollectionList from "../CollectionList/CollectionList"; + +export interface CollectionListPageProps extends PageListProps, ListActions { + collections: CollectionList_collections_edges_node[]; +} + +const CollectionListPage: React.StatelessComponent = ({ + disabled, + onAdd, + ...listProps +}) => ( + + + + + + +); +CollectionListPage.displayName = "CollectionListPage"; +export default CollectionListPage; diff --git a/src/collections/components/CollectionListPage/index.ts b/src/collections/components/CollectionListPage/index.ts new file mode 100644 index 000000000..3324e1926 --- /dev/null +++ b/src/collections/components/CollectionListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CollectionListPage"; +export * from "./CollectionListPage"; diff --git a/src/collections/components/CollectionProducts/CollectionProducts.tsx b/src/collections/components/CollectionProducts/CollectionProducts.tsx new file mode 100644 index 000000000..fc8a420df --- /dev/null +++ b/src/collections/components/CollectionProducts/CollectionProducts.tsx @@ -0,0 +1,189 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import IconButton from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Checkbox from "@saleor/components/Checkbox"; +import Skeleton from "@saleor/components/Skeleton"; +import StatusLabel from "@saleor/components/StatusLabel"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ListActions, PageListProps } from "../../../types"; +import { CollectionDetails_collection } from "../../types/CollectionDetails"; + +const styles = (theme: Theme) => + createStyles({ + iconCell: { + "&:last-child": { + paddingRight: 0 + }, + width: 48 + theme.spacing.unit / 2 + }, + tableRow: { + cursor: "pointer" + } + }); + +export interface CollectionProductsProps + extends PageListProps, + ListActions, + WithStyles { + collection: CollectionDetails_collection; + onProductUnassign: (id: string, event: React.MouseEvent) => void; +} + +const CollectionProducts = withStyles(styles, { name: "CollectionProducts" })( + ({ + classes, + collection, + disabled, + onAdd, + onNextPage, + onPreviousPage, + onProductUnassign, + onRowClick, + pageInfo, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: CollectionProductsProps) => ( + + + ) + } + toolbar={ + + } + /> + + collection.products.edges.map(edge => edge.node))} + toggleAll={toggleAll} + toolbar={toolbar} + > + {i18n.t("Name", { context: "table header" })} + {i18n.t("Type", { context: "table header" })} + + {i18n.t("Published", { context: "table header" })} + + + + + pageInfo.hasNextPage)} + onNextPage={onNextPage} + hasPreviousPage={maybe(() => pageInfo.hasPreviousPage)} + onPreviousPage={onPreviousPage} + /> + + + + {renderCollection( + maybe(() => collection.products.edges.map(edge => edge.node)), + product => { + const isSelected = product ? isChecked(product.id) : false; + + return ( + + + toggle(product.id)} + /> + + product.thumbnail.url)} + /> + + {maybe(() => product.name, )} + + + {maybe( + () => product.productType.name, + + )} + + + {maybe( + () => ( + + ), + + )} + + + onProductUnassign(product.id, event)} + > + + + + + ); + }, + () => ( + + + {i18n.t("No products found")} + + ) + )} + +
+
+ ) +); +CollectionProducts.displayName = "CollectionProducts"; +export default CollectionProducts; diff --git a/src/collections/components/CollectionProducts/index.ts b/src/collections/components/CollectionProducts/index.ts new file mode 100644 index 000000000..3f37d0ff8 --- /dev/null +++ b/src/collections/components/CollectionProducts/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CollectionProducts"; +export * from "./CollectionProducts"; diff --git a/src/collections/containers/CollectionOperations.tsx b/src/collections/containers/CollectionOperations.tsx new file mode 100644 index 000000000..a9f3d8c84 --- /dev/null +++ b/src/collections/containers/CollectionOperations.tsx @@ -0,0 +1,107 @@ +import * as React from "react"; + +import { getMutationProviderData } from "../../misc"; +import { PartialMutationProviderOutput } from "../../types"; +import { + TypedCollectionAssignProductMutation, + TypedCollectionRemoveMutation, + TypedCollectionUpdateMutation, + TypedCollectionUpdateWithHomepageMutation, + TypedUnassignCollectionProductMutation +} from "../mutations"; +import { + CollectionAssignProduct, + CollectionAssignProductVariables +} from "../types/CollectionAssignProduct"; +import { + CollectionUpdate, + CollectionUpdateVariables +} from "../types/CollectionUpdate"; +import { + CollectionUpdateWithHomepage, + CollectionUpdateWithHomepageVariables +} from "../types/CollectionUpdateWithHomepage"; +import { + RemoveCollection, + RemoveCollectionVariables +} from "../types/RemoveCollection"; +import { + UnassignCollectionProduct, + UnassignCollectionProductVariables +} from "../types/UnassignCollectionProduct"; + +interface CollectionUpdateOperationsProps { + children: ( + props: { + updateCollectionWithHomepage: PartialMutationProviderOutput< + CollectionUpdateWithHomepage, + CollectionUpdateWithHomepageVariables + >; + assignProduct: PartialMutationProviderOutput< + CollectionAssignProduct, + CollectionAssignProductVariables + >; + unassignProduct: PartialMutationProviderOutput< + UnassignCollectionProduct, + UnassignCollectionProductVariables + >; + updateCollection: PartialMutationProviderOutput< + CollectionUpdate, + CollectionUpdateVariables + >; + removeCollection: PartialMutationProviderOutput< + RemoveCollection, + RemoveCollectionVariables + >; + } + ) => React.ReactNode; + onUpdate: (data: CollectionUpdate) => void; + onProductAssign: (data: CollectionAssignProduct) => void; + onProductUnassign: (data: UnassignCollectionProduct) => void; + onRemove: (data: RemoveCollection) => void; +} + +const CollectionOperations: React.StatelessComponent< + CollectionUpdateOperationsProps +> = ({ children, onUpdate, onProductAssign, onProductUnassign, onRemove }) => ( + + {(...updateCollection) => ( + + {(...removeCollection) => ( + + {(...assignProduct) => ( + + {(...updateWithHomepage) => ( + + {(...unassignProduct) => + children({ + assignProduct: getMutationProviderData( + ...assignProduct + ), + removeCollection: getMutationProviderData( + ...removeCollection + ), + unassignProduct: getMutationProviderData( + ...unassignProduct + ), + updateCollection: getMutationProviderData( + ...updateCollection + ), + updateCollectionWithHomepage: getMutationProviderData( + ...updateWithHomepage + ) + }) + } + + )} + + )} + + )} + + )} + +); +export default CollectionOperations; diff --git a/src/collections/fixtures.ts b/src/collections/fixtures.ts new file mode 100644 index 000000000..423cf82fc --- /dev/null +++ b/src/collections/fixtures.ts @@ -0,0 +1,123 @@ +import { content } from "../storybook/stories/components/RichTextEditor"; +import { CollectionDetails_collection } from "./types/CollectionDetails"; +import { CollectionList_collections_edges_node } from "./types/CollectionList"; + +export const collections: CollectionList_collections_edges_node[] = [ + { + __typename: "Collection", + id: "Q29sbGVjdGlvbjox", + isPublished: true, + name: "Summer collection", + products: { + __typename: "ProductCountableConnection", + totalCount: 4 + } + }, + { + __typename: "Collection", + id: "Q29sbGVjdGlvbjoy", + isPublished: true, + name: "Winter sale", + products: { + __typename: "ProductCountableConnection", + totalCount: 4 + } + } +]; +export const collection: ( + placeholderCollectionImage: string, + placeholderProductImage: string +) => CollectionDetails_collection = ( + placeholderCollectionImage, + placeholderImage +) => ({ + __typename: "Collection", + backgroundImage: { + __typename: "Image", + alt: "Alt text", + url: placeholderCollectionImage + }, + descriptionJson: JSON.stringify(content), + id: "Q29sbGVjdGlvbjox", + isPublished: true, + name: "Summer collection", + products: { + __typename: "ProductCountableConnection", + edges: [ + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjA=", + node: { + __typename: "Product", + id: "UHJvZHVjdDoxNw==", + isPublished: true, + name: "Murray Inc", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mg==", + name: "Mugs" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjE=", + node: { + __typename: "Product", + id: "UHJvZHVjdDoyNw==", + isPublished: true, + name: "Williams-Taylor", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjI=", + node: { + __typename: "Product", + id: "UHJvZHVjdDoyOQ==", + isPublished: true, + name: "Hebert-Sherman", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Mw==", + name: "Coffee" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + }, + { + __typename: "ProductCountableEdge", + cursor: "YXJyYXljb25uZWN0aW9uOjM=", + node: { + __typename: "Product", + id: "UHJvZHVjdDo1Mw==", + isPublished: true, + name: "Estes, Johnson and Graham", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6Ng==", + name: "Books" + }, + thumbnail: { __typename: "Image", url: placeholderImage } + } + } + ], + pageInfo: { + __typename: "PageInfo", + endCursor: "", + hasNextPage: false, + hasPreviousPage: false, + startCursor: "" + } + }, + publicationDate: "2018-08-25T18:45:54.125Z", + seoDescription: "", + seoTitle: "" +}); diff --git a/src/collections/index.tsx b/src/collections/index.tsx new file mode 100644 index 000000000..9706de5ce --- /dev/null +++ b/src/collections/index.tsx @@ -0,0 +1,52 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { WindowTitle } from "../components/WindowTitle"; +import i18n from "../i18n"; +import { + collectionAddPath, + collectionListPath, + CollectionListUrlQueryParams, + collectionPath, + CollectionUrlQueryParams +} from "./urls"; +import CollectionCreate from "./views/CollectionCreate"; +import CollectionDetailsView from "./views/CollectionDetails"; +import CollectionListView from "./views/CollectionList"; + +const CollectionList: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: CollectionListUrlQueryParams = qs; + return ; +}; + +interface CollectionDetailsRouteProps { + id: string; +} +const CollectionDetails: React.StatelessComponent< + RouteComponentProps +> = ({ location, match }) => { + const qs = parseQs(location.search.substr(1)); + const params: CollectionUrlQueryParams = qs; + return ( + + ); +}; + +const Component = () => ( + <> + + + + + + + +); +export default Component; diff --git a/src/collections/mutations.ts b/src/collections/mutations.ts new file mode 100644 index 000000000..94623492f --- /dev/null +++ b/src/collections/mutations.ts @@ -0,0 +1,245 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { + collectionDetailsFragment, + collectionProductFragment +} from "./queries"; +import { + CollectionAssignProduct, + CollectionAssignProductVariables +} from "./types/CollectionAssignProduct"; +import { + CollectionBulkDelete, + CollectionBulkDeleteVariables +} from "./types/CollectionBulkDelete"; +import { + CollectionBulkPublish, + CollectionBulkPublishVariables +} from "./types/CollectionBulkPublish"; +import { + CollectionUpdate, + CollectionUpdateVariables +} from "./types/CollectionUpdate"; +import { + CollectionUpdateWithHomepage, + CollectionUpdateWithHomepageVariables +} from "./types/CollectionUpdateWithHomepage"; +import { + CreateCollection, + CreateCollectionVariables +} from "./types/CreateCollection"; +import { + RemoveCollection, + RemoveCollectionVariables +} from "./types/RemoveCollection"; +import { + UnassignCollectionProduct, + UnassignCollectionProductVariables +} from "./types/UnassignCollectionProduct"; + +const collectionUpdate = gql` + ${collectionDetailsFragment} + mutation CollectionUpdate($id: ID!, $input: CollectionInput!) { + collectionUpdate(id: $id, input: $input) { + errors { + field + message + } + collection { + ...CollectionDetailsFragment + } + } + } +`; +export const TypedCollectionUpdateMutation = TypedMutation< + CollectionUpdate, + CollectionUpdateVariables +>(collectionUpdate); + +const collectionUpdateWithHomepage = gql` + ${collectionDetailsFragment} + mutation CollectionUpdateWithHomepage( + $id: ID! + $input: CollectionInput! + $homepageId: ID + ) { + homepageCollectionUpdate(collection: $homepageId) { + errors { + field + message + } + shop { + homepageCollection { + id + } + } + } + collectionUpdate(id: $id, input: $input) { + errors { + field + message + } + collection { + ...CollectionDetailsFragment + } + } + } +`; +export const TypedCollectionUpdateWithHomepageMutation = TypedMutation< + CollectionUpdateWithHomepage, + CollectionUpdateWithHomepageVariables +>(collectionUpdateWithHomepage); + +const assignCollectionProduct = gql` + ${collectionProductFragment} + mutation CollectionAssignProduct( + $collectionId: ID! + $productIds: [ID!]! + $first: Int + $after: String + $last: Int + $before: String + ) { + collectionAddProducts(collectionId: $collectionId, products: $productIds) { + errors { + field + message + } + collection { + id + products(first: $first, after: $after, before: $before, last: $last) { + edges { + node { + ...CollectionProductFragment + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + } + } + } +`; +export const TypedCollectionAssignProductMutation = TypedMutation< + CollectionAssignProduct, + CollectionAssignProductVariables +>(assignCollectionProduct); + +const createCollection = gql` + ${collectionDetailsFragment} + mutation CreateCollection($input: CollectionCreateInput!) { + collectionCreate(input: $input) { + errors { + field + message + } + collection { + ...CollectionDetailsFragment + } + } + } +`; +export const TypedCollectionCreateMutation = TypedMutation< + CreateCollection, + CreateCollectionVariables +>(createCollection); + +const removeCollection = gql` + mutation RemoveCollection($id: ID!) { + collectionDelete(id: $id) { + errors { + field + message + } + } + } +`; +export const TypedCollectionRemoveMutation = TypedMutation< + RemoveCollection, + RemoveCollectionVariables +>(removeCollection); + +const unassignCollectionProduct = gql` + mutation UnassignCollectionProduct( + $collectionId: ID! + $productIds: [ID]! + $first: Int + $after: String + $last: Int + $before: String + ) { + collectionRemoveProducts( + collectionId: $collectionId + products: $productIds + ) { + errors { + field + message + } + collection { + id + products(first: $first, after: $after, before: $before, last: $last) { + edges { + node { + id + isPublished + name + productType { + id + name + } + thumbnail { + url + } + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + } + } + } +`; +export const TypedUnassignCollectionProductMutation = TypedMutation< + UnassignCollectionProduct, + UnassignCollectionProductVariables +>(unassignCollectionProduct); + +const collectionBulkDelete = gql` + mutation CollectionBulkDelete($ids: [ID]!) { + collectionBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedCollectionBulkDelete = TypedMutation< + CollectionBulkDelete, + CollectionBulkDeleteVariables +>(collectionBulkDelete); + +const collectionBulkPublish = gql` + mutation CollectionBulkPublish($ids: [ID]!, $isPublished: Boolean!) { + collectionBulkPublish(ids: $ids, isPublished: $isPublished) { + errors { + field + message + } + } + } +`; +export const TypedCollectionBulkPublish = TypedMutation< + CollectionBulkPublish, + CollectionBulkPublishVariables +>(collectionBulkPublish); diff --git a/src/collections/queries.ts b/src/collections/queries.ts new file mode 100644 index 000000000..f13bcc24e --- /dev/null +++ b/src/collections/queries.ts @@ -0,0 +1,123 @@ +import gql from "graphql-tag"; + +import { TypedQuery } from "../queries"; +import { + CollectionDetails, + CollectionDetailsVariables +} from "./types/CollectionDetails"; +import { + CollectionList, + CollectionListVariables +} from "./types/CollectionList"; + +export const collectionFragment = gql` + fragment CollectionFragment on Collection { + id + isPublished + name + } +`; + +export const collectionDetailsFragment = gql` + ${collectionFragment} + fragment CollectionDetailsFragment on Collection { + ...CollectionFragment + backgroundImage { + alt + url + } + descriptionJson + publicationDate + seoDescription + seoTitle + isPublished + } +`; + +// This fragment is used to make sure that product's fields that are returned +// are always the same - fixes apollo cache +// https://github.com/apollographql/apollo-client/issues/2496 +// https://github.com/apollographql/apollo-client/issues/3468 +export const collectionProductFragment = gql` + fragment CollectionProductFragment on Product { + id + isPublished + name + productType { + id + name + } + thumbnail { + url + } + } +`; + +export const collectionList = gql` + ${collectionFragment} + query CollectionList( + $first: Int + $after: String + $last: Int + $before: String + ) { + collections(first: $first, after: $after, before: $before, last: $last) { + edges { + node { + ...CollectionFragment + products { + totalCount + } + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + } +`; +export const TypedCollectionListQuery = TypedQuery< + CollectionList, + CollectionListVariables +>(collectionList); + +export const collectionDetails = gql` + ${collectionDetailsFragment} + ${collectionProductFragment} + query CollectionDetails( + $id: ID! + $first: Int + $after: String + $last: Int + $before: String + ) { + collection(id: $id) { + ...CollectionDetailsFragment + products(first: $first, after: $after, before: $before, last: $last) { + edges { + node { + ...CollectionProductFragment + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + } + shop { + homepageCollection { + id + } + } + } +`; +export const TypedCollectionDetailsQuery = TypedQuery< + CollectionDetails, + CollectionDetailsVariables +>(collectionDetails); diff --git a/src/collections/types/AssignHomepageCollection.ts b/src/collections/types/AssignHomepageCollection.ts new file mode 100644 index 000000000..48c912009 --- /dev/null +++ b/src/collections/types/AssignHomepageCollection.ts @@ -0,0 +1,36 @@ +/* tslint:disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: AssignHomepageCollection +// ==================================================== + +export interface AssignHomepageCollection_homepageCollectionUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface AssignHomepageCollection_homepageCollectionUpdate_shop_homepageCollection { + __typename: "Collection"; + id: string; +} + +export interface AssignHomepageCollection_homepageCollectionUpdate_shop { + __typename: "Shop"; + homepageCollection: AssignHomepageCollection_homepageCollectionUpdate_shop_homepageCollection | null; +} + +export interface AssignHomepageCollection_homepageCollectionUpdate { + __typename: "HomepageCollectionUpdate"; + errors: AssignHomepageCollection_homepageCollectionUpdate_errors[] | null; + shop: AssignHomepageCollection_homepageCollectionUpdate_shop | null; +} + +export interface AssignHomepageCollection { + homepageCollectionUpdate: AssignHomepageCollection_homepageCollectionUpdate | null; +} + +export interface AssignHomepageCollectionVariables { + id?: string | null; +} diff --git a/src/collections/types/CollectionAssignProduct.ts b/src/collections/types/CollectionAssignProduct.ts new file mode 100644 index 000000000..dc8fd3839 --- /dev/null +++ b/src/collections/types/CollectionAssignProduct.ts @@ -0,0 +1,77 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: CollectionAssignProduct +// ==================================================== + +export interface CollectionAssignProduct_collectionAddProducts_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CollectionAssignProduct_collectionAddProducts_collection_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface CollectionAssignProduct_collectionAddProducts_collection_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface CollectionAssignProduct_collectionAddProducts_collection_products_edges_node { + __typename: "Product"; + id: string; + isPublished: boolean; + name: string; + productType: CollectionAssignProduct_collectionAddProducts_collection_products_edges_node_productType; + thumbnail: CollectionAssignProduct_collectionAddProducts_collection_products_edges_node_thumbnail | null; +} + +export interface CollectionAssignProduct_collectionAddProducts_collection_products_edges { + __typename: "ProductCountableEdge"; + node: CollectionAssignProduct_collectionAddProducts_collection_products_edges_node; +} + +export interface CollectionAssignProduct_collectionAddProducts_collection_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface CollectionAssignProduct_collectionAddProducts_collection_products { + __typename: "ProductCountableConnection"; + edges: CollectionAssignProduct_collectionAddProducts_collection_products_edges[]; + pageInfo: CollectionAssignProduct_collectionAddProducts_collection_products_pageInfo; +} + +export interface CollectionAssignProduct_collectionAddProducts_collection { + __typename: "Collection"; + id: string; + products: CollectionAssignProduct_collectionAddProducts_collection_products | null; +} + +export interface CollectionAssignProduct_collectionAddProducts { + __typename: "CollectionAddProducts"; + errors: CollectionAssignProduct_collectionAddProducts_errors[] | null; + collection: CollectionAssignProduct_collectionAddProducts_collection | null; +} + +export interface CollectionAssignProduct { + collectionAddProducts: CollectionAssignProduct_collectionAddProducts | null; +} + +export interface CollectionAssignProductVariables { + collectionId: string; + productIds: string[]; + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/collections/types/CollectionBulkDelete.ts b/src/collections/types/CollectionBulkDelete.ts new file mode 100644 index 000000000..3afafab50 --- /dev/null +++ b/src/collections/types/CollectionBulkDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: CollectionBulkDelete +// ==================================================== + +export interface CollectionBulkDelete_collectionBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CollectionBulkDelete_collectionBulkDelete { + __typename: "CollectionBulkDelete"; + errors: CollectionBulkDelete_collectionBulkDelete_errors[] | null; +} + +export interface CollectionBulkDelete { + collectionBulkDelete: CollectionBulkDelete_collectionBulkDelete | null; +} + +export interface CollectionBulkDeleteVariables { + ids: (string | null)[]; +} diff --git a/src/collections/types/CollectionBulkPublish.ts b/src/collections/types/CollectionBulkPublish.ts new file mode 100644 index 000000000..9cb56e743 --- /dev/null +++ b/src/collections/types/CollectionBulkPublish.ts @@ -0,0 +1,27 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: CollectionBulkPublish +// ==================================================== + +export interface CollectionBulkPublish_collectionBulkPublish_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CollectionBulkPublish_collectionBulkPublish { + __typename: "CollectionBulkPublish"; + errors: CollectionBulkPublish_collectionBulkPublish_errors[] | null; +} + +export interface CollectionBulkPublish { + collectionBulkPublish: CollectionBulkPublish_collectionBulkPublish | null; +} + +export interface CollectionBulkPublishVariables { + ids: (string | null)[]; + isPublished: boolean; +} diff --git a/src/collections/types/CollectionDetails.ts b/src/collections/types/CollectionDetails.ts new file mode 100644 index 000000000..bfbc9441c --- /dev/null +++ b/src/collections/types/CollectionDetails.ts @@ -0,0 +1,88 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: CollectionDetails +// ==================================================== + +export interface CollectionDetails_collection_backgroundImage { + __typename: "Image"; + alt: string | null; + url: string; +} + +export interface CollectionDetails_collection_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface CollectionDetails_collection_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface CollectionDetails_collection_products_edges_node { + __typename: "Product"; + id: string; + isPublished: boolean; + name: string; + productType: CollectionDetails_collection_products_edges_node_productType; + thumbnail: CollectionDetails_collection_products_edges_node_thumbnail | null; +} + +export interface CollectionDetails_collection_products_edges { + __typename: "ProductCountableEdge"; + node: CollectionDetails_collection_products_edges_node; +} + +export interface CollectionDetails_collection_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface CollectionDetails_collection_products { + __typename: "ProductCountableConnection"; + edges: CollectionDetails_collection_products_edges[]; + pageInfo: CollectionDetails_collection_products_pageInfo; +} + +export interface CollectionDetails_collection { + __typename: "Collection"; + id: string; + isPublished: boolean; + name: string; + backgroundImage: CollectionDetails_collection_backgroundImage | null; + descriptionJson: any; + publicationDate: any | null; + seoDescription: string | null; + seoTitle: string | null; + products: CollectionDetails_collection_products | null; +} + +export interface CollectionDetails_shop_homepageCollection { + __typename: "Collection"; + id: string; +} + +export interface CollectionDetails_shop { + __typename: "Shop"; + homepageCollection: CollectionDetails_shop_homepageCollection | null; +} + +export interface CollectionDetails { + collection: CollectionDetails_collection | null; + shop: CollectionDetails_shop | null; +} + +export interface CollectionDetailsVariables { + id: string; + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/collections/types/CollectionDetailsFragment.ts b/src/collections/types/CollectionDetailsFragment.ts new file mode 100644 index 000000000..24ae24d14 --- /dev/null +++ b/src/collections/types/CollectionDetailsFragment.ts @@ -0,0 +1,25 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: CollectionDetailsFragment +// ==================================================== + +export interface CollectionDetailsFragment_backgroundImage { + __typename: "Image"; + alt: string | null; + url: string; +} + +export interface CollectionDetailsFragment { + __typename: "Collection"; + id: string; + isPublished: boolean; + name: string; + backgroundImage: CollectionDetailsFragment_backgroundImage | null; + descriptionJson: any; + publicationDate: any | null; + seoDescription: string | null; + seoTitle: string | null; +} diff --git a/src/collections/types/CollectionFragment.ts b/src/collections/types/CollectionFragment.ts new file mode 100644 index 000000000..0dfb0475a --- /dev/null +++ b/src/collections/types/CollectionFragment.ts @@ -0,0 +1,14 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: CollectionFragment +// ==================================================== + +export interface CollectionFragment { + __typename: "Collection"; + id: string; + isPublished: boolean; + name: string; +} diff --git a/src/collections/types/CollectionList.ts b/src/collections/types/CollectionList.ts new file mode 100644 index 000000000..c17574dc0 --- /dev/null +++ b/src/collections/types/CollectionList.ts @@ -0,0 +1,50 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: CollectionList +// ==================================================== + +export interface CollectionList_collections_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface CollectionList_collections_edges_node { + __typename: "Collection"; + id: string; + isPublished: boolean; + name: string; + products: CollectionList_collections_edges_node_products | null; +} + +export interface CollectionList_collections_edges { + __typename: "CollectionCountableEdge"; + node: CollectionList_collections_edges_node; +} + +export interface CollectionList_collections_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface CollectionList_collections { + __typename: "CollectionCountableConnection"; + edges: CollectionList_collections_edges[]; + pageInfo: CollectionList_collections_pageInfo; +} + +export interface CollectionList { + collections: CollectionList_collections | null; +} + +export interface CollectionListVariables { + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/collections/types/CollectionProductFragment.ts b/src/collections/types/CollectionProductFragment.ts new file mode 100644 index 000000000..987f310e0 --- /dev/null +++ b/src/collections/types/CollectionProductFragment.ts @@ -0,0 +1,27 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: CollectionProductFragment +// ==================================================== + +export interface CollectionProductFragment_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface CollectionProductFragment_thumbnail { + __typename: "Image"; + url: string; +} + +export interface CollectionProductFragment { + __typename: "Product"; + id: string; + isPublished: boolean; + name: string; + productType: CollectionProductFragment_productType; + thumbnail: CollectionProductFragment_thumbnail | null; +} diff --git a/src/collections/types/CollectionUpdate.ts b/src/collections/types/CollectionUpdate.ts new file mode 100644 index 000000000..91453df7d --- /dev/null +++ b/src/collections/types/CollectionUpdate.ts @@ -0,0 +1,48 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { CollectionInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: CollectionUpdate +// ==================================================== + +export interface CollectionUpdate_collectionUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CollectionUpdate_collectionUpdate_collection_backgroundImage { + __typename: "Image"; + alt: string | null; + url: string; +} + +export interface CollectionUpdate_collectionUpdate_collection { + __typename: "Collection"; + id: string; + isPublished: boolean; + name: string; + backgroundImage: CollectionUpdate_collectionUpdate_collection_backgroundImage | null; + descriptionJson: any; + publicationDate: any | null; + seoDescription: string | null; + seoTitle: string | null; +} + +export interface CollectionUpdate_collectionUpdate { + __typename: "CollectionUpdate"; + errors: CollectionUpdate_collectionUpdate_errors[] | null; + collection: CollectionUpdate_collectionUpdate_collection | null; +} + +export interface CollectionUpdate { + collectionUpdate: CollectionUpdate_collectionUpdate | null; +} + +export interface CollectionUpdateVariables { + id: string; + input: CollectionInput; +} diff --git a/src/collections/types/CollectionUpdateWithHomepage.ts b/src/collections/types/CollectionUpdateWithHomepage.ts new file mode 100644 index 000000000..f378cc904 --- /dev/null +++ b/src/collections/types/CollectionUpdateWithHomepage.ts @@ -0,0 +1,72 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { CollectionInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: CollectionUpdateWithHomepage +// ==================================================== + +export interface CollectionUpdateWithHomepage_homepageCollectionUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CollectionUpdateWithHomepage_homepageCollectionUpdate_shop_homepageCollection { + __typename: "Collection"; + id: string; +} + +export interface CollectionUpdateWithHomepage_homepageCollectionUpdate_shop { + __typename: "Shop"; + homepageCollection: CollectionUpdateWithHomepage_homepageCollectionUpdate_shop_homepageCollection | null; +} + +export interface CollectionUpdateWithHomepage_homepageCollectionUpdate { + __typename: "HomepageCollectionUpdate"; + errors: CollectionUpdateWithHomepage_homepageCollectionUpdate_errors[] | null; + shop: CollectionUpdateWithHomepage_homepageCollectionUpdate_shop | null; +} + +export interface CollectionUpdateWithHomepage_collectionUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CollectionUpdateWithHomepage_collectionUpdate_collection_backgroundImage { + __typename: "Image"; + alt: string | null; + url: string; +} + +export interface CollectionUpdateWithHomepage_collectionUpdate_collection { + __typename: "Collection"; + id: string; + isPublished: boolean; + name: string; + backgroundImage: CollectionUpdateWithHomepage_collectionUpdate_collection_backgroundImage | null; + descriptionJson: any; + publicationDate: any | null; + seoDescription: string | null; + seoTitle: string | null; +} + +export interface CollectionUpdateWithHomepage_collectionUpdate { + __typename: "CollectionUpdate"; + errors: CollectionUpdateWithHomepage_collectionUpdate_errors[] | null; + collection: CollectionUpdateWithHomepage_collectionUpdate_collection | null; +} + +export interface CollectionUpdateWithHomepage { + homepageCollectionUpdate: CollectionUpdateWithHomepage_homepageCollectionUpdate | null; + collectionUpdate: CollectionUpdateWithHomepage_collectionUpdate | null; +} + +export interface CollectionUpdateWithHomepageVariables { + id: string; + input: CollectionInput; + homepageId?: string | null; +} diff --git a/src/collections/types/CreateCollection.ts b/src/collections/types/CreateCollection.ts new file mode 100644 index 000000000..25987de78 --- /dev/null +++ b/src/collections/types/CreateCollection.ts @@ -0,0 +1,47 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { CollectionCreateInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: CreateCollection +// ==================================================== + +export interface CreateCollection_collectionCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CreateCollection_collectionCreate_collection_backgroundImage { + __typename: "Image"; + alt: string | null; + url: string; +} + +export interface CreateCollection_collectionCreate_collection { + __typename: "Collection"; + id: string; + isPublished: boolean; + name: string; + backgroundImage: CreateCollection_collectionCreate_collection_backgroundImage | null; + descriptionJson: any; + publicationDate: any | null; + seoDescription: string | null; + seoTitle: string | null; +} + +export interface CreateCollection_collectionCreate { + __typename: "CollectionCreate"; + errors: CreateCollection_collectionCreate_errors[] | null; + collection: CreateCollection_collectionCreate_collection | null; +} + +export interface CreateCollection { + collectionCreate: CreateCollection_collectionCreate | null; +} + +export interface CreateCollectionVariables { + input: CollectionCreateInput; +} diff --git a/src/collections/types/RemoveCollection.ts b/src/collections/types/RemoveCollection.ts new file mode 100644 index 000000000..de2c96483 --- /dev/null +++ b/src/collections/types/RemoveCollection.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: RemoveCollection +// ==================================================== + +export interface RemoveCollection_collectionDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface RemoveCollection_collectionDelete { + __typename: "CollectionDelete"; + errors: RemoveCollection_collectionDelete_errors[] | null; +} + +export interface RemoveCollection { + collectionDelete: RemoveCollection_collectionDelete | null; +} + +export interface RemoveCollectionVariables { + id: string; +} diff --git a/src/collections/types/SearchProducts.ts b/src/collections/types/SearchProducts.ts new file mode 100644 index 000000000..495338a8e --- /dev/null +++ b/src/collections/types/SearchProducts.ts @@ -0,0 +1,44 @@ +/* tslint:disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: SearchProducts +// ==================================================== + +export interface SearchProducts_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface SearchProducts_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface SearchProducts_products_edges_node { + __typename: "Product"; + id: string; + isPublished: boolean; + name: string; + productType: SearchProducts_products_edges_node_productType; + thumbnail: SearchProducts_products_edges_node_thumbnail | null; +} + +export interface SearchProducts_products_edges { + __typename: "ProductCountableEdge"; + node: SearchProducts_products_edges_node; +} + +export interface SearchProducts_products { + __typename: "ProductCountableConnection"; + edges: SearchProducts_products_edges[]; +} + +export interface SearchProducts { + products: SearchProducts_products | null; +} + +export interface SearchProductsVariables { + query: string; +} diff --git a/src/collections/types/UnassignCollectionProduct.ts b/src/collections/types/UnassignCollectionProduct.ts new file mode 100644 index 000000000..d5bbfc650 --- /dev/null +++ b/src/collections/types/UnassignCollectionProduct.ts @@ -0,0 +1,77 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: UnassignCollectionProduct +// ==================================================== + +export interface UnassignCollectionProduct_collectionRemoveProducts_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface UnassignCollectionProduct_collectionRemoveProducts_collection_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface UnassignCollectionProduct_collectionRemoveProducts_collection_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface UnassignCollectionProduct_collectionRemoveProducts_collection_products_edges_node { + __typename: "Product"; + id: string; + isPublished: boolean; + name: string; + productType: UnassignCollectionProduct_collectionRemoveProducts_collection_products_edges_node_productType; + thumbnail: UnassignCollectionProduct_collectionRemoveProducts_collection_products_edges_node_thumbnail | null; +} + +export interface UnassignCollectionProduct_collectionRemoveProducts_collection_products_edges { + __typename: "ProductCountableEdge"; + node: UnassignCollectionProduct_collectionRemoveProducts_collection_products_edges_node; +} + +export interface UnassignCollectionProduct_collectionRemoveProducts_collection_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface UnassignCollectionProduct_collectionRemoveProducts_collection_products { + __typename: "ProductCountableConnection"; + edges: UnassignCollectionProduct_collectionRemoveProducts_collection_products_edges[]; + pageInfo: UnassignCollectionProduct_collectionRemoveProducts_collection_products_pageInfo; +} + +export interface UnassignCollectionProduct_collectionRemoveProducts_collection { + __typename: "Collection"; + id: string; + products: UnassignCollectionProduct_collectionRemoveProducts_collection_products | null; +} + +export interface UnassignCollectionProduct_collectionRemoveProducts { + __typename: "CollectionRemoveProducts"; + errors: UnassignCollectionProduct_collectionRemoveProducts_errors[] | null; + collection: UnassignCollectionProduct_collectionRemoveProducts_collection | null; +} + +export interface UnassignCollectionProduct { + collectionRemoveProducts: UnassignCollectionProduct_collectionRemoveProducts | null; +} + +export interface UnassignCollectionProductVariables { + collectionId: string; + productIds: (string | null)[]; + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/collections/urls.ts b/src/collections/urls.ts new file mode 100644 index 000000000..305fadbee --- /dev/null +++ b/src/collections/urls.ts @@ -0,0 +1,29 @@ +import { stringify as stringifyQs } from "qs"; +import * as urlJoin from "url-join"; + +import { BulkAction, Dialog, Pagination } from "../types"; + +const collectionSectionUrl = "/collections/"; + +export const collectionListPath = collectionSectionUrl; +export type CollectionListUrlDialog = "publish" | "unpublish" | "remove"; +export type CollectionListUrlQueryParams = BulkAction & + Dialog & + Pagination; +export const collectionListUrl = (params?: CollectionListUrlQueryParams) => + collectionSectionUrl + "?" + stringifyQs(params); + +export const collectionPath = (id: string) => urlJoin(collectionSectionUrl, id); +export type CollectionUrlDialog = + | "remove" + | "removeImage" + | "assign" + | "unassign"; +export type CollectionUrlQueryParams = BulkAction & + Pagination & + Dialog; +export const collectionUrl = (id: string, params?: CollectionUrlQueryParams) => + collectionPath(encodeURIComponent(id)) + "?" + stringifyQs(params); + +export const collectionAddPath = urlJoin(collectionSectionUrl, "add"); +export const collectionAddUrl = collectionAddPath; diff --git a/src/collections/views/CollectionCreate.tsx b/src/collections/views/CollectionCreate.tsx new file mode 100644 index 000000000..24c4eb73f --- /dev/null +++ b/src/collections/views/CollectionCreate.tsx @@ -0,0 +1,78 @@ +import * as React from "react"; + +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import { CollectionCreateInput } from "../../types/globalTypes"; +import CollectionCreatePage from "../components/CollectionCreatePage/CollectionCreatePage"; +import { TypedCollectionCreateMutation } from "../mutations"; +import { CreateCollection } from "../types/CreateCollection"; +import { collectionListUrl, collectionUrl } from "../urls"; + +export const CollectionCreate: React.StatelessComponent<{}> = () => { + const navigate = useNavigator(); + const notify = useNotifier(); + + const handleCollectionCreateSuccess = (data: CreateCollection) => { + if (data.collectionCreate.errors.length === 0) { + notify({ + text: i18n.t("Created collection", { + context: "notification" + }) + }); + navigate(collectionUrl(data.collectionCreate.collection.id)); + } else { + const backgroundImageError = data.collectionCreate.errors.find( + error => + error.field === ("backgroundImage" as keyof CollectionCreateInput) + ); + if (backgroundImageError) { + notify({ + text: backgroundImageError.message + }); + } + } + }; + return ( + + {(createCollection, { called, data, loading }) => { + const formTransitionState = getMutationState( + called, + loading, + maybe(() => data.collectionCreate.errors) + ); + return ( + <> + + data.collectionCreate.errors, [])} + onBack={() => navigate(collectionListUrl())} + disabled={loading} + onSubmit={formData => + createCollection({ + variables: { + input: { + backgroundImage: formData.backgroundImage.value, + backgroundImageAlt: formData.backgroundImageAlt, + descriptionJson: JSON.stringify(formData.description), + isPublished: formData.isPublished, + name: formData.name, + seo: { + description: formData.seoDescription, + title: formData.seoTitle + } + } + } + }) + } + saveButtonBarState={formTransitionState} + /> + + ); + }} + + ); +}; +export default CollectionCreate; diff --git a/src/collections/views/CollectionDetails.tsx b/src/collections/views/CollectionDetails.tsx new file mode 100644 index 000000000..f9e8c7a3c --- /dev/null +++ b/src/collections/views/CollectionDetails.tsx @@ -0,0 +1,395 @@ +import Button from "@material-ui/core/Button"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import AssignProductDialog from "@saleor/components/AssignProductDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config"; +import SearchProducts from "../../containers/SearchProducts"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import { productUrl } from "../../products/urls"; +import { CollectionInput } from "../../types/globalTypes"; +import CollectionDetailsPage, { + CollectionDetailsPageFormData +} from "../components/CollectionDetailsPage/CollectionDetailsPage"; +import CollectionOperations from "../containers/CollectionOperations"; +import { TypedCollectionDetailsQuery } from "../queries"; +import { CollectionAssignProduct } from "../types/CollectionAssignProduct"; +import { CollectionUpdate } from "../types/CollectionUpdate"; +import { RemoveCollection } from "../types/RemoveCollection"; +import { UnassignCollectionProduct } from "../types/UnassignCollectionProduct"; +import { + collectionListUrl, + collectionUrl, + CollectionUrlDialog, + CollectionUrlQueryParams +} from "../urls"; + +interface CollectionDetailsProps { + id: string; + params: CollectionUrlQueryParams; +} + +export const CollectionDetails: React.StatelessComponent< + CollectionDetailsProps +> = ({ id, params }) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + const paginate = usePaginator(); + + const closeModal = () => + navigate( + collectionUrl(id, { + ...params, + action: undefined + }), + true + ); + const openModal = (action: CollectionUrlDialog) => + navigate( + collectionUrl(id, { + ...params, + action + }), + false + ); + + const paginationState = createPaginationState(PAGINATE_BY, params); + + return ( + + {({ data, loading }) => { + const handleCollectionUpdate = (data: CollectionUpdate) => { + if (data.collectionUpdate.errors.length === 0) { + notify({ + text: i18n.t("Updated collection", { + context: "notification" + }) + }); + navigate(collectionUrl(id)); + } else { + const backgroundImageError = data.collectionUpdate.errors.find( + error => + error.field === ("backgroundImage" as keyof CollectionInput) + ); + if (backgroundImageError) { + notify({ + text: backgroundImageError.message + }); + } + } + }; + + const handleProductAssign = (data: CollectionAssignProduct) => { + if (data.collectionAddProducts.errors.length === 0) { + notify({ + text: i18n.t("Added product to collection", { + context: "notification" + }) + }); + navigate(collectionUrl(id), true); + } + }; + + const handleProductUnassign = (data: UnassignCollectionProduct) => { + if (data.collectionRemoveProducts.errors.length === 0) { + notify({ + text: i18n.t("Removed product from collection", { + context: "notification" + }) + }); + reset(); + closeModal(); + } + }; + + const handleCollectionRemove = (data: RemoveCollection) => { + if (data.collectionDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed collection", { + context: "notification" + }) + }); + navigate(collectionListUrl()); + } + }; + return ( + + {({ + updateCollection, + updateCollectionWithHomepage, + assignProduct, + unassignProduct, + removeCollection + }) => { + const handleSubmit = ( + formData: CollectionDetailsPageFormData + ) => { + const input: CollectionInput = { + backgroundImageAlt: formData.backgroundImageAlt, + descriptionJson: JSON.stringify(formData.description), + isPublished: formData.isPublished, + name: formData.name, + publicationDate: formData.publicationDate, + seo: { + description: formData.seoDescription, + title: formData.seoTitle + } + }; + const isFeatured = data.shop.homepageCollection + ? data.shop.homepageCollection.id === data.collection.id + : false; + + if (formData.isFeatured !== isFeatured) { + updateCollectionWithHomepage.mutate({ + homepageId: formData.isFeatured ? id : null, + id, + input + }); + } else { + updateCollection.mutate({ + id, + input + }); + } + }; + + const formTransitionState = getMutationState( + updateCollection.opts.called || + updateCollectionWithHomepage.opts.called, + updateCollection.opts.loading || + updateCollectionWithHomepage.opts.loading, + maybe(() => updateCollection.opts.data.collectionUpdate.errors), + maybe( + () => + updateCollectionWithHomepage.opts.data.collectionUpdate + .errors + ), + maybe( + () => + updateCollectionWithHomepage.opts.data + .homepageCollectionUpdate.errors + ) + ); + const assignTransitionState = getMutationState( + assignProduct.opts.called, + assignProduct.opts.loading, + maybe( + () => assignProduct.opts.data.collectionAddProducts.errors + ) + ); + const unassignTransitionState = getMutationState( + unassignProduct.opts.called, + unassignProduct.opts.loading, + maybe( + () => + unassignProduct.opts.data.collectionRemoveProducts.errors + ) + ); + const removeTransitionState = getMutationState( + removeCollection.opts.called, + removeCollection.opts.loading, + maybe(() => removeCollection.opts.data.collectionDelete.errors) + ); + const imageRemoveTransitionState = getMutationState( + updateCollection.opts.called, + updateCollection.opts.loading, + maybe(() => updateCollection.opts.data.collectionUpdate.errors) + ); + + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.collection.products.pageInfo), + paginationState, + params + ); + + return ( + <> + data.collection.name)} /> + openModal("assign")} + onBack={() => navigate(collectionListUrl())} + disabled={loading} + collection={data.collection} + isFeatured={maybe( + () => + data.shop.homepageCollection.id === data.collection.id, + false + )} + onCollectionRemove={() => openModal("remove")} + onImageDelete={() => openModal("removeImage")} + onImageUpload={file => + updateCollection.mutate({ + id, + input: { + backgroundImage: file + } + }) + } + onSubmit={handleSubmit} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + pageInfo={pageInfo} + onProductUnassign={(productId, event) => { + event.stopPropagation(); + unassignProduct.mutate({ + collectionId: id, + productIds: [productId], + ...paginationState + }); + }} + onRowClick={id => () => navigate(productUrl(id))} + saveButtonBarState={formTransitionState} + toolbar={ + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + /> + + {({ search, result }) => ( + navigate(collectionUrl(id), true, true)} + onSubmit={formData => + assignProduct.mutate({ + ...paginationState, + collectionId: id, + productIds: formData.products.map( + product => product.id + ) + }) + } + products={maybe(() => + result.data.products.edges + .map(edge => edge.node) + .filter(suggestedProduct => suggestedProduct.id) + )} + /> + )} + + removeCollection.mutate({ id })} + open={params.action === "remove"} + title={i18n.t("Remove collection", { + context: "modal title" + })} + variant="delete" + > + {{ collectionName }}?", + { + collectionName: maybe( + () => data.collection.name, + "..." + ), + context: "modal" + } + ) + }} + /> + + + unassignProduct.mutate({ + ...paginationState, + collectionId: id, + productIds: params.ids + }) + } + open={params.action === "unassign"} + title={i18n.t("Unassign products from collection", { + context: "modal title" + })} + > + {{ number }} products?", + { + context: "modal", + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + updateCollection.mutate({ + id, + input: { + backgroundImage: null + } + }) + } + open={params.action === "removeImage"} + title={i18n.t("Remove image", { + context: "modal title" + })} + variant="delete" + > + + {i18n.t( + "Are you sure you want to remove collection's image?" + )} + + + + ); + }} + + ); + }} + + ); +}; +export default CollectionDetails; diff --git a/src/collections/views/CollectionList.tsx b/src/collections/views/CollectionList.tsx new file mode 100644 index 000000000..4914dbbaf --- /dev/null +++ b/src/collections/views/CollectionList.tsx @@ -0,0 +1,262 @@ +import Button from "@material-ui/core/Button"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { PAGINATE_BY } from "../../config"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import CollectionListPage from "../components/CollectionListPage/CollectionListPage"; +import { + TypedCollectionBulkDelete, + TypedCollectionBulkPublish +} from "../mutations"; +import { TypedCollectionListQuery } from "../queries"; +import { CollectionBulkDelete } from "../types/CollectionBulkDelete"; +import { CollectionBulkPublish } from "../types/CollectionBulkPublish"; +import { + collectionAddUrl, + collectionListUrl, + CollectionListUrlDialog, + CollectionListUrlQueryParams, + collectionUrl +} from "../urls"; + +interface CollectionListProps { + params: CollectionListUrlQueryParams; +} + +export const CollectionList: React.StatelessComponent = ({ + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const closeModal = () => + navigate( + collectionListUrl({ + ...params, + action: undefined, + ids: undefined + }), + true + ); + + const openModal = (action: CollectionListUrlDialog, ids: string[]) => + navigate( + collectionListUrl({ + action, + ids + }) + ); + + const paginationState = createPaginationState(PAGINATE_BY, params); + return ( + + {({ data, loading, refetch }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.collections.pageInfo), + paginationState, + params + ); + + const handleCollectionBulkDelete = (data: CollectionBulkDelete) => { + if (data.collectionBulkDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed collections") + }); + refetch(); + reset(); + closeModal(); + } + }; + + const handleCollectionBulkPublish = (data: CollectionBulkPublish) => { + if (data.collectionBulkPublish.errors.length === 0) { + notify({ + text: i18n.t("Changed publication status") + }); + refetch(); + reset(); + closeModal(); + } + }; + + return ( + + {(collectionBulkDelete, collectionBulkDeleteOpts) => ( + + {(collectionBulkPublish, collectionBulkPublishOpts) => { + const bulkDeleteTransitionState = getMutationState( + collectionBulkDeleteOpts.called, + collectionBulkDeleteOpts.loading, + maybe( + () => + collectionBulkDeleteOpts.data.collectionBulkDelete + .errors + ) + ); + + const bulkPublishTransitionState = getMutationState( + collectionBulkPublishOpts.called, + collectionBulkPublishOpts.loading, + maybe( + () => + collectionBulkPublishOpts.data.collectionBulkPublish + .errors + ) + ); + + return ( + <> + navigate(collectionAddUrl)} + disabled={loading} + collections={maybe(() => + data.collections.edges.map(edge => edge.node) + )} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + pageInfo={pageInfo} + onRowClick={id => () => navigate(collectionUrl(id))} + toolbar={ + <> + + + openModal("remove", listElements)} + > + + + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + /> + + collectionBulkPublish({ + variables: { + ids: params.ids, + isPublished: true + } + }) + } + variant="default" + title={i18n.t("Publish collections")} + > + {{ number }} collections?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + collectionBulkPublish({ + variables: { + ids: params.ids, + isPublished: false + } + }) + } + variant="default" + title={i18n.t("Unpublish collections")} + > + {{ number }} collections?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + collectionBulkDelete({ + variables: { + ids: params.ids + } + }) + } + variant="delete" + title={i18n.t("Remove collections")} + > + {{ number }} collections?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + ); + }} + + )} + + ); + }} + + ); +}; +export default CollectionList; diff --git a/src/components/ActionDialog/ActionDialog.tsx b/src/components/ActionDialog/ActionDialog.tsx new file mode 100644 index 000000000..ef4e4786f --- /dev/null +++ b/src/components/ActionDialog/ActionDialog.tsx @@ -0,0 +1,80 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as classNames from "classnames"; +import * as React from "react"; + +import i18n from "../../i18n"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "../ConfirmButton/ConfirmButton"; + +const styles = (theme: Theme) => + createStyles({ + deleteButton: { + "&:hover": { + backgroundColor: theme.palette.error.main + }, + backgroundColor: theme.palette.error.main, + color: theme.palette.error.contrastText + } + }); + +interface ActionDialogProps extends WithStyles { + children?: React.ReactNode; + confirmButtonLabel?: string; + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + title: string; + variant?: "default" | "delete"; + onClose?(); + onConfirm(); +} + +const ActionDialog = withStyles(styles, { name: "ActionDialog" })( + ({ + children, + classes, + confirmButtonLabel, + confirmButtonState, + open, + title, + variant, + onConfirm, + onClose + }: ActionDialogProps) => ( + + {title} + {children} + + + + {confirmButtonLabel || + (variant === "delete" + ? i18n.t("Delete", { context: "button" }) + : i18n.t("Confirm", { context: "button" }))} + + + + ) +); +ActionDialog.displayName = "ActionDialog"; +export default ActionDialog; diff --git a/src/components/ActionDialog/index.ts b/src/components/ActionDialog/index.ts new file mode 100644 index 000000000..1b7746fa0 --- /dev/null +++ b/src/components/ActionDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ActionDialog"; +export * from "./ActionDialog"; diff --git a/src/components/AddressEdit/AddressEdit.tsx b/src/components/AddressEdit/AddressEdit.tsx new file mode 100644 index 000000000..0e93fd823 --- /dev/null +++ b/src/components/AddressEdit/AddressEdit.tsx @@ -0,0 +1,187 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import { AddressTypeInput } from "../../customers/types"; +import i18n from "../../i18n"; +import { maybe } from "../../misc"; +import { FormErrors } from "../../types"; +import FormSpacer from "../FormSpacer"; +import SingleAutocompleteSelectField from "../SingleAutocompleteSelectField"; + +const styles = (theme: Theme) => + createStyles({ + root: { + display: "grid", + gridColumnGap: `${theme.spacing.unit * 2}px`, + gridTemplateColumns: "1fr 1fr" + } + }); + +interface AddressEditProps extends WithStyles { + countries?: Array<{ + code: string; + label: string; + }>; + data: AddressTypeInput; + disabled?: boolean; + errors: FormErrors; + onChange(event: React.ChangeEvent); +} + +const AddressEdit = withStyles(styles, { name: "AddressEdit" })( + ({ + classes, + countries, + data, + disabled, + errors, + onChange + }: AddressEditProps) => ( + <> +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + + + + +
+
+ +
+
+ +
+
+ + +
+
+ countries.map(c => ({ ...c, value: c.code })), + [] + )} + InputProps={{ + autoComplete: "off" + }} + /> +
+
+ +
+
+ + ) +); +AddressEdit.displayName = "AddressEdit"; +export default AddressEdit; diff --git a/src/components/AddressEdit/index.ts b/src/components/AddressEdit/index.ts new file mode 100644 index 000000000..677fa7730 --- /dev/null +++ b/src/components/AddressEdit/index.ts @@ -0,0 +1,2 @@ +export { default } from "./AddressEdit"; +export * from "./AddressEdit"; diff --git a/src/components/AddressFormatter/AddressFormatter.tsx b/src/components/AddressFormatter/AddressFormatter.tsx new file mode 100644 index 000000000..db16de1a4 --- /dev/null +++ b/src/components/AddressFormatter/AddressFormatter.tsx @@ -0,0 +1,48 @@ +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import { AddressType } from "../../customers/types"; +import Skeleton from "../Skeleton"; + +interface AddressFormatterProps { + address?: AddressType; +} + +const AddressFormatter: React.StatelessComponent = ({ + address +}) => { + if (!address) { + return ; + } + return ( +
+ + {address.firstName} {address.lastName} + + {address.companyName && ( + {address.companyName} + )} + + {address.streetAddress1} +
+ {address.streetAddress2} +
+ + {" "} + {address.postalCode} {address.city} + {address.cityArea ? ", " + address.cityArea : ""} + + + {address.countryArea + ? address.countryArea + ", " + address.country.country + : address.country.country} + +
+ ); +}; +AddressFormatter.displayName = "AddressFormatter"; +export default AddressFormatter; diff --git a/src/components/AddressFormatter/index.ts b/src/components/AddressFormatter/index.ts new file mode 100644 index 000000000..43c84b55e --- /dev/null +++ b/src/components/AddressFormatter/index.ts @@ -0,0 +1,2 @@ +export { default } from "./AddressFormatter"; +export * from "./AddressFormatter"; diff --git a/src/components/AppHeader/AppHeader.tsx b/src/components/AppHeader/AppHeader.tsx new file mode 100644 index 000000000..1cd32ed5a --- /dev/null +++ b/src/components/AppHeader/AppHeader.tsx @@ -0,0 +1,74 @@ +import Portal from "@material-ui/core/Portal"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import ArrowBackIcon from "@material-ui/icons/ArrowBack"; +import * as React from "react"; +import AppHeaderContext from "../AppLayout/AppHeaderContext"; +import Skeleton from "../Skeleton"; + +export interface AppHeaderProps { + children: React.ReactNode; + onBack(); +} + +const styles = (theme: Theme) => + createStyles({ + menuButton: { + flex: "0 0 auto", + marginLeft: theme.spacing.unit * -2, + marginRight: theme.spacing.unit, + marginTop: -theme.spacing.unit * 2 + }, + root: { + "&:hover": { + color: theme.typography.body2.color + }, + alignItems: "center", + color: theme.palette.grey[500], + cursor: "pointer", + display: "flex", + marginTop: theme.spacing.unit / 2, + transition: theme.transitions.duration.standard + "ms" + }, + skeleton: { + marginBottom: theme.spacing.unit * 2, + width: "10rem" + }, + title: { + color: "inherit", + flex: 1, + marginLeft: theme.spacing.unit, + textTransform: "uppercase" + } + }); +const AppHeader = withStyles(styles, { name: "AppHeader" })( + ({ + children, + classes, + onBack + }: AppHeaderProps & WithStyles) => ( + + {anchor => + anchor ? ( + +
+ + {children ? ( + {children} + ) : ( + + )} +
+
+ ) : null + } +
+ ) +); +AppHeader.displayName = "AppHeader"; +export default AppHeader; diff --git a/src/components/AppHeader/index.ts b/src/components/AppHeader/index.ts new file mode 100644 index 000000000..a17981843 --- /dev/null +++ b/src/components/AppHeader/index.ts @@ -0,0 +1,2 @@ +export { default } from './AppHeader'; +export * from './AppHeader'; \ No newline at end of file diff --git a/src/components/AppLayout/AppActionContext.tsx b/src/components/AppLayout/AppActionContext.tsx new file mode 100644 index 000000000..31e3de50d --- /dev/null +++ b/src/components/AppLayout/AppActionContext.tsx @@ -0,0 +1,7 @@ +import * as React from "react"; + +const AppActionContext = React.createContext>( + undefined +); + +export default AppActionContext; diff --git a/src/components/AppLayout/AppHeaderContext.tsx b/src/components/AppLayout/AppHeaderContext.tsx new file mode 100644 index 000000000..73255b665 --- /dev/null +++ b/src/components/AppLayout/AppHeaderContext.tsx @@ -0,0 +1,7 @@ +import * as React from "react"; + +const AppHeaderContext = React.createContext>( + undefined +); + +export default AppHeaderContext; diff --git a/src/components/AppLayout/AppLayout.tsx b/src/components/AppLayout/AppLayout.tsx new file mode 100644 index 000000000..ed7759580 --- /dev/null +++ b/src/components/AppLayout/AppLayout.tsx @@ -0,0 +1,355 @@ +import Chip from "@material-ui/core/Chip"; +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import Grow from "@material-ui/core/Grow"; +import LinearProgress from "@material-ui/core/LinearProgress"; +import MenuItem from "@material-ui/core/MenuItem"; +import Menu from "@material-ui/core/MenuList"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as classNames from "classnames"; +import * as React from "react"; +import SVG from "react-inlinesvg"; +import { RouteComponentProps, withRouter } from "react-router"; + +import * as saleorDarkLogo from "@assets/images/logo-dark.svg"; +import * as saleorLightLogo from "@assets/images/logo-light.svg"; +import AppProgressProvider from "@saleor/components/AppProgress"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useTheme from "@saleor/hooks/useTheme"; +import useUser from "@saleor/hooks/useUser"; +import i18n from "../../i18n"; +import ArrowDropdown from "../../icons/ArrowDropdown"; +import Container from "../Container"; +import AppActionContext from "./AppActionContext"; +import AppHeaderContext from "./AppHeaderContext"; +import { appLoaderHeight, drawerWidth } from "./consts"; +import MenuList from "./MenuList"; +import menuStructure from "./menuStructure"; +import ResponsiveDrawer from "./ResponsiveDrawer"; +import ThemeSwitch from "./ThemeSwitch"; + +const styles = (theme: Theme) => + createStyles({ + appAction: { + bottom: 0, + gridColumn: 2, + position: "sticky", + zIndex: 1 + }, + appLoader: { + height: appLoaderHeight, + zIndex: 1201 + }, + arrow: { + marginLeft: theme.spacing.unit * 2, + transition: theme.transitions.duration.standard + "ms" + }, + content: { + display: "flex", + flexDirection: "column", + minHeight: `calc(100vh - ${appLoaderHeight}px)` + }, + darkThemeSwitch: { + marginRight: theme.spacing.unit * 2 + }, + header: { + display: "flex", + height: 40, + marginBottom: theme.spacing.unit * 3, + marginTop: theme.spacing.unit * 2 + }, + hide: { + opacity: 0 + }, + logo: { + "& svg": { + height: "100%" + }, + display: "block", + height: 28 + }, + menu: { + marginTop: theme.spacing.unit * 4 + }, + menuIcon: { + [theme.breakpoints.up("md")]: { + display: "none" + }, + "& span": { + "&:nth-child(1)": { + top: 15 + }, + "&:nth-child(2), &:nth-child(3)": { + top: 20 + }, + "&:nth-child(4)": { + top: 25 + }, + background: theme.palette.secondary.light, + display: "block", + height: 1, + left: "20%", + opacity: 1, + position: "absolute", + transform: "rotate(0deg)", + transition: ".25s ease-in-out", + width: "60%" + }, + background: theme.palette.background.paper, + borderRadius: "50%", + cursor: "pointer", + height: 42, + left: theme.spacing.unit, + marginRight: theme.spacing.unit * 2, + position: "relative", + transform: "rotate(0deg)", + transition: ".2s ease-in-out", + width: 42 + }, + menuIconDark: { + "& span": { + background: theme.palette.common.white + } + }, + menuIconOpen: { + "& span": { + "&:nth-child(1), &:nth-child(4)": { + left: "50%", + top: 20, + width: 0 + }, + "&:nth-child(2)": { + transform: "rotate(45deg)" + }, + "&:nth-child(3)": { + transform: "rotate(-45deg)" + } + }, + left: 280, + position: "absolute", + zIndex: 1999 + }, + popover: { + zIndex: 1 + }, + root: { + [theme.breakpoints.down("sm")]: { + gridTemplateColumns: "1fr" + }, + display: "grid", + gridTemplateColumns: `${drawerWidth}px 1fr` + }, + rotate: { + transform: "rotate(180deg)" + }, + sideBar: { + [theme.breakpoints.down("sm")]: { + padding: 0 + }, + background: theme.palette.background.paper, + padding: `${theme.spacing.unit * 2}px ${theme.spacing.unit * 4}px` + }, + spacer: { + flex: 1 + }, + userBar: { + alignItems: "center", + display: "flex" + }, + userChip: { + backgroundColor: theme.palette.common.white, + border: `1px solid ${theme.palette.grey[200]}` + }, + userMenuContainer: { + position: "relative" + }, + userMenuItem: { + textAlign: "right" + }, + view: { + backgroundColor: theme.palette.background.default, + flex: 1, + flexGrow: 1, + marginLeft: 0, + paddingBottom: theme.spacing.unit, + [theme.breakpoints.up("sm")]: { + paddingBottom: theme.spacing.unit * 3 + } + } + }); + +interface AppLayoutProps { + children: React.ReactNode; +} + +const AppLayout = withStyles(styles, { + name: "AppLayout" +})( + withRouter>( + ({ + classes, + children, + location + }: AppLayoutProps & + WithStyles & + RouteComponentProps) => { + const { isDark, toggleTheme } = useTheme(); + const [isDrawerOpened, setDrawerState] = React.useState(false); + const [isMenuOpened, setMenuState] = React.useState(false); + const appActionAnchor = React.useRef(); + const appHeaderAnchor = React.useRef(); + const anchor = React.useRef(); + const { logout, user } = useUser(); + const navigate = useNavigator(); + + const handleLogout = () => { + close(); + logout(); + }; + + const handleMenuItemClick = ( + url: string, + event: React.MouseEvent + ) => { + event.stopPropagation(); + event.preventDefault(); + setDrawerState(false); + navigate(url); + }; + + return ( + + {({ isProgress }) => ( + + + +
+
+ setDrawerState(false)} + open={isDrawerOpened} + > + + + +
+
+
+ +
+
setDrawerState(!isDrawerOpened)} + > + + + + +
+
+
+
+ +
+ + {user.email} + + + } + onClick={() => setMenuState(!isMenuOpened)} + /> + + {({ TransitionProps, placement }) => ( + + + setMenuState(false)} + mouseEvent="onClick" + > + + + {i18n.t("Log out", { + context: "button" + })} + + + + + + )} + +
+
+
+ +
+
{children}
+
+
+
+ + + )} + + ); + } + ) +); + +export default AppLayout; diff --git a/src/components/AppLayout/MenuList.tsx b/src/components/AppLayout/MenuList.tsx new file mode 100644 index 000000000..b875a8a9f --- /dev/null +++ b/src/components/AppLayout/MenuList.tsx @@ -0,0 +1,176 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import classNames from "classnames"; +import * as React from "react"; +import { matchPath } from "react-router"; + +import { User } from "../../auth/types/User"; +import { configurationMenu, configurationMenuUrl } from "../../configuration"; +import i18n from "../../i18n"; +import { createHref } from "../../misc"; +import { orderDraftListUrl, orderListUrl } from "../../orders/urls"; +import MenuNested from "./MenuNested"; +import { IMenuItem } from "./menuStructure"; + +const styles = (theme: Theme) => + createStyles({ + menuList: { + display: "flex", + flexDirection: "column", + height: "100%", + marginLeft: theme.spacing.unit * 4, + marginTop: theme.spacing.unit * 2, + paddingBottom: theme.spacing.unit * 3 + }, + menuListItem: { + "&:hover": { + color: theme.palette.primary.main + }, + alignItems: "center", + display: "block", + marginTop: theme.spacing.unit * 2, + paddingLeft: 0, + textDecoration: "none", + transition: theme.transitions.duration.standard + "ms" + }, + menuListItemActive: { + "&:before": { + background: theme.palette.primary.main, + content: "''", + height: "100%", + left: -32, + position: "absolute", + width: 5 + }, + position: "relative" + }, + menuListItemText: { + "&:hover": { + color: theme.palette.primary.main + }, + cursor: "pointer", + fontSize: "1rem", + fontWeight: 500, + textTransform: "uppercase", + transition: theme.transitions.duration.standard + "ms" + }, + menuListNested: { + "& $menuListItemActive": { + "& $menuListItemText": { + color: theme.palette.primary.main + }, + "&:before": { + borderRadius: "100%", + height: 8, + marginLeft: 9, + marginTop: 7, + width: 8 + } + }, + "& $menuListItemText": { + textTransform: "none" + }, + marginLeft: theme.spacing.unit * 3 + } + }); + +interface MenuListProps { + className?: string; + menuItems: IMenuItem[]; + location: string; + user: User; + renderConfigure: boolean; + onMenuItemClick: (url: string, event: React.MouseEvent) => void; +} +const MenuList = withStyles(styles, { name: "MenuList" })( + ({ + classes, + className, + menuItems, + location, + user, + renderConfigure, + onMenuItemClick + }: MenuListProps & WithStyles) => ( +
+ {/* FIXME: this .split("?")[0] looks gross */} + {menuItems.map(menuItem => { + const isActive = (menuItem: IMenuItem) => + location.split("?")[0] === orderDraftListUrl().split("?")[0] && + menuItem.url.split("?")[0] === orderListUrl().split("?")[0] + ? false + : !!matchPath(location.split("?")[0], { + exact: menuItem.url.split("?")[0] === "/", + path: menuItem.url.split("?")[0] + }); + + if ( + menuItem.permission && + !user.permissions.map(perm => perm.code).includes(menuItem.permission) + ) { + return null; + } + + if (!menuItem.url) { + const isAnyChildActive = menuItem.children.reduce( + (acc, child) => acc || isActive(child), + false + ); + + return ( + + ); + } + + return ( + onMenuItemClick(menuItem.url, event)} + key={menuItem.label} + > + + {menuItem.label} + + + ); + })} + {renderConfigure && + configurationMenu.filter(menuItem => + user.permissions.map(perm => perm.code).includes(menuItem.permission) + ).length > 0 && ( + onMenuItemClick(configurationMenuUrl, event)} + > + + {i18n.t("Configure")} + + + )} +
+ ) +); +export default MenuList; diff --git a/src/components/AppLayout/MenuNested.tsx b/src/components/AppLayout/MenuNested.tsx new file mode 100644 index 000000000..44f69ed88 --- /dev/null +++ b/src/components/AppLayout/MenuNested.tsx @@ -0,0 +1,61 @@ +import Typography from "@material-ui/core/Typography"; +import classNames from "classnames"; +import * as React from "react"; + +import { User } from "../../auth/types/User"; +import MenuList from "./MenuList"; +import { IMenuItem } from "./menuStructure"; + +export interface MenuNestedProps { + classes: Record< + | "menuListItem" + | "menuListItemActive" + | "menuListItemText" + | "menuListNested", + string + >; + isAnyChildActive: boolean; + menuItem: IMenuItem; + location: string; + user: User; + onMenuItemClick: (url: string, event: React.MouseEvent) => void; +} + +const MenuNested: React.FC = ({ + classes, + isAnyChildActive, + location, + menuItem, + onMenuItemClick, + user +}) => { + const [isOpened, setOpenStatus] = React.useState(false); + + return ( +
setOpenStatus(!isOpened)} + className={classNames(classes.menuListItem, { + [classes.menuListItemActive]: isAnyChildActive + })} + > + + {menuItem.label} + + {isOpened && ( +
+ +
+ )} +
+ ); +}; +export default MenuNested; diff --git a/src/components/AppLayout/ResponsiveDrawer.tsx b/src/components/AppLayout/ResponsiveDrawer.tsx new file mode 100644 index 000000000..224149999 --- /dev/null +++ b/src/components/AppLayout/ResponsiveDrawer.tsx @@ -0,0 +1,61 @@ +import Drawer from "@material-ui/core/Drawer"; +import Hidden from "@material-ui/core/Hidden"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; +import { drawerWidth } from "./consts"; + +const styles = (theme: Theme) => + createStyles({ + drawerDesktop: { + backgroundColor: theme.palette.background.paper, + border: "none", + height: "100vh", + padding: `${theme.spacing.unit * 2}px ${theme.spacing.unit * 4}px`, + position: "fixed" as "fixed", + width: drawerWidth + }, + drawerMobile: { + padding: `${theme.spacing.unit * 2}px ${theme.spacing.unit * 4}px`, + width: drawerWidth, + } + }); + +interface ResponsiveDrawerProps extends WithStyles { + children?: React.ReactNode; + open: boolean; + onClose?(); +} + +const ResponsiveDrawer = withStyles(styles, { name: "ResponsiveDrawer" })( + ({ children, classes, onClose, open }: ResponsiveDrawerProps) => ( + <> + + + {children} + + + + + {children} + + + + ) +); +export default ResponsiveDrawer; diff --git a/src/components/AppLayout/ThemeSwitch.tsx b/src/components/AppLayout/ThemeSwitch.tsx new file mode 100644 index 000000000..4292f1c73 --- /dev/null +++ b/src/components/AppLayout/ThemeSwitch.tsx @@ -0,0 +1,43 @@ +import { Theme, withStyles } from "@material-ui/core/styles"; +import Switch, { SwitchProps } from "@material-ui/core/Switch"; +import * as React from "react"; + +import MoonIcon from "../../icons/Moon"; +import SunIcon from "../../icons/Sun"; + +const switchStyles = (theme: Theme) => ({ + bar: { + "$colorPrimary$checked + &": { + backgroundColor: theme.palette.background.paper + }, + background: theme.palette.background.paper + }, + checked: { + "& svg": { + background: theme.palette.primary.main, + color: theme.palette.background.paper + } + }, + colorPrimary: {}, + root: { + "& svg": { + background: theme.palette.primary.main, + borderRadius: "100%", + height: 20, + width: 20 + }, + width: 58 + } +}); +const ThemeSwitch = withStyles(switchStyles, { + name: "ThemeSwitch" +})((props: SwitchProps) => ( + } + checkedIcon={} + /> +)); +ThemeSwitch.displayName = "ThemeSwitch"; +export default ThemeSwitch; diff --git a/src/components/AppLayout/consts.ts b/src/components/AppLayout/consts.ts new file mode 100644 index 000000000..eb1ecfeef --- /dev/null +++ b/src/components/AppLayout/consts.ts @@ -0,0 +1,3 @@ +export const drawerWidth = 256; +export const navigationBarHeight = 64; +export const appLoaderHeight = 4; diff --git a/src/components/AppLayout/index.ts b/src/components/AppLayout/index.ts new file mode 100644 index 000000000..41632b30c --- /dev/null +++ b/src/components/AppLayout/index.ts @@ -0,0 +1,2 @@ +export { default } from './AppLayout'; +export * from './AppLayout'; \ No newline at end of file diff --git a/src/components/AppLayout/menuStructure.ts b/src/components/AppLayout/menuStructure.ts new file mode 100644 index 000000000..1ff572241 --- /dev/null +++ b/src/components/AppLayout/menuStructure.ts @@ -0,0 +1,97 @@ +import { categoryListUrl } from "../../categories/urls"; +import { collectionListUrl } from "../../collections/urls"; +import { customerListUrl } from "../../customers/urls"; +import { saleListUrl, voucherListUrl } from "../../discounts/urls"; +import i18n from "../../i18n"; +import { orderDraftListUrl, orderListUrl } from "../../orders/urls"; +import { productListUrl } from "../../products/urls"; +import { languageListUrl } from "../../translations/urls"; +import { PermissionEnum } from "../../types/globalTypes"; + +export interface IMenuItem { + ariaLabel: string; + children?: IMenuItem[]; + label: string; + permission?: PermissionEnum; + url?: string; +} + +const menuStructure: IMenuItem[] = [ + { + ariaLabel: "home", + label: i18n.t("Home", { context: "Menu label" }), + url: "/" + }, + { + ariaLabel: "catalogue", + children: [ + { + ariaLabel: "products", + label: i18n.t("Products", { context: "Menu label" }), + url: productListUrl() + }, + { + ariaLabel: "categories", + label: i18n.t("Categories", { context: "Menu label" }), + url: categoryListUrl() + }, + { + ariaLabel: "collections", + label: i18n.t("Collections", { context: "Menu label" }), + url: collectionListUrl() + } + ], + label: i18n.t("Catalog", { context: "Menu label" }), + permission: PermissionEnum.MANAGE_PRODUCTS + }, + { + ariaLabel: "orders", + children: [ + { + ariaLabel: "orders", + label: i18n.t("Orders", { context: "Menu label" }), + permission: PermissionEnum.MANAGE_ORDERS, + url: orderListUrl() + }, + { + ariaLabel: "order drafts", + label: i18n.t("Drafts", { context: "Menu label" }), + permission: PermissionEnum.MANAGE_ORDERS, + url: orderDraftListUrl() + } + ], + label: i18n.t("Orders", { context: "Menu label" }), + permission: PermissionEnum.MANAGE_ORDERS + }, + { + ariaLabel: "customers", + label: i18n.t("Customers", { context: "Menu label" }), + permission: PermissionEnum.MANAGE_USERS, + url: customerListUrl() + }, + + { + ariaLabel: "discounts", + children: [ + { + ariaLabel: "sales", + label: i18n.t("Sales", { context: "Menu label" }), + url: saleListUrl() + }, + { + ariaLabel: "vouchers", + label: i18n.t("Vouchers", { context: "Menu label" }), + url: voucherListUrl() + } + ], + label: i18n.t("Discounts", { context: "Menu label" }), + permission: PermissionEnum.MANAGE_DISCOUNTS + }, + { + ariaLabel: "translations", + label: i18n.t("Translations", { context: "Menu label" }), + permission: PermissionEnum.MANAGE_TRANSLATIONS, + url: languageListUrl + } +]; +export default menuStructure; diff --git a/src/components/AppProgress/index.tsx b/src/components/AppProgress/index.tsx new file mode 100644 index 000000000..7be0c2132 --- /dev/null +++ b/src/components/AppProgress/index.tsx @@ -0,0 +1,30 @@ +import * as React from "react"; + +interface IAppProgressContext { + isProgress: boolean; + setProgressState: (isOpened: boolean) => void; +} + +export const AppProgressContext = React.createContext( + undefined +); + +export const AppProgressProvider: React.StatelessComponent<{}> = ({ + children +}) => { + const [isProgress, setProgressState] = React.useState(false); + + return ( + + {children} + + ); +}; + +export const AppProgress = AppProgressContext.Consumer; +export default AppProgress; diff --git a/src/components/AssignCategoryDialog/AssignCategoryDialog.tsx b/src/components/AssignCategoryDialog/AssignCategoryDialog.tsx new file mode 100644 index 000000000..656c63905 --- /dev/null +++ b/src/components/AssignCategoryDialog/AssignCategoryDialog.tsx @@ -0,0 +1,172 @@ +import Button from "@material-ui/core/Button"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import FormSpacer from "@saleor/components/FormSpacer"; +import { SearchCategories_categories_edges_node } from "../../containers/SearchCategories/types/SearchCategories"; +import i18n from "../../i18n"; +import Checkbox from "../Checkbox"; + +export interface FormData { + categories: SearchCategories_categories_edges_node[]; + query: string; +} + +const styles = createStyles({ + avatar: { + "&:first-child": { + paddingLeft: 0 + } + }, + checkboxCell: { + paddingLeft: 0 + }, + overflow: { + overflowY: "visible" + }, + wideCell: { + width: "100%" + } +}); + +interface AssignCategoriesDialogProps extends WithStyles { + categories: SearchCategories_categories_edges_node[]; + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + loading: boolean; + onClose: () => void; + onFetch: (value: string) => void; + onSubmit: (data: FormData) => void; +} + +const initialForm: FormData = { + categories: [], + query: "" +}; +const AssignCategoriesDialog = withStyles(styles, { + name: "AssignCategoriesDialog" +})( + ({ + classes, + confirmButtonState, + open, + loading, + categories: categories, + onClose, + onFetch, + onSubmit + }: AssignCategoriesDialogProps) => ( + +
+ {({ data, change }) => ( + <> + {i18n.t("Assign Categories")} + + change(event, () => onFetch(data.query))} + label={i18n.t("Search Categories", { + context: "product search input label" + })} + placeholder={i18n.t( + "Search by product name, attribute, product type etc...", + { + context: "product search input placeholder" + } + )} + fullWidth + InputProps={{ + autoComplete: "off", + endAdornment: loading && + }} + /> + + + + {categories && + categories.map(category => { + const isChecked = !!data.categories.find( + selectedCategories => + selectedCategories.id === category.id + ); + + return ( + + + + isChecked + ? change({ + target: { + name: "categories", + value: data.categories.filter( + selectedCategories => + selectedCategories.id !== + category.id + ) + } + } as any) + : change({ + target: { + name: "categories", + value: [...data.categories, category] + } + } as any) + } + /> + + + {category.name} + + + ); + })} + +
+
+ + + + {i18n.t("Assign categories", { context: "button" })} + + + + )} +
+
+ ) +); +AssignCategoriesDialog.displayName = "AssignCategoriesDialog"; +export default AssignCategoriesDialog; diff --git a/src/components/AssignCategoryDialog/index.ts b/src/components/AssignCategoryDialog/index.ts new file mode 100644 index 000000000..b3790ef8d --- /dev/null +++ b/src/components/AssignCategoryDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./AssignCategoryDialog"; +export * from "./AssignCategoryDialog"; diff --git a/src/components/AssignCollectionDialog/AssignCollectionDialog.tsx b/src/components/AssignCollectionDialog/AssignCollectionDialog.tsx new file mode 100644 index 000000000..bd4cd2dbd --- /dev/null +++ b/src/components/AssignCollectionDialog/AssignCollectionDialog.tsx @@ -0,0 +1,172 @@ +import Button from "@material-ui/core/Button"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import { SearchCollections_collections_edges_node } from "../../containers/SearchCollections/types/SearchCollections"; +import i18n from "../../i18n"; +import Checkbox from "../Checkbox"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "../ConfirmButton/ConfirmButton"; +import Form from "../Form"; +import FormSpacer from "../FormSpacer"; + +export interface FormData { + collections: SearchCollections_collections_edges_node[]; + query: string; +} + +const styles = createStyles({ + avatar: { + "&:first-child": { + paddingLeft: 0 + } + }, + checkboxCell: { + paddingLeft: 0 + }, + overflow: { + overflowY: "visible" + }, + wideCell: { + width: "100%" + } +}); + +interface AssignCollectionDialogProps extends WithStyles { + collections: SearchCollections_collections_edges_node[]; + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + loading: boolean; + onClose: () => void; + onFetch: (value: string) => void; + onSubmit: (data: FormData) => void; +} + +const initialForm: FormData = { + collections: [], + query: "" +}; +const AssignCollectionDialog = withStyles(styles, { + name: "AssignCollectionDialog" +})( + ({ + classes, + confirmButtonState, + open, + loading, + collections, + onClose, + onFetch, + onSubmit + }: AssignCollectionDialogProps) => ( + +
+ {({ data, change }) => ( + <> + {i18n.t("Assign Collection")} + + change(event, () => onFetch(data.query))} + label={i18n.t("Search Collection", { + context: "product search input label" + })} + placeholder={i18n.t( + "Search by product name, attribute, product type etc...", + { + context: "product search input placeholder" + } + )} + fullWidth + InputProps={{ + autoComplete: "off", + endAdornment: loading && + }} + /> + + + + {collections && + collections.map(category => { + const isChecked = !!data.collections.find( + selectedCollection => + selectedCollection.id === category.id + ); + + return ( + + + + isChecked + ? change({ + target: { + name: "collections", + value: data.collections.filter( + selectedCollection => + selectedCollection.id !== + category.id + ) + } + } as any) + : change({ + target: { + name: "collections", + value: [...data.collections, category] + } + } as any) + } + /> + + + {category.name} + + + ); + })} + +
+
+ + + + {i18n.t("Assign collections", { context: "button" })} + + + + )} +
+
+ ) +); +AssignCollectionDialog.displayName = "AssignCollectionDialog"; +export default AssignCollectionDialog; diff --git a/src/components/AssignCollectionDialog/index.ts b/src/components/AssignCollectionDialog/index.ts new file mode 100644 index 000000000..8484530c8 --- /dev/null +++ b/src/components/AssignCollectionDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./AssignCollectionDialog"; +export * from "./AssignCollectionDialog"; diff --git a/src/components/AssignProductDialog/AssignProductDialog.tsx b/src/components/AssignProductDialog/AssignProductDialog.tsx new file mode 100644 index 000000000..a675a6d47 --- /dev/null +++ b/src/components/AssignProductDialog/AssignProductDialog.tsx @@ -0,0 +1,176 @@ +import Button from "@material-ui/core/Button"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import FormSpacer from "@saleor/components/FormSpacer"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import { SearchProducts_products_edges_node } from "../../containers/SearchProducts/types/SearchProducts"; +import i18n from "../../i18n"; +import { maybe } from "../../misc"; +import Checkbox from "../Checkbox"; + +export interface FormData { + products: SearchProducts_products_edges_node[]; + query: string; +} + +const styles = createStyles({ + avatar: { + "&:first-child": { + paddingLeft: 0 + } + }, + checkboxCell: { + paddingLeft: 0 + }, + overflow: { + overflowY: "visible" + }, + wideCell: { + width: "100%" + } +}); + +interface AssignProductDialogProps extends WithStyles { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + products: SearchProducts_products_edges_node[]; + loading: boolean; + onClose: () => void; + onFetch: (value: string) => void; + onSubmit: (data: FormData) => void; +} + +const initialForm: FormData = { + products: [], + query: "" +}; +const AssignProductDialog = withStyles(styles, { + name: "AssignProductDialog" +})( + ({ + classes, + confirmButtonState, + open, + loading, + products, + onClose, + onFetch, + onSubmit + }: AssignProductDialogProps) => ( + +
+ {({ data, change }) => ( + <> + {i18n.t("Assign Product")} + + change(event, () => onFetch(data.query))} + label={i18n.t("Search Products", { + context: "product search input label" + })} + placeholder={i18n.t( + "Search by product name, attribute, product type etc...", + { + context: "product search input placeholder" + } + )} + fullWidth + InputProps={{ + autoComplete: "off", + endAdornment: loading && + }} + /> + + + + {products && + products.map(product => { + const isChecked = !!data.products.find( + selectedProduct => selectedProduct.id === product.id + ); + + return ( + + product.thumbnail.url)} + /> + + {product.name} + + + + isChecked + ? change({ + target: { + name: "products", + value: data.products.filter( + selectedProduct => + selectedProduct.id !== product.id + ) + } + } as any) + : change({ + target: { + name: "products", + value: [...data.products, product] + } + } as any) + } + /> + + + ); + })} + +
+
+ + + + {i18n.t("Assign products", { context: "button" })} + + + + )} +
+
+ ) +); +AssignProductDialog.displayName = "AssignProductDialog"; +export default AssignProductDialog; diff --git a/src/components/AssignProductDialog/index.ts b/src/components/AssignProductDialog/index.ts new file mode 100644 index 000000000..52e20ebb1 --- /dev/null +++ b/src/components/AssignProductDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./AssignProductDialog"; +export * from "./AssignProductDialog"; diff --git a/src/components/AutocompleteSelectMenu/AutocompleteSelectMenu.tsx b/src/components/AutocompleteSelectMenu/AutocompleteSelectMenu.tsx new file mode 100644 index 000000000..d00ca186f --- /dev/null +++ b/src/components/AutocompleteSelectMenu/AutocompleteSelectMenu.tsx @@ -0,0 +1,194 @@ +import CircularProgress from "@material-ui/core/CircularProgress"; +import MenuItem from "@material-ui/core/MenuItem"; +import Paper from "@material-ui/core/Paper"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import ArrowBack from "@material-ui/icons/ArrowBack"; +import Downshift from "downshift"; +import * as React from "react"; + +import i18n from "../../i18n"; +import { + getMenuItemByPath, + IMenu, + validateMenuOptions +} from "../../utils/menu"; +import Debounce, { DebounceProps } from "../Debounce"; + +export interface AutocompleteSelectMenuProps { + disabled: boolean; + displayValue: string; + error: boolean; + helperText: string; + label: string; + loading: boolean; + name: string; + options: IMenu; + placeholder: string; + onChange: (event: React.ChangeEvent) => void; + onInputChange?: (value: string) => void; +} + +const validationError: Error = new Error( + "Values supplied to AutocompleteSelectMenu should be unique" +); + +const DebounceAutocomplete: React.ComponentType< + DebounceProps +> = Debounce; + +const styles = (theme: Theme) => + createStyles({ + container: { + flexGrow: 1, + position: "relative" + }, + menuBack: { + marginLeft: -theme.spacing.unit / 2, + marginRight: theme.spacing.unit + }, + paper: { + left: 0, + marginTop: theme.spacing.unit, + padding: theme.spacing.unit, + position: "absolute", + right: 0, + zIndex: 2 + }, + root: {} + }); +const AutocompleteSelectMenu = withStyles(styles, { + name: "AutocompleteSelectMenu" +})( + ({ + classes, + disabled, + displayValue, + error, + helperText, + label, + loading, + name, + options, + placeholder, + onChange, + onInputChange + }: AutocompleteSelectMenuProps & WithStyles) => { + const [inputValue, setInputValue] = React.useState(displayValue || ""); + const [menuPath, setMenuPath] = React.useState([]); + + const handleChange = (value: string) => + onChange({ + target: { + name, + value + } + } as any); + + // Validate if option values are duplicated + React.useEffect(() => { + if (!validateMenuOptions(options)) { + throw validationError; + } + }, []); + + // Navigate back to main menu after input field change + React.useEffect(() => setMenuPath([]), [options]); + + // Reset input value after displayValue change + React.useEffect(() => setInputValue(displayValue), [displayValue]); + + return ( + + {debounceFn => ( + (item ? item.label : "")} + onSelect={handleChange} + > + {({ getItemProps, isOpen, openMenu, closeMenu, selectItem }) => { + return ( +
+ , + id: undefined, + onBlur: () => { + closeMenu(); + setMenuPath([]); + setInputValue(displayValue); + }, + onChange: event => { + debounceFn(event.target.value); + setInputValue(event.target.value); + }, + onFocus: () => openMenu(), + placeholder + }} + disabled={disabled} + error={error} + helperText={helperText} + label={label} + fullWidth={true} + value={inputValue} + /> + {isOpen && ( + + {options.length ? ( + <> + {menuPath.length > 0 && ( + + setMenuPath( + menuPath.slice(0, menuPath.length - 2) + ) + } + > + + {i18n.t("Back")} + + )} + {(menuPath.length + ? getMenuItemByPath(options, menuPath).children + : options + ).map((suggestion, index) => ( + + suggestion.value + ? selectItem(suggestion.value) + : setMenuPath([...menuPath, index]) + } + > + {suggestion.label} + + ))} + + ) : ( + + {i18n.t("No results")} + + )} + + )} +
+ ); + }} +
+ )} +
+ ); + } +); +AutocompleteSelectMenu.displayName = "AutocompleteSelectMenu"; +export default AutocompleteSelectMenu; diff --git a/src/components/AutocompleteSelectMenu/index.ts b/src/components/AutocompleteSelectMenu/index.ts new file mode 100644 index 000000000..3a0e4e0d2 --- /dev/null +++ b/src/components/AutocompleteSelectMenu/index.ts @@ -0,0 +1,2 @@ +export { default } from './AutocompleteSelectMenu'; +export * from './AutocompleteSelectMenu'; \ No newline at end of file diff --git a/src/components/CardMenu/CardMenu.tsx b/src/components/CardMenu/CardMenu.tsx new file mode 100644 index 000000000..4135ce418 --- /dev/null +++ b/src/components/CardMenu/CardMenu.tsx @@ -0,0 +1,102 @@ +import IconButton from "@material-ui/core/IconButton"; +import Menu from "@material-ui/core/Menu"; +import MenuItem from "@material-ui/core/MenuItem"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import MoreVertIcon from "@material-ui/icons/MoreVert"; +import * as React from "react"; + +const ITEM_HEIGHT = 48; + +export interface CardMenuItem { + label: string; + onSelect: () => void; +} + +export interface CardMenuProps { + className?: string; + disabled?: boolean; + menuItems: CardMenuItem[]; +} + +const styles = (theme: Theme) => + createStyles({ + iconButton: { + background: theme.palette.background.paper, + borderRadius: "100%", + height: 32, + padding: 0, + width: 32 + } + }); + +const CardMenu = withStyles(styles, { + name: "CardMenu" +})( + ({ + className, + classes, + disabled, + menuItems + }: CardMenuProps & WithStyles) => { + const [anchorEl, setAnchor] = React.useState(null); + + const handleClick = (event: React.MouseEvent) => { + setAnchor(event.currentTarget); + }; + + const handleClose = () => { + setAnchor(null); + }; + + const handleMenuClick = (menuItemIndex: number) => { + menuItems[menuItemIndex].onSelect(); + handleClose(); + }; + + const open = !!anchorEl; + + return ( +
+ + + + + {menuItems.map((menuItem, menuItemIndex) => ( + handleMenuClick(menuItemIndex)} + key={menuItem.label} + > + {menuItem.label} + + ))} + +
+ ); + } +); +CardMenu.displayName = "CardMenu"; +export default CardMenu; diff --git a/src/components/CardMenu/index.ts b/src/components/CardMenu/index.ts new file mode 100644 index 000000000..69518dc40 --- /dev/null +++ b/src/components/CardMenu/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CardMenu"; +export * from "./CardMenu"; diff --git a/src/components/CardSpacer.tsx b/src/components/CardSpacer.tsx new file mode 100644 index 000000000..98d70f95a --- /dev/null +++ b/src/components/CardSpacer.tsx @@ -0,0 +1,29 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + spacer: { + [theme.breakpoints.down("sm")]: { + marginTop: theme.spacing.unit + }, + marginTop: theme.spacing.unit * 3 + } + }); + +interface CardSpacerProps extends WithStyles { + children?: React.ReactNode; +} + +export const CardSpacer = withStyles(styles, { name: "CardSpacer" })( + ({ classes, children }: CardSpacerProps) => ( +
{children}
+ ) +); +CardSpacer.displayName = "CardSpacer"; +export default CardSpacer; diff --git a/src/components/CardTitle/CardTitle.tsx b/src/components/CardTitle/CardTitle.tsx new file mode 100644 index 000000000..92c061f0a --- /dev/null +++ b/src/components/CardTitle/CardTitle.tsx @@ -0,0 +1,83 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as classNames from "classnames"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + children: theme.mixins.gutters({}), + constantHeight: { + height: 56 + }, + hr: { + border: "none", + borderTop: `1px solid ${theme.overrides.MuiCard.root.borderColor}`, + height: 0, + marginBottom: 0, + marginTop: 0, + width: "100%" + }, + root: theme.mixins.gutters({ + alignItems: "center", + display: "flex", + minHeight: 56 + }), + title: { + flex: 1, + lineHeight: 1 + }, + toolbar: { + marginRight: -theme.spacing.unit * 2 + } + }); + +interface CardTitleProps extends WithStyles { + children?: React.ReactNode; + className?: string; + height?: "default" | "const"; + title: string | React.ReactNode; + toolbar?: React.ReactNode; + onClick?: (event: React.MouseEvent) => void; +} + +const CardTitle = withStyles(styles, { name: "CardTitle" })( + ({ + classes, + className, + children, + height, + title, + toolbar, + onClick, + ...props + }: CardTitleProps) => ( + <> +
+ + {title} + +
{toolbar}
+
+
{children}
+
+ + ) +); +CardTitle.displayName = "CardTitle"; +export default CardTitle; diff --git a/src/components/CardTitle/index.ts b/src/components/CardTitle/index.ts new file mode 100644 index 000000000..0adbc156d --- /dev/null +++ b/src/components/CardTitle/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CardTitle"; +export * from "./CardTitle"; diff --git a/src/components/Checkbox/Checkbox.tsx b/src/components/Checkbox/Checkbox.tsx new file mode 100644 index 000000000..a82a63d7c --- /dev/null +++ b/src/components/Checkbox/Checkbox.tsx @@ -0,0 +1,121 @@ +import { Omit } from "@material-ui/core"; +import ButtonBase from "@material-ui/core/ButtonBase"; +import { CheckboxProps as MuiCheckboxProps } from "@material-ui/core/Checkbox"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import classNames from "classnames"; +import * as React from "react"; +import { stopPropagation } from "../../misc"; + +export type CheckboxProps = Omit< + MuiCheckboxProps, + | "checkedIcon" + | "color" + | "icon" + | "indeterminateIcon" + | "classes" + | "onChange" +> & { + onChange?: (event: React.ChangeEvent) => void; +}; + +const styles = (theme: Theme) => + createStyles({ + box: { + "&$checked": { + "&:before": { + background: theme.palette.primary.main + }, + borderColor: theme.palette.primary.main + }, + "&$disabled": { + borderColor: theme.palette.grey[200] + }, + "&$indeterminate": { + "&:before": { + background: theme.palette.primary.main, + height: 2, + top: 5 + }, + borderColor: theme.palette.primary.main + }, + "&:before": { + background: "rgba(0, 0, 0, 0)", + borderRadius: 2, + content: '""', + height: 8, + left: 2, + position: "absolute", + top: 2, + transition: theme.transitions.duration.short + "ms", + width: 8 + }, + WebkitAppearance: "none", + border: `1px solid ${theme.palette.grey[500]}`, + borderRadius: 4, + boxSizing: "border-box", + cursor: "pointer", + height: 14, + outline: "0", + position: "relative", + userSelect: "none", + width: 14 + }, + checked: {}, + disabled: {}, + indeterminate: {}, + root: { + alignItems: "center", + borderRadius: "100%", + cursor: "pointer", + display: "flex", + height: 48, + justifyContent: "center", + width: 48 + } + }); +const Checkbox = withStyles(styles, { name: "Checkbox" })( + ({ + checked, + className, + classes, + disabled, + indeterminate, + onChange, + onClick, + value, + name, + ...props + }: CheckboxProps & WithStyles) => { + const inputRef = React.useRef(null); + return ( + inputRef.current.click())} + > + + + ); + } +); +Checkbox.displayName = "Checkbox"; +export default Checkbox; diff --git a/src/components/Checkbox/index.ts b/src/components/Checkbox/index.ts new file mode 100644 index 000000000..3d46e4f82 --- /dev/null +++ b/src/components/Checkbox/index.ts @@ -0,0 +1,2 @@ +export { default } from './Checkbox'; +export * from './Checkbox'; \ No newline at end of file diff --git a/src/components/Chip/Chip.tsx b/src/components/Chip/Chip.tsx new file mode 100644 index 000000000..f003b16b0 --- /dev/null +++ b/src/components/Chip/Chip.tsx @@ -0,0 +1,56 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; +import Typography from "@material-ui/core/Typography"; +import CloseIcon from "@material-ui/icons/Close"; +import classNames from "classnames"; +import * as React from "react"; + +export interface ChipProps { + className?: string; + label: React.ReactNode; + onClose?: () => void; +} + +const styles = (theme: Theme) => + createStyles({ + closeIcon: { + cursor: "pointer", + fontSize: 16, + marginLeft: theme.spacing.unit, + verticalAlign: "middle" + }, + label: { + color: theme.palette.common.white + }, + root: { + background: fade(theme.palette.secondary.main, 0.6), + borderRadius: 8, + display: "inline-block", + marginRight: theme.spacing.unit * 2, + padding: "6px 12px" + } + }); +const Chip = withStyles(styles, { name: "Chip" })( + ({ + classes, + className, + label, + onClose + }: ChipProps & WithStyles) => ( +
+ + {label} + {onClose && ( + + )} + +
+ ) +); +Chip.displayName = "Chip"; +export default Chip; diff --git a/src/components/Chip/index.ts b/src/components/Chip/index.ts new file mode 100644 index 000000000..6de8518ff --- /dev/null +++ b/src/components/Chip/index.ts @@ -0,0 +1,2 @@ +export { default } from './Chip'; +export * from './Chip'; \ No newline at end of file diff --git a/src/components/ConfirmButton/ConfirmButton.tsx b/src/components/ConfirmButton/ConfirmButton.tsx new file mode 100644 index 000000000..b1a1c7b91 --- /dev/null +++ b/src/components/ConfirmButton/ConfirmButton.tsx @@ -0,0 +1,188 @@ +import { Omit } from "@material-ui/core"; +import Button, { ButtonProps } from "@material-ui/core/Button"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import CheckIcon from "@material-ui/icons/Check"; +import classNames from "classnames"; +import * as React from "react"; + +import i18n from "../../i18n"; + +export type ConfirmButtonTransitionState = + | "loading" + | "success" + | "error" + | "default"; + +const styles = (theme: Theme) => + createStyles({ + error: { + "&:hover": { + backgroundColor: theme.palette.error.main + }, + backgroundColor: theme.palette.error.main, + color: theme.palette.error.contrastText + }, + icon: { + marginLeft: "0 !important", + position: "absolute", + transitionDuration: theme.transitions.duration.standard + "ms" + }, + invisible: { + opacity: 0 + }, + label: { + alignItems: "center", + display: "flex", + transitionDuration: theme.transitions.duration.standard + "ms" + }, + progress: { + "& svg": { + color: theme.palette.common.white, + margin: 0 + }, + position: "absolute", + transitionDuration: theme.transitions.duration.standard + "ms" + }, + success: { + "&:hover": { + backgroundColor: theme.palette.primary.main + }, + backgroundColor: theme.palette.primary.main, + color: theme.palette.primary.contrastText + } + }); + +export interface ConfirmButtonProps + extends Omit, + WithStyles { + transitionState: ConfirmButtonTransitionState; +} + +interface ConfirmButtonState { + displayCompletedActionState: boolean; +} + +const ConfirmButton = withStyles(styles)( + class ConfirmButtonComponent extends React.Component< + ConfirmButtonProps & + WithStyles< + "error" | "icon" | "invisible" | "label" | "progress" | "success" + >, + ConfirmButtonState + > { + static getDerivedStateFromProps( + nextProps: ConfirmButtonProps, + prevState: ConfirmButtonState + ): ConfirmButtonState { + if (nextProps.transitionState === "loading") { + return { + displayCompletedActionState: true + }; + } + return prevState; + } + + state: ConfirmButtonState = { + displayCompletedActionState: false + }; + timeout = null; + + componentDidUpdate(prevProps: ConfirmButtonProps) { + const { transitionState } = this.props; + if (prevProps.transitionState !== transitionState) { + if ( + (["error", "success"] as ConfirmButtonTransitionState[]).includes( + transitionState + ) + ) { + this.timeout = setTimeout( + () => + this.setState({ + displayCompletedActionState: false + }), + 2000 + ); + } else if (transitionState === "loading") { + clearTimeout(this.timeout); + } + } + } + + componentWillUnmount() { + clearTimeout(this.timeout); + } + + render() { + const { + children, + classes, + className, + disabled, + transitionState, + onClick, + ...props + } = this.props; + const { displayCompletedActionState } = this.state; + + return ( + + ); + } + } +); +ConfirmButton.displayName = "ConfirmButton"; +export default ConfirmButton; diff --git a/src/components/ConfirmButton/index.ts b/src/components/ConfirmButton/index.ts new file mode 100644 index 000000000..4fe09023d --- /dev/null +++ b/src/components/ConfirmButton/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ConfirmButton"; +export * from "./ConfirmButton"; diff --git a/src/components/ConfirmFormLeaveDialog.tsx b/src/components/ConfirmFormLeaveDialog.tsx new file mode 100644 index 000000000..41bce42b8 --- /dev/null +++ b/src/components/ConfirmFormLeaveDialog.tsx @@ -0,0 +1,62 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; +import NavigationPrompt from "react-router-navigation-prompt"; + +import i18n from "../i18n"; +import { FormContext } from "./Form"; + +const styles = (theme: Theme) => + createStyles({ + deleteButton: { + "&:hover": { + backgroundColor: theme.palette.error.main + }, + backgroundColor: theme.palette.error.main, + color: theme.palette.error.contrastText + } + }); + +export const ConfirmFormLeaveDialog = withStyles(styles, { + name: "ConfirmFormLeaveDialog" +})(({ classes }: WithStyles) => ( + + {({ hasChanged: hasFormChanged }) => ( + + {({ isActive, onCancel, onConfirm }) => ( + + {i18n.t("Unsaved changes")} + + + {i18n.t( + "If you leave this page, unsaved changes will be lost. Are you sure you want to leave?", + { + context: "form leave confirmation" + } + )} + + + + + + + + )} + + )} + +)); diff --git a/src/components/Container.tsx b/src/components/Container.tsx new file mode 100644 index 000000000..57d552d01 --- /dev/null +++ b/src/components/Container.tsx @@ -0,0 +1,35 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as classNames from "classnames"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + root: { + [theme.breakpoints.up("lg")]: { + marginLeft: "auto", + marginRight: "auto", + maxWidth: theme.breakpoints.width("lg") + }, + [theme.breakpoints.up("sm")]: { + padding: `0 ${theme.spacing.unit * 3}px` + }, + padding: `0 ${theme.spacing.unit}px` + } + }); + +interface ContainerProps extends WithStyles { + className?: string; +} + +export const Container = withStyles(styles, { + name: "Container" +})(({ classes, className, ...props }: ContainerProps) => ( +
+)); +Container.displayName = "Container"; +export default Container; diff --git a/src/components/ControlledCheckbox.tsx b/src/components/ControlledCheckbox.tsx new file mode 100644 index 000000000..6e948e6f9 --- /dev/null +++ b/src/components/ControlledCheckbox.tsx @@ -0,0 +1,31 @@ +import FormControlLabel from "@material-ui/core/FormControlLabel"; +import * as React from "react"; + +import Checkbox from "./Checkbox"; + +interface ControlledCheckboxProps { + name: string; + label?: React.ReactNode; + checked: boolean; + disabled?: boolean; + onChange(event: any); +} + +export const ControlledCheckbox: React.StatelessComponent< + ControlledCheckboxProps +> = ({ checked, disabled, name, label, onChange }) => ( + onChange({ target: { name, value: !checked } })} + onChange={() => onChange({ target: { name, value: !checked } })} + /> + } + label={label} + /> +); +ControlledCheckbox.displayName = "ControlledCheckbox"; +export default ControlledCheckbox; diff --git a/src/components/ControlledSwitch.tsx b/src/components/ControlledSwitch.tsx new file mode 100644 index 000000000..6b0b341fd --- /dev/null +++ b/src/components/ControlledSwitch.tsx @@ -0,0 +1,58 @@ +import { createStyles, Theme, withStyles, WithStyles } from "@material-ui/core"; +import FormControlLabel from "@material-ui/core/FormControlLabel"; +import Switch from "@material-ui/core/Switch"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + label: { + marginLeft: theme.spacing.unit * 2 + } + }); + +interface ControlledSwitchProps extends WithStyles { + checked: boolean; + disabled?: boolean; + label: string | React.ReactNode; + name: string; + secondLabel?: string; + uncheckedLabel?: string | React.ReactNode; + onChange?(event: React.ChangeEvent); +} + +export const ControlledSwitch = withStyles(styles, { + name: "ControlledSwitch" +})( + ({ + classes, + checked, + disabled, + onChange, + label, + name, + secondLabel, + uncheckedLabel + }: ControlledSwitchProps) => ( + + onChange({ target: { name, value: !checked } } as any) + } + checked={checked} + color="primary" + name={name} + /> + } + label={ +
+ {uncheckedLabel ? (checked ? label : uncheckedLabel) : label} +
{secondLabel ? secondLabel : null}
+
+ } + disabled={disabled} + /> + ) +); +ControlledSwitch.displayName = "ControlledSwitch"; +export default ControlledSwitch; diff --git a/src/components/CountryList/CountryList.tsx b/src/components/CountryList/CountryList.tsx new file mode 100644 index 000000000..014a7db66 --- /dev/null +++ b/src/components/CountryList/CountryList.tsx @@ -0,0 +1,183 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import IconButton from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown"; +import DeleteIcon from "@material-ui/icons/Delete"; +import classNames from "classnames"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../i18n"; +import { maybe, renderCollection } from "../../misc"; +import { CountryFragment } from "../../taxes/types/CountryFragment"; + +export interface CountryListProps { + countries: CountryFragment[]; + disabled: boolean; + emptyText: React.ReactNode; + title: React.ReactNode; + onCountryAssign: () => void; + onCountryUnassign: (country: string) => void; +} + +const styles = (theme: Theme) => + createStyles({ + iconCell: { + "&:last-child": { + paddingRight: 0 + }, + width: 48 + theme.spacing.unit / 2 + }, + indicator: { + color: theme.palette.text.disabled, + display: "inline-block", + left: 0, + marginRight: theme.spacing.unit * 2, + position: "absolute" + }, + offsetCell: { + "&:first-child": { + paddingLeft: theme.spacing.unit * 3 + }, + position: "relative" + }, + pointer: { + cursor: "pointer" + }, + root: { + "&:last-child": { + paddingBottom: 0 + }, + paddingTop: 0 + }, + rotate: { + transform: "rotate(180deg)" + }, + textRight: { + textAlign: "right" + }, + toLeft: { + "&:first-child": { + paddingLeft: 0 + } + }, + wideColumn: { + width: "100%" + } + }); + +const CountryList = withStyles(styles, { + name: "CountryList" +})( + ({ + classes, + countries, + disabled, + emptyText, + title, + onCountryAssign, + onCountryUnassign + }: CountryListProps & WithStyles) => { + const [isCollapsed, setCollapseStatus] = React.useState(true); + const toggleCollapse = () => setCollapseStatus(!isCollapsed); + + return ( + + + {i18n.t("Assign countries")} + + } + /> + + + + + + {i18n.t("{{ number }} Countries", { + context: "number of countries", + number: maybe(() => countries.length.toString(), "...") + })} + + + + + + + + {!isCollapsed && + renderCollection( + countries, + (country, countryIndex) => ( + + + {maybe( + () => ( + <> + {(countryIndex === 0 || + countries[countryIndex].country[0] !== + countries[countryIndex - 1].country[0]) && ( + + {country.country[0]} + + )} + {country.country} + + ), + + )} + + + onCountryUnassign(country.code)} + > + + + + + ), + () => ( + + + {emptyText} + + + ) + )} + +
+
+
+ ); + } +); +export default CountryList; diff --git a/src/components/CountryList/index.ts b/src/components/CountryList/index.ts new file mode 100644 index 000000000..3ad707c62 --- /dev/null +++ b/src/components/CountryList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CountryList"; +export * from "./CountryList"; diff --git a/src/components/Date/Date.test.tsx b/src/components/Date/Date.test.tsx new file mode 100644 index 000000000..a1d233515 --- /dev/null +++ b/src/components/Date/Date.test.tsx @@ -0,0 +1,44 @@ +import * as React from "react"; +import * as renderer from "react-test-renderer"; + +import { TimezoneProvider } from "../Timezone"; +import Date from "./Date"; + +const testDate = "2018-04-07"; +const expectedDate = "Apr 7, 2018"; + +test("Render plain date with timezone GMT-11", () => { + const date = renderer.create( + + + + ); + expect(date.toJSON()).toEqual(expectedDate); +}); + +test("Render plain date with timezone GMT+13", () => { + const date = renderer.create( + + + + ); + expect(date.toJSON()).toEqual(expectedDate); +}); + +test("Render humanized date with timezone GMT-11", () => { + const date = renderer.create( + + + + ); + expect(date.toJSON().props.dateTime).toEqual(testDate); +}); + +test("Render humanized date with timezone GMT+13", () => { + const date = renderer.create( + + + + ); + expect(date.toJSON().props.dateTime).toEqual(testDate); +}); diff --git a/src/components/Date/Date.tsx b/src/components/Date/Date.tsx new file mode 100644 index 000000000..f72d7a3be --- /dev/null +++ b/src/components/Date/Date.tsx @@ -0,0 +1,42 @@ +import Tooltip from "@material-ui/core/Tooltip"; +import * as moment from "moment-timezone"; +import * as React from "react"; + +import useDateLocalize from "@saleor/hooks/useDateLocalize"; +import { LocaleConsumer } from "../Locale"; +import { Consumer } from "./DateContext"; + +interface DateProps { + date: string; + plain?: boolean; +} + +export const Date: React.FC = ({ date, plain }) => { + const localizeDate = useDateLocalize(); + const getHumanized = (value: string, locale: string, currentDate: number) => + moment(value) + .locale(locale) + .from(currentDate); + + return ( + + {locale => ( + + {currentDate => + plain ? ( + localizeDate(date) + ) : ( + + + + ) + } + + )} + + ); +}; +Date.displayName = "Date"; +export default Date; diff --git a/src/components/Date/DateContext.tsx b/src/components/Date/DateContext.tsx new file mode 100644 index 000000000..449f1bc13 --- /dev/null +++ b/src/components/Date/DateContext.tsx @@ -0,0 +1,6 @@ +import * as React from "react"; + +export const DateContext = React.createContext(undefined); +const { Provider, Consumer } = DateContext; + +export { Consumer, Provider }; diff --git a/src/components/Date/DateProvider.tsx b/src/components/Date/DateProvider.tsx new file mode 100644 index 000000000..c54f779ce --- /dev/null +++ b/src/components/Date/DateProvider.tsx @@ -0,0 +1,34 @@ +import * as React from "react"; + +import { Provider } from "./DateContext"; + +interface DateProviderState { + date: number; +} + +export class DateProvider extends React.Component<{}, DateProviderState> { + static contextTypes = {}; + + intervalId: number; + + state = { + date: Date.now() + }; + + componentDidMount() { + this.intervalId = window.setInterval( + () => this.setState({ date: Date.now() }), + 10_000 + ); + } + + componentWillUnmount() { + window.clearInterval(this.intervalId); + } + + render() { + const { children } = this.props; + const { date } = this.state; + return {children}; + } +} diff --git a/src/components/Date/DateTime.tsx b/src/components/Date/DateTime.tsx new file mode 100644 index 000000000..c3199ce7c --- /dev/null +++ b/src/components/Date/DateTime.tsx @@ -0,0 +1,51 @@ +import Tooltip from "@material-ui/core/Tooltip"; +import * as moment from "moment-timezone"; +import * as React from "react"; +import ReactMoment from "react-moment"; + +import { LocaleConsumer } from "../Locale"; +import { TimezoneConsumer } from "../Timezone"; +import { Consumer } from "./DateContext"; + +interface DateTimeProps { + date: string; + plain?: boolean; +} + +export const DateTime: React.StatelessComponent = ({ + date, + plain +}) => { + const getTitle = (value: string, locale?: string, tz?: string) => { + let date = moment(value).locale(locale); + if (tz !== undefined) { + date = date.tz(tz); + } + return date.format("lll"); + }; + return ( + + {tz => ( + + {locale => ( + + {currentDate => + plain ? ( + getTitle(date, locale, tz) + ) : ( + + + {date} + + + ) + } + + )} + + )} + + ); +}; +DateTime.displayName = "DateTime"; +export default DateTime; diff --git a/src/components/Date/index.ts b/src/components/Date/index.ts new file mode 100644 index 000000000..a969a978f --- /dev/null +++ b/src/components/Date/index.ts @@ -0,0 +1,4 @@ +export { default } from "./Date"; +export * from "./Date"; +export * from "./DateTime"; +export * from "./DateProvider"; diff --git a/src/components/Debounce.tsx b/src/components/Debounce.tsx new file mode 100644 index 000000000..533c52aba --- /dev/null +++ b/src/components/Debounce.tsx @@ -0,0 +1,28 @@ +import * as React from "react"; + +export interface DebounceProps { + children: ((props: (...args: T[]) => void) => React.ReactNode); + debounceFn: (...args: T[]) => void; + time?: number; +} + +export class Debounce extends React.Component> { + timer = null; + + handleDebounce = (...args: T[]) => { + const { debounceFn, time } = this.props; + if (this.timer) { + clearTimeout(this.timer); + } + this.timer = setTimeout(() => debounceFn(...args), time || 200); + }; + + componentWillUnmount() { + clearTimeout(this.timer); + } + + render() { + return this.props.children(this.handleDebounce); + } +} +export default Debounce; diff --git a/src/components/DebounceForm.tsx b/src/components/DebounceForm.tsx new file mode 100644 index 000000000..0742aa50b --- /dev/null +++ b/src/components/DebounceForm.tsx @@ -0,0 +1,27 @@ +import * as React from "react"; +import Debounce from "./Debounce"; + +export interface DebounceFormProps { + change: (event: React.ChangeEvent, cb?: () => void) => void; + children: (( + props: (event: React.ChangeEvent) => void + ) => React.ReactNode); + submit: (event: React.FormEvent) => void; + time?: number; +} + +export const DebounceForm: React.StatelessComponent = ({ + change, + children, + submit, + time +}) => ( + + {debounceFn => + children(event => { + change(event, debounceFn); + }) + } + +); +export default DebounceForm; diff --git a/src/components/DeleteFilterTabDialog/DeleteFilterTabDialog.tsx b/src/components/DeleteFilterTabDialog/DeleteFilterTabDialog.tsx new file mode 100644 index 000000000..aa4fb9125 --- /dev/null +++ b/src/components/DeleteFilterTabDialog/DeleteFilterTabDialog.tsx @@ -0,0 +1,46 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import i18n from "../../i18n"; +import ActionDialog from "../ActionDialog"; +import { ConfirmButtonTransitionState } from "../ConfirmButton"; + +export interface DeleteFilterTabDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + tabName: string; + onClose: () => void; + onSubmit: () => void; +} + +const DeleteFilterTabDialog: React.FC = ({ + confirmButtonState, + onClose, + onSubmit, + open, + tabName +}) => ( + + {{ name }} search tab?", + { + name: tabName + } + ) + }} + /> + +); +DeleteFilterTabDialog.displayName = "DeleteFilterTabDialog"; +export default DeleteFilterTabDialog; diff --git a/src/components/DeleteFilterTabDialog/index.ts b/src/components/DeleteFilterTabDialog/index.ts new file mode 100644 index 000000000..3f4ef0d56 --- /dev/null +++ b/src/components/DeleteFilterTabDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from './DeleteFilterTabDialog'; +export * from './DeleteFilterTabDialog'; \ No newline at end of file diff --git a/src/components/DraftRenderer.tsx b/src/components/DraftRenderer.tsx new file mode 100644 index 000000000..d6fcd508f --- /dev/null +++ b/src/components/DraftRenderer.tsx @@ -0,0 +1,17 @@ +import { RawDraftContentState } from "draft-js"; +import * as draftToHtml from "draftjs-to-html"; +import * as React from "react"; + +interface DraftRendererProps { + content: RawDraftContentState; +} + +const DraftRenderer: React.FC = ({ content }) => ( +
+); +DraftRenderer.displayName = "DraftRenderer"; +export default DraftRenderer; diff --git a/src/components/Dropzone.tsx b/src/components/Dropzone.tsx new file mode 100644 index 000000000..1a8c62114 --- /dev/null +++ b/src/components/Dropzone.tsx @@ -0,0 +1,3 @@ +/* tslint:disable:no-submodule-imports */ +import * as Dropzone from "react-dropzone/dist/index"; +export default Dropzone; diff --git a/src/components/EditableTableCell/EditableTableCell.tsx b/src/components/EditableTableCell/EditableTableCell.tsx new file mode 100644 index 000000000..7438e0762 --- /dev/null +++ b/src/components/EditableTableCell/EditableTableCell.tsx @@ -0,0 +1,116 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TableCell from "@material-ui/core/TableCell"; +import TextField, { TextFieldProps } from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import * as classNames from "classnames"; +import * as React from "react"; + +import Form from "@saleor/components/Form"; + +const styles = (theme: Theme) => + createStyles({ + card: { + border: `1px solid ${theme.overrides.MuiCard.root.borderColor}` + }, + container: { + position: "relative" + }, + overlay: { + cursor: "pointer", + height: "100vh", + left: 0, + position: "fixed", + top: 0, + width: "100vw", + zIndex: 1 + }, + root: { + left: 0, + minWidth: theme.spacing.unit * 20, + position: "absolute", + top: 0, + width: `calc(100% + ${4 * theme.spacing.unit}px)`, + zIndex: 2 + }, + text: { + cursor: "pointer", + fontSize: "0.8125rem" + } + }); + +interface EditableTableCellProps extends WithStyles { + className?: string; + defaultValue?: string; + focused?: boolean; + InputProps?: TextFieldProps; + value: string; + onConfirm(value: string): any; +} + +export const EditableTableCell = withStyles(styles, { + name: "EditableTableCell" +})( + ({ + classes, + className, + defaultValue, + focused, + InputProps, + value, + onConfirm + }: EditableTableCellProps) => { + const [opened, setOpenStatus] = React.useState(focused); + const enable = () => setOpenStatus(true); + const disable = () => setOpenStatus(false); + + const handleConfirm = (data: { value: string }) => { + disable(); + onConfirm(data.value); + }; + + return ( + + {opened &&
} +
+ {({ change, data }) => ( + <> + + {value || defaultValue} + + {opened && ( +
+ + + + + +
+ )} + + )} +
+ + ); + } +); +EditableTableCell.displayName = "EditableTableCell"; +export default EditableTableCell; diff --git a/src/components/EditableTableCell/index.ts b/src/components/EditableTableCell/index.ts new file mode 100644 index 000000000..82c842fa9 --- /dev/null +++ b/src/components/EditableTableCell/index.ts @@ -0,0 +1,2 @@ +export { default } from "./EditableTableCell"; +export * from "./EditableTableCell"; diff --git a/src/components/ErrorMessageCard/ErrorMessageCard.tsx b/src/components/ErrorMessageCard/ErrorMessageCard.tsx new file mode 100644 index 000000000..ed64be6f2 --- /dev/null +++ b/src/components/ErrorMessageCard/ErrorMessageCard.tsx @@ -0,0 +1,25 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import i18n from "../../i18n"; + +interface ErrorMessageCardProps { + message: string; +} + +const ErrorMessageCard: React.StatelessComponent = ({ + message +}) => ( + + + + {i18n.t("Error", { context: "title" })} + + {message} + + +); +ErrorMessageCard.displayName = "ErrorMessageCard"; +export default ErrorMessageCard; diff --git a/src/components/ErrorMessageCard/index.ts b/src/components/ErrorMessageCard/index.ts new file mode 100644 index 000000000..e5e67e8be --- /dev/null +++ b/src/components/ErrorMessageCard/index.ts @@ -0,0 +1 @@ +export { default } from "./ErrorMessageCard"; diff --git a/src/components/ErrorPage/ErrorPage.tsx b/src/components/ErrorPage/ErrorPage.tsx new file mode 100644 index 000000000..299613e9b --- /dev/null +++ b/src/components/ErrorPage/ErrorPage.tsx @@ -0,0 +1,100 @@ +import Button from "@material-ui/core/Button"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; +import SVG from "react-inlinesvg"; + +import * as notFoundImage from "@assets/images/what.svg"; +import i18n from "../../i18n"; + +export interface ErrorPageProps extends WithStyles { + onBack: () => void; +} + +const styles = (theme: Theme) => + createStyles({ + bottomHeader: { + fontWeight: 600 as 600, + textTransform: "uppercase" + }, + button: { + marginTop: theme.spacing.unit * 2, + padding: 20 + }, + container: { + [theme.breakpoints.down("sm")]: { + gridTemplateColumns: "1fr", + padding: theme.spacing.unit * 3, + width: "100%" + }, + display: "grid", + gridTemplateColumns: "1fr 487px", + margin: "0 auto", + width: 830 + }, + innerContainer: { + [theme.breakpoints.down("sm")]: { + order: 1, + textAlign: "center" + }, + display: "flex", + flexDirection: "column", + justifyContent: "center" + }, + notFoundImage: { + "& svg": { + width: "100%" + } + }, + root: { + alignItems: "center", + display: "flex", + height: "calc(100vh - 88px)" + }, + upperHeader: { + fontWeight: 600 as 600 + } + }); + +const ErrorPage = withStyles(styles, { name: "NotFoundPage" })( + ({ classes, onBack }: ErrorPageProps) => ( +
+
+
+
+ + {i18n.t("Ooops!...")} + + + {i18n.t("Error")} + + {i18n.t("We've encountered a problem...")} + + {i18n.t("Don't worry, everything is gonna be fine")} + +
+
+ +
+
+
+ +
+
+
+ ) +); +ErrorPage.displayName = "ErrorPage"; +export default ErrorPage; diff --git a/src/components/ErrorPage/index.ts b/src/components/ErrorPage/index.ts new file mode 100644 index 000000000..3d294a58f --- /dev/null +++ b/src/components/ErrorPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ErrorPage"; +export * from "./ErrorPage"; diff --git a/src/components/ExtendedPageHeader/ExtendedPageHeader.tsx b/src/components/ExtendedPageHeader/ExtendedPageHeader.tsx new file mode 100644 index 000000000..52affe67f --- /dev/null +++ b/src/components/ExtendedPageHeader/ExtendedPageHeader.tsx @@ -0,0 +1,55 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as classNames from "classnames"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + action: { + flex: "0 0 auto" + }, + grid: { + padding: theme.spacing.unit * 2 + }, + menuButton: { + flex: "0 0 auto", + marginLeft: theme.spacing.unit * -2, + marginRight: theme.spacing.unit * 3, + marginTop: -theme.spacing.unit * 2 + }, + root: { + alignItems: "center", + display: "flex", + marginBottom: theme.spacing.unit * 3 + }, + subtitle: { + alignItems: "center", + display: "flex", + marginBottom: theme.spacing.unit * 2 + }, + title: { + flex: 1, + paddingBottom: theme.spacing.unit * 2 + } + }); + +interface ExtendedPageHeaderProps extends WithStyles { + children?: React.ReactNode; + className?: string; + title?: React.ReactNode; +} + +const ExtendedPageHeader = withStyles(styles, { name: "ExtendedPageHeader" })( + ({ children, classes, className, title }: ExtendedPageHeaderProps) => ( +
+ {title} +
{children}
+
+ ) +); +ExtendedPageHeader.displayName = "ExtendedPageHeader"; +export default ExtendedPageHeader; diff --git a/src/components/ExtendedPageHeader/index.ts b/src/components/ExtendedPageHeader/index.ts new file mode 100644 index 000000000..d1ee37996 --- /dev/null +++ b/src/components/ExtendedPageHeader/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ExtendedPageHeader"; +export * from "./ExtendedPageHeader"; diff --git a/src/components/ExternalLink/ExternalLink.tsx b/src/components/ExternalLink/ExternalLink.tsx new file mode 100644 index 000000000..d3b64db1d --- /dev/null +++ b/src/components/ExternalLink/ExternalLink.tsx @@ -0,0 +1,36 @@ +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import Typography, { TypographyProps } from "@material-ui/core/Typography"; +import * as React from "react"; + +const styles = createStyles({ + link: { + textDecoration: "none" + } +}); + +interface ExternalLinkProps + extends React.HTMLProps, + WithStyles { + href: string; + className?: string; + typographyProps?: TypographyProps; +} + +const ExternalLink = withStyles(styles, { name: "ExternalLink" })( + ({ + classes, + className, + children, + href, + typographyProps, + ...props + }: ExternalLinkProps) => ( + + + {children} + + + ) +); +ExternalLink.displayName = "ExternalLink"; +export default ExternalLink; diff --git a/src/components/ExternalLink/index.ts b/src/components/ExternalLink/index.ts new file mode 100644 index 000000000..ec7bc81ba --- /dev/null +++ b/src/components/ExternalLink/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ExternalLink"; +export * from "./ExternalLink"; diff --git a/src/components/FileUpload/FileUpload.tsx b/src/components/FileUpload/FileUpload.tsx new file mode 100644 index 000000000..ecccddd38 --- /dev/null +++ b/src/components/FileUpload/FileUpload.tsx @@ -0,0 +1,51 @@ +import Button from "@material-ui/core/Button"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; +import i18n from "../../i18n"; + +const styles = createStyles({ + fileUploadField: { + display: "none" + }, + root: { + display: "flex" + }, + textField: { + flex: 1 + } +}); + +interface FileUploadProps extends WithStyles { + disabled?: boolean; + name?: string; + value?: any; + onChange?(event: React.ChangeEvent); +} + +const FileUpload = withStyles(styles, { name: "FileUpload" })( + ({ classes, disabled, name, value, onChange }: FileUploadProps) => ( +
+ (this.upload = ref)} + className={classes.fileUploadField} + type="file" + value={value} + /> + + +
+ ) +); +FileUpload.displayName = "FileUpload"; +export default FileUpload; diff --git a/src/components/FileUpload/index.ts b/src/components/FileUpload/index.ts new file mode 100644 index 000000000..7082935e4 --- /dev/null +++ b/src/components/FileUpload/index.ts @@ -0,0 +1,2 @@ +export { default } from "./FileUpload"; +export * from "./FileUpload"; diff --git a/src/components/Filter/Filter.tsx b/src/components/Filter/Filter.tsx new file mode 100644 index 000000000..8e31b8ea4 --- /dev/null +++ b/src/components/Filter/Filter.tsx @@ -0,0 +1,152 @@ +import ButtonBase from "@material-ui/core/ButtonBase"; +import Grow from "@material-ui/core/Grow"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; +import Typography from "@material-ui/core/Typography"; +import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown"; +import * as classNames from "classnames"; +import * as React from "react"; + +import { FilterContent } from "."; +import i18n from "../../i18n"; +import { FilterContentSubmitData } from "./FilterContent"; +import { IFilter } from "./types"; + +export interface FilterProps { + currencySymbol: string; + menu: IFilter; + filterLabel: string; + onFilterAdd: (filter: FilterContentSubmitData) => void; +} + +const styles = (theme: Theme) => + createStyles({ + addFilterButton: { + "&$filterButton": { + "&:hover, &:focus": { + backgroundColor: fade(theme.palette.primary.main, 0.1) + }, + backgroundColor: theme.palette.background.paper, + border: `1px solid ${theme.palette.primary.main}`, + cursor: "pointer", + marginBottom: 0, + marginRight: theme.spacing.unit * 2, + marginTop: 0, + transition: theme.transitions.duration.short + "ms" + } + }, + addFilterButtonActive: { + "&$addFilterButton": { + backgroundColor: fade(theme.palette.primary.main, 0.1) + } + }, + addFilterIcon: { + transition: theme.transitions.duration.short + "ms" + }, + addFilterText: { + color: theme.palette.primary.main, + fontSize: 14, + fontWeight: 600 as 600, + marginRight: 4, + textTransform: "uppercase" + }, + filterButton: { + alignItems: "center", + backgroundColor: fade(theme.palette.primary.main, 0.6), + borderRadius: "19px", + display: "flex", + height: "38px", + justifyContent: "space-around", + margin: `0 ${theme.spacing.unit * 2}px ${theme.spacing.unit}px`, + marginLeft: 0, + padding: "0 16px" + }, + filterLabel: { + marginBottom: theme.spacing.unit + }, + paper: { + marginTop: theme.spacing.unit * 2, + padding: theme.spacing.unit * 2, + width: 240 + }, + popover: { + zIndex: 1 + }, + rotate: { + transform: "rotate(180deg)" + } + }); +const Filter = withStyles(styles, { name: "Filter" })( + ({ + classes, + currencySymbol, + filterLabel, + menu, + onFilterAdd + }: FilterProps & WithStyles) => { + const anchor = React.useRef(); + const [isFilterMenuOpened, setFilterMenuOpened] = React.useState(false); + + return ( +
+ setFilterMenuOpened(!isFilterMenuOpened)} + > + + {i18n.t("Add Filter")} + + + + + {({ TransitionProps, placement }) => ( + + + + {filterLabel} + + { + onFilterAdd(data); + setFilterMenuOpened(false); + }} + /> + + + )} + +
+ ); + } +); +Filter.displayName = "Filter"; +export default Filter; diff --git a/src/components/Filter/FilterContent.tsx b/src/components/Filter/FilterContent.tsx new file mode 100644 index 000000000..3822d8cdb --- /dev/null +++ b/src/components/Filter/FilterContent.tsx @@ -0,0 +1,137 @@ +import Button from "@material-ui/core/Button"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import { makeStyles } from "@material-ui/styles"; +import i18n from "../../i18n"; +import { getMenuItemByValue, isLeaf, walkToRoot } from "../../utils/menu"; +import FormSpacer from "../FormSpacer"; +import SingleSelectField from "../SingleSelectField"; +import FilterElement from "./FilterElement"; +import { IFilter } from "./types"; + +export interface FilterContentSubmitData { + name: string; + value: string | string[]; +} +export interface FilterContentProps { + currencySymbol: string; + filters: IFilter; + onSubmit: (data: FilterContentSubmitData) => void; +} + +function checkFilterValue(value: string | string[]): boolean { + if (typeof value === "string") { + return !!value; + } + return value.some(v => !!v); +} + +function getFilterChoices(items: IFilter) { + return items.map(filterItem => ({ + label: filterItem.label, + value: filterItem.value + })); +} + +const useStyles = makeStyles({ + input: { + padding: "20px 12px 17px" + } +}); + +const FilterContent: React.FC = ({ + currencySymbol, + filters, + onSubmit +}) => { + const [menuValue, setMenuValue] = React.useState(""); + const [filterValue, setFilterValue] = React.useState(""); + const classes = useStyles(); + + const activeMenu = menuValue + ? getMenuItemByValue(filters, menuValue) + : undefined; + const menus = menuValue + ? walkToRoot(filters, menuValue).slice(-1) + : undefined; + + const onMenuChange = (event: React.ChangeEvent) => { + setMenuValue(event.target.value); + setFilterValue(""); + }; + + return ( + <> + + {menus && + menus.map( + (filterItem, filterItemIndex) => + !isLeaf(filterItem) && ( + + + + + ) + )} + {activeMenu && isLeaf(activeMenu) && ( + <> + + {activeMenu.data.additionalText && ( + {activeMenu.data.additionalText} + )} + setFilterValue(value)} + /> + {checkFilterValue(filterValue) && ( + <> + + + + )} + + )} + + ); +}; +FilterContent.displayName = "FilterContent"; +export default FilterContent; diff --git a/src/components/Filter/FilterElement.tsx b/src/components/Filter/FilterElement.tsx new file mode 100644 index 000000000..590ebffff --- /dev/null +++ b/src/components/Filter/FilterElement.tsx @@ -0,0 +1,211 @@ +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import { makeStyles } from "@material-ui/styles"; +import * as React from "react"; + +import i18n from "../../i18n"; +import Calendar from "../../icons/Calendar"; +import FormSpacer from "../FormSpacer"; +import PriceField from "../PriceField"; +import SingleSelectField from "../SingleSelectField"; +import { FieldType, IFilterItem } from "./types"; + +export interface FilterElementProps { + className?: string; + filter: IFilterItem; + value: string | string[]; + onChange: (value: string | string[]) => void; +} + +const useStyles = makeStyles({ + calendar: { + margin: 8 + }, + input: { + padding: "20px 12px 17px" + } +}); + +export interface FilterElementProps { + className?: string; + currencySymbol: string; + filter: IFilterItem; + value: string | string[]; + onChange: (value: string | string[]) => void; +} + +const FilterElement: React.FC = ({ + currencySymbol, + className, + filter, + onChange, + value +}) => { + const classes = useStyles(); + + if (filter.data.type === FieldType.date) { + return ( + onChange(event.target.value)} + value={value} + InputProps={{ + classes: { + input: classes.input + }, + startAdornment: + }} + /> + ); + } else if (filter.data.type === FieldType.rangeDate) { + return ( + <> + {i18n.t("from")} + onChange([event.target.value, value[1]])} + InputProps={{ + classes: { + input: classes.input + }, + startAdornment: + }} + /> + + {i18n.t("to")} + onChange([value[0], event.target.value])} + InputProps={{ + classes: { + input: classes.input + }, + startAdornment: + }} + /> + + ); + } else if (filter.data.type === FieldType.range) { + return ( + <> + {i18n.t("from")} + onChange([event.target.value, value[1]])} + type="number" + InputProps={{ + classes: { + input: classes.input + } + }} + /> + + {i18n.t("to")} + onChange([value[0], event.target.value])} + type="number" + InputProps={{ + classes: { + input: classes.input + } + }} + /> + + ); + } else if (filter.data.type === FieldType.rangePrice) { + return ( + <> + {i18n.t("from")} + onChange([event.target.value, value[1]])} + InputProps={{ + classes: { + input: classes.input + } + }} + /> + + {i18n.t("to")} + onChange([value[0], event.target.value])} + InputProps={{ + classes: { + input: classes.input + } + }} + /> + + ); + } else if (filter.data.type === FieldType.select) { + return ( + ({ + ...option, + value: option.value.toString() + }))} + selectProps={{ + className, + inputProps: { + className: classes.input + } + }} + value={value as string} + placeholder={i18n.t("Select Filter...")} + onChange={event => onChange(event.target.value)} + /> + ); + } else if (filter.data.type === FieldType.price) { + return ( + onChange(event.target.value)} + InputProps={{ + classes: { + input: !filter.data.fieldLabel && classes.input + } + }} + value={value as string} + /> + ); + } else if (filter.data.type === FieldType.hidden) { + onChange(filter.data.value); + return ; + } + return ( + onChange(event.target.value)} + value={value as string} + /> + ); +}; +FilterElement.displayName = "FilterElement"; +export default FilterElement; diff --git a/src/components/Filter/index.ts b/src/components/Filter/index.ts new file mode 100644 index 000000000..2bc2cf752 --- /dev/null +++ b/src/components/Filter/index.ts @@ -0,0 +1,5 @@ +export { default } from "./Filter"; +export * from "./Filter"; +export { default as FilterContent } from "./FilterContent"; +export * from "./FilterContent"; +export * from "./types"; diff --git a/src/components/Filter/types.ts b/src/components/Filter/types.ts new file mode 100644 index 000000000..53bf9302a --- /dev/null +++ b/src/components/Filter/types.ts @@ -0,0 +1,30 @@ +import { IMenu, IMenuItem } from "../../utils/menu"; + +export enum FieldType { + date, + hidden, + number, + price, + range, + rangeDate, + rangePrice, + select, + text +} + +export interface FilterChoice { + label: string; + value: string | boolean; +} + +export interface FilterData { + additionalText?: string; + fieldLabel: string; + options?: FilterChoice[]; + type: FieldType; + value?: string; +} + +export type IFilterItem = IMenuItem; + +export type IFilter = IMenu; diff --git a/src/components/FilterBar/FilterBar.tsx b/src/components/FilterBar/FilterBar.tsx new file mode 100644 index 000000000..e8a75a229 --- /dev/null +++ b/src/components/FilterBar/FilterBar.tsx @@ -0,0 +1,82 @@ +import * as React from "react"; + +import i18n from "../../i18n"; +import { FilterProps } from "../../types"; +import Debounce from "../Debounce"; +import { IFilter } from "../Filter/types"; +import FilterTabs, { FilterChips, FilterTab } from "../TableFilter"; + +export interface FilterBarProps + extends FilterProps { + filterMenu: IFilter; +} + +const FilterBar: React.FC = ({ + allTabLabel, + currencySymbol, + filterLabel, + filtersList, + filterTabs, + filterMenu, + currentTab, + initialSearch, + searchPlaceholder, + onAll, + onSearchChange, + onFilterAdd, + onFilterSave, + onTabChange, + onFilterDelete +}) => { + const [search, setSearch] = React.useState(initialSearch); + React.useEffect(() => setSearch(initialSearch), [currentTab, initialSearch]); + + const isCustom = currentTab === filterTabs.length + 1; + + return ( + <> + + + {filterTabs.map((tab, tabIndex) => ( + onTabChange(tabIndex + 1)} + label={tab.name} + /> + ))} + {isCustom && ( + undefined} + label={i18n.t("Custom Filter")} + /> + )} + + + {debounceSearchChange => { + const handleSearchChange = (event: React.ChangeEvent) => { + const value = event.target.value; + setSearch(value); + debounceSearchChange(value); + }; + + return ( + + ); + }} + + + ); +}; +FilterBar.displayName = "FilterBar"; +export default FilterBar; diff --git a/src/components/FilterBar/index.ts b/src/components/FilterBar/index.ts new file mode 100644 index 000000000..000078c21 --- /dev/null +++ b/src/components/FilterBar/index.ts @@ -0,0 +1,2 @@ +export { default } from './FilterBar'; +export * from './FilterBar'; \ No newline at end of file diff --git a/src/components/FilterCard/FilterCard.tsx b/src/components/FilterCard/FilterCard.tsx new file mode 100644 index 000000000..2a03d0fa8 --- /dev/null +++ b/src/components/FilterCard/FilterCard.tsx @@ -0,0 +1,33 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import CardHeader from "@material-ui/core/CardHeader"; +import IconButton from "@material-ui/core/IconButton"; +import RefreshIcon from "@material-ui/icons/Refresh"; +import * as React from "react"; + +import i18n from "../../i18n"; + +export interface FilterCardProps { + handleClear(); +} + +const FilterCard: React.StatelessComponent = ({ + children, + handleClear +}) => ( + +
+ + + + } + title={i18n.t("Filters")} + /> + {children} + +
+); +FilterCard.displayName = "FilterCard"; +export default FilterCard; diff --git a/src/components/FilterCard/index.ts b/src/components/FilterCard/index.ts new file mode 100644 index 000000000..f9e07b97d --- /dev/null +++ b/src/components/FilterCard/index.ts @@ -0,0 +1 @@ +export { default } from "./FilterCard"; diff --git a/src/components/Form/Form.tsx b/src/components/Form/Form.tsx new file mode 100644 index 000000000..7b19a244b --- /dev/null +++ b/src/components/Form/Form.tsx @@ -0,0 +1,170 @@ +import * as React from "react"; +import { UserError } from "../../types"; + +export interface FormProps { + children: (props: { + data: T; + hasChanged: boolean; + errors: { [key: string]: string }; + change(event: React.ChangeEvent, cb?: () => void); + reset(); + submit(event?: React.FormEvent); + }) => React.ReactElement; + errors?: UserError[]; + initial?: T; + confirmLeave?: boolean; + useForm?: boolean; + resetOnSubmit?: boolean; + onSubmit?(data: T); +} + +interface FormComponentProps extends FormProps { + hasChanged: boolean; + toggleFormChangeState: () => void; +} + +interface FormState { + initial: T; + fields: T; + hasChanged: boolean; +} + +class FormComponent extends React.Component< + FormComponentProps, + FormState +> { + static getDerivedStateFromProps( + nextProps: FormComponentProps, + prevState: FormState + ): FormState { + const changedFields = Object.keys(nextProps.initial).filter( + nextFieldName => + JSON.stringify(nextProps.initial[nextFieldName]) !== + JSON.stringify(prevState.initial[nextFieldName]) + ); + if (changedFields.length > 0) { + const swapFields = changedFields.reduce((prev, curr) => { + prev[curr] = nextProps.initial[curr]; + return prev; + }, {}); + + return { + fields: { + ...(prevState.fields as any), + ...swapFields + }, + hasChanged: false, + initial: { + ...(prevState.initial as any), + ...swapFields + } + }; + } + return null; + } + + state: FormState = { + fields: this.props.initial, + hasChanged: false, + initial: this.props.initial + }; + + componentDidUpdate() { + const { hasChanged, confirmLeave, toggleFormChangeState } = this.props; + if (this.state.hasChanged !== hasChanged && confirmLeave) { + toggleFormChangeState(); + } + } + + componentDidMount() { + const { hasChanged, confirmLeave, toggleFormChangeState } = this.props; + if (this.state.hasChanged !== hasChanged && confirmLeave) { + toggleFormChangeState(); + } + } + + componentWillUnmount() { + const { hasChanged, confirmLeave, toggleFormChangeState } = this.props; + if (hasChanged && confirmLeave) { + toggleFormChangeState(); + } + } + + handleChange = (event: React.ChangeEvent, cb?: () => void) => { + const { target } = event; + if (!(target.name in this.state.fields)) { + console.error(`Unknown form field: ${target.name}`); + return; + } + + this.setState( + { + fields: { + ...(this.state.fields as any), + [target.name]: target.value + }, + hasChanged: true + }, + typeof cb === "function" ? cb : undefined + ); + }; + + handleKeyDown = (event: React.KeyboardEvent) => { + switch (event.keyCode) { + // Enter + case 13: + this.props.onSubmit(this.state.fields); + break; + } + }; + + handleSubmit = (event?: React.FormEvent, cb?: () => void) => { + const { resetOnSubmit, onSubmit } = this.props; + if (event) { + event.stopPropagation(); + event.preventDefault(); + } + if (onSubmit !== undefined) { + onSubmit(this.state.fields); + } + if (cb) { + cb(); + } + if (resetOnSubmit) { + this.setState({ + fields: this.state.initial + }); + } + }; + + render() { + const { children, errors, useForm = true } = this.props; + + const contents = children({ + change: this.handleChange, + data: this.state.fields, + errors: errors + ? errors.reduce( + (prev, curr) => ({ + ...prev, + [curr.field.split(":")[0]]: curr.message + }), + {} + ) + : {}, + hasChanged: this.state.hasChanged, + reset: () => + this.setState({ + fields: this.state.initial + }), + submit: this.handleSubmit + }); + + return useForm ? ( +
{contents}
+ ) : ( +
{contents}
+ ); + } +} +export default FormComponent; diff --git a/src/components/Form/FormActions.tsx b/src/components/Form/FormActions.tsx new file mode 100644 index 000000000..3a1a49a6f --- /dev/null +++ b/src/components/Form/FormActions.tsx @@ -0,0 +1,40 @@ +import Button from "@material-ui/core/Button"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import Toolbar from "@material-ui/core/Toolbar"; +import * as React from "react"; + +import i18n from "../../i18n"; + +const styles = createStyles({ + cardActions: { + flexDirection: "row-reverse" as "row-reverse" + } +}); + +interface FormActionsProps extends WithStyles { + submitLabel: string; + onCancel?(); + onSubmit?(event: React.FormEvent); +} + +const FormActions = withStyles(styles, { name: "FormActions" })( + ({ classes, onCancel, onSubmit, submitLabel }: FormActionsProps) => ( + + + {onCancel && ( + + )} + + ) +); +FormActions.displayName = "FormActions"; +export default FormActions; diff --git a/src/components/Form/FormContext.tsx b/src/components/Form/FormContext.tsx new file mode 100644 index 000000000..b8d73029c --- /dev/null +++ b/src/components/Form/FormContext.tsx @@ -0,0 +1,54 @@ +import * as React from "react"; + +import FormComponent, { FormProps } from "./Form"; + +interface IFormContext { + hasChanged: boolean; + toggle: () => void; +} + +export const FormContext = React.createContext(undefined); + +interface FormProviderState { + hasChanged: boolean; +} + +export class FormProvider extends React.Component<{}, FormProviderState> { + state: FormProviderState = { + hasChanged: false + }; + + toggle = () => + this.setState(prevState => ({ + hasChanged: !prevState.hasChanged + })); + + render() { + return ( + + {this.props.children} + + ); + } +} + +export function Form(props: FormProps) { + return ( + + {({ hasChanged, toggle }) => ( + + )} + + ); +} + +export default Form; diff --git a/src/components/Form/index.ts b/src/components/Form/index.ts new file mode 100644 index 000000000..1f0b7dda4 --- /dev/null +++ b/src/components/Form/index.ts @@ -0,0 +1,5 @@ +export * from "./Form"; +export { default as FormActions } from "./FormActions"; +export * from "./FormActions"; +export * from "./FormContext"; +export { default } from "./FormContext"; diff --git a/src/components/FormSpacer.tsx b/src/components/FormSpacer.tsx new file mode 100644 index 000000000..3401eb6cf --- /dev/null +++ b/src/components/FormSpacer.tsx @@ -0,0 +1,27 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + spacer: { + marginTop: theme.spacing.unit * 3 + } + }); + +interface FormSpacerProps extends WithStyles { + children?: React.ReactNode; +} + +export const FormSpacer = withStyles(styles, { name: "FormSpacer" })( + ({ classes, children }: FormSpacerProps) => ( +
{children}
+ ) +); + +FormSpacer.displayName = "FormSpacer"; +export default FormSpacer; diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx new file mode 100644 index 000000000..b5cc6664c --- /dev/null +++ b/src/components/Grid/Grid.tsx @@ -0,0 +1,56 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import classNames from "classnames"; +import * as React from "react"; + +export type GridVariant = "default" | "inverted" | "uniform"; +export interface GridProps extends WithStyles { + children: React.ReactNodeArray | React.ReactNode; + className?: string; + variant?: GridVariant; +} + +const styles = (theme: Theme) => + createStyles({ + default: { + gridTemplateColumns: "9fr 4fr" + }, + inverted: { + gridTemplateColumns: "4fr 9fr" + }, + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 3 + "px", + gridRowGap: theme.spacing.unit * 3 + "px", + [theme.breakpoints.down("sm")]: { + gridRowGap: theme.spacing.unit + "px", + gridTemplateColumns: "1fr" + } + }, + uniform: { + gridTemplateColumns: "1fr 1fr" + } + }); + +export const Grid = withStyles(styles, { name: "Grid" })( + ({ className, children, classes, variant }: GridProps) => ( +
+ {children} +
+ ) +); +Grid.displayName = "Grid"; +Grid.defaultProps = { + variant: "default" +}; +export default Grid; diff --git a/src/components/Grid/index.ts b/src/components/Grid/index.ts new file mode 100644 index 000000000..e8a8dd689 --- /dev/null +++ b/src/components/Grid/index.ts @@ -0,0 +1,2 @@ +export { default } from "./Grid"; +export * from "./Grid"; diff --git a/src/components/Hr.tsx b/src/components/Hr.tsx new file mode 100644 index 000000000..458434005 --- /dev/null +++ b/src/components/Hr.tsx @@ -0,0 +1,32 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import classNames from "classnames"; +import * as React from "react"; + +interface HrProps { + className?: string; +} + +const styles = (theme: Theme) => + createStyles({ + root: { + backgroundColor: theme.overrides.MuiCard.root.borderColor, + border: "none", + display: "block", + height: 1, + margin: 0, + width: "100%" + } + }); + +export const Hr = withStyles(styles, { name: "Hr" })( + ({ className, classes }: HrProps & WithStyles) => ( +
+ ) +); +Hr.displayName = "Hr"; +export default Hr; diff --git a/src/components/IconButtonTableCell/IconButtonTableCell.tsx b/src/components/IconButtonTableCell/IconButtonTableCell.tsx new file mode 100644 index 000000000..558891746 --- /dev/null +++ b/src/components/IconButtonTableCell/IconButtonTableCell.tsx @@ -0,0 +1,49 @@ +import IconButton from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TableCell from "@material-ui/core/TableCell"; +import * as React from "react"; + +import { stopPropagation } from "../../misc"; +import { ICONBUTTON_SIZE } from "../../theme"; + +export interface IconButtonTableCellProps { + children: React.ReactNode; + disabled?: boolean; + onClick: () => void; +} + +const styles = (theme: Theme) => + createStyles({ + root: { + "&:last-child": { + paddingRight: 0 + }, + paddingRight: 0, + width: ICONBUTTON_SIZE + theme.spacing.unit / 2 + } + }); +const IconButtonTableCell = withStyles(styles, { name: "IconButtonTableCell" })( + ({ + children, + classes, + disabled, + onClick + }: IconButtonTableCellProps & WithStyles) => ( + + + {children} + + + ) +); +IconButtonTableCell.displayName = "IconButtonTableCell"; +export default IconButtonTableCell; diff --git a/src/components/IconButtonTableCell/index.ts b/src/components/IconButtonTableCell/index.ts new file mode 100644 index 000000000..ec9027bd4 --- /dev/null +++ b/src/components/IconButtonTableCell/index.ts @@ -0,0 +1,2 @@ +export { default } from './IconButtonTableCell'; +export * from './IconButtonTableCell'; \ No newline at end of file diff --git a/src/components/ImageTile/ImageTile.tsx b/src/components/ImageTile/ImageTile.tsx new file mode 100644 index 000000000..deb2c8f93 --- /dev/null +++ b/src/components/ImageTile/ImageTile.tsx @@ -0,0 +1,83 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import EditIcon from "@material-ui/icons/Edit"; + +const styles = (theme: Theme) => + createStyles({ + image: { + height: "100%", + objectFit: "contain", + userSelect: "none", + width: "100%" + }, + imageContainer: { + "&:hover, &.dragged": { + "& $imageOverlay": { + display: "block" + } + }, + background: theme.palette.background.paper, + border: `1px solid ${theme.overrides.MuiCard.root.borderColor}`, + borderRadius: theme.spacing.unit, + height: 148, + overflow: "hidden", + padding: theme.spacing.unit * 2, + position: "relative", + width: 148 + }, + imageOverlay: { + background: "rgba(0, 0, 0, 0.6)", + cursor: "move", + display: "none", + height: 148, + left: 0, + position: "absolute", + top: 0, + width: 148 + }, + imageOverlayToolbar: { + display: "flex", + justifyContent: "flex-end" + } + }); + +interface ImageTileProps extends WithStyles { + image: { + alt?: string; + url: string; + }; + onImageDelete?: () => void; + onImageEdit?: (event: React.ChangeEvent) => void; +} + +const ImageTile = withStyles(styles, { name: "ImageTile" })( + ({ classes, onImageDelete, onImageEdit, image }: ImageTileProps) => ( +
+
+
+ {onImageEdit && ( + + + + )} + {onImageDelete && ( + + + + )} +
+
+ {image.alt} +
+ ) +); +ImageTile.displayName = "ImageTile"; +export default ImageTile; diff --git a/src/components/ImageTile/index.ts b/src/components/ImageTile/index.ts new file mode 100644 index 000000000..56297f884 --- /dev/null +++ b/src/components/ImageTile/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ImageTile"; +export * from "./ImageTile"; diff --git a/src/components/ImageUpload/ImageUpload.tsx b/src/components/ImageUpload/ImageUpload.tsx new file mode 100644 index 000000000..f6d75eb4d --- /dev/null +++ b/src/components/ImageUpload/ImageUpload.tsx @@ -0,0 +1,111 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; +import Typography from "@material-ui/core/Typography"; +import classNames from "classnames"; +import * as React from "react"; + +import i18n from "../../i18n"; +import ImageIcon from "../../icons/Image"; +import Dropzone from "../Dropzone"; + +interface ImageUploadProps { + children?: (props: { isDragActive: boolean }) => React.ReactNode; + className?: string; + disableClick?: boolean; + isActiveClassName?: string; + iconContainerClassName?: string; + iconContainerActiveClassName?: string; + onImageUpload: (file: File) => void; +} + +const styles = (theme: Theme) => + createStyles({ + containerDragActive: { + background: fade(theme.palette.primary.main, 0.1), + color: theme.palette.primary.main + }, + fileField: { + display: "none" + }, + imageContainer: { + background: "#ffffff", + border: "1px solid #eaeaea", + borderRadius: theme.spacing.unit, + height: 148, + justifySelf: "start", + overflow: "hidden", + padding: theme.spacing.unit * 2, + position: "relative", + transition: theme.transitions.duration.standard + "s", + width: 148 + }, + photosIcon: { + height: "64px", + margin: "0 auto", + width: "64px" + }, + photosIconContainer: { + padding: `${theme.spacing.unit * 5}px 0`, + textAlign: "center" + }, + uploadText: { + color: theme.typography.body2.color, + textTransform: "uppercase" + } + }); + +export const ImageUpload = withStyles(styles, { name: "ImageUpload" })( + ({ + children, + classes, + className, + disableClick, + isActiveClassName, + iconContainerActiveClassName, + iconContainerClassName, + onImageUpload + }: ImageUploadProps & WithStyles) => ( + onImageUpload(files[0])} + > + {({ isDragActive, getInputProps, getRootProps }) => ( + <> +
+
+ + + + {i18n.t("Drop here to upload", { + context: "image upload" + })} + +
+
+ {children && children({ isDragActive })} + + )} +
+ ) +); +ImageUpload.displayName = "ImageUpload"; +export default ImageUpload; diff --git a/src/components/ImageUpload/index.tsx b/src/components/ImageUpload/index.tsx new file mode 100644 index 000000000..1ff646a38 --- /dev/null +++ b/src/components/ImageUpload/index.tsx @@ -0,0 +1,2 @@ +export { default } from "./ImageUpload"; +export * from "./ImageUpload"; diff --git a/src/components/LanguageSwitch/LanguageSwitch.tsx b/src/components/LanguageSwitch/LanguageSwitch.tsx new file mode 100644 index 000000000..1ec7e5a5b --- /dev/null +++ b/src/components/LanguageSwitch/LanguageSwitch.tsx @@ -0,0 +1,131 @@ +import Card from "@material-ui/core/Card"; +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import Grow from "@material-ui/core/Grow"; +import MenuItem from "@material-ui/core/MenuItem"; +import Menu from "@material-ui/core/MenuList"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import ArrowDropDown from "@material-ui/icons/ArrowDropDown"; +import classNames from "classnames"; +import * as React from "react"; + +import i18n from "../../i18n"; +import { LanguageCodeEnum } from "../../types/globalTypes"; +import { ShopInfo_shop_languages } from "../Shop/types/ShopInfo"; + +export interface LanguageSwitchProps { + currentLanguage: LanguageCodeEnum; + languages: ShopInfo_shop_languages[]; + onLanguageChange: (lang: LanguageCodeEnum) => void; +} + +const styles = (theme: Theme) => + createStyles({ + arrow: { + color: theme.palette.primary.main, + transition: theme.transitions.duration.standard + "ms" + }, + container: { + paddingBottom: theme.spacing.unit + }, + menuContainer: { + cursor: "pointer", + display: "flex", + justifyContent: "space-between", + minWidth: 90, + padding: theme.spacing.unit, + position: "relative" + }, + menuItem: { + textAlign: "justify" + }, + menuPaper: { + maxHeight: `calc(100vh - ${theme.spacing.unit * 2}px)`, + overflow: "scroll" + }, + popover: { + zIndex: 1 + }, + rotate: { + transform: "rotate(180deg)" + } + }); +const LanguageSwitch = withStyles(styles, { name: "LanguageSwitch" })( + ({ + classes, + currentLanguage, + languages, + onLanguageChange + }: LanguageSwitchProps & WithStyles) => { + const [isExpanded, setExpandedState] = React.useState(false); + const anchor = React.useRef(); + + return ( +
+ setExpandedState(!isExpanded)} + > + {currentLanguage} + + + + {({ TransitionProps, placement }) => ( + + + setExpandedState(false)} + mouseEvent="onClick" + > + {languages.map(lang => ( + + { + setExpandedState(false); + onLanguageChange(lang.code); + }} + > + {i18n.t("{{ languageName }} - {{ languageCode }}", { + context: "button", + languageCode: lang.code, + languageName: lang.language + })} + + + ))} + + + + )} + +
+ ); + } +); +LanguageSwitch.displayName = "LanguageSwitch"; +export default LanguageSwitch; diff --git a/src/components/LanguageSwitch/index.ts b/src/components/LanguageSwitch/index.ts new file mode 100644 index 000000000..4c425527e --- /dev/null +++ b/src/components/LanguageSwitch/index.ts @@ -0,0 +1,2 @@ +export { default } from './LanguageSwitch'; +export * from './LanguageSwitch'; \ No newline at end of file diff --git a/src/components/Link.tsx b/src/components/Link.tsx new file mode 100644 index 000000000..6ee63d192 --- /dev/null +++ b/src/components/Link.tsx @@ -0,0 +1,65 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography, { TypographyProps } from "@material-ui/core/Typography"; +import * as classNames from "classnames"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + primary: { + color: theme.palette.primary.main + }, + root: { + cursor: "pointer", + display: "inline" + }, + secondary: { + color: theme.palette.primary.main + }, + underline: { + textDecoration: "underline" + } + }); + +interface LinkProps + extends React.AnchorHTMLAttributes, + WithStyles { + color?: "primary" | "secondary"; + underline?: boolean; + typographyProps?: TypographyProps; + onClick: () => void; +} + +const Link = withStyles(styles, { name: "Link" })( + ({ + classes, + className, + children, + color = "primary", + underline = false, + onClick, + ...linkProps + }: LinkProps) => ( + { + event.preventDefault(); + onClick(); + }} + {...linkProps} + > + {children} + + ) +); +Link.displayName = "Link"; +export default Link; diff --git a/src/components/ListField/ListField.tsx b/src/components/ListField/ListField.tsx new file mode 100644 index 000000000..67ffc58c9 --- /dev/null +++ b/src/components/ListField/ListField.tsx @@ -0,0 +1,132 @@ +import { Omit } from "@material-ui/core"; +import Button from "@material-ui/core/Button"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField, { StandardTextFieldProps } from "@material-ui/core/TextField"; +import * as React from "react"; +import i18n from "../../i18n"; +import Chip from "../Chip"; + +interface ListFieldState { + newValueCounter: number; + value: string; +} + +const styles = (theme: Theme) => + createStyles({ + chip: { + marginBottom: theme.spacing.unit + }, + chipContainer: { + marginTop: theme.spacing.unit * 2, + width: 552 + } + }); + +interface ListFieldProps + extends Omit, + WithStyles { + values: Array<{ + label: string; + value: string; + }>; +} + +const ListField = withStyles(styles)( + class ListFieldComponent extends React.Component< + ListFieldProps, + ListFieldState + > { + state: ListFieldState = { + newValueCounter: 0, + value: "" + }; + handleFieldChange = (event: React.ChangeEvent) => + this.setState({ + value: event.target.value + }); + + handleFieldSubmit = (event: React.KeyboardEvent) => { + // Check if pressed 'enter' key + if (event.keyCode === 13) { + if (this.state.value !== "") { + event.preventDefault(); + event.stopPropagation(); + this.handleValueAdd(); + } + } + }; + + handleValueAdd = () => { + if (this.state.value !== "") { + this.props.onChange({ + target: { + name: this.props.name, + value: [ + ...this.props.values, + { + label: this.state.value, + value: "generated-" + this.state.newValueCounter + } + ] + } + } as any); + this.setState({ + newValueCounter: this.state.newValueCounter + 1, + value: "" + }); + } + }; + + handleValueRemove = (index: number) => + this.props.onChange({ + target: { + name: this.props.name, + value: this.props.values + .slice(0, index) + .concat(this.props.values.slice(index + 1)) + } + } as any); + + render() { + const { classes, values, onChange, ...props } = this.props; + return ( +
+ + {i18n.t("Add", { context: "button" })} + + ) + }} + value={this.state.value} + onChange={this.handleFieldChange} + onKeyDown={this.handleFieldSubmit} + /> +
+ {values.map((value, valueIndex) => ( + this.handleValueRemove(valueIndex)} + /> + ))} +
+
+ ); + } + } +); +ListField.displayName = "ListField"; +export default ListField; diff --git a/src/components/ListField/index.ts b/src/components/ListField/index.ts new file mode 100644 index 000000000..85b671d73 --- /dev/null +++ b/src/components/ListField/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ListField"; +export * from "./ListField"; diff --git a/src/components/Locale/Locale.tsx b/src/components/Locale/Locale.tsx new file mode 100644 index 000000000..05c19a513 --- /dev/null +++ b/src/components/Locale/Locale.tsx @@ -0,0 +1,11 @@ +import * as React from "react"; + +export const LocaleContext = React.createContext("en"); + +const { Consumer: LocaleConsumer, Provider } = LocaleContext; + +const LocaleProvider = ({ children }) => { + return {children}; +}; + +export { LocaleConsumer, LocaleProvider }; diff --git a/src/components/Locale/index.ts b/src/components/Locale/index.ts new file mode 100644 index 000000000..e3a67a9e1 --- /dev/null +++ b/src/components/Locale/index.ts @@ -0,0 +1 @@ +export * from "./Locale"; diff --git a/src/components/MenuToggle.tsx b/src/components/MenuToggle.tsx new file mode 100644 index 000000000..54ed5548e --- /dev/null +++ b/src/components/MenuToggle.tsx @@ -0,0 +1,44 @@ +import * as React from "react"; + +interface MenuToggleProps { + ariaOwns?: string; + children: (( + props: { + actions: { + open: () => void; + close: () => void; + }; + open: boolean; + } + ) => React.ReactElement); +} + +interface MenuToggleState { + open: boolean; +} + +class MenuToggle extends React.Component { + state = { + open: false + }; + + handleClick = () => { + this.setState({ open: true }); + }; + + handleClose = () => { + this.setState({ open: false }); + }; + + render() { + const { children } = this.props; + const { open } = this.state; + + return children({ + actions: { open: this.handleClick, close: this.handleClose }, + open + }); + } +} + +export default MenuToggle; diff --git a/src/components/Money/Money.tsx b/src/components/Money/Money.tsx new file mode 100644 index 000000000..62ba7aaaa --- /dev/null +++ b/src/components/Money/Money.tsx @@ -0,0 +1,25 @@ +import * as React from "react"; + +import { LocaleConsumer } from "../Locale"; + +export interface IMoney { + amount: number; + currency: string; +} +export interface MoneyProps { + money: IMoney; +} + +export const Money: React.StatelessComponent = ({ money }) => ( + + {locale => { + return money.amount.toLocaleString(locale, { + currency: money.currency, + style: "currency" + }); + }} + +); + +Money.displayName = "Money"; +export default Money; diff --git a/src/components/Money/index.ts b/src/components/Money/index.ts new file mode 100644 index 000000000..e8e2d3a59 --- /dev/null +++ b/src/components/Money/index.ts @@ -0,0 +1,17 @@ +import Money from "./Money"; + +export { default } from "./Money"; +export * from "./Money"; + +export function addMoney(init: Money, ...args: Money[]): Money { + return { + amount: args.reduce((acc, curr) => acc + curr.amount, init.amount), + currency: init.currency + }; +} +export function subtractMoney(init: Money, ...args: Money[]): Money { + return { + amount: args.reduce((acc, curr) => acc - curr.amount, init.amount), + currency: init.currency + }; +} diff --git a/src/components/MoneyRange/MoneyRange.tsx b/src/components/MoneyRange/MoneyRange.tsx new file mode 100644 index 000000000..c2d1ac103 --- /dev/null +++ b/src/components/MoneyRange/MoneyRange.tsx @@ -0,0 +1,46 @@ +import * as React from "react"; + +import i18n from "../../i18n"; +import { LocaleConsumer } from "../Locale"; +import IMoney from "../Money"; + +export interface MoneyRangeProps { + from?: IMoney; + to?: IMoney; +} + +const formatMoney = (money: IMoney, locale: string) => + money.amount.toLocaleString(locale, { + currency: money.currency, + style: "currency" + }); + +export const MoneyRange: React.StatelessComponent = ({ + from, + to +}) => ( + + {locale => + from && to + ? i18n.t("{{ fromMoney }} - {{ toMoney }}", { + context: "money", + fromMoney: formatMoney(from, locale), + toMoney: formatMoney(to, locale) + }) + : from && !to + ? i18n.t("from {{ money }}", { + context: "money", + money: formatMoney(from, locale) + }) + : !from && to + ? i18n.t("to {{ money }}", { + context: "money", + money: formatMoney(to, locale) + }) + : "-" + } + +); + +MoneyRange.displayName = "MoneyRange"; +export default MoneyRange; diff --git a/src/components/MoneyRange/index.ts b/src/components/MoneyRange/index.ts new file mode 100644 index 000000000..131c9f9a5 --- /dev/null +++ b/src/components/MoneyRange/index.ts @@ -0,0 +1,2 @@ +export { default } from './MoneyRange'; +export * from './MoneyRange'; \ No newline at end of file diff --git a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx new file mode 100644 index 000000000..ed8d7452f --- /dev/null +++ b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx @@ -0,0 +1,181 @@ +import CircularProgress from "@material-ui/core/CircularProgress"; +import MenuItem from "@material-ui/core/MenuItem"; +import Paper from "@material-ui/core/Paper"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import Downshift, { ControllerStateAndHelpers } from "downshift"; +import * as React from "react"; + +import i18n from "../../i18n"; +import ArrowDropdownIcon from "../../icons/ArrowDropdown"; +import Debounce, { DebounceProps } from "../Debounce"; + +interface ChoiceType { + label: string; + value: string; +} + +const styles = (theme: Theme) => + createStyles({ + chip: { + margin: `${theme.spacing.unit / 2}px ${theme.spacing.unit / 2}px` + }, + container: { + flexGrow: 1, + position: "relative" + }, + paper: { + left: 0, + marginTop: theme.spacing.unit, + padding: theme.spacing.unit, + position: "absolute", + right: 0, + zIndex: 2 + } + }); + +export interface MultiAutocompleteSelectFieldChildrenFunc { + deleteItem: (item: ChoiceType) => void; + items: ChoiceType[]; +} +export type MultiAutocompleteSelectFieldChildren = ( + props: MultiAutocompleteSelectFieldChildrenFunc +) => React.ReactNode; + +export interface MultiAutocompleteSelectFieldProps + extends WithStyles { + name: string; + children: MultiAutocompleteSelectFieldChildren; + choices: ChoiceType[]; + value?: ChoiceType[]; + loading?: boolean; + placeholder?: string; + helperText?: string; + label?: string; + fetchChoices(value: string); + onChange(event); +} + +const DebounceAutocomplete: React.ComponentType< + DebounceProps +> = Debounce; + +export const MultiAutocompleteSelectField = withStyles(styles, { + name: "MultiAutocompleteSelectField" +})( + ({ + children, + choices, + classes, + helperText, + label, + loading, + name, + placeholder, + value, + fetchChoices, + onChange + }: MultiAutocompleteSelectFieldProps) => { + const handleSelect = ( + item: ChoiceType, + { reset }: ControllerStateAndHelpers + ) => { + reset({ inputValue: "" }); + onChange({ target: { name, value: [...value, item] } }); + }; + const handleDelete = (item: ChoiceType) => { + const newValue = value.slice(); + newValue.splice( + value.findIndex(listItem => listItem.value === item.value), + 1 + ); + onChange({ target: { name, value: newValue } }); + }; + + const filteredChoices = choices.filter( + suggestion => value.map(v => v.value).indexOf(suggestion.value) === -1 + ); + + return ( + + {debounce => ( + (item ? item.label : "")} + onSelect={handleSelect} + onInputValueChange={value => debounce(value)} + > + {({ + getInputProps, + getItemProps, + isOpen, + selectedItem, + toggleMenu, + closeMenu, + openMenu, + highlightedIndex + }) => { + return ( +
+ + {loading ? ( + + ) : ( + + )} +
+ ), + id: undefined, + onBlur: closeMenu, + onFocus: openMenu + }} + helperText={helperText} + label={label} + fullWidth={true} + /> + {isOpen && ( + + {!loading && filteredChoices.length > 0 + ? filteredChoices.map((suggestion, index) => ( + + {suggestion.label} + + )) + : !loading && ( + + {i18n.t("No results found")} + + )} + + )} + {children({ + deleteItem: handleDelete, + items: selectedItem + })} +
+ ); + }} + + )} + + ); + } +); +MultiAutocompleteSelectField.displayName = "MultiAutocompleteSelectField"; +export default MultiAutocompleteSelectField; diff --git a/src/components/MultiAutocompleteSelectField/index.ts b/src/components/MultiAutocompleteSelectField/index.ts new file mode 100644 index 000000000..e7e4cfd9b --- /dev/null +++ b/src/components/MultiAutocompleteSelectField/index.ts @@ -0,0 +1,2 @@ +export { default } from "./MultiAutocompleteSelectField"; +export * from "./MultiAutocompleteSelectField"; diff --git a/src/components/MultiSelectField/MultiSelectField.tsx b/src/components/MultiSelectField/MultiSelectField.tsx new file mode 100644 index 000000000..4d11946b7 --- /dev/null +++ b/src/components/MultiSelectField/MultiSelectField.tsx @@ -0,0 +1,126 @@ +import FilledInput from "@material-ui/core/FilledInput"; +import FormControl from "@material-ui/core/FormControl"; +import FormHelperText from "@material-ui/core/FormHelperText"; +import InputLabel from "@material-ui/core/InputLabel"; +import MenuItem from "@material-ui/core/MenuItem"; +import Select, { SelectProps } from "@material-ui/core/Select"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import i18n from "../../i18n"; +import Checkbox from "../Checkbox"; + +const styles = (theme: Theme) => + createStyles({ + checkbox: { + marginRight: -theme.spacing.unit * 2 + }, + formControl: { + width: "100%" + }, + menuItem: { + alignItems: "center", + display: "flex", + justifyContent: "space-between", + width: "100%" + } + }); + +interface MultiSelectFieldProps extends WithStyles { + choices: Array<{ + value: string; + label: string; + }>; + disabled?: boolean; + error?: boolean; + hint?: string; + label?: string; + name?: string; + selectProps?: SelectProps; + value?: string[]; + onChange(event: any); +} + +export const MultiSelectField = withStyles(styles, { + name: "MultiSelectField" +})( + ({ + classes, + disabled, + error, + label, + choices, + value, + onChange, + name, + hint, + selectProps + }: MultiSelectFieldProps) => { + const choicesByKey = disabled + ? {} + : choices.reduce((prev, curr) => { + prev[curr.value] = curr.label; + return prev; + }, {}); + + return ( + + {label && {label}} + + {hint && {hint}} + + ); + } +); +MultiSelectField.defaultProps = { + value: [] +}; + +MultiSelectField.displayName = "MultiSelectField"; +export default MultiSelectField; diff --git a/src/components/MultiSelectField/index.ts b/src/components/MultiSelectField/index.ts new file mode 100644 index 000000000..16d075951 --- /dev/null +++ b/src/components/MultiSelectField/index.ts @@ -0,0 +1,2 @@ +export { default } from "./MultiSelectField"; +export * from "./MultiSelectField"; diff --git a/src/components/NotFoundPage/NotFoundPage.tsx b/src/components/NotFoundPage/NotFoundPage.tsx new file mode 100644 index 000000000..6e51e86a1 --- /dev/null +++ b/src/components/NotFoundPage/NotFoundPage.tsx @@ -0,0 +1,94 @@ +import Button from "@material-ui/core/Button"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; +import SVG from "react-inlinesvg"; + +import * as notFoundImage from "@assets/images/not-found-404.svg"; +import i18n from "../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + button: { + marginTop: theme.spacing.unit * 2, + padding: 20 + }, + container: { + [theme.breakpoints.down("sm")]: { + gridTemplateColumns: "1fr", + padding: theme.spacing.unit * 3, + width: "100%" + }, + display: "grid", + gridTemplateColumns: "1fr 487px", + margin: "0 auto", + width: 830 + }, + header: { + fontWeight: 600 as 600 + }, + innerContainer: { + [theme.breakpoints.down("sm")]: { + order: 1, + textAlign: "center" + }, + display: "flex", + flexDirection: "column", + justifyContent: "center" + }, + notFoundImage: { + "& svg": { + width: "100%" + } + }, + root: { + alignItems: "center", + display: "flex", + height: "100vh", + width: "100vw" + } + }); + +interface NotFoundPageProps extends WithStyles { + onBack: () => void; +} + +const NotFoundPage = withStyles(styles, { name: "NotFoundPage" })( + ({ classes, onBack }: NotFoundPageProps) => ( +
+
+
+
+ + {i18n.t("Ooops!...")} + + + {i18n.t("Something's missing")} + + {i18n.t("Sorry, the page was not found")} +
+
+ +
+
+
+ +
+
+
+ ) +); +NotFoundPage.displayName = "NotFoundPage"; +export default NotFoundPage; diff --git a/src/components/NotFoundPage/index.ts b/src/components/NotFoundPage/index.ts new file mode 100644 index 000000000..df151ffeb --- /dev/null +++ b/src/components/NotFoundPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./NotFoundPage"; +export * from "./NotFoundPage"; diff --git a/src/components/PageHeader/PageHeader.tsx b/src/components/PageHeader/PageHeader.tsx new file mode 100644 index 000000000..8c20e8186 --- /dev/null +++ b/src/components/PageHeader/PageHeader.tsx @@ -0,0 +1,43 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import ExtendedPageHeader from "../ExtendedPageHeader"; +import Skeleton from "../Skeleton"; + +const styles = (theme: Theme) => + createStyles({ + title: { + flex: 1, + fontSize: 24, + paddingBottom: theme.spacing.unit * 2 + } + }); + +interface PageHeaderProps extends WithStyles { + children?: React.ReactNode; + className?: string; + title?: string; +} + +const PageHeader = withStyles(styles)( + ({ children, classes, className, title }: PageHeaderProps) => ( + + {title !== undefined ? title : } + + } + > + {children} + + ) +); +PageHeader.displayName = "PageHeader"; +export default PageHeader; diff --git a/src/components/PageHeader/index.ts b/src/components/PageHeader/index.ts new file mode 100644 index 000000000..fbf397de4 --- /dev/null +++ b/src/components/PageHeader/index.ts @@ -0,0 +1,2 @@ +export { default } from "./PageHeader"; +export * from "./PageHeader"; diff --git a/src/components/Percent/Percent.tsx b/src/components/Percent/Percent.tsx new file mode 100644 index 000000000..dc34ff8a9 --- /dev/null +++ b/src/components/Percent/Percent.tsx @@ -0,0 +1,20 @@ +import * as React from "react"; + +import { LocaleConsumer } from "../Locale"; + +interface PercentProps { + amount: number; +} + +const Percent: React.StatelessComponent = ({ amount }) => ( + + {locale => { + return (amount / 100).toLocaleString(locale, { + maximumFractionDigits: 2, + style: "percent" + }); + }} + +); +Percent.displayName = "Percent"; +export default Percent; diff --git a/src/components/Percent/index.ts b/src/components/Percent/index.ts new file mode 100644 index 000000000..7c1ab1d74 --- /dev/null +++ b/src/components/Percent/index.ts @@ -0,0 +1,2 @@ +export { default } from "./Percent"; +export * from "./Percent"; diff --git a/src/components/PhoneField/PhoneField.tsx b/src/components/PhoneField/PhoneField.tsx new file mode 100644 index 000000000..800b8affb --- /dev/null +++ b/src/components/PhoneField/PhoneField.tsx @@ -0,0 +1,58 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import SingleSelectField from "@saleor/components/SingleSelectField"; + +const styles = (theme: Theme) => + createStyles({ + root: { + display: "grid", + gridColumnGap: `${theme.spacing.unit * 2}px`, + gridTemplateColumns: "5rem 1fr" + } + }); + +interface PhoneFieldProps extends WithStyles { + name: string; + prefix: string; + number: string; + prefixes: string[]; + label?: string; + onChange(event: React.ChangeEvent); +} + +const PhoneField = withStyles(styles, { name: "PhoneField" })( + ({ + classes, + name, + number: phoneNumber, + prefix, + prefixes, + label, + onChange + }: PhoneFieldProps) => ( +
+ ({ label: "+" + p, value: p }))} + onChange={onChange} + value={prefix} + label={label} + /> + +
+ ) +); +PhoneField.displayName = "PhoneField"; +export default PhoneField; diff --git a/src/components/PhoneField/index.ts b/src/components/PhoneField/index.ts new file mode 100644 index 000000000..2f53bef78 --- /dev/null +++ b/src/components/PhoneField/index.ts @@ -0,0 +1,2 @@ +export { default } from "./PhoneField"; +export * from "./PhoneField"; diff --git a/src/components/PriceField/PriceField.tsx b/src/components/PriceField/PriceField.tsx new file mode 100644 index 000000000..684da90e2 --- /dev/null +++ b/src/components/PriceField/PriceField.tsx @@ -0,0 +1,90 @@ +import { InputProps } from "@material-ui/core/Input"; +import InputAdornment from "@material-ui/core/InputAdornment"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + currencySymbol: { + fontSize: "0.875rem" + }, + inputContainer: { + display: "grid", + gridTemplateColumns: "1fr 2rem 1fr" + }, + pullDown: { + marginTop: theme.spacing.unit * 2 + }, + separator: { + marginTop: theme.spacing.unit * 3, + textAlign: "center", + width: "100%" + }, + widgetContainer: { + marginTop: theme.spacing.unit * 2 + } + }); + +interface PriceFieldProps extends WithStyles { + className?: string; + currencySymbol?: string; + disabled?: boolean; + error?: boolean; + hint?: string; + label?: string; + name?: string; + value?: string | number; + InputProps?: InputProps; + onChange(event: any); +} + +export const PriceField = withStyles(styles, { name: "PriceField" })( + ({ + className, + disabled, + error, + label, + hint, + currencySymbol, + name, + classes, + onChange, + value, + InputProps + }: PriceFieldProps) => ( + + {currencySymbol} + + ) : ( + + ), + type: "number" + }} + name={name} + disabled={disabled} + onChange={onChange} + /> + ) +); +PriceField.defaultProps = { + name: "price" +}; + +PriceField.displayName = "PriceField"; +export default PriceField; diff --git a/src/components/PriceField/index.ts b/src/components/PriceField/index.ts new file mode 100644 index 000000000..17b4249c5 --- /dev/null +++ b/src/components/PriceField/index.ts @@ -0,0 +1,2 @@ +export { default } from "./PriceField"; +export * from "./PriceField"; diff --git a/src/components/ProductList/ProductList.tsx b/src/components/ProductList/ProductList.tsx new file mode 100644 index 000000000..4b760b0d5 --- /dev/null +++ b/src/components/ProductList/ProductList.tsx @@ -0,0 +1,194 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import { CategoryDetails_category_products_edges_node } from "../../categories/types/CategoryDetails"; +import i18n from "../../i18n"; +import { maybe, renderCollection } from "../../misc"; +import { ListActions, ListProps } from "../../types"; +import Checkbox from "../Checkbox"; +import Money from "../Money"; +import Skeleton from "../Skeleton"; +import StatusLabel from "../StatusLabel"; +import TableHead from "../TableHead"; +import TablePagination from "../TablePagination"; + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colName: { + width: 430 + }, + colPrice: { + width: 200 + }, + colPublished: { + width: 200 + }, + colType: { + width: 200 + } + }, + avatarCell: { + paddingLeft: theme.spacing.unit * 2, + paddingRight: 0, + width: theme.spacing.unit * 5 + }, + colName: {}, + colPrice: { + textAlign: "right" + }, + colPublished: {}, + colType: {}, + link: { + cursor: "pointer" + }, + textLeft: { + textAlign: "left" + }, + textRight: { + textAlign: "right" + } + }); + +interface ProductListProps + extends ListProps, + ListActions, + WithStyles { + products: CategoryDetails_category_products_edges_node[]; +} + +export const ProductList = withStyles(styles, { name: "ProductList" })( + ({ + classes, + disabled, + isChecked, + pageInfo, + products, + selected, + toggle, + toggleAll, + toolbar, + onNextPage, + onPreviousPage, + onRowClick + }: ProductListProps) => ( + + + + + {i18n.t("Name", { context: "object" })} + + + {i18n.t("Type", { context: "object" })} + + + {i18n.t("Published", { context: "object" })} + + + {i18n.t("Price", { context: "object" })} + + + + + + + + + {renderCollection( + products, + product => { + const isSelected = product ? isChecked(product.id) : false; + + return ( + + + toggle(product.id)} + /> + + product.thumbnail.url)} + /> + + {product ? product.name : } + + + {product && product.productType ? ( + product.productType.name + ) : ( + + )} + + + {product && maybe(() => product.isAvailable !== undefined) ? ( + + ) : ( + + )} + + + {maybe(() => product.basePrice) && + maybe(() => product.basePrice.amount) !== undefined && + maybe(() => product.basePrice.currency) !== undefined ? ( + + ) : ( + + )} + + + ); + }, + () => ( + + {i18n.t("No products found")} + + ) + )} + +
+ ) +); +ProductList.displayName = "ProductList"; +export default ProductList; diff --git a/src/components/ProductList/index.ts b/src/components/ProductList/index.ts new file mode 100644 index 000000000..17fd4319e --- /dev/null +++ b/src/components/ProductList/index.ts @@ -0,0 +1 @@ +export { default } from "./ProductList"; diff --git a/src/components/RichTextEditor/ImageEntity.tsx b/src/components/RichTextEditor/ImageEntity.tsx new file mode 100644 index 000000000..b676114a5 --- /dev/null +++ b/src/components/RichTextEditor/ImageEntity.tsx @@ -0,0 +1,112 @@ +import Button from "@material-ui/core/Button"; +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import Grow from "@material-ui/core/Grow"; +import IconButton from "@material-ui/core/IconButton"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import DeleteIcon from "@material-ui/icons/Delete"; +import { ContentState } from "draft-js"; +import * as React from "react"; + +import i18n from "../../i18n"; + +interface ImageEntityProps { + children: React.ReactNode; + contentState: ContentState; + entityKey: string; + onEdit: (entityKey: string) => void; + onRemove: (entityKey: string) => void; +} + +const styles = (theme: Theme) => + createStyles({ + anchor: { + display: "inline-block" + }, + container: { + alignItems: "center", + display: "flex" + }, + image: { maxWidth: "100%" }, + inline: { + display: "inline-block" + }, + root: { + alignItems: "center", + display: "flex", + minHeight: 72, + padding: theme.spacing.unit * 1.5 + } + }); + +const ImageEntity = withStyles(styles, { + name: "ImageEntity" +})( + ({ + classes, + contentState, + entityKey, + onEdit, + onRemove + }: ImageEntityProps & WithStyles) => { + const [isOpened, setOpenStatus] = React.useState(false); + const anchor = React.useRef(); + + const disable = () => setOpenStatus(false); + const toggle = () => setOpenStatus(!isOpened); + + return ( + <> +
+ + {({ TransitionProps, placement }) => ( + + + +
+ + onRemove(entityKey)}> + + +
+
+
+
+ )} +
+
+ + + ); + } +); +export default ImageEntity; diff --git a/src/components/RichTextEditor/ImageSource.tsx b/src/components/RichTextEditor/ImageSource.tsx new file mode 100644 index 000000000..698c846ab --- /dev/null +++ b/src/components/RichTextEditor/ImageSource.tsx @@ -0,0 +1,100 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import TextField from "@material-ui/core/TextField"; +import { AtomicBlockUtils, EditorState, EntityInstance } from "draft-js"; +import * as React from "react"; + +import i18n from "../../i18n"; +import Form from "../Form"; + +interface ImageSourceProps { + editorState: EditorState; + entity?: EntityInstance; + entityKey?: string; + entityType: { + type: string; + }; + onComplete: (updateState: EditorState) => void; + onClose: () => void; +} + +class ImageSource extends React.Component { + submit = (href: string) => { + const { + editorState, + entity, + entityKey, + entityType, + onComplete + } = this.props; + + if (href) { + const content = editorState.getCurrentContent(); + if (entity) { + const nextContent = content.mergeEntityData(entityKey, { href }); + const nextState = EditorState.push( + editorState, + nextContent, + "apply-entity" + ); + onComplete(nextState); + } else { + const contentWithEntity = content.createEntity( + entityType.type, + "IMMUTABLE", + { href } + ); + const nextState = AtomicBlockUtils.insertAtomicBlock( + editorState, + contentWithEntity.getLastCreatedEntityKey(), + " " + ); + + onComplete(nextState); + } + } else { + onComplete(editorState); + } + }; + + render() { + const { entity, onClose } = this.props; + const initial = entity ? entity.getData().href : ""; + + return ( + +
this.submit(href)} + > + {({ data, change, submit }) => ( + <> + {i18n.t("Add Image Link")} + + + + + + + + + )} +
+
+ ); + } +} +export default ImageSource; diff --git a/src/components/RichTextEditor/LinkEntity.tsx b/src/components/RichTextEditor/LinkEntity.tsx new file mode 100644 index 000000000..c84c205da --- /dev/null +++ b/src/components/RichTextEditor/LinkEntity.tsx @@ -0,0 +1,132 @@ +import Button from "@material-ui/core/Button"; +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import Grow from "@material-ui/core/Grow"; +import IconButton from "@material-ui/core/IconButton"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import DeleteIcon from "@material-ui/icons/Delete"; +import { ContentState } from "draft-js"; +import * as React from "react"; + +import i18n from "../../i18n"; +import Link from "../Link"; + +interface LinkEntityProps { + children: React.ReactNode; + contentState: ContentState; + entityKey: string; + onEdit: (entityKey: string) => void; + onRemove: (entityKey: string) => void; +} + +const styles = (theme: Theme) => + createStyles({ + anchor: { + display: "inline-block" + }, + container: { + alignItems: "center", + display: "flex" + }, + inline: { + display: "inline-block" + }, + popover: { + zIndex: 1 + }, + root: { + alignItems: "center", + display: "flex", + minHeight: 72, + padding: `${theme.spacing.unit * 1.5}px ${theme.spacing.unit * + 1.5}px ${theme.spacing.unit * 1.5}px ${theme.spacing.unit * 3}px` + }, + separator: { + backgroundColor: theme.palette.grey[300], + display: "inline-block", + height: 30, + marginLeft: theme.spacing.unit * 2, + marginRight: theme.spacing.unit, + width: 1 + } + }); + +const LinkEntity = withStyles(styles, { + name: "LinkEntity" +})( + ({ + classes, + children, + contentState, + entityKey, + onEdit, + onRemove + }: LinkEntityProps & WithStyles) => { + const [isOpened, setOpenStatus] = React.useState(false); + const anchor = React.useRef(); + + const disable = () => setOpenStatus(false); + const toggle = () => setOpenStatus(!isOpened); + + return ( + <> +
+ + {({ TransitionProps, placement }) => ( + + + +
+ + {contentState.getEntity(entityKey).getData().url} + + + + onRemove(entityKey)}> + + +
+
+
+
+ )} +
+
+ + {children} + + + ); + } +); +export default LinkEntity; diff --git a/src/components/RichTextEditor/LinkSource.tsx b/src/components/RichTextEditor/LinkSource.tsx new file mode 100644 index 000000000..3b639fc9a --- /dev/null +++ b/src/components/RichTextEditor/LinkSource.tsx @@ -0,0 +1,87 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import TextField from "@material-ui/core/TextField"; +import { EditorState, EntityInstance, RichUtils } from "draft-js"; +import * as React from "react"; + +import i18n from "../../i18n"; +import Form from "../Form"; + +interface LinkSourceProps { + editorState: EditorState; + entity?: EntityInstance; + entityType: { + type: string; + }; + onComplete: (updateState: EditorState) => void; + onClose: () => void; +} + +class LinkSource extends React.Component { + submit = (url: string) => { + const { editorState, entityType, onComplete } = this.props; + + if (url) { + const content = editorState.getCurrentContent(); + const contentWithEntity = content.createEntity( + entityType.type, + "MUTABLE", + { url } + ); + const entityKey = contentWithEntity.getLastCreatedEntityKey(); + const newEditorState = EditorState.set(editorState, { + currentContent: contentWithEntity + }); + const nextState = RichUtils.toggleLink( + newEditorState, + newEditorState.getSelection(), + entityKey + ); + + onComplete(nextState); + } else { + onComplete(editorState); + } + }; + + render() { + const { entity, onClose } = this.props; + const initial = entity ? entity.getData().url : ""; + + return ( + +
this.submit(url)} + > + {({ data, change, submit }) => ( + <> + {i18n.t("Add or Edit Link")} + + + + + + + + + )} +
+
+ ); + } +} +export default LinkSource; diff --git a/src/components/RichTextEditor/RichTextEditor.tsx b/src/components/RichTextEditor/RichTextEditor.tsx new file mode 100644 index 000000000..d9a650191 --- /dev/null +++ b/src/components/RichTextEditor/RichTextEditor.tsx @@ -0,0 +1,343 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; +import Typography from "@material-ui/core/Typography"; +import * as classNames from "classnames"; +import { RawDraftContentState } from "draft-js"; +import { + BLOCK_TYPE, + DraftailEditor, + ENTITY_TYPE, + INLINE_STYLE +} from "draftail"; +import * as React from "react"; + +import BoldIcon from "../../icons/BoldIcon"; +import HeaderOne from "../../icons/HeaderOne"; +import HeaderThree from "../../icons/HeaderThree"; +import HeaderTwo from "../../icons/HeaderTwo"; +import ItalicIcon from "../../icons/ItalicIcon"; +import LinkIcon from "../../icons/LinkIcon"; +import OrderedListIcon from "../../icons/OrderedListIcon"; +import QuotationIcon from "../../icons/QuotationIcon"; +import StrikethroughIcon from "../../icons/StrikethroughIcon"; +import UnorderedListIcon from "../../icons/UnorderedListIcon"; + +// import ImageEntity from "./ImageEntity"; +// import ImageSource from "./ImageSource"; +import LinkEntity from "./LinkEntity"; +import LinkSource from "./LinkSource"; + +export interface RichTextEditorProps { + disabled: boolean; + error: boolean; + helperText: string; + label: string; + name: string; + scroll?: boolean; + initial?: RawDraftContentState; + onChange: (event: React.ChangeEvent) => void; +} + +const styles = (theme: Theme) => + createStyles({ + "@keyframes focus": { + from: { + transform: "scaleX(0) scaleY(1)" + }, + to: { + transform: "scaleX(1) scaleY(1)" + } + }, + "@keyframes hover": { + from: { + transform: "scaleX(1) scaleY(0)" + }, + to: { + transform: "scaleX(1) scaleY(1)" + } + }, + error: { + color: theme.palette.error.main + }, + helperText: { + marginTop: theme.spacing.unit * 0.75 + }, + input: { + "&:hover": { + borderBottomColor: theme.palette.primary.main + }, + backgroundColor: theme.overrides.MuiFilledInput.root.backgroundColor, + borderBottom: `1px rgba(0, 0, 0, 0) solid`, + borderTopLeftRadius: 4, + borderTopRightRadius: 4, + padding: "27px 12px 10px", + position: "relative", + transition: theme.transitions.duration.shortest + "ms" + }, + label: { + fontSize: theme.typography.caption.fontSize, + marginBottom: theme.spacing.unit * 2, + marginTop: -21 + }, + linkIcon: { + marginTop: 2 + }, + root: { + "& .DraftEditor": { + "&-editorContainer": { + "& .public-DraftEditor-content": { + lineHeight: 1.62 + }, + "& a": { + color: theme.palette.primary.light + }, + "&:after": { + animationDuration: theme.transitions.duration.shortest + "ms", + animationFillMode: "both", + background: theme.palette.getContrastText( + theme.palette.background.default + ), + bottom: -11, + content: "''", + display: "block", + height: 2, + left: -12, + position: "absolute", + transform: "scaleX(0) scaleY(0)", + width: "calc(100% + 24px)" + }, + position: "relative" + }, + "&-root": { + ...theme.typography.body2 + } + }, + "& .Draftail": { + "&-Editor": { + "&--focus": { + "& .DraftEditor": { + "&-editorContainer": { + "&:after": { + animationName: "focus !important", + background: theme.palette.primary.main, + transform: "scaleX(0) scaleY(1)" + } + } + } + } + }, + "&-Toolbar": { + "&Button": { + "& svg": { + padding: 2 + }, + "&--active": { + "&:hover": { + background: theme.palette.primary.main + }, + "&:not(:hover)": { + borderRightColor: theme.palette.primary.main + }, + background: theme.palette.primary.main + }, + "&:focus": { + "&:active": { + "&:after": { + background: fade(theme.palette.primary.main, 0.3), + borderRadius: "100%", + content: "''", + display: "block", + height: "100%", + width: "100%" + } + } + }, + "&:hover": { + background: fade(theme.palette.primary.main, 0.3) + }, + alignItems: "center", + background: "none", + border: "none", + borderRight: `1px ${ + theme.overrides.MuiCard.root.borderColor + } solid`, + color: theme.typography.body2.color, + cursor: "pointer", + display: "inline-flex", + height: 36, + justifyContent: "center", + padding: theme.spacing.unit + 2, + transition: theme.transitions.duration.short + "ms", + width: 36 + }, + "&Group": { + "&:last-of-type": { + "& .Draftail-ToolbarButton": { + "&:last-of-type": { + border: "none" + } + } + }, + display: "flex" + }, + background: theme.palette.background.default, + border: `1px ${theme.overrides.MuiCard.root.borderColor} solid`, + display: "inline-flex", + flexWrap: "wrap", + marginBottom: theme.spacing.unit, + [theme.breakpoints.down(460)]: { + width: "min-content" + } + }, + "&-block": { + "&--blockquote": { + borderLeft: `2px solid ${theme.overrides.MuiCard.root.borderColor}`, + margin: 0, + padding: `${theme.spacing.unit}px ${theme.spacing.unit * 2}px` + } + } + }, + "&$error": { + "& .Draftail": { + "&-Editor": { + "& .DraftEditor": { + "&-editorContainer": { + "&:after": { + animationName: "none", + background: theme.palette.error.main, + transform: "scaleX(1) scaleY(1)" + } + } + }, + "&--focus": { + "& .DraftEditor": { + "&-editorContainer": { + "&:after": { + animationName: "none !important" + } + } + } + } + } + } + } + }, + scroll: { + "& .DraftEditor": { + "&-editorContainer": { + "& .public-DraftEditor-content": { + lineHeight: 1.62 + } + } + } + }, + smallIcon: { + marginLeft: 10 + } + }); +const RichTextEditor = withStyles(styles, { name: "RichTextEditor" })( + ({ + classes, + error, + helperText, + initial, + label, + name, + scroll, + onChange + }: RichTextEditorProps & WithStyles) => ( +
+
+ + {label} + + 0 ? initial : null + } + onSave={value => + onChange({ + target: { + name, + value + } + } as any) + } + blockTypes={[ + { + icon: , + type: BLOCK_TYPE.HEADER_ONE + }, + { icon: , type: BLOCK_TYPE.HEADER_TWO }, + { icon: , type: BLOCK_TYPE.HEADER_THREE }, + { icon: , type: BLOCK_TYPE.BLOCKQUOTE }, + { + icon: , + type: BLOCK_TYPE.UNORDERED_LIST_ITEM + }, + { icon: , type: BLOCK_TYPE.ORDERED_LIST_ITEM } + ]} + inlineStyles={[ + { + icon: , + type: INLINE_STYLE.BOLD + }, + { + icon: , + type: INLINE_STYLE.ITALIC + }, + { + icon: , + type: INLINE_STYLE.STRIKETHROUGH + } + ]} + enableLineBreak + entityTypes={[ + { + attributes: ["url"], + decorator: LinkEntity, + icon: , + source: LinkSource, + type: ENTITY_TYPE.LINK + } + // { + // attributes: ["href"], + // decorator: ImageEntity, + // icon: , + // source: ImageSource, + // type: ENTITY_TYPE.IMAGE + // } + ]} + /> +
+ {helperText && ( + + {helperText} + + )} +
+ ) +); +RichTextEditor.displayName = "RichTextEditor"; +RichTextEditor.defaultProps = { + scroll: true +}; +export default RichTextEditor; diff --git a/src/components/RichTextEditor/index.ts b/src/components/RichTextEditor/index.ts new file mode 100644 index 000000000..2a07ed090 --- /dev/null +++ b/src/components/RichTextEditor/index.ts @@ -0,0 +1,2 @@ +export { default } from './RichTextEditor'; +export * from './RichTextEditor'; \ No newline at end of file diff --git a/src/components/SaveButtonBar/SaveButtonBar.tsx b/src/components/SaveButtonBar/SaveButtonBar.tsx new file mode 100644 index 000000000..4fb7a8bfc --- /dev/null +++ b/src/components/SaveButtonBar/SaveButtonBar.tsx @@ -0,0 +1,147 @@ +import Button from "@material-ui/core/Button"; +import Portal from "@material-ui/core/Portal"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import classNames from "classnames"; +import * as React from "react"; + +import useScroll from "@saleor/hooks/useScroll"; +import i18n from "../../i18n"; +import { maybe } from "../../misc"; +import AppActionContext from "../AppLayout/AppActionContext"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "../ConfirmButton/ConfirmButton"; +import Container from "../Container"; + +const styles = (theme: Theme) => + createStyles({ + button: { + marginRight: theme.spacing.unit + }, + cancelButton: { + marginRight: theme.spacing.unit * 2 + }, + container: { + display: "flex", + paddingBottom: theme.spacing.unit * 2, + paddingTop: theme.spacing.unit * 2, + [theme.breakpoints.down("sm")]: { + marginTop: theme.spacing.unit + } + }, + deleteButton: { + "&:hover": { + backgroundColor: theme.palette.error.dark + }, + backgroundColor: theme.palette.error.main, + color: theme.palette.error.contrastText + }, + root: { + background: theme.palette.background.default, + borderTop: "1px solid transparent", + boxShadow: `0 -5px 5px 0 ${theme.overrides.MuiCard.root.borderColor}`, + transition: `box-shadow ${theme.transitions.duration.shortest}ms` + }, + spacer: { + flex: "1" + }, + stop: { + "&$root": { + borderTopColor: theme.overrides.MuiCard.root.borderColor, + boxShadow: `0 0 0 0 ${theme.overrides.MuiCard.root.borderColor}` + } + } + }); + +interface SaveButtonBarProps extends WithStyles { + disabled: boolean; + state: ConfirmButtonTransitionState; + labels?: { + cancel?: string; + delete?: string; + save?: string; + }; + onCancel: () => void; + onDelete?: () => void; + onSave(event: any); +} + +export const SaveButtonBar = withStyles(styles, { name: "SaveButtonBar" })( + ({ + classes, + disabled, + labels, + state, + onCancel, + onDelete, + onSave, + ...props + }: SaveButtonBarProps) => { + const scrollPosition = useScroll(); + const scrolledToBottom = + scrollPosition.y + window.innerHeight >= document.body.scrollHeight; + + return ( + + {anchor => + anchor ? ( + +
+ + {!!onDelete && ( + + )} +
+ + + {maybe( + () => labels.save, + i18n.t("Save", { + context: "button" + }) + )} + + +
+ + ) : null + } + + ); + } +); +SaveButtonBar.displayName = "SaveButtonBar"; +export default SaveButtonBar; diff --git a/src/components/SaveButtonBar/index.ts b/src/components/SaveButtonBar/index.ts new file mode 100644 index 000000000..edc3e6397 --- /dev/null +++ b/src/components/SaveButtonBar/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SaveButtonBar"; +export * from "./SaveButtonBar"; diff --git a/src/components/SaveFilterTabDialog/SaveFilterTabDialog.tsx b/src/components/SaveFilterTabDialog/SaveFilterTabDialog.tsx new file mode 100644 index 000000000..0b257873d --- /dev/null +++ b/src/components/SaveFilterTabDialog/SaveFilterTabDialog.tsx @@ -0,0 +1,87 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import i18n from "../../i18n"; +import ConfirmButton, { ConfirmButtonTransitionState } from "../ConfirmButton"; +import Form from "../Form"; + +export interface SaveFilterTabDialogFormData { + name: string; +} + +const initialForm: SaveFilterTabDialogFormData = { + name: "" +}; + +export interface SaveFilterTabDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + onClose: () => void; + onSubmit: (data: SaveFilterTabDialogFormData) => void; +} + +const SaveFilterTabDialog: React.FC = ({ + confirmButtonState, + onClose, + onSubmit, + open +}) => { + const [errors, setErrors] = React.useState(false); + const handleErrors = data => { + if (data.name.length) { + onSubmit(data); + setErrors(false); + } else { + setErrors(true); + } + }; + + return ( + + + {i18n.t("Save Custom Search", { + context: "save filter tab" + })} + +
+ {({ change, data, submit }) => ( + <> + + + + + + + {i18n.t("Save")} + + + + )} +
+
+ ); +}; +SaveFilterTabDialog.displayName = "SaveFilterTabDialog"; +export default SaveFilterTabDialog; diff --git a/src/components/SaveFilterTabDialog/index.ts b/src/components/SaveFilterTabDialog/index.ts new file mode 100644 index 000000000..8b281bdd2 --- /dev/null +++ b/src/components/SaveFilterTabDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from './SaveFilterTabDialog'; +export * from './SaveFilterTabDialog'; \ No newline at end of file diff --git a/src/components/SeoForm/SeoForm.tsx b/src/components/SeoForm/SeoForm.tsx new file mode 100644 index 000000000..c4af34cdc --- /dev/null +++ b/src/components/SeoForm/SeoForm.tsx @@ -0,0 +1,177 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import * as classNames from "classnames"; +import * as React from "react"; + +import i18n from "../../i18n"; +import CardTitle from "../CardTitle"; +import FormSpacer from "../FormSpacer"; + +const styles = (theme: Theme) => + createStyles({ + addressBar: { + color: "#006621", + fontSize: "13px", + lineHeight: "16px", + marginBottom: "2px", + overflow: "hidden", + textOverflow: "ellipsis", + whiteSpace: "nowrap" + }, + container: { + width: "100%" + }, + descriptionBar: { + color: "#545454", + fontSize: "13px", + lineHeight: "18px", + overflowWrap: "break-word" + }, + helperText: { + marginBottom: theme.spacing.unit * 3 + }, + label: { + flex: 1 + }, + labelContainer: { + display: "flex" + }, + preview: { + minHeight: theme.spacing.unit * 10 + }, + title: { + padding: 0 + }, + titleBar: { + color: "#1a0dab", + fontSize: "18px", + lineHeight: "21px", + overflowWrap: "break-word", + textDecoration: "none", + wordWrap: "break-word" + } + }); + +interface SeoFormProps extends WithStyles { + description?: string; + descriptionPlaceholder: string; + disabled?: boolean; + loading?: boolean; + helperText?: string; + title: string; + titlePlaceholder: string; + onChange(event: any); + onClick?(); +} + +const SeoForm = withStyles(styles, { name: "SeoForm" })( + ({ + classes, + description, + descriptionPlaceholder, + disabled, + helperText, + loading, + title, + titlePlaceholder, + onChange + }: SeoFormProps) => { + const [expanded, setExpansionStatus] = React.useState(false); + const toggleExpansion = () => setExpansionStatus(!expanded); + + return ( + + + {i18n.t("Edit website SEO")} + + } + /> + + {helperText && ( + + {helperText} + + )} + {expanded && ( +
+ +
+ {i18n.t("Search engine title")} +
+ + {i18n.t("{{ letters }} of {{ maxLetters }} characters", { + letters: title.length, + maxLetters: 70 + })} + +
+ } + helperText={i18n.t( + "If empty, the preview shows what will be autogenerated." + )} + value={title.slice(0, 69)} + disabled={loading || disabled} + InputLabelProps={{ shrink: true }} + placeholder={titlePlaceholder} + onChange={onChange} + fullWidth + /> + + +
+ {i18n.t("Search engine description")} +
+ + {i18n.t("{{ letters }} of {{ maxLetters }} characters", { + letters: description.length, + maxLetters: 300 + })} + +
+ } + helperText={i18n.t( + "If empty, the preview shows what will be autogenerated." + )} + value={description ? description.slice(0, 299) : undefined} + onChange={onChange} + disabled={loading || disabled} + fullWidth + multiline + placeholder={descriptionPlaceholder} + InputLabelProps={{ shrink: true }} + rows={10} + /> +
+ )} + + + ); + } +); +SeoForm.displayName = "SeoForm"; +SeoForm.defaultProps = { + helperText: i18n.t( + "Add search engine title and description to make this product easier to find" + ) +}; +export default SeoForm; diff --git a/src/components/SeoForm/index.ts b/src/components/SeoForm/index.ts new file mode 100644 index 000000000..1f1393243 --- /dev/null +++ b/src/components/SeoForm/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SeoForm"; +export * from "./SeoForm"; diff --git a/src/components/Shop/index.tsx b/src/components/Shop/index.tsx new file mode 100644 index 000000000..1c3a017c2 --- /dev/null +++ b/src/components/Shop/index.tsx @@ -0,0 +1,20 @@ +import * as React from "react"; + +import { TypedShopInfoQuery } from "./query"; +import { ShopInfo_shop } from "./types/ShopInfo"; + +type ShopContext = ShopInfo_shop; + +export const shopContext = React.createContext(undefined); + +export const ShopProvider: React.StatelessComponent<{}> = ({ children }) => ( + + {({ data }) => ( + + {children} + + )} + +); +export const Shop = shopContext.Consumer; +export default Shop; diff --git a/src/components/Shop/query.ts b/src/components/Shop/query.ts new file mode 100644 index 000000000..b67e048bb --- /dev/null +++ b/src/components/Shop/query.ts @@ -0,0 +1,34 @@ +import gql from "graphql-tag"; + +import { TypedQuery } from "../../queries"; +import { ShopInfo } from "./types/ShopInfo"; + +const shopInfo = gql` + query ShopInfo { + shop { + countries { + country + code + } + defaultCountry { + code + country + } + defaultCurrency + defaultWeightUnit + displayGrossPrices + domain { + host + url + } + languages { + code + language + } + includeTaxesInPrices + name + trackInventoryByDefault + } + } +`; +export const TypedShopInfoQuery = TypedQuery(shopInfo); diff --git a/src/components/Shop/types/ShopInfo.ts b/src/components/Shop/types/ShopInfo.ts new file mode 100644 index 000000000..b3b4fa6d7 --- /dev/null +++ b/src/components/Shop/types/ShopInfo.ts @@ -0,0 +1,51 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { WeightUnitsEnum, LanguageCodeEnum } from "./../../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: ShopInfo +// ==================================================== + +export interface ShopInfo_shop_countries { + __typename: "CountryDisplay"; + country: string; + code: string; +} + +export interface ShopInfo_shop_defaultCountry { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface ShopInfo_shop_domain { + __typename: "Domain"; + host: string; + url: string; +} + +export interface ShopInfo_shop_languages { + __typename: "LanguageDisplay"; + code: LanguageCodeEnum; + language: string; +} + +export interface ShopInfo_shop { + __typename: "Shop"; + countries: (ShopInfo_shop_countries | null)[]; + defaultCountry: ShopInfo_shop_defaultCountry | null; + defaultCurrency: string; + defaultWeightUnit: WeightUnitsEnum | null; + displayGrossPrices: boolean; + domain: ShopInfo_shop_domain; + languages: (ShopInfo_shop_languages | null)[]; + includeTaxesInPrices: boolean; + name: string; + trackInventoryByDefault: boolean | null; +} + +export interface ShopInfo { + shop: ShopInfo_shop | null; +} diff --git a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx new file mode 100644 index 000000000..3d798cf65 --- /dev/null +++ b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx @@ -0,0 +1,223 @@ +import { Omit } from "@material-ui/core"; +import { InputProps } from "@material-ui/core/Input"; +import MenuItem from "@material-ui/core/MenuItem"; +import Paper from "@material-ui/core/Paper"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import Downshift from "downshift"; +import * as React from "react"; +import { compareTwoStrings } from "string-similarity"; + +import i18n from "../../i18n"; +import ArrowDropdownIcon from "../../icons/ArrowDropdown"; +import Debounce, { DebounceProps } from "../Debounce"; + +const styles = (theme: Theme) => + createStyles({ + container: { + flexGrow: 1, + position: "relative" + }, + paper: { + borderRadius: 4, + left: 0, + marginTop: theme.spacing.unit, + padding: 8, + position: "absolute", + right: 0, + zIndex: 2 + } + }); + +export interface SingleAutocompleteSelectFieldProps { + error?: boolean; + name: string; + choices: Array<{ + label: string; + value: any; + }>; + value?: { + label: string; + value: any; + }; + disabled?: boolean; + loading?: boolean; + placeholder?: string; + custom?: boolean; + helperText?: string; + label?: string; + InputProps?: InputProps; + fetchChoices?(value: string); + onChange(event); +} + +interface SingleAutocompleteSelectFieldState { + choices: Array<{ + label: string; + value: string; + }>; +} + +const DebounceAutocomplete: React.ComponentType< + DebounceProps +> = Debounce; + +const SingleAutocompleteSelectFieldComponent = withStyles(styles, { + name: "SingleAutocompleteSelectField" +})( + ({ + choices, + classes, + custom, + disabled, + error, + helperText, + label, + loading, + name, + placeholder, + value, + InputProps, + fetchChoices, + onChange + }: SingleAutocompleteSelectFieldProps & WithStyles) => { + const handleChange = item => onChange({ target: { name, value: item } }); + + return ( + + {debounceFn => ( + (item ? item.label : "")} + onSelect={handleChange} + onInputValueChange={value => debounceFn(value)} + > + {({ + getInputProps, + getItemProps, + isOpen, + inputValue, + selectedItem, + toggleMenu, + openMenu, + closeMenu, + highlightedIndex + }) => { + const isCustom = + choices && selectedItem + ? choices.filter(c => c.value === selectedItem.value) + .length === 0 + : false; + return ( +
+ + ), + error, + id: undefined, + onBlur: closeMenu, + onFocus: openMenu + }} + disabled={disabled} + helperText={helperText} + label={label} + fullWidth={true} + /> + {isOpen && ( + + {loading ? ( + + {i18n.t("Loading...")} + + ) : choices.length > 0 || custom ? ( + <> + {choices.map((suggestion, index) => ( + + {suggestion.label} + + ))} + {custom && ( + + {i18n.t("Add custom value")} + + )} + + ) : ( + + {i18n.t("No results found")} + + )} + + )} +
+ ); + }} +
+ )} +
+ ); + } +); + +export class SingleAutocompleteSelectField extends React.Component< + Omit, + SingleAutocompleteSelectFieldState +> { + state = { choices: this.props.choices }; + + handleInputChange = (value: string) => + this.setState((_, props) => ({ + choices: props.choices + .sort((a, b) => { + const ratingA = compareTwoStrings(value || "", a.label); + const ratingB = compareTwoStrings(value || "", b.label); + if (ratingA > ratingB) { + return -1; + } + if (ratingA < ratingB) { + return 1; + } + return 0; + }) + .slice(0, 5) + })); + + render() { + if (!!this.props.fetchChoices) { + return ; + } + return ( + + ); + } +} +export default SingleAutocompleteSelectField; diff --git a/src/components/SingleAutocompleteSelectField/index.ts b/src/components/SingleAutocompleteSelectField/index.ts new file mode 100644 index 000000000..c1cdf064d --- /dev/null +++ b/src/components/SingleAutocompleteSelectField/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SingleAutocompleteSelectField"; +export * from "./SingleAutocompleteSelectField"; diff --git a/src/components/SingleSelectField/SingleSelectField.tsx b/src/components/SingleSelectField/SingleSelectField.tsx new file mode 100644 index 000000000..695c29784 --- /dev/null +++ b/src/components/SingleSelectField/SingleSelectField.tsx @@ -0,0 +1,95 @@ +import FilledInput from "@material-ui/core/FilledInput"; +import FormControl from "@material-ui/core/FormControl"; +import FormHelperText from "@material-ui/core/FormHelperText"; +import InputLabel from "@material-ui/core/InputLabel"; +import MenuItem from "@material-ui/core/MenuItem"; +import Select, { SelectProps } from "@material-ui/core/Select"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import classNames from "classnames"; +import * as React from "react"; + +import i18n from "../../i18n"; + +const styles = createStyles({ + formControl: { + width: "100%" + } +}); + +interface SingleSelectFieldProps extends WithStyles { + choices: Array<{ + value: string; + label: string | React.ReactNode; + }>; + className?: string; + disabled?: boolean; + error?: boolean; + hint?: string; + label?: string; + name?: string; + selectProps?: SelectProps; + placeholder?: string; + value?: string; + onChange(event: any); +} + +export const SingleSelectField = withStyles(styles, { + name: "SingleSelectField" +})( + ({ + className, + classes, + disabled, + error, + label, + choices, + value, + onChange, + name, + hint, + selectProps, + placeholder + }: SingleSelectFieldProps) => { + const choicesByKey: { [key: string]: string } = + choices === undefined + ? {} + : choices.reduce((prev, curr) => { + prev[curr.value] = curr.label; + return prev; + }, {}); + + return ( + + {label} + + {hint && {hint}} + + ); + } +); +SingleSelectField.displayName = "SingleSelectField"; +export default SingleSelectField; diff --git a/src/components/SingleSelectField/index.ts b/src/components/SingleSelectField/index.ts new file mode 100644 index 000000000..c8af8bf3f --- /dev/null +++ b/src/components/SingleSelectField/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SingleSelectField"; +export * from "./SingleSelectField"; diff --git a/src/components/Skeleton.tsx b/src/components/Skeleton.tsx new file mode 100644 index 000000000..ef5d8b7ec --- /dev/null +++ b/src/components/Skeleton.tsx @@ -0,0 +1,44 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import classNames from "classnames"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + "@keyframes skeleton-animation": { + "0%": { + opacity: 0.6 + }, + "100%": { + opacity: 1 + } + }, + skeleton: { + animation: "skeleton-animation .75s linear infinite forwards alternate", + background: theme.palette.background.default, + borderRadius: 4, + display: "block", + height: "0.8em", + margin: "0.2em 0" + } + }); + +interface SkeletonProps extends WithStyles { + className?: string; + style?: React.CSSProperties; +} + +const Skeleton = withStyles(styles, { name: "Skeleton" })( + ({ className, classes, style }: SkeletonProps) => ( + + ‌ + + ) +); + +Skeleton.displayName = "Skeleton"; +export default Skeleton; diff --git a/src/components/StatusLabel/StatusLabel.tsx b/src/components/StatusLabel/StatusLabel.tsx new file mode 100644 index 000000000..f3be842da --- /dev/null +++ b/src/components/StatusLabel/StatusLabel.tsx @@ -0,0 +1,83 @@ +import yellow from "@material-ui/core/colors/yellow"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography, { TypographyProps } from "@material-ui/core/Typography"; +import * as classNames from "classnames"; +import * as React from "react"; + +const styles = (theme: Theme) => { + const dot = { + borderRadius: "100%", + content: "''", + display: "block", + height: 8, + left: -theme.spacing.unit * 2, + position: "absolute" as "absolute", + top: "calc(50% - 5px)", + width: 8 + }; + return createStyles({ + errorDot: { + "&:before": { backgroundColor: theme.palette.error.main, ...dot } + }, + neutralDot: { + "&:before": { backgroundColor: yellow[500], ...dot } + }, + root: { + display: "inline-block", + marginLeft: theme.spacing.unit + 8, + position: "relative" + }, + span: { + display: "inline" + }, + successDot: { + "&:before": { backgroundColor: theme.palette.primary.main, ...dot } + } + }); +}; + +interface StatusLabelProps extends WithStyles { + className?: string; + label: string | React.ReactNode; + status: "success" | "neutral" | "error" | string; + typographyProps?: TypographyProps; +} + +const StatusLabel = withStyles(styles, { name: "StatusLabel" })( + ({ + classes, + className, + label, + status, + typographyProps + }: StatusLabelProps) => ( +
+ {typographyProps ? ( + + {label} + + ) : ( + label + )} +
+ ) +); +StatusLabel.displayName = "StatusLabel"; +export default StatusLabel; diff --git a/src/components/StatusLabel/index.ts b/src/components/StatusLabel/index.ts new file mode 100644 index 000000000..277ccdc27 --- /dev/null +++ b/src/components/StatusLabel/index.ts @@ -0,0 +1,2 @@ +export { default } from "./StatusLabel"; +export * from "./StatusLabel"; diff --git a/src/components/Tab/Tab.tsx b/src/components/Tab/Tab.tsx new file mode 100644 index 000000000..1b74444e5 --- /dev/null +++ b/src/components/Tab/Tab.tsx @@ -0,0 +1,60 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as classNames from "classnames"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + active: {}, + root: { + "&$active": { + borderBottomColor: theme.palette.primary.main, + color: theme.typography.body2.color + }, + "&:focus": { + color: theme.palette.primary.main + }, + "&:hover": { + color: theme.palette.primary.main + }, + borderBottom: "1px solid transparent", + color: theme.typography.caption.color, + cursor: "pointer", + display: "inline-block", + fontWeight: theme.typography.fontWeightRegular, + marginRight: theme.spacing.unit * 2, + minWidth: 40, + padding: `0 ${theme.spacing.unit}px`, + transition: theme.transitions.duration.short + "ms" + } + }); + +interface TabProps extends WithStyles { + children?: React.ReactNode; + isActive: boolean; + changeTab: (index: T) => void; +} + +export function Tab(value: T) { + return withStyles(styles, { name: "Tab" })( + ({ classes, children, isActive, changeTab }: TabProps) => ( + changeTab(value)} + > + {children} + + ) + ); +} + +export default Tab; diff --git a/src/components/Tab/TabContainer.tsx b/src/components/Tab/TabContainer.tsx new file mode 100644 index 000000000..b266e8929 --- /dev/null +++ b/src/components/Tab/TabContainer.tsx @@ -0,0 +1,27 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +export interface TabContainerProps { + children: React.ReactNode | React.ReactNodeArray; +} + +const styles = (theme: Theme) => + createStyles({ + root: { + borderBottom: `1px solid ${theme.overrides.MuiCard.root.borderColor}` + } + }); + +const TabContainer = withStyles(styles, { + name: "TabContainer" +})(({ classes, children }: TabContainerProps & WithStyles) => ( +
{children}
+)); +TabContainer.displayName = "TabContainer"; + +export default TabContainer; diff --git a/src/components/Tab/Tabs.tsx b/src/components/Tab/Tabs.tsx new file mode 100644 index 000000000..5eb09a3ff --- /dev/null +++ b/src/components/Tab/Tabs.tsx @@ -0,0 +1,31 @@ +import * as React from "react"; + +export interface TabsProps { + children: ( + props: { + changeTab: (index: number) => void; + currentTab: number; + } + ) => React.ReactNode; +} + +interface TabsState { + currentTab: number; +} + +class Tabs extends React.Component { + state: TabsState = { + currentTab: 0 + }; + + changeTab = (index: number) => this.setState({ currentTab: index }); + + render() { + return this.props.children({ + changeTab: this.changeTab, + currentTab: this.state.currentTab + }); + } +} + +export default Tabs; diff --git a/src/components/Tab/index.ts b/src/components/Tab/index.ts new file mode 100644 index 000000000..69393a774 --- /dev/null +++ b/src/components/Tab/index.ts @@ -0,0 +1,6 @@ +export * from "./Tab"; +export { default as Tab } from "./Tab"; +export * from "./TabContainer"; +export { default as TabContainer } from "./TabContainer"; +export { default as Tabs } from "./Tabs"; +export { default } from "./Tabs"; diff --git a/src/components/TableCellAvatar/TableCellAvatar.tsx b/src/components/TableCellAvatar/TableCellAvatar.tsx new file mode 100644 index 000000000..369694ff9 --- /dev/null +++ b/src/components/TableCellAvatar/TableCellAvatar.tsx @@ -0,0 +1,57 @@ +import Avatar from "@material-ui/core/Avatar"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TableCell from "@material-ui/core/TableCell"; +import Cached from "@material-ui/icons/Cached"; +import * as classNames from "classnames"; +import * as React from "react"; + +import Image from "../../icons/Image"; + +const styles = (theme: Theme) => + createStyles({ + avatar: { + background: "none", + border: `1px solid ${theme.overrides.MuiCard.root.borderColor}`, + borderRadius: 2, + color: "#bdbdbd", + padding: theme.spacing.unit / 2 + }, + root: { + paddingRight: theme.spacing.unit * 3, + width: "1%" + } + }); + +interface TableCellAvatarProps extends WithStyles { + className?: string; + thumbnail?: string; + avatarProps?: string; +} + +const TableCellAvatar = withStyles(styles, { name: "TableCellAvatar" })( + ({ classes, className, thumbnail, avatarProps }: TableCellAvatarProps) => ( + + {thumbnail === undefined ? ( + + + + ) : thumbnail === null ? ( + + + + ) : ( + + )} + + ) +); +TableCellAvatar.displayName = "TableCellAvatar"; +export default TableCellAvatar; diff --git a/src/components/TableCellAvatar/index.ts b/src/components/TableCellAvatar/index.ts new file mode 100644 index 000000000..606c7449a --- /dev/null +++ b/src/components/TableCellAvatar/index.ts @@ -0,0 +1,2 @@ +export { default } from "./TableCellAvatar"; +export * from "./TableCellAvatar"; diff --git a/src/components/TableFilter/FilterChips.tsx b/src/components/TableFilter/FilterChips.tsx new file mode 100644 index 000000000..a5101de02 --- /dev/null +++ b/src/components/TableFilter/FilterChips.tsx @@ -0,0 +1,178 @@ +import ButtonBase from "@material-ui/core/ButtonBase"; +import { Theme } from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; +import TextField, { TextFieldProps } from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import ClearIcon from "@material-ui/icons/Clear"; +import { createStyles, makeStyles, useTheme } from "@material-ui/styles"; +import * as React from "react"; + +import i18n from "../../i18n"; +import Filter, { FilterContentSubmitData, IFilter } from "../Filter"; +import Hr from "../Hr"; +import Link from "../Link"; + +export interface Filter { + label: string; + onClick: () => void; +} + +const useInputStyles = makeStyles({ + input: { + padding: "10px 12px" + }, + root: { + flex: 1 + } +}); + +const Search: React.FC = props => { + const classes = useInputStyles(); + return ( + + ); +}; + +const useStyles = makeStyles( + (theme: Theme) => + createStyles({ + actionContainer: { + display: "flex", + flexWrap: "wrap", + padding: `${theme.spacing.unit}px ${theme.spacing.unit * 3}px` + }, + filterButton: { + alignItems: "center", + backgroundColor: fade(theme.palette.primary.main, 0.6), + borderRadius: "19px", + display: "flex", + height: "38px", + justifyContent: "space-around", + margin: `0 ${theme.spacing.unit * 2}px ${theme.spacing.unit}px`, + marginLeft: 0, + padding: "0 16px" + }, + filterChipContainer: { + display: "flex", + flex: 1, + flexWrap: "wrap" + }, + filterContainer: { + borderBottom: "1px solid #e8e8e8", + display: "flex", + marginTop: theme.spacing.unit, + padding: `0 ${theme.spacing.unit * 3}px ${theme.spacing.unit}px` + }, + filterIcon: { + color: theme.palette.common.white, + height: 16, + width: 16 + }, + filterIconContainer: { + WebkitAppearance: "none", + background: "transparent", + border: "none", + borderRadius: "100%", + cursor: "pointer", + height: 32, + marginRight: -13, + padding: 8, + width: 32 + }, + filterLabel: { + marginBottom: theme.spacing.unit + }, + filterText: { + color: theme.palette.common.white, + fontSize: 12, + fontWeight: 400 as 400 + } + }), + { + name: "FilterChips" + } +); + +interface FilterChipProps { + currencySymbol: string; + menu: IFilter; + filtersList: Filter[]; + filterLabel: string; + placeholder: string; + search: string; + isCustomSearch: boolean; + onSearchChange: (event: React.ChangeEvent) => void; + onFilterAdd: (filter: FilterContentSubmitData) => void; + onFilterDelete: () => void; + onFilterSave: () => void; +} + +export const FilterChips: React.FC = ({ + currencySymbol, + filtersList, + menu, + filterLabel, + placeholder, + onSearchChange, + search, + onFilterAdd, + onFilterSave, + onFilterDelete, + isCustomSearch +}) => { + const theme = useTheme(); + const classes = useStyles({ theme }); + + return ( + <> +
+ + +
+ {search || (filtersList && filtersList.length) ? ( +
+
+ {filtersList.map(filter => ( +
+ + {filter.label} + + + + +
+ ))} +
+ {isCustomSearch ? ( + {i18n.t("Save Custom Search")} + ) : ( + {i18n.t("Delete Search")} + )} +
+ ) : ( +
+ )} + + ); +}; + +export default FilterChips; diff --git a/src/components/TableFilter/FilterTab.tsx b/src/components/TableFilter/FilterTab.tsx new file mode 100644 index 000000000..e56e77fc5 --- /dev/null +++ b/src/components/TableFilter/FilterTab.tsx @@ -0,0 +1,58 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Tab from "@material-ui/core/Tab"; +import classNames from "classnames"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + selectedTabLabel: { + "&$tabLabel": { + color: theme.typography.body2.color + } + }, + tabLabel: { + "&:hover": { + color: theme.typography.body2.color + }, + color: theme.typography.caption.color, + fontSize: "1rem", + fontWeight: 400 + }, + tabRoot: { + minWidth: "80px", + opacity: 1, + paddingTop: `${theme.spacing.unit * 1}px`, + textTransform: "initial" as "initial" + } + }); + +interface FilterTabProps extends WithStyles { + onClick: () => void; + label: string; + selected?: boolean; + value?: number; +} + +export const FilterTab = withStyles(styles, { name: "FilterTab" })( + ({ classes, onClick, label, selected, value }: FilterTabProps) => ( + + ) +); +FilterTab.displayName = "FilterTab"; +export default FilterTab; diff --git a/src/components/TableFilter/FilterTabs.tsx b/src/components/TableFilter/FilterTabs.tsx new file mode 100644 index 000000000..380f6ca8f --- /dev/null +++ b/src/components/TableFilter/FilterTabs.tsx @@ -0,0 +1,35 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Tabs from "@material-ui/core/Tabs"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + tabsRoot: { + borderBottom: `1px solid ${theme.overrides.MuiCard.root.borderColor}`, + paddingLeft: `${theme.spacing.unit * 3}px` + } + }); + +interface FilterTabsProps extends WithStyles { + children?: React.ReactNode; + currentTab: number; +} + +export const FilterTabs = withStyles(styles, { name: "FilterTabs" })( + ({ classes, children, currentTab }: FilterTabsProps) => ( + + {children} + + ) +); + +export default FilterTabs; diff --git a/src/components/TableFilter/index.ts b/src/components/TableFilter/index.ts new file mode 100644 index 000000000..d2d907900 --- /dev/null +++ b/src/components/TableFilter/index.ts @@ -0,0 +1,5 @@ +export { default } from "./FilterTabs"; +export { Filter } from "./FilterChips"; +export * from "./FilterTabs"; +export * from "./FilterTab"; +export * from "./FilterChips"; diff --git a/src/components/TableHead/TableHead.tsx b/src/components/TableHead/TableHead.tsx new file mode 100644 index 000000000..5e65c6a5d --- /dev/null +++ b/src/components/TableHead/TableHead.tsx @@ -0,0 +1,133 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; +import TableCell from "@material-ui/core/TableCell"; +import MuiTableHead, { + TableHeadProps as MuiTableHeadProps +} from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import * as classNames from "classnames"; +import * as React from "react"; + +import { Node } from "../../types"; + +import i18n from "../../i18n"; +import Checkbox from "../Checkbox"; + +export interface TableHeadProps extends MuiTableHeadProps { + disabled: boolean; + selected: number; + items: Node[]; + toolbar: React.ReactNode | React.ReactNodeArray; + toggleAll: (items: Node[], selected: number) => void; +} + +const styles = (theme: Theme) => + createStyles({ + cell: { + padding: 0 + }, + checkboxPartialSelect: { + "&:after": { + background: "#fff", + content: "''", + height: 2, + position: "absolute", + width: 4 + } + }, + checkboxSelected: { + backgroundColor: fade(theme.palette.primary.main, 0.05) + }, + container: { + alignItems: "center", + display: "flex", + height: 47, + marginRight: -theme.spacing.unit * 2 + }, + padding: { + "&:last-child": { + padding: 0 + } + }, + root: { + backgroundColor: fade(theme.palette.primary.main, 0.05), + borderBottom: "1px solid rgba(224, 224, 224, 1)", + paddingLeft: 0, + paddingRight: 24 + }, + spacer: { + flex: 1 + }, + toolbar: { + "& > *": { + marginLeft: theme.spacing.unit + } + } + }); + +const TableHead = withStyles(styles, { + name: "TableHead" +})( + ({ + classes, + children, + disabled, + items, + selected, + toggleAll, + toolbar, + ...muiTableHeadProps + }: TableHeadProps & WithStyles) => { + return ( + + + + {items && items.length > 0 ? ( + selected && selected > 0 + })} + checked={selected === 0 ? false : true} + disabled={disabled} + onChange={() => toggleAll(items, selected)} + /> + ) : null} + + {selected ? ( + <> + +
+ {selected && ( + + {i18n.t("Selected {{ number }} items", { + number: selected + })} + + )} +
+
{toolbar}
+
+ + + ) : ( + children + )} + + + ); + } +); +TableHead.displayName = "TableHead"; +export default TableHead; diff --git a/src/components/TableHead/index.ts b/src/components/TableHead/index.ts new file mode 100644 index 000000000..bbb62bd2f --- /dev/null +++ b/src/components/TableHead/index.ts @@ -0,0 +1,2 @@ +export { default } from './TableHead'; +export * from './TableHead'; \ No newline at end of file diff --git a/src/components/TablePagination/TablePagination.tsx b/src/components/TablePagination/TablePagination.tsx new file mode 100644 index 000000000..93d149baa --- /dev/null +++ b/src/components/TablePagination/TablePagination.tsx @@ -0,0 +1,112 @@ +// @inheritedComponent TableCell + +import { IconButtonProps } from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TableCell from "@material-ui/core/TableCell"; +import Toolbar from "@material-ui/core/Toolbar"; +import * as React from "react"; + +import TablePaginationActions from "./TablePaginationActions"; + +const styles = (theme: Theme) => + createStyles({ + actions: { + color: theme.palette.text.secondary, + flexShrink: 0, + marginLeft: theme.spacing.unit * 2.5 + }, + caption: { + flexShrink: 0 + }, + input: { + flexShrink: 0, + fontSize: "inherit" + }, + root: { + "&:last-child": { + padding: 0 + } + }, + select: { + paddingLeft: theme.spacing.unit, + paddingRight: theme.spacing.unit * 2 + }, + selectIcon: { + top: 1 + }, + selectRoot: { + color: theme.palette.text.secondary, + marginLeft: theme.spacing.unit, + marginRight: theme.spacing.unit * 4 + }, + spacer: { + flex: "1 1 100%" + }, + toolbar: { + height: 56, + minHeight: 56, + paddingRight: 2 + } + }); + +interface TablePaginationProps extends WithStyles { + Actions?: typeof TablePaginationActions; + backIconButtonProps?: Partial; + colSpan: number; + component?: string | typeof TableCell; + hasNextPage: boolean; + hasPreviousPage: boolean; + nextIconButtonProps?: Partial; + onNextPage(event); + onPreviousPage(event); +} + +const TablePagination = withStyles(styles, { name: "TablePagination" })( + ({ + Actions, + backIconButtonProps, + classes, + colSpan: colSpanProp, + component: Component, + hasNextPage, + hasPreviousPage, + nextIconButtonProps, + onNextPage, + onPreviousPage, + ...other + }: TablePaginationProps) => { + let colSpan; + + if (Component === TableCell || Component === "td") { + colSpan = colSpanProp || 1000; + } + + return ( + + +
+ + + + ); + } +); +TablePagination.defaultProps = { + Actions: TablePaginationActions, + component: TableCell +}; + +TablePagination.displayName = "TablePagination"; +export default TablePagination; diff --git a/src/components/TablePagination/TablePaginationActions.tsx b/src/components/TablePagination/TablePaginationActions.tsx new file mode 100644 index 000000000..a6ca73715 --- /dev/null +++ b/src/components/TablePagination/TablePaginationActions.tsx @@ -0,0 +1,112 @@ +import IconButton from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; +import ArrowLeft from "@material-ui/icons/ArrowLeft"; +import ArrowRight from "@material-ui/icons/ArrowRight"; +import useTheme from "@saleor/hooks/useTheme"; +import * as classNames from "classnames"; +import * as React from "react"; + +const styles = (theme: Theme) => + createStyles({ + dark: { + "& svg": { + color: theme.palette.primary.main + }, + "&$disabled": { + "& svg": { + color: fade(theme.palette.primary.main, 0.2) + } + }, + "&:focus, &:hover": { + "& > span:first-of-type": { + backgroundColor: fade(theme.palette.primary.main, 0.2) + } + } + }, + disabled: {}, + iconButton: { + "& > span:first-of-type": { + backgroundColor: theme.palette.background.default, + borderRadius: "100%", + transition: theme.transitions.duration.standard + "ms" + }, + "&:focus, &:hover": { + "& > span:first-of-type": { + backgroundColor: fade(theme.palette.primary.main, 0.2) + }, + backgroundColor: "transparent" + } + }, + root: { + color: theme.palette.text.secondary, + flexShrink: 0, + marginLeft: theme.spacing.unit * 2.5 + } + }); + +export interface TablePaginationActionsProps + extends WithStyles { + backIconButtonProps?: any; + classes: any; + className?: string; + hasNextPage: boolean; + hasPreviousPage: boolean; + nextIconButtonProps?: any; + onNextPage(event); + onPreviousPage(event); +} + +export const TablePaginationActions = withStyles(styles, { + name: "TablePaginationActions", + withTheme: true +})( + ({ + backIconButtonProps, + classes, + className, + hasNextPage, + hasPreviousPage, + nextIconButtonProps, + onNextPage, + onPreviousPage, + theme, + ...other + }: TablePaginationActionsProps) => { + const { isDark } = useTheme(); + return ( +
+ + {theme.direction === "rtl" ? : } + + + {theme.direction === "rtl" ? : } + +
+ ); + } +); + +TablePaginationActions.displayName = "TablePaginationActions"; +export default TablePaginationActions; diff --git a/src/components/TablePagination/index.ts b/src/components/TablePagination/index.ts new file mode 100644 index 000000000..0d128c72d --- /dev/null +++ b/src/components/TablePagination/index.ts @@ -0,0 +1,3 @@ +export { default } from "./TablePagination"; +export * from "./TablePagination"; +export * from "./TablePaginationActions"; diff --git a/src/components/TextFieldWithChoice/TextFieldWithChoice.tsx b/src/components/TextFieldWithChoice/TextFieldWithChoice.tsx new file mode 100644 index 000000000..07b311710 --- /dev/null +++ b/src/components/TextFieldWithChoice/TextFieldWithChoice.tsx @@ -0,0 +1,132 @@ +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import Grow from "@material-ui/core/Grow"; +import MenuItem from "@material-ui/core/MenuItem"; +import Menu from "@material-ui/core/MenuList"; +import Paper from "@material-ui/core/Paper"; +import Popper from "@material-ui/core/Popper"; +import { createStyles, WithStyles, withStyles } from "@material-ui/core/styles"; +import TextField, { TextFieldProps } from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import DropdownIcon from "@material-ui/icons/ArrowDropDown"; +import * as React from "react"; + +import MenuToggle from "../MenuToggle"; + +export type TextFieldWithChoiceProps = TextFieldProps & { + ChoiceProps: { + name: string; + label: string | React.ReactNode; + values: Array<{ + label: string | React.ReactNode; + value: TValue; + }>; + }; +}; + +const styles = createStyles({ + adornment: { + alignItems: "center", + cursor: "pointer", + display: "flex" + }, + menu: { + zIndex: 10 + } +}); + +const TextFieldWithChoice = withStyles(styles, { + name: "TextFieldWithChoices" +})( + ({ + ChoiceProps, + InputProps, + classes, + onChange, + ...props + }: TextFieldWithChoiceProps & WithStyles) => { + const anchor = React.useRef(); + + return ( + + {({ + open: menuOpen, + actions: { open: openMenu, close: closeMenu } + }) => { + const handleSelect = value => { + onChange({ + target: { + name: ChoiceProps.name, + value + } + } as any); + closeMenu(); + }; + + return ( + <> +
+ + {ChoiceProps.label} + + +
+ + {({ TransitionProps, placement }) => ( + + + + + {ChoiceProps.values.map(choice => ( + handleSelect(choice.value)} + key={choice.value} + > + {choice.label} + + ))} + + + + + )} + + + ); + }} + + ) + }} + /> + ); + } +); +TextFieldWithChoice.displayName = "TextFieldWithChoice"; +export default TextFieldWithChoice; diff --git a/src/components/TextFieldWithChoice/index.ts b/src/components/TextFieldWithChoice/index.ts new file mode 100644 index 000000000..064783078 --- /dev/null +++ b/src/components/TextFieldWithChoice/index.ts @@ -0,0 +1,2 @@ +export { default } from "./TextFieldWithChoice"; +export * from "./TextFieldWithChoice"; diff --git a/src/components/Theme/ThemeProvider.tsx b/src/components/Theme/ThemeProvider.tsx new file mode 100644 index 000000000..71abbcc57 --- /dev/null +++ b/src/components/Theme/ThemeProvider.tsx @@ -0,0 +1,99 @@ +// FIXME: https://github.com/mirumee/saleor/issues/4174 +import OldMuiThemeProvider from "@material-ui/core/styles/MuiThemeProvider"; +import MuiThemeProvider from "@material-ui/styles/ThemeProvider"; +import * as React from "react"; + +import Baseline from "../../Baseline"; +import createTheme, { IThemeColors } from "../../theme"; + +const dark: IThemeColors = { + autofill: "#5D5881", + background: { + default: "#1D1E1F", + paper: "#2E2F31" + }, + error: "#C22D74", + font: { + default: "#FCFCFC", + gray: "#9E9D9D" + }, + gray: { + default: "#202124", + disabled: "rgba(32, 33, 36, 0.6)" + }, + input: { + default: "#25262A", + disabled: "#292A2D", + focused: "#25262A" + }, + paperBorder: "#252728", + primary: "#13BEBB", + secondary: "#21125E" +}; +const light: IThemeColors = { + autofill: "#f4f6c5", + background: { + default: "#F1F6F6", + paper: "#FFFFFF" + }, + error: "#C22D74", + font: { + default: "#3D3D3D", + gray: "#616161" + }, + gray: { + default: "#C8C8C8", + disabled: "rgba(216, 216, 216, 0.3)" + }, + input: { + default: "#F1F6F6", + disabled: "#EAEAEA", + focused: "#DCEBEB" + }, + paperBorder: "#EAEAEA", + primary: "#13BEBB", + secondary: "#21125E" +}; + +interface IThemeContext { + isDark: boolean; + toggleTheme: () => void; +} +export const ThemeContext = React.createContext({ + isDark: false, + toggleTheme: () => undefined +}); + +interface ThemeProviderProps { + isDefaultDark?: boolean; +} +const ThemeProvider: React.FC = ({ + children, + isDefaultDark +}) => { + const [isDark, setDark] = React.useState(isDefaultDark); + const toggleTheme = () => { + setDark(!isDark); + localStorage.setItem("theme", (!isDark).toString()); + }; + + return ( + + + + + {children} + + + + ); +}; +ThemeProvider.defaultProps = { + isDefaultDark: false +}; +export default ThemeProvider; diff --git a/src/components/Theme/index.ts b/src/components/Theme/index.ts new file mode 100644 index 000000000..337b9a0d3 --- /dev/null +++ b/src/components/Theme/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ThemeProvider"; +export * from "./ThemeProvider"; diff --git a/src/components/Timeline/Timeline.tsx b/src/components/Timeline/Timeline.tsx new file mode 100644 index 000000000..8591932d8 --- /dev/null +++ b/src/components/Timeline/Timeline.tsx @@ -0,0 +1,106 @@ +import Avatar from "@material-ui/core/Avatar"; +import Button from "@material-ui/core/Button"; +import CardContent from "@material-ui/core/CardContent"; +import deepPurple from "@material-ui/core/colors/deepPurple"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import PersonIcon from "@material-ui/icons/Person"; +import * as React from "react"; + +import i18n from "../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + avatar: { + "& span": { + height: "100%", + width: "100%" + }, + alignSelf: "flex-start", + marginRight: theme.spacing.unit * 5.5 + }, + cardActionsExpanded: { + maxHeight: theme.spacing.unit * 6 + }, + input: { + marginTop: -theme.spacing.unit + }, + noteRoot: { + left: -theme.spacing.unit * 8.5 - 1, + marginBottom: theme.spacing.unit * 3, + position: "relative", + width: `calc(100% + ${theme.spacing.unit * 8.5}px)` + }, + noteTitle: { + "&:last-child": { + paddingBottom: 0 + }, + alignItems: "center", + background: theme.palette.background.default, + display: "flex" + }, + root: { + borderColor: theme.overrides.MuiCard.root.borderColor, + borderStyle: "solid", + borderWidth: "0 0 0 2px", + marginLeft: 20, + paddingLeft: theme.spacing.unit * 3 + } + }); + +interface TimelineProps extends WithStyles { + children?: React.ReactNode; +} + +interface TimelineAddNoteProps extends WithStyles { + message: string; + onChange(event: React.ChangeEvent); + onSubmit(event: React.FormEvent); +} + +export const Timeline = withStyles(styles, { name: "Timeline" })( + ({ classes, children }: TimelineProps) => ( +
{children}
+ ) +); + +export const TimelineAddNote = withStyles(styles, { name: "TimelineAddNote" })( + ({ classes, message, onChange, onSubmit }: TimelineAddNoteProps) => ( +
+ + + + + + {i18n.t("Send", { + context: "add order note" + })} + + ) + }} + variant="standard" + /> + +
+ ) +); +Timeline.displayName = "Timeline"; +export default Timeline; diff --git a/src/components/Timeline/TimelineEvent.tsx b/src/components/Timeline/TimelineEvent.tsx new file mode 100644 index 000000000..6e2ccd86e --- /dev/null +++ b/src/components/Timeline/TimelineEvent.tsx @@ -0,0 +1,100 @@ +import ExpansionPanel from "@material-ui/core/ExpansionPanel"; +import ExpansionPanelDetails from "@material-ui/core/ExpansionPanelDetails"; +import ExpansionPanelSummary from "@material-ui/core/ExpansionPanelSummary"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; +import * as React from "react"; + +import { DateTime } from "../Date"; + +const styles = (theme: Theme) => + createStyles({ + date: { + color: theme.typography.caption.color, + }, + dateExpander:{ + color: theme.typography.caption.color, + position: "absolute", + right: theme.spacing.unit * 3 + }, + dot: { + backgroundColor: theme.palette.primary.main, + borderRadius: "100%", + height: 8, + left: -29, + position: "absolute", + top: 6, + width: 8 + }, + noExpander: { + alignItems: "center", + display: "flex", + justifyContent: "space-between", + marginBottom: theme.spacing.unit, + marginLeft: theme.spacing.unit * 3, + width: "100%" + }, + panel: { + "&:before": { + display: "none" + }, + background: "none", + width: "100%" + }, + root: { + "&:last-child:after": { + background: theme.palette.background.default, + content: "''", + height: "calc(50% - 4px)", + left: `${-theme.spacing.unit * 3 - 2}px`, + position: "absolute", + top: "calc(50% + 4px)", + width: "2px" + }, + alignItems: "center", + display: "flex", + marginBottom: theme.spacing.unit * 3, + position: "relative", + width: "100%" + } + }); + +interface TimelineEventProps extends WithStyles { + children?: React.ReactNode; + date: string; + title: string; +} + +export const TimelineEvent = withStyles(styles)( + ({ classes, children, date, title }: TimelineEventProps) => ( +
+ + {children ? ( + + }> + {title} + {title} + + + {children} + + + ) : ( +
+ {title} + + + +
+ )} +
+ ) +); +TimelineEvent.displayName = "TimelineEvent"; +export default TimelineEvent; diff --git a/src/components/Timeline/TimelineNote.tsx b/src/components/Timeline/TimelineNote.tsx new file mode 100644 index 000000000..4059a7bd6 --- /dev/null +++ b/src/components/Timeline/TimelineNote.tsx @@ -0,0 +1,107 @@ +import Avatar from "@material-ui/core/Avatar"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import * as colors from "@material-ui/core/colors"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import PersonIcon from "@material-ui/icons/Person"; +import * as CRC from "crc-32"; +import * as React from "react"; + +import { DateTime } from "../Date"; +import Hr from "../Hr"; + +const palette = [ + colors.amber, + colors.blue, + colors.cyan, + colors.deepOrange, + colors.deepPurple, + colors.green, + colors.indigo, + colors.lightBlue, + colors.lightGreen, + colors.lime, + colors.orange, + colors.pink, + colors.purple, + colors.red, + colors.teal, + colors.yellow +].map(color => color[500]); + +const styles = (theme: Theme) => + createStyles({ + avatar: { + left: -45, + position: "absolute", + top: 0 + }, + card: { + marginBottom: theme.spacing.unit * 3, + marginLeft: theme.spacing.unit * 3, + position: "relative" + }, + cardContent: { + "&:last-child": { + paddingBottom: 16 + } + }, + content: { + marginTop: theme.spacing.unit * 2 + }, + root: { + position: "relative" + }, + title: { + alignItems: "center", + display: "flex", + justifyContent: "space-between", + marginBottom: theme.spacing.unit + } + }); + +interface TimelineNoteProps extends WithStyles { + date: string; + message: string | null; + user: { + email: string; + }; +} + +export const TimelineNote = withStyles(styles, { name: "TimelineNote" })( + ({ classes, date, user, message }: TimelineNoteProps) => ( +
+ + + + + +
+ {user.email} + + + +
+
+ ") + }} + /> +
+
+
+ ) +); +TimelineNote.displayName = "TimelineNote"; +export default TimelineNote; diff --git a/src/components/Timeline/index.ts b/src/components/Timeline/index.ts new file mode 100644 index 000000000..8c3807205 --- /dev/null +++ b/src/components/Timeline/index.ts @@ -0,0 +1,4 @@ +export { default } from "./Timeline"; +export * from "./Timeline"; +export * from "./TimelineEvent"; +export * from "./TimelineNote"; diff --git a/src/components/Timezone/Timezone.tsx b/src/components/Timezone/Timezone.tsx new file mode 100644 index 000000000..2690b5d7a --- /dev/null +++ b/src/components/Timezone/Timezone.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; + +export const TimezoneContext = React.createContext(undefined); +const { + Consumer: TimezoneConsumer, + Provider: TimezoneProvider +} = TimezoneContext; + +export { TimezoneConsumer, TimezoneProvider }; +export default TimezoneContext; diff --git a/src/components/Timezone/index.ts b/src/components/Timezone/index.ts new file mode 100644 index 000000000..d94e90445 --- /dev/null +++ b/src/components/Timezone/index.ts @@ -0,0 +1,2 @@ +export * from "./Timezone"; +export { default } from "./Timezone"; diff --git a/src/components/VisibilityCard/VisibilityCard.tsx b/src/components/VisibilityCard/VisibilityCard.tsx new file mode 100644 index 000000000..5600ff2d3 --- /dev/null +++ b/src/components/VisibilityCard/VisibilityCard.tsx @@ -0,0 +1,119 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import ControlledSwitch from "@saleor/components/ControlledSwitch"; +import { FormSpacer } from "@saleor/components/FormSpacer"; +import useDateLocalize from "@saleor/hooks/useDateLocalize"; +import i18n from "../../i18n"; +import { DateContext } from "../Date/DateContext"; + +const styles = (theme: Theme) => + createStyles({ + date: { + "& svg": { + fill: theme.palette.primary.main + }, + marginTop: theme.spacing.unit * 4 + }, + expandedSwitchContainer: { + marginBottom: 0 + }, + switchContainer: { + marginBottom: -theme.spacing.unit + } + }); + +interface VisibilityCardProps extends WithStyles { + children?: React.ReactNode | React.ReactNodeArray; + data: { + isPublished: boolean; + publicationDate: string; + }; + errors: { [key: string]: string }; + disabled?: boolean; + onChange(event: any); +} + +export const VisibilityCard = withStyles(styles, { + name: "VisibilityCard" +})( + ({ + children, + classes, + data: { isPublished, publicationDate }, + errors, + disabled, + onChange + }: VisibilityCardProps) => { + const localizeDate = useDateLocalize(); + const dateNow = React.useContext(DateContext); + return ( + + + +
+ dateNow + ? i18n.t("will be visible from {{ date }}", { + date: localizeDate(publicationDate) + }) + : null + : null + } + checked={isPublished} + onChange={onChange} + disabled={disabled} + /> +
+ {!isPublished && ( + <> + + + )} + + {children} +
+
+ ); + } +); +VisibilityCard.displayName = "VisibilityCard"; +export default VisibilityCard; diff --git a/src/components/VisibilityCard/index.ts b/src/components/VisibilityCard/index.ts new file mode 100644 index 000000000..9881a1d85 --- /dev/null +++ b/src/components/VisibilityCard/index.ts @@ -0,0 +1,2 @@ +export { default } from "./VisibilityCard"; +export * from "./VisibilityCard"; diff --git a/src/components/Weight/Weight.tsx b/src/components/Weight/Weight.tsx new file mode 100644 index 000000000..35defbf0b --- /dev/null +++ b/src/components/Weight/Weight.tsx @@ -0,0 +1,18 @@ +import * as React from "react"; +import i18n from "../../i18n"; + +export interface Weight { + unit: string; + value: number; +} +export interface WeightProps { + weight: Weight; +} + +const Weight: React.StatelessComponent = ({ weight }) => + i18n.t("{{ value }} {{ unit }}", { + context: "weight", + ...weight + }); +Weight.displayName = "Weight"; +export default Weight; diff --git a/src/components/Weight/index.ts b/src/components/Weight/index.ts new file mode 100644 index 000000000..1a73fcf9a --- /dev/null +++ b/src/components/Weight/index.ts @@ -0,0 +1,2 @@ +export { default } from './Weight'; +export * from './Weight'; \ No newline at end of file diff --git a/src/components/WeightRange/WeightRange.tsx b/src/components/WeightRange/WeightRange.tsx new file mode 100644 index 000000000..2552fae68 --- /dev/null +++ b/src/components/WeightRange/WeightRange.tsx @@ -0,0 +1,35 @@ +import * as React from "react"; + +import i18n from "../../i18n"; +import { Weight } from "../Weight"; + +export interface WeightRangeProps { + from?: Weight; + to?: Weight; +} + +const WeightRange: React.StatelessComponent = ({ + from, + to +}) => + from && to + ? i18n.t("{{ fromValue }} {{ fromUnit }} - {{ toValue }} {{ toUnit }}", { + context: "weight", + fromUnit: from.unit, + fromValue: from.value, + toUnit: to.unit, + toValue: to.value + }) + : from && !to + ? i18n.t("from {{ value }} {{ unit }}", { + context: "weight", + ...from + }) + : !from && to + ? i18n.t("to {{ value }} {{ unit }}", { + context: "weight", + ...to + }) + : "-"; +WeightRange.displayName = "WeightRange"; +export default WeightRange; diff --git a/src/components/WeightRange/index.ts b/src/components/WeightRange/index.ts new file mode 100644 index 000000000..b07752efe --- /dev/null +++ b/src/components/WeightRange/index.ts @@ -0,0 +1,2 @@ +export { default } from './WeightRange'; +export * from './WeightRange'; \ No newline at end of file diff --git a/src/components/WindowTitle/index.tsx b/src/components/WindowTitle/index.tsx new file mode 100644 index 000000000..63c99f54b --- /dev/null +++ b/src/components/WindowTitle/index.tsx @@ -0,0 +1,18 @@ +import * as React from "react"; +import { Helmet } from "react-helmet"; + +import useShop from "@saleor/hooks/useShop"; + +interface WindowTitleProps { + title: string; +} + +export const WindowTitle: React.StatelessComponent = ({ + title +}) => { + const shop = useShop(); + + return shop === undefined || !title ? null : ( + + ); +}; diff --git a/src/components/messages/MessageManager.tsx b/src/components/messages/MessageManager.tsx new file mode 100644 index 000000000..b698d0dc3 --- /dev/null +++ b/src/components/messages/MessageManager.tsx @@ -0,0 +1,105 @@ +import Button from "@material-ui/core/Button"; +import IconButton from "@material-ui/core/IconButton"; +import Snackbar from "@material-ui/core/Snackbar"; +import CloseIcon from "@material-ui/icons/Close"; +import * as React from "react"; + +import { IMessage, MessageContext } from "./"; + +interface Message extends IMessage { + key: string; +} +interface MessageManagerState { + message: Message; + opened: boolean; +} + +export class MessageManager extends React.Component<{}, MessageManagerState> { + state = { + message: { text: "", key: "0", onUndo: undefined }, + opened: false + }; + queue = []; + + handleClose = (_, reason) => { + if (reason === "clickaway") { + return; + } + this.setState({ opened: false }); + }; + + handleExited = () => { + this.processQueue(); + }; + + pushMessage = (message: IMessage) => { + this.queue.push({ + key: new Date().getTime(), + ...message + }); + + if (this.state.opened) { + this.setState({ opened: false }); + } else { + this.processQueue(); + } + }; + + processQueue = () => { + if (this.queue.length > 0) { + this.setState({ + message: this.queue.shift(), + opened: true + }); + } + }; + + render() { + const { text, key, onUndo } = this.state.message; + return ( + <> + {text}} + action={[ + !!onUndo ? ( + + ) : ( + undefined + ), + + + + ]} + /> + + {this.props.children} + + + ); + } +} +export default MessageManager; diff --git a/src/components/messages/index.ts b/src/components/messages/index.ts new file mode 100644 index 000000000..b5d621a0c --- /dev/null +++ b/src/components/messages/index.ts @@ -0,0 +1,11 @@ +import { createContext } from "react"; + +export interface IMessage { + text: string; + onUndo?: () => void; +} +export type IMessageContext = (message: IMessage) => void; +export const MessageContext = createContext(undefined); + +export * from "./MessageManager"; +export default MessageContext.Consumer; diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 000000000..1b4214a1b --- /dev/null +++ b/src/config.ts @@ -0,0 +1,12 @@ +import { SearchQueryVariables } from "./containers/BaseSearch"; + +export const APP_MOUNT_URI = process.env.APP_MOUNT_URI || "/"; +export const API_URI = process.env.API_URI || "/graphql/"; + +export const DEFAULT_INITIAL_SEARCH_DATA: SearchQueryVariables = { + after: null, + first: 5, + query: "" +}; + +export const PAGINATE_BY = 20; diff --git a/src/configuration/ConfigurationPage.tsx b/src/configuration/ConfigurationPage.tsx new file mode 100644 index 000000000..8466c11c0 --- /dev/null +++ b/src/configuration/ConfigurationPage.tsx @@ -0,0 +1,110 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import { IconProps } from "@material-ui/core/Icon"; +import { User } from "../auth/types/User"; +import Container from "../components/Container"; +import PageHeader from "../components/PageHeader"; +import i18n from "../i18n"; +import { PermissionEnum } from "../types/globalTypes"; + +export interface MenuItem { + description: string; + icon: React.ReactElement; + permission: PermissionEnum; + title: string; + url?: string; +} + +const styles = (theme: Theme) => + createStyles({ + card: { + "&:hover": { + boxShadow: "0px 5px 15px rgba(0, 0, 0, 0.15);" + }, + cursor: "pointer", + marginBottom: theme.spacing.unit * 3, + transition: theme.transitions.duration.standard + "ms" + }, + cardContent: { + // Overrides Material-UI default theme + "&:last-child": { + paddingBottom: 16 + }, + display: "grid", + gridColumnGap: theme.spacing.unit * 4 + "px", + gridTemplateColumns: "48px 1fr" + }, + cardDisabled: { + "& $icon, & $sectionTitle, & $sectionDescription": { + color: theme.palette.text.disabled + }, + marginBottom: theme.spacing.unit * 3 + }, + icon: { + color: theme.palette.primary.main, + fontSize: 48 + }, + root: { + [theme.breakpoints.down("md")]: { + gridTemplateColumns: "1fr" + }, + display: "grid", + gridColumnGap: theme.spacing.unit * 4 + "px", + gridTemplateColumns: "1fr 1fr" + }, + sectionDescription: {}, + sectionTitle: { + fontSize: 20, + fontWeight: 600 as 600 + } + }); + +export interface ConfigurationPageProps extends WithStyles { + menu: MenuItem[]; + user: User; + onSectionClick: (sectionName: string) => void; +} + +export const ConfigurationPage = withStyles(styles, { + name: "ConfigurationPage" +})(({ classes, menu, user, onSectionClick }: ConfigurationPageProps) => ( + + +
+ {menu + .filter(menuItem => + user.permissions.map(perm => perm.code).includes(menuItem.permission) + ) + .map((menuItem, menuItemIndex) => ( + onSectionClick(menuItem.url)} + key={menuItemIndex} + > + +
{menuItem.icon}
+
+ + {menuItem.title} + + + {menuItem.description} + +
+
+
+ ))} +
+
+)); +ConfigurationPage.displayName = "ConfigurationPage"; +export default ConfigurationPage; diff --git a/src/configuration/index.tsx b/src/configuration/index.tsx new file mode 100644 index 000000000..78a406ee2 --- /dev/null +++ b/src/configuration/index.tsx @@ -0,0 +1,94 @@ +import * as React from "react"; + +import useNavigator from "@saleor/hooks/useNavigator"; +import useUser from "@saleor/hooks/useUser"; +import { WindowTitle } from "../components/WindowTitle"; +import i18n from "../i18n"; +import Navigation from "../icons/Navigation"; +import Pages from "../icons/Pages"; +import ProductTypes from "../icons/ProductTypes"; +import ShippingMethods from "../icons/ShippingMethods"; +import SiteSettings from "../icons/SiteSettings"; +import StaffMembers from "../icons/StaffMembers"; +import Taxes from "../icons/Taxes"; +import { maybe } from "../misc"; +import { menuListUrl } from "../navigation/urls"; +import { pageListUrl } from "../pages/urls"; +import { productTypeListUrl } from "../productTypes/urls"; +import { shippingZonesListUrl } from "../shipping/urls"; +import { siteSettingsUrl } from "../siteSettings/urls"; +import { staffListUrl } from "../staff/urls"; +import { taxSection } from "../taxes/urls"; +import { PermissionEnum } from "../types/globalTypes"; +import ConfigurationPage, { MenuItem } from "./ConfigurationPage"; + +export const configurationMenu: MenuItem[] = [ + { + description: i18n.t("Define types of products you sell"), + icon: , + permission: PermissionEnum.MANAGE_PRODUCTS, + title: i18n.t("Product Types"), + url: productTypeListUrl() + }, + { + description: i18n.t("Manage your employees and their permissions"), + icon: , + permission: PermissionEnum.MANAGE_STAFF, + title: i18n.t("Staff Members"), + url: staffListUrl() + }, + { + description: i18n.t("Manage how you ship out orders."), + icon: , + permission: PermissionEnum.MANAGE_SHIPPING, + title: i18n.t("Shipping Methods"), + url: shippingZonesListUrl() + }, + { + description: i18n.t("Manage how your store charges tax"), + icon: , + permission: PermissionEnum.MANAGE_PRODUCTS, + title: i18n.t("Taxes"), + url: taxSection + }, + { + description: i18n.t("Define how users can navigate through your store"), + icon: , + permission: PermissionEnum.MANAGE_MENUS, + title: i18n.t("Navigation"), + url: menuListUrl() + }, + { + description: i18n.t("View and update your site settings"), + icon: , + permission: PermissionEnum.MANAGE_SETTINGS, + title: i18n.t("Site Settings"), + url: siteSettingsUrl() + }, + { + description: i18n.t("Manage and add additional pages"), + icon: , + permission: PermissionEnum.MANAGE_PAGES, + title: i18n.t("Pages"), + url: pageListUrl() + } +]; + +export const configurationMenuUrl = "/configuration/"; + +export const ConfigurationSection: React.StatelessComponent = () => { + const navigate = useNavigator(); + const user = useUser(); + + return ( + <> + + user.user)} + onSectionClick={navigate} + /> + + ); +}; +export default ConfigurationSection; diff --git a/src/containers/BaseSearch.tsx b/src/containers/BaseSearch.tsx new file mode 100644 index 000000000..920d542d7 --- /dev/null +++ b/src/containers/BaseSearch.tsx @@ -0,0 +1,66 @@ +import { DocumentNode } from "graphql"; +import * as React from "react"; + +import Debounce from "../components/Debounce"; +import { TypedQuery, TypedQueryResult } from "../queries"; + +export interface SearchQueryVariables { + after?: string; + first: number; + query: string; +} + +function BaseSearch( + query: DocumentNode +) { + const Query = TypedQuery(query); + interface BaseSearchProps { + children: (props: { + search: (query: string) => void; + result: TypedQueryResult; + }) => React.ReactElement; + variables: TQueryVariables; + } + interface BaseSearchState { + query: string; + } + + class BaseSearchComponent extends React.Component< + BaseSearchProps, + BaseSearchState + > { + state: BaseSearchState = { + query: this.props.variables.query + }; + + search = (query: string) => { + if (query === undefined) { + this.setState({ query: "" }); + } else { + this.setState({ query }); + } + }; + + render() { + const { children, variables } = this.props; + + return ( + + {search => ( + + {result => children({ search, result })} + + )} + + ); + } + } + return BaseSearchComponent; +} +export default BaseSearch; diff --git a/src/containers/SearchCategories/index.tsx b/src/containers/SearchCategories/index.tsx new file mode 100644 index 000000000..0179c7e58 --- /dev/null +++ b/src/containers/SearchCategories/index.tsx @@ -0,0 +1,24 @@ +import gql from "graphql-tag"; + +import BaseSearch from "../BaseSearch"; +import { + SearchCategories, + SearchCategoriesVariables +} from "./types/SearchCategories"; + +export const searchCategories = gql` + query SearchCategories($after: String, $first: Int!, $query: String!) { + categories(after: $after, first: $first, query: $query) { + edges { + node { + id + name + } + } + } + } +`; + +export default BaseSearch( + searchCategories +); diff --git a/src/containers/SearchCategories/types/SearchCategories.ts b/src/containers/SearchCategories/types/SearchCategories.ts new file mode 100644 index 000000000..0bd976f19 --- /dev/null +++ b/src/containers/SearchCategories/types/SearchCategories.ts @@ -0,0 +1,33 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: SearchCategories +// ==================================================== + +export interface SearchCategories_categories_edges_node { + __typename: "Category"; + id: string; + name: string; +} + +export interface SearchCategories_categories_edges { + __typename: "CategoryCountableEdge"; + node: SearchCategories_categories_edges_node; +} + +export interface SearchCategories_categories { + __typename: "CategoryCountableConnection"; + edges: SearchCategories_categories_edges[]; +} + +export interface SearchCategories { + categories: SearchCategories_categories | null; +} + +export interface SearchCategoriesVariables { + after?: string | null; + first: number; + query: string; +} diff --git a/src/containers/SearchCollections/index.tsx b/src/containers/SearchCollections/index.tsx new file mode 100644 index 000000000..54f2177f9 --- /dev/null +++ b/src/containers/SearchCollections/index.tsx @@ -0,0 +1,24 @@ +import gql from "graphql-tag"; + +import BaseSearch from "../BaseSearch"; +import { + SearchCollections, + SearchCollectionsVariables +} from "./types/SearchCollections"; + +export const searchCollections = gql` + query SearchCollections($after: String, $first: Int!, $query: String!) { + collections(after: $after, first: $first, query: $query) { + edges { + node { + id + name + } + } + } + } +`; + +export default BaseSearch( + searchCollections +); diff --git a/src/containers/SearchCollections/types/SearchCollections.ts b/src/containers/SearchCollections/types/SearchCollections.ts new file mode 100644 index 000000000..ce9c70cca --- /dev/null +++ b/src/containers/SearchCollections/types/SearchCollections.ts @@ -0,0 +1,33 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: SearchCollections +// ==================================================== + +export interface SearchCollections_collections_edges_node { + __typename: "Collection"; + id: string; + name: string; +} + +export interface SearchCollections_collections_edges { + __typename: "CollectionCountableEdge"; + node: SearchCollections_collections_edges_node; +} + +export interface SearchCollections_collections { + __typename: "CollectionCountableConnection"; + edges: SearchCollections_collections_edges[]; +} + +export interface SearchCollections { + collections: SearchCollections_collections | null; +} + +export interface SearchCollectionsVariables { + after?: string | null; + first: number; + query: string; +} diff --git a/src/containers/SearchCustomers/index.ts b/src/containers/SearchCustomers/index.ts new file mode 100644 index 000000000..2ed50f4a2 --- /dev/null +++ b/src/containers/SearchCustomers/index.ts @@ -0,0 +1,24 @@ +import gql from "graphql-tag"; + +import BaseSearch from "../BaseSearch"; +import { + SearchCustomers, + SearchCustomersVariables +} from "./types/SearchCustomers"; + +export const searchCustomers = gql` + query SearchCustomers($after: String, $first: Int!, $query: String!) { + customers(after: $after, first: $first, query: $query) { + edges { + node { + id + email + } + } + } + } +`; + +export default BaseSearch( + searchCustomers +); diff --git a/src/containers/SearchCustomers/types/SearchCustomers.ts b/src/containers/SearchCustomers/types/SearchCustomers.ts new file mode 100644 index 000000000..ad51c10ab --- /dev/null +++ b/src/containers/SearchCustomers/types/SearchCustomers.ts @@ -0,0 +1,33 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: SearchCustomers +// ==================================================== + +export interface SearchCustomers_customers_edges_node { + __typename: "User"; + id: string; + email: string; +} + +export interface SearchCustomers_customers_edges { + __typename: "UserCountableEdge"; + node: SearchCustomers_customers_edges_node; +} + +export interface SearchCustomers_customers { + __typename: "UserCountableConnection"; + edges: SearchCustomers_customers_edges[]; +} + +export interface SearchCustomers { + customers: SearchCustomers_customers | null; +} + +export interface SearchCustomersVariables { + after?: string | null; + first: number; + query: string; +} diff --git a/src/containers/SearchPages/index.tsx b/src/containers/SearchPages/index.tsx new file mode 100644 index 000000000..70bf13053 --- /dev/null +++ b/src/containers/SearchPages/index.tsx @@ -0,0 +1,19 @@ +import gql from "graphql-tag"; + +import BaseSearch from "../BaseSearch"; +import { SearchPages, SearchPagesVariables } from "./types/SearchPages"; + +export const searchPages = gql` + query SearchPages($after: String, $first: Int!, $query: String!) { + pages(after: $after, first: $first, query: $query) { + edges { + node { + id + title + } + } + } + } +`; + +export default BaseSearch(searchPages); diff --git a/src/containers/SearchPages/types/SearchPages.ts b/src/containers/SearchPages/types/SearchPages.ts new file mode 100644 index 000000000..7357bb965 --- /dev/null +++ b/src/containers/SearchPages/types/SearchPages.ts @@ -0,0 +1,33 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: SearchPages +// ==================================================== + +export interface SearchPages_pages_edges_node { + __typename: "Page"; + id: string; + title: string; +} + +export interface SearchPages_pages_edges { + __typename: "PageCountableEdge"; + node: SearchPages_pages_edges_node; +} + +export interface SearchPages_pages { + __typename: "PageCountableConnection"; + edges: SearchPages_pages_edges[]; +} + +export interface SearchPages { + pages: SearchPages_pages | null; +} + +export interface SearchPagesVariables { + after?: string | null; + first: number; + query: string; +} diff --git a/src/containers/SearchProducts/index.tsx b/src/containers/SearchProducts/index.tsx new file mode 100644 index 000000000..c5029eff3 --- /dev/null +++ b/src/containers/SearchProducts/index.tsx @@ -0,0 +1,27 @@ +import gql from "graphql-tag"; + +import BaseSearch from "../BaseSearch"; +import { + SearchProducts, + SearchProductsVariables +} from "./types/SearchProducts"; + +export const searchProducts = gql` + query SearchProducts($after: String, $first: Int!, $query: String!) { + products(after: $after, first: $first, query: $query) { + edges { + node { + id + name + thumbnail { + url + } + } + } + } + } +`; + +export default BaseSearch( + searchProducts +); diff --git a/src/containers/SearchProducts/types/SearchProducts.ts b/src/containers/SearchProducts/types/SearchProducts.ts new file mode 100644 index 000000000..fdafa6e10 --- /dev/null +++ b/src/containers/SearchProducts/types/SearchProducts.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: SearchProducts +// ==================================================== + +export interface SearchProducts_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface SearchProducts_products_edges_node { + __typename: "Product"; + id: string; + name: string; + thumbnail: SearchProducts_products_edges_node_thumbnail | null; +} + +export interface SearchProducts_products_edges { + __typename: "ProductCountableEdge"; + node: SearchProducts_products_edges_node; +} + +export interface SearchProducts_products { + __typename: "ProductCountableConnection"; + edges: SearchProducts_products_edges[]; +} + +export interface SearchProducts { + products: SearchProducts_products | null; +} + +export interface SearchProductsVariables { + after?: string | null; + first: number; + query: string; +} diff --git a/src/customers/components/CustomerAddress/CustomerAddress.tsx b/src/customers/components/CustomerAddress/CustomerAddress.tsx new file mode 100644 index 000000000..a54e15575 --- /dev/null +++ b/src/customers/components/CustomerAddress/CustomerAddress.tsx @@ -0,0 +1,115 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardActions from "@material-ui/core/CardActions"; +import CardContent from "@material-ui/core/CardContent"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import AddressFormatter from "@saleor/components/AddressFormatter"; +import CardMenu from "@saleor/components/CardMenu"; +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { AddressTypeEnum } from "../../../types/globalTypes"; +import { CustomerAddresses_user_addresses } from "../../types/CustomerAddresses"; + +export interface CustomerAddressProps { + address: CustomerAddresses_user_addresses; + disabled: boolean; + isDefaultBillingAddress: boolean; + isDefaultShippingAddress: boolean; + addressNumber: number; + onEdit: () => void; + onRemove: () => void; + onSetAsDefault: (type: AddressTypeEnum) => void; +} + +const styles = createStyles({ + actions: { + flexDirection: "row" + }, + actionsContainer: { + display: "flex", + flexDirection: "column", + height: "100%", + justifyContent: "flex-end" + }, + card: { + display: "flex", + flexDirection: "column" + } +}); +const CustomerAddress = withStyles(styles, { name: "CustomerAddress" })( + ({ + address, + addressNumber, + classes, + disabled, + isDefaultBillingAddress, + isDefaultShippingAddress, + onEdit, + onRemove, + onSetAsDefault + }: CustomerAddressProps & WithStyles) => ( + + + {i18n.t("Address {{ addressNumber }}", { + addressNumber + })} + + {isDefaultBillingAddress && isDefaultShippingAddress + ? i18n.t("Default Address") + : isDefaultShippingAddress + ? i18n.t("Default Shipping Address") + : isDefaultBillingAddress + ? i18n.t("Default Billing Address") + : null} + + + ) : ( + + ) + } + height="const" + toolbar={ + onSetAsDefault(AddressTypeEnum.SHIPPING) + }, + { + label: i18n.t("Set as default billing address", { + context: "button" + }), + onSelect: () => onSetAsDefault(AddressTypeEnum.BILLING) + } + ]} + /> + } + /> + + + +
+ + + + +
+
+ ) +); +CustomerAddress.displayName = "CustomerAddress"; +export default CustomerAddress; diff --git a/src/customers/components/CustomerAddress/index.ts b/src/customers/components/CustomerAddress/index.ts new file mode 100644 index 000000000..937bf0048 --- /dev/null +++ b/src/customers/components/CustomerAddress/index.ts @@ -0,0 +1,2 @@ +export { default } from './CustomerAddress'; +export * from './CustomerAddress'; \ No newline at end of file diff --git a/src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx b/src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx new file mode 100644 index 000000000..b7dca9f12 --- /dev/null +++ b/src/customers/components/CustomerAddressDialog/CustomerAddressDialog.tsx @@ -0,0 +1,116 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import AddressEdit from "@saleor/components/AddressEdit"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { UserError } from "../../../types"; +import { AddressTypeInput } from "../../types"; +import { CustomerAddresses_user_addresses } from "../../types/CustomerAddresses"; + +export interface CustomerAddressDialogProps { + address: CustomerAddresses_user_addresses; + confirmButtonState: ConfirmButtonTransitionState; + countries: Array<{ + code: string; + label: string; + }>; + errors: UserError[]; + open: boolean; + variant: "create" | "edit"; + onClose: () => void; + onConfirm: (data: AddressTypeInput) => void; +} + +const styles = createStyles({ + overflow: { + overflowY: "visible" + } +}); + +const CustomerAddressDialog = withStyles(styles, {})( + ({ + address, + classes, + confirmButtonState, + countries, + errors, + open, + variant, + onClose, + onConfirm + }: CustomerAddressDialogProps & WithStyles) => { + const initialForm: AddressTypeInput = { + city: maybe(() => address.city, ""), + cityArea: maybe(() => address.cityArea, ""), + companyName: maybe(() => address.companyName, ""), + country: { + label: maybe(() => address.country.country, ""), + value: maybe(() => address.country.code, "") + }, + countryArea: maybe(() => address.countryArea, ""), + firstName: maybe(() => address.firstName, ""), + lastName: maybe(() => address.lastName, ""), + phone: maybe(() => address.phone, ""), + postalCode: maybe(() => address.postalCode, ""), + streetAddress1: maybe(() => address.streetAddress1, ""), + streetAddress2: maybe(() => address.streetAddress2, "") + }; + return ( + +
+ {({ change, data, errors, submit }) => ( + <> + + {variant === "create" + ? i18n.t("Add Address") + : i18n.t("Edit Address")} + + + + + + + + {i18n.t("Save Address", { context: "button" })} + + + + + )} +
+
+ ); + } +); +CustomerAddressDialog.displayName = "CustomerAddressDialog"; +export default CustomerAddressDialog; diff --git a/src/customers/components/CustomerAddressDialog/index.ts b/src/customers/components/CustomerAddressDialog/index.ts new file mode 100644 index 000000000..a5f6e9973 --- /dev/null +++ b/src/customers/components/CustomerAddressDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from './CustomerAddressDialog'; +export * from './CustomerAddressDialog'; \ No newline at end of file diff --git a/src/customers/components/CustomerAddressListPage/CustomerAddressListPage.tsx b/src/customers/components/CustomerAddressListPage/CustomerAddressListPage.tsx new file mode 100644 index 000000000..e6df42c58 --- /dev/null +++ b/src/customers/components/CustomerAddressListPage/CustomerAddressListPage.tsx @@ -0,0 +1,144 @@ +import Button from "@material-ui/core/Button"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { AddressTypeEnum } from "../../../types/globalTypes"; +import { CustomerAddresses_user } from "../../types/CustomerAddresses"; +import CustomerAddress from "../CustomerAddress/CustomerAddress"; + +export interface CustomerAddressListPageProps { + customer: CustomerAddresses_user; + disabled: boolean; + onAdd: () => void; + onBack: () => void; + onEdit: (id: string) => void; + onRemove: (id: string) => void; + onSetAsDefault: (id: string, type: AddressTypeEnum) => void; +} + +const styles = (theme: Theme) => + createStyles({ + addButton: { + marginTop: theme.spacing.unit * 2 + }, + description: { + marginTop: theme.spacing.unit + }, + empty: { + margin: `${theme.spacing.unit * 13}px auto 0`, + textAlign: "center", + width: 600 + }, + root: { + columnGap: theme.spacing.unit * 3 + "px", + display: "grid", + gridTemplateColumns: "repeat(3, 1fr)", + rowGap: theme.spacing.unit * 3 + "px" + } + }); + +const CustomerAddressListPage = withStyles(styles, { + name: "CustomerAddressListPage" +})( + ({ + classes, + customer, + disabled, + onAdd, + onBack, + onEdit, + onRemove, + onSetAsDefault + }: CustomerAddressListPageProps & WithStyles) => { + const isEmpty = maybe(() => customer.addresses.length) === 0; + return ( + + + {i18n.t("Customer Info", { + context: "navigation" + })} + + {!isEmpty && ( + + i18n.t("{{ firstName }} {{ lastName }} Address Book", { + context: "customer address book", + firstName: customer.firstName, + lastName: customer.lastName + }) + )} + > + + + )} + {isEmpty ? ( +
+ + {i18n.t("There is no address to show for this customer")} + + + {i18n.t( + "This customer doesn’t have any adresses added to his address book. You can add address using the button below." + )} + + +
+ ) : ( +
+ {renderCollection( + maybe(() => customer.addresses), + (address, addressNumber) => ( + customer.defaultBillingAddress.id) === + maybe(() => address.id) + } + isDefaultShippingAddress={ + maybe(() => customer.defaultShippingAddress.id) === + maybe(() => address.id) + } + onEdit={() => onEdit(address.id)} + onRemove={() => onRemove(address.id)} + onSetAsDefault={type => onSetAsDefault(address.id, type)} + key={maybe(() => address.id, "skeleton")} + /> + ) + )} +
+ )} +
+ ); + } +); +CustomerAddressListPage.displayName = "CustomerAddressListPage"; +export default CustomerAddressListPage; diff --git a/src/customers/components/CustomerAddressListPage/index.ts b/src/customers/components/CustomerAddressListPage/index.ts new file mode 100644 index 000000000..a2fe444c5 --- /dev/null +++ b/src/customers/components/CustomerAddressListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from './CustomerAddressListPage'; +export * from './CustomerAddressListPage'; \ No newline at end of file diff --git a/src/customers/components/CustomerAddresses/CustomerAddresses.tsx b/src/customers/components/CustomerAddresses/CustomerAddresses.tsx new file mode 100644 index 000000000..ddc0ef85f --- /dev/null +++ b/src/customers/components/CustomerAddresses/CustomerAddresses.tsx @@ -0,0 +1,102 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import AddressFormatter from "@saleor/components/AddressFormatter"; +import CardTitle from "@saleor/components/CardTitle"; +import { Hr } from "@saleor/components/Hr"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { CustomerDetails_user } from "../../types/CustomerDetails"; + +const styles = (theme: Theme) => + createStyles({ + label: { + fontWeight: 600, + marginBottom: theme.spacing.unit + } + }); + +export interface CustomerAddressesProps extends WithStyles { + customer: CustomerDetails_user; + disabled: boolean; + onAddressManageClick: () => void; +} + +const CustomerAddresses = withStyles(styles, { name: "CustomerAddresses" })( + ({ + classes, + customer, + disabled, + onAddressManageClick + }: CustomerAddressesProps) => ( + + + {i18n.t("Manage", { context: "button" })} + + } + /> + {maybe(() => customer.defaultBillingAddress.id) !== + maybe(() => customer.defaultShippingAddress.id) ? ( + <> + {maybe(() => customer.defaultBillingAddress) !== null && ( + + + {i18n.t("Billing address")} + + customer.defaultBillingAddress)} + /> + + )} + {maybe( + () => + customer.defaultBillingAddress && customer.defaultShippingAddress + ) &&
} + {maybe(() => customer.defaultShippingAddress) && ( + + + {i18n.t("Shipping address")} + + customer.defaultShippingAddress)} + /> + + )} + + ) : maybe(() => customer.defaultBillingAddress) === null && + maybe(() => customer.defaultShippingAddress) === null ? ( + + + {i18n.t("This customer has no addresses yet")} + + + ) : ( + + {i18n.t("Address")} + customer.defaultBillingAddress)} + /> + + )} +
+ ) +); +CustomerAddresses.displayName = "CustomerAddresses"; +export default CustomerAddresses; diff --git a/src/customers/components/CustomerAddresses/index.ts b/src/customers/components/CustomerAddresses/index.ts new file mode 100644 index 000000000..f26348a2c --- /dev/null +++ b/src/customers/components/CustomerAddresses/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CustomerAddresses"; +export * from "./CustomerAddresses"; diff --git a/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.tsx b/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.tsx new file mode 100644 index 000000000..c5ce829bd --- /dev/null +++ b/src/customers/components/CustomerCreateAddress/CustomerCreateAddress.tsx @@ -0,0 +1,62 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { createStyles, WithStyles, withStyles } from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import AddressEdit from "@saleor/components/AddressEdit"; +import CardTitle from "@saleor/components/CardTitle"; +import { FormSpacer } from "@saleor/components/FormSpacer"; +import i18n from "../../../i18n"; +import { FormErrors } from "../../../types"; +import { AddressTypeInput } from "../../types"; +import { CustomerCreateData_shop_countries } from "../../types/CustomerCreateData"; + +const styles = createStyles({ + overflow: { + overflow: "visible" + } +}); + +export interface CustomerCreateAddressProps extends WithStyles { + countries: CustomerCreateData_shop_countries[]; + data: AddressTypeInput; + disabled: boolean; + errors: FormErrors; + onChange(event: React.ChangeEvent); +} + +const CustomerCreateAddress = withStyles(styles, { + name: "CustomerCreateAddress" +})( + ({ + classes, + countries, + data, + disabled, + errors, + onChange + }: CustomerCreateAddressProps) => ( + + + + + {i18n.t("The primary address of this customer.")} + + + ({ + code: country.code, + label: country.country + }))} + data={data} + disabled={disabled} + errors={errors} + onChange={onChange} + /> + + + ) +); +CustomerCreateAddress.displayName = "CustomerCreateAddress"; +export default CustomerCreateAddress; diff --git a/src/customers/components/CustomerCreateAddress/index.ts b/src/customers/components/CustomerCreateAddress/index.ts new file mode 100644 index 000000000..32bb82ede --- /dev/null +++ b/src/customers/components/CustomerCreateAddress/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CustomerCreateAddress"; +export * from "./CustomerCreateAddress"; diff --git a/src/customers/components/CustomerCreateDetails/CustomerCreateDetails.tsx b/src/customers/components/CustomerCreateDetails/CustomerCreateDetails.tsx new file mode 100644 index 000000000..e57113dc5 --- /dev/null +++ b/src/customers/components/CustomerCreateDetails/CustomerCreateDetails.tsx @@ -0,0 +1,87 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import i18n from "../../../i18n"; +import { FormErrors } from "../../../types"; +import { CustomerCreatePageFormData } from "../CustomerCreatePage"; + +const styles = (theme: Theme) => + createStyles({ + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridRowGap: theme.spacing.unit * 3 + "px", + gridTemplateColumns: "1fr 1fr" + } + }); + +export interface CustomerCreateDetailsProps extends WithStyles { + data: CustomerCreatePageFormData; + disabled: boolean; + errors: FormErrors<"customerFirstName" | "customerLastName" | "email">; + onChange: (event: React.ChangeEvent) => void; +} + +const CustomerCreateDetails = withStyles(styles, { + name: "CustomerCreateDetails" +})( + ({ + classes, + data, + disabled, + errors, + onChange + }: CustomerCreateDetailsProps) => ( + + + +
+ + + +
+
+
+ ) +); +CustomerCreateDetails.displayName = "CustomerCreateDetails"; +export default CustomerCreateDetails; diff --git a/src/customers/components/CustomerCreateDetails/index.ts b/src/customers/components/CustomerCreateDetails/index.ts new file mode 100644 index 000000000..b7353f089 --- /dev/null +++ b/src/customers/components/CustomerCreateDetails/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CustomerCreateDetails"; +export * from "./CustomerCreateDetails"; diff --git a/src/customers/components/CustomerCreateNote/CustomerCreateNote.tsx b/src/customers/components/CustomerCreateNote/CustomerCreateNote.tsx new file mode 100644 index 000000000..f90e27cb6 --- /dev/null +++ b/src/customers/components/CustomerCreateNote/CustomerCreateNote.tsx @@ -0,0 +1,50 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import { FormSpacer } from "@saleor/components/FormSpacer"; +import i18n from "../../../i18n"; + +export interface CustomerCreateNoteProps { + data: { + note: string; + }; + disabled: boolean; + errors: Partial<{ + note: string; + }>; + onChange: (event: React.ChangeEvent) => void; +} + +const CustomerCreateNote: React.StatelessComponent = ({ + data, + disabled, + errors, + onChange +}) => ( + + + + + {i18n.t("Enter any extra infotmation regarding this customer.")} + + + + + +); +CustomerCreateNote.displayName = "CustomerCreateNote"; +export default CustomerCreateNote; diff --git a/src/customers/components/CustomerCreateNote/index.ts b/src/customers/components/CustomerCreateNote/index.ts new file mode 100644 index 000000000..71a3ac5dd --- /dev/null +++ b/src/customers/components/CustomerCreateNote/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CustomerCreateNote"; +export * from "./CustomerCreateNote"; diff --git a/src/customers/components/CustomerCreatePage/CustomerCreatePage.tsx b/src/customers/components/CustomerCreatePage/CustomerCreatePage.tsx new file mode 100644 index 000000000..54e316002 --- /dev/null +++ b/src/customers/components/CustomerCreatePage/CustomerCreatePage.tsx @@ -0,0 +1,105 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import { CardSpacer } from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { UserError } from "../../../types"; +import { AddressTypeInput } from "../../types"; +import { CustomerCreateData_shop_countries } from "../../types/CustomerCreateData"; +import CustomerCreateAddress from "../CustomerCreateAddress/CustomerCreateAddress"; +import CustomerCreateDetails from "../CustomerCreateDetails"; +import CustomerCreateNote from "../CustomerCreateNote/CustomerCreateNote"; + +export interface CustomerCreatePageFormData extends AddressTypeInput { + customerFirstName: string; + customerLastName: string; + email: string; + note: string; +} + +const initialForm: CustomerCreatePageFormData = { + city: "", + cityArea: "", + companyName: "", + country: { + label: "", + value: "" + }, + countryArea: "", + customerFirstName: "", + customerLastName: "", + email: "", + firstName: "", + lastName: "", + note: "", + phone: "", + postalCode: "", + streetAddress1: "", + streetAddress2: "" +}; + +export interface CustomerCreatePageProps { + countries: CustomerCreateData_shop_countries[]; + disabled: boolean; + errors: UserError[]; + saveButtonBar: ConfirmButtonTransitionState; + onBack: () => void; + onSubmit: (data: CustomerCreatePageFormData) => void; +} + +const CustomerCreatePage: React.StatelessComponent = ({ + countries, + disabled, + errors, + saveButtonBar, + onBack, + onSubmit +}: CustomerCreatePageProps) => ( +
+ {({ change, data, errors: formErrors, hasChanged, submit }) => ( + + {i18n.t("Customers")} + + +
+ + + + + +
+
+ +
+ )} +
+); +CustomerCreatePage.displayName = "CustomerCreatePage"; +export default CustomerCreatePage; diff --git a/src/customers/components/CustomerCreatePage/index.ts b/src/customers/components/CustomerCreatePage/index.ts new file mode 100644 index 000000000..c30fee317 --- /dev/null +++ b/src/customers/components/CustomerCreatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CustomerCreatePage"; +export * from "./CustomerCreatePage"; diff --git a/src/customers/components/CustomerDetails/CustomerDetails.tsx b/src/customers/components/CustomerDetails/CustomerDetails.tsx new file mode 100644 index 000000000..d6f7693e0 --- /dev/null +++ b/src/customers/components/CustomerDetails/CustomerDetails.tsx @@ -0,0 +1,145 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import * as moment from "moment-timezone"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; +import { FormSpacer } from "@saleor/components/FormSpacer"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { CustomerDetails_user } from "../../types/CustomerDetails"; + +const styles = (theme: Theme) => + createStyles({ + cardTitle: { + height: 64 + }, + root: { + display: "grid" as "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridRowGap: theme.spacing.unit * 3 + "px", + gridTemplateColumns: "1fr 1fr" + } + }); + +export interface CustomerDetailsProps extends WithStyles { + customer: CustomerDetails_user; + data: { + firstName: string; + lastName: string; + email: string; + isActive: boolean; + note: string; + }; + disabled: boolean; + errors: { + firstName?: string; + lastName?: string; + email?: string; + note?: string; + }; + onChange: (event: React.ChangeEvent) => void; +} + +const CustomerDetails = withStyles(styles, { name: "CustomerDetails" })( + ({ + classes, + customer, + data, + disabled, + errors, + onChange + }: CustomerDetailsProps) => ( + + + {i18n.t("General Information")} + {customer && customer.dateJoined ? ( + + {i18n.t("Customer since: {{ month }} {{ year }}", { + month: moment(customer.dateJoined).format("MMM"), + year: moment(customer.dateJoined).format("YYYY") + })} + + ) : ( + + )} + + } + /> + + + +
+ + +
+ + + + +
+
+ ) +); +CustomerDetails.displayName = "CustomerDetails"; +export default CustomerDetails; diff --git a/src/customers/components/CustomerDetails/index.ts b/src/customers/components/CustomerDetails/index.ts new file mode 100644 index 000000000..0c9569a11 --- /dev/null +++ b/src/customers/components/CustomerDetails/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CustomerDetails"; +export * from "./CustomerDetails"; diff --git a/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx b/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx new file mode 100644 index 000000000..041c0fe50 --- /dev/null +++ b/src/customers/components/CustomerDetailsPage/CustomerDetailsPage.tsx @@ -0,0 +1,109 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import { CardSpacer } from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { getUserName, maybe } from "../../../misc"; +import { UserError } from "../../../types"; +import { CustomerDetails_user } from "../../types/CustomerDetails"; +import CustomerAddresses from "../CustomerAddresses/CustomerAddresses"; +import CustomerDetails from "../CustomerDetails/CustomerDetails"; +import CustomerOrders from "../CustomerOrders/CustomerOrders"; +import CustomerStats from "../CustomerStats/CustomerStats"; + +export interface CustomerDetailsPageFormData { + firstName: string; + lastName: string; + email: string; + isActive: boolean; + note: string; +} + +export interface CustomerDetailsPageProps { + customer: CustomerDetails_user; + disabled: boolean; + errors: UserError[]; + saveButtonBar: ConfirmButtonTransitionState; + onBack: () => void; + onSubmit: (data: CustomerDetailsPageFormData) => void; + onViewAllOrdersClick: () => void; + onRowClick: (id: string) => void; + onAddressManageClick: () => void; + onDelete: () => void; +} + +const CustomerDetailsPage: React.StatelessComponent< + CustomerDetailsPageProps +> = ({ + customer, + disabled, + errors, + saveButtonBar, + onBack, + onSubmit, + onViewAllOrdersClick, + onRowClick, + onAddressManageClick, + onDelete +}: CustomerDetailsPageProps) => ( +
customer.email), + firstName: maybe(() => customer.firstName), + isActive: maybe(() => customer.isActive, false), + lastName: maybe(() => customer.lastName), + note: maybe(() => customer.note) + }} + onSubmit={onSubmit} + confirmLeave + > + {({ change, data, errors: formErrors, hasChanged, submit }) => ( + + {i18n.t("Customers")} + + +
+ + + customer.orders.edges.map(edge => edge.node))} + onViewAllOrdersClick={onViewAllOrdersClick} + onRowClick={onRowClick} + /> +
+
+ + + +
+
+ +
+ )} +
+); +CustomerDetailsPage.displayName = "CustomerDetailsPage"; +export default CustomerDetailsPage; diff --git a/src/customers/components/CustomerDetailsPage/index.ts b/src/customers/components/CustomerDetailsPage/index.ts new file mode 100644 index 000000000..7625dc872 --- /dev/null +++ b/src/customers/components/CustomerDetailsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CustomerDetailsPage"; +export * from "./CustomerDetailsPage"; diff --git a/src/customers/components/CustomerList/CustomerList.tsx b/src/customers/components/CustomerList/CustomerList.tsx new file mode 100644 index 000000000..2dfb35021 --- /dev/null +++ b/src/customers/components/CustomerList/CustomerList.tsx @@ -0,0 +1,147 @@ +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import Checkbox from "@saleor/components/Checkbox"; +import Skeleton from "@saleor/components/Skeleton"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { getUserName, maybe, renderCollection } from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { ListCustomers_customers_edges_node } from "../../types/ListCustomers"; + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colEmail: {}, + colName: {}, + colOrders: { + width: 200 + } + }, + colEmail: {}, + colName: {}, + colOrders: { + textAlign: "center" + }, + tableRow: { + cursor: "pointer" + } + }); + +export interface CustomerListProps + extends ListProps, + ListActions, + WithStyles { + customers: ListCustomers_customers_edges_node[]; +} + +const CustomerList = withStyles(styles, { name: "CustomerList" })( + ({ + classes, + disabled, + customers, + pageInfo, + onNextPage, + onPreviousPage, + onRowClick, + toolbar, + toggle, + toggleAll, + selected, + isChecked + }: CustomerListProps) => ( + + + + + {i18n.t("Customer Name", { context: "table header" })} + + + {i18n.t("Customer e-mail", { context: "table header" })} + + + {i18n.t("Orders", { context: "table header" })} + + + + + + + + + {renderCollection( + customers, + customer => { + const isSelected = customer ? isChecked(customer.id) : false; + + return ( + + + toggle(customer.id)} + /> + + + {getUserName(customer)} + + + {maybe(() => customer.email, )} + + + {maybe( + () => customer.orders.totalCount, + + )} + + + ); + }, + () => ( + + + {i18n.t("No customers found")} + + + ) + )} + +
+
+ ) +); +CustomerList.displayName = "CustomerList"; +export default CustomerList; diff --git a/src/customers/components/CustomerList/index.ts b/src/customers/components/CustomerList/index.ts new file mode 100644 index 000000000..c5517efd0 --- /dev/null +++ b/src/customers/components/CustomerList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CustomerList"; +export * from "./CustomerList"; diff --git a/src/customers/components/CustomerListPage/CustomerListPage.tsx b/src/customers/components/CustomerListPage/CustomerListPage.tsx new file mode 100644 index 000000000..d240eec34 --- /dev/null +++ b/src/customers/components/CustomerListPage/CustomerListPage.tsx @@ -0,0 +1,44 @@ +import Button from "@material-ui/core/Button"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { ListActions, PageListProps } from "../../../types"; +import { ListCustomers_customers_edges_node } from "../../types/ListCustomers"; +import CustomerList from "../CustomerList/CustomerList"; + +export interface CustomerListPageProps extends PageListProps, ListActions { + customers: ListCustomers_customers_edges_node[]; +} + +const CustomerListPage: React.StatelessComponent = ({ + customers, + disabled, + onAdd, + ...customerListProps +}) => ( + + + + + + +); +CustomerListPage.displayName = "CustomerListPage"; +export default CustomerListPage; diff --git a/src/customers/components/CustomerListPage/index.ts b/src/customers/components/CustomerListPage/index.ts new file mode 100644 index 000000000..59481bef5 --- /dev/null +++ b/src/customers/components/CustomerListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CustomerListPage"; +export * from "./CustomerListPage"; diff --git a/src/customers/components/CustomerOrders/CustomerOrders.tsx b/src/customers/components/CustomerOrders/CustomerOrders.tsx new file mode 100644 index 000000000..25c22bbd1 --- /dev/null +++ b/src/customers/components/CustomerOrders/CustomerOrders.tsx @@ -0,0 +1,137 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import { DateTime } from "@saleor/components/Date"; +import Money from "@saleor/components/Money"; +import Skeleton from "@saleor/components/Skeleton"; +import StatusLabel from "@saleor/components/StatusLabel"; +import i18n from "../../../i18n"; +import { maybe, renderCollection, transformPaymentStatus } from "../../../misc"; +import { CustomerDetails_user_orders_edges_node } from "../../types/CustomerDetails"; + +const styles = createStyles({ + link: { + cursor: "pointer" + }, + textRight: { + textAlign: "right" + } +}); + +export interface CustomerOrdersProps extends WithStyles { + orders: CustomerDetails_user_orders_edges_node[]; + onViewAllOrdersClick: () => void; + onRowClick: (id: string) => void; +} + +const CustomerOrders = withStyles(styles, { name: "CustomerOrders" })( + ({ + classes, + orders, + onRowClick, + onViewAllOrdersClick + }: CustomerOrdersProps) => { + const orderList = orders + ? orders.map(order => ({ + ...order, + paymentStatus: transformPaymentStatus(order.paymentStatus) + })) + : undefined; + return ( + + + {i18n.t("View all orders")} + + } + /> + + + + + {i18n.t("No. of Order", { context: "table header" })} + + + {i18n.t("Date", { context: "table header" })} + + + {i18n.t("Status", { context: "table header" })} + + + {i18n.t("Total", { context: "table header" })} + + + + + {renderCollection( + orderList, + order => ( + onRowClick(order.id) : undefined} + key={order ? order.id : "skeleton"} + > + + {maybe(() => order.number) ? ( + "#" + order.number + ) : ( + + )} + + + {maybe(() => order.created) ? ( + + ) : ( + + )} + + + {maybe(() => order.paymentStatus.status) !== undefined ? ( + order.paymentStatus.status === null ? null : ( + + ) + ) : ( + + )} + + + {maybe(() => order.total.gross) ? ( + + ) : ( + + )} + + + ), + () => ( + + {i18n.t("No orders found")} + + ) + )} + +
+
+ ); + } +); +CustomerOrders.displayName = "CustomerOrders"; +export default CustomerOrders; diff --git a/src/customers/components/CustomerOrders/index.ts b/src/customers/components/CustomerOrders/index.ts new file mode 100644 index 000000000..8a3fbc533 --- /dev/null +++ b/src/customers/components/CustomerOrders/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CustomerOrders"; +export * from "./CustomerOrders"; diff --git a/src/customers/components/CustomerStats/CustomerStats.tsx b/src/customers/components/CustomerStats/CustomerStats.tsx new file mode 100644 index 000000000..58ca6d18f --- /dev/null +++ b/src/customers/components/CustomerStats/CustomerStats.tsx @@ -0,0 +1,79 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import { DateTime } from "@saleor/components/Date"; +import { Hr } from "@saleor/components/Hr"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { CustomerDetails_user } from "../../types/CustomerDetails"; + +const styles = (theme: Theme) => + createStyles({ + label: { + marginBottom: theme.spacing.unit + }, + value: { + fontSize: 24 + } + }); + +export interface CustomerStatsProps extends WithStyles { + customer: CustomerDetails_user; +} + +const CustomerStats = withStyles(styles, { name: "CustomerStats" })( + ({ classes, customer }: CustomerStatsProps) => ( + + + + + {i18n.t("Last login")} + + {maybe( + () => ( + + {customer.lastLogin === null ? ( + i18n.t("-") + ) : ( + + )} + + ), + + )} + +
+ + + {i18n.t("Last order")} + + {maybe( + () => ( + + {customer.lastPlacedOrder.edges.length === 0 ? ( + i18n.t("-") + ) : ( + + )} + + ), + + )} + +
+ ) +); +CustomerStats.displayName = "CustomerStats"; +export default CustomerStats; diff --git a/src/customers/components/CustomerStats/index.ts b/src/customers/components/CustomerStats/index.ts new file mode 100644 index 000000000..f34d3e1cc --- /dev/null +++ b/src/customers/components/CustomerStats/index.ts @@ -0,0 +1,2 @@ +export { default } from "./CustomerStats"; +export * from "./CustomerStats"; diff --git a/src/customers/fixtures.ts b/src/customers/fixtures.ts new file mode 100644 index 000000000..9d3e60e1d --- /dev/null +++ b/src/customers/fixtures.ts @@ -0,0 +1,1072 @@ +import { PaymentChargeStatusEnum } from "../types/globalTypes"; +import { CustomerAddresses_user } from "./types/CustomerAddresses"; +import { CustomerDetails_user } from "./types/CustomerDetails"; +import { ListCustomers_customers_edges_node } from "./types/ListCustomers"; + +export const customers = [ + { + dateJoined: "2017-10-11T13:22:30.831Z", + defaultBillingAddress: { + city: "Thompsontown", + cityArea: "Rhode Island", + companyName: null, + country: { + code: "SW", + country: "Swaziland" + }, + countryArea: "Buckinghamshire", + firstName: "Alexander", + id: "52402", + lastName: "Simonis", + phone: "+17 253-928-8945", + postalCode: "47639-5237", + streetAddress1: "83772 Savanah Summit", + streetAddress2: null + }, + defaultShippingAddress: { + city: "West Bret", + cityArea: "North Dakota", + companyName: null, + country: { + code: "SD", + country: "Sudan" + }, + countryArea: null, + firstName: "Alexander", + id: "77109", + lastName: "Simonis", + phone: "+21 463-243-6545", + postalCode: "21665", + streetAddress1: "780 Jaime Prairie", + streetAddress2: null + }, + email: "alexander_simonis@example.com", + id: "11810", + isActive: true, + isStaff: false, + note: null + }, + { + dateJoined: "2018-01-21T22:41:38.241Z", + defaultBillingAddress: { + city: "Lake Adela", + cityArea: "Maryland", + companyName: "Kemmer Group", + country: { + code: "KE", + country: "Kenya" + }, + countryArea: null, + firstName: "Augustus", + id: "81868", + lastName: "Crist", + phone: "+19 583-374-8576", + postalCode: "29966", + streetAddress1: "5656 Crooks Park", + streetAddress2: null + }, + defaultShippingAddress: { + city: "East Brandttown", + cityArea: "Missouri", + companyName: null, + country: { + code: "SO", + country: "Somalia" + }, + countryArea: null, + firstName: "Augustus", + id: "11788", + lastName: "Crist", + phone: "+52 584-961-3073", + postalCode: "80218", + streetAddress1: "37212 O'Reilly Ford", + streetAddress2: null + }, + email: "augustus_crist@example.com", + id: "34351", + isActive: true, + isStaff: false, + note: null + }, + { + dateJoined: "2018-01-19T21:36:19.298Z", + defaultBillingAddress: { + city: "East Raymond", + cityArea: "Delaware", + companyName: null, + country: { + code: "SM", + country: "San Marino" + }, + countryArea: null, + firstName: "Kelton", + id: "77939", + lastName: "Eichmann", + phone: "+17 650-119-2676", + postalCode: "94747-5311", + streetAddress1: "5060 Aufderhar Common", + streetAddress2: null + }, + defaultShippingAddress: { + city: "East Raymond", + cityArea: "Delaware", + companyName: null, + country: { + code: "SM", + country: "San Marino" + }, + countryArea: null, + firstName: "Kelton", + id: "77939", + lastName: "Eichmann", + phone: "+17 650-119-2676", + postalCode: "94747-5311", + streetAddress1: "5060 Aufderhar Common", + streetAddress2: null + }, + email: "kelton_eichmann@example.com", + id: "47883", + isActive: true, + isStaff: true, + note: null + }, + { + dateJoined: "2018-01-18T15:08:59.535Z", + defaultBillingAddress: { + city: "Torphyton", + cityArea: "Iowa", + companyName: null, + country: { + code: "CD", + country: "Chad" + }, + countryArea: null, + firstName: "Magnolia", + id: "2237", + lastName: "Brakus", + phone: "+52 136-461-3995", + postalCode: "64573", + streetAddress1: "106 Swift Squares", + streetAddress2: null + }, + defaultShippingAddress: { + city: "Torphyton", + cityArea: "Iowa", + companyName: null, + country: { + code: "CD", + country: "Chad" + }, + countryArea: null, + firstName: "Magnolia", + id: "2237", + lastName: "Brakus", + phone: "+52 136-461-3995", + postalCode: "64573", + streetAddress1: "106 Swift Squares", + streetAddress2: null + }, + email: "magnolia_brakus@example.com", + id: "53433", + isActive: true, + isStaff: false, + note: "Dolorem qui vero iure." + }, + { + dateJoined: "2017-07-22T05:21:13.774Z", + defaultBillingAddress: { + city: "Port Savanahfort", + cityArea: "Nebraska", + companyName: null, + country: { + code: "GD", + country: "Greenland" + }, + countryArea: null, + firstName: "Adonis", + id: "10532", + lastName: "Pacocha", + phone: "+11 944-018-0185", + postalCode: "52460-3432", + streetAddress1: "32181 Lindgren Turnpike", + streetAddress2: null + }, + defaultShippingAddress: { + city: "East Fletcher", + cityArea: "New Hampshire", + companyName: null, + country: { + code: "KR", + country: "Kyrgyz Republic" + }, + countryArea: null, + firstName: "Adonis", + id: "45425", + lastName: "Pacocha", + phone: "+36 549-984-7736", + postalCode: "29123-8368", + streetAddress1: "938 Jordyn Harbor", + streetAddress2: null + }, + email: "adonis_pacocha@example.com", + id: "42657", + isActive: true, + isStaff: false, + note: "Unde qui et." + }, + { + dateJoined: "2018-05-31T06:55:23.938Z", + defaultBillingAddress: { + city: "Reykjavik", + cityArea: "Höfuðborgarsvæði", + companyName: null, + country: { + code: "IS", + country: "Iceland" + }, + countryArea: null, + firstName: "Carlie", + id: "83778", + lastName: "Walsh", + phone: "+27 387-984-3969", + postalCode: "48003", + streetAddress1: "08030 Corrine Row", + streetAddress2: null + }, + defaultShippingAddress: { + city: "North Tanyafurt", + cityArea: "Wyoming", + companyName: null, + country: { + code: "RW", + country: "Rwanda" + }, + countryArea: null, + firstName: "Carlie", + id: "14941", + lastName: "Walsh", + phone: "+44 320-941-3747", + postalCode: "33296", + streetAddress1: "1231 Eriberto Stravenue", + streetAddress2: null + }, + email: "carlie_walsh@example.com", + id: "93594", + isActive: true, + isStaff: false, + note: null + }, + { + dateJoined: "2017-08-26T08:37:16.497Z", + defaultBillingAddress: { + city: "Labadiechester", + cityArea: "Iowa", + companyName: null, + country: { + code: "MA", + country: "Morocco" + }, + countryArea: "Buckinghamshire", + firstName: "Junius", + id: "86163", + lastName: "Crist", + phone: "+47 605-434-6759", + postalCode: "39521", + streetAddress1: "333 Bernie Fords", + streetAddress2: null + }, + defaultShippingAddress: { + city: "Kaylistad", + cityArea: "Louisiana", + companyName: null, + country: { + code: "EG", + country: "Equatorial Guinea" + }, + countryArea: "Bedfordshire", + firstName: "Junius", + id: "78537", + lastName: "Crist", + phone: "+20 893-019-4257", + postalCode: "43886-6932", + streetAddress1: "0597 Angeline Gateway", + streetAddress2: null + }, + email: "junius_crist@example.com", + id: "70932", + isActive: true, + isStaff: false, + note: "Et cumque consequatur aliquam." + }, + { + dateJoined: "2018-01-08T11:55:39.220Z", + defaultBillingAddress: { + city: "Lydiahaven", + cityArea: "Arkansas", + companyName: null, + country: { + code: "CB", + country: "Cambodia" + }, + countryArea: "Berkshire", + firstName: "Pedro", + id: "70545", + lastName: "Harvey", + phone: "+35 817-342-0603", + postalCode: "72196", + streetAddress1: "9280 Asa Center", + streetAddress2: null + }, + defaultShippingAddress: { + city: "Lydiahaven", + cityArea: "Arkansas", + companyName: null, + country: { + code: "CB", + country: "Cambodia" + }, + countryArea: "Berkshire", + firstName: "Pedro", + id: "70545", + lastName: "Harvey", + phone: "+35 817-342-0603", + postalCode: "72196", + streetAddress1: "9280 Asa Center", + streetAddress2: null + }, + email: "pedro_harvey@example.com", + id: "61255", + isActive: false, + isStaff: false, + note: null + }, + { + dateJoined: "2017-07-28T00:49:40.975Z", + defaultBillingAddress: { + city: "East Leilafurt", + cityArea: "Arizona", + companyName: null, + country: { + code: "BG", + country: "Bulgaria" + }, + countryArea: null, + firstName: "Raven", + id: "9167", + lastName: "Deckow", + phone: "+62 210-019-3184", + postalCode: "02296", + streetAddress1: "8546 Marks Highway", + streetAddress2: null + }, + defaultShippingAddress: { + city: "South Hendersonbury", + cityArea: "Nevada", + companyName: "Raynor Inc", + country: { + code: "TK", + country: "Turkmenistan" + }, + countryArea: null, + firstName: "Raven", + id: "48467", + lastName: "Deckow", + phone: "+46 654-130-2375", + postalCode: "00611", + streetAddress1: "87001 Howell Forge", + streetAddress2: null + }, + email: "raven_deckow@example.com", + id: "84610", + isActive: true, + isStaff: false, + note: null + }, + { + dateJoined: "2018-05-04T03:17:55.298Z", + defaultBillingAddress: { + city: "Windlerton", + cityArea: "Texas", + companyName: "Heller, Bauch and Friesen", + country: { + code: "AN", + country: "Andorra" + }, + countryArea: null, + firstName: "Paige", + id: "63622", + lastName: "Lesch", + phone: "+08 972-463-2863", + postalCode: "80681-4790", + streetAddress1: "93719 Hackett Mountain", + streetAddress2: null + }, + defaultShippingAddress: { + city: "Windlerton", + cityArea: "Texas", + companyName: "Heller, Bauch and Friesen", + country: { + code: "AN", + country: "Andorra" + }, + countryArea: null, + firstName: "Paige", + id: "63622", + lastName: "Lesch", + phone: "+08 972-463-2863", + postalCode: "80681-4790", + streetAddress1: "93719 Hackett Mountain", + streetAddress2: null + }, + email: "paige_lesch@example.com", + id: "28741", + isActive: true, + isStaff: false, + note: null + }, + { + dateJoined: "2018-01-27T13:43:07.363Z", + defaultBillingAddress: { + city: "Gleichnerborough", + cityArea: "Missouri", + companyName: null, + country: { + code: "DM", + country: "Dominica" + }, + countryArea: null, + firstName: "Santino", + id: "89962", + lastName: "Bins", + phone: "+45 844-752-5593", + postalCode: "33593-8299", + streetAddress1: "557 Jacobi Gateway", + streetAddress2: null + }, + defaultShippingAddress: { + city: "West Jolieland", + cityArea: "Connecticut", + companyName: null, + country: { + code: "SH", + country: "Saint Helena" + }, + countryArea: "Bedfordshire", + firstName: "Santino", + id: "58915", + lastName: "Bins", + phone: "+25 685-424-9436", + postalCode: "58377", + streetAddress1: "6647 Kody Locks", + streetAddress2: null + }, + email: "santino_bins@example.com", + id: "46991", + isActive: false, + isStaff: false, + note: null + }, + { + dateJoined: "2018-03-13T22:04:39.414Z", + defaultBillingAddress: { + city: "North Sister", + cityArea: "Ohio", + companyName: null, + country: { + code: "BN", + country: "Bangladesh" + }, + countryArea: "Bedfordshire", + firstName: "Quinn", + id: "94894", + lastName: "Barrows", + phone: "+35 995-317-3324", + postalCode: "41805", + streetAddress1: "146 Dee Station", + streetAddress2: null + }, + defaultShippingAddress: { + city: "North Sister", + cityArea: "Ohio", + companyName: null, + country: { + code: "BN", + country: "Bangladesh" + }, + countryArea: "Bedfordshire", + firstName: "Quinn", + id: "94894", + lastName: "Barrows", + phone: "+35 995-317-3324", + postalCode: "41805", + streetAddress1: "146 Dee Station", + streetAddress2: null + }, + email: "quinn_barrows@example.com", + id: "50687", + isActive: true, + isStaff: false, + note: null + }, + { + dateJoined: "2018-01-27T01:40:52.437Z", + defaultBillingAddress: { + city: "Kenstad", + cityArea: "Alabama", + companyName: null, + country: { + code: "UA", + country: "United Arab Emirates" + }, + countryArea: null, + firstName: "Berry", + id: "93575", + lastName: "Windler", + phone: "+41 876-373-9137", + postalCode: "89880-6342", + streetAddress1: "01419 Bernhard Plain", + streetAddress2: null + }, + defaultShippingAddress: { + city: "Kenstad", + cityArea: "Alabama", + companyName: null, + country: { + code: "UA", + country: "United Arab Emirates" + }, + countryArea: null, + firstName: "Berry", + id: "93575", + lastName: "Windler", + phone: "+41 876-373-9137", + postalCode: "89880-6342", + streetAddress1: "01419 Bernhard Plain", + streetAddress2: null + }, + email: "berry_windler@example.com", + id: "36798", + isActive: true, + isStaff: false, + note: null + }, + { + dateJoined: "2017-07-17T22:43:18.274Z", + defaultBillingAddress: { + city: "Jamilstad", + cityArea: "Idaho", + companyName: "Kilback - Crooks", + country: { + code: "UR", + country: "Uruguay" + }, + countryArea: null, + firstName: "Johnathon", + id: "78744", + lastName: "Kohler", + phone: "+63 888-798-4522", + postalCode: "43892-8110", + streetAddress1: "287 Rowe Mews", + streetAddress2: null + }, + defaultShippingAddress: { + city: "Jamilstad", + cityArea: "Idaho", + companyName: "Kilback - Crooks", + country: { + code: "UR", + country: "Uruguay" + }, + countryArea: null, + firstName: "Johnathon", + id: "78744", + lastName: "Kohler", + phone: "+63 888-798-4522", + postalCode: "43892-8110", + streetAddress1: "287 Rowe Mews", + streetAddress2: null + }, + email: "johnathon_kohler@example.com", + id: "98483", + isActive: true, + isStaff: false, + note: null + }, + { + dateJoined: "2017-07-10T00:09:56.552Z", + defaultBillingAddress: { + city: "Keltonland", + cityArea: "West Virginia", + companyName: "Bailey, Barrows and Prosacco", + country: { + code: "DN", + country: "Denmark" + }, + countryArea: null, + firstName: "Linwood", + id: "19005", + lastName: "Windler", + phone: "+60 815-222-0791", + postalCode: "12595", + streetAddress1: "496 Sporer Mountain", + streetAddress2: null + }, + defaultShippingAddress: { + city: "Keltonland", + cityArea: "West Virginia", + companyName: "Bailey, Barrows and Prosacco", + country: { + code: "DN", + country: "Denmark" + }, + countryArea: null, + firstName: "Linwood", + id: "19005", + lastName: "Windler", + phone: "+60 815-222-0791", + postalCode: "12595", + streetAddress1: "496 Sporer Mountain", + streetAddress2: null + }, + email: "linwood_windler@example.com", + id: "18050", + isActive: true, + isStaff: false, + note: null + }, + { + dateJoined: "2017-08-25T06:08:19.951Z", + defaultBillingAddress: { + city: "West Feliciamouth", + cityArea: "Montana", + companyName: null, + country: { + code: "JA", + country: "Japan" + }, + countryArea: null, + firstName: "Timmy", + id: "33855", + lastName: "Macejkovic", + phone: "+41 460-907-9374", + postalCode: "15926", + streetAddress1: "0238 Cremin Freeway", + streetAddress2: null + }, + defaultShippingAddress: { + city: "Larkinstad", + cityArea: "California", + companyName: null, + country: { + code: "SO", + country: "Somalia" + }, + countryArea: null, + firstName: "Timmy", + id: "67467", + lastName: "Macejkovic", + phone: "+64 943-882-1295", + postalCode: "43425", + streetAddress1: "96332 Corkery Lane", + streetAddress2: null + }, + email: "timmy_macejkovic@example.com", + id: "65578", + isActive: true, + isStaff: false, + note: "Dolorem vitae." + } +]; + +export const customerList: ListCustomers_customers_edges_node[] = [ + { + __typename: "User", + email: "Curtis.bailey@example.com", + firstName: "curtis", + id: "VXNlcjox", + lastName: "Bailey", + orders: { + __typename: "OrderCountableConnection", + totalCount: 2 + } + }, + { + __typename: "User", + email: "curtis.bailey@example.com", + firstName: "Curtis", + id: "VXNlcjox", + lastName: "Bailey", + orders: { + __typename: "OrderCountableConnection", + totalCount: 2 + } + }, + { + __typename: "User", + email: "elizabeth.vaughn@example.com", + firstName: "Elizabeth", + id: "VXNlcjoy", + lastName: "Vaughn", + orders: { + __typename: "OrderCountableConnection", + totalCount: 1 + } + }, + { + __typename: "User", + email: "michael.martinez@example.com", + firstName: "Michael", + id: "VXNlcjoz", + lastName: "Martinez", + orders: { + __typename: "OrderCountableConnection", + totalCount: 1 + } + }, + { + __typename: "User", + email: "kayla.griffin@example.com", + firstName: "Kayla", + id: "VXNlcjo0", + lastName: "Griffin", + orders: { + __typename: "OrderCountableConnection", + totalCount: 0 + } + }, + { + __typename: "User", + email: "donna.robinson@example.com", + firstName: "Donna", + id: "VXNlcjo1", + lastName: "Robinson", + orders: { + __typename: "OrderCountableConnection", + totalCount: 0 + } + }, + { + __typename: "User", + email: "james.ball@example.com", + firstName: "James", + id: "VXNlcjo2", + lastName: "Bqall", + orders: { + __typename: "OrderCountableConnection", + totalCount: 1 + } + }, + { + __typename: "User", + email: "anthony.gonzalez@example.com", + firstName: "Anthony", + id: "VXNlcjo3", + lastName: "Gonzalez", + orders: { + __typename: "OrderCountableConnection", + totalCount: 2 + } + }, + { + __typename: "User", + email: "anthony.gonzalez@example.com", + firstName: "Anthony", + id: "VXNlcjo3", + lastName: "Gonzalez", + orders: { + __typename: "OrderCountableConnection", + totalCount: 2 + } + }, + { + __typename: "User", + email: "wesley.davis@example.com", + firstName: "Wesley", + id: "VXNlcjo4", + lastName: "Davis", + orders: { + __typename: "OrderCountableConnection", + totalCount: 1 + } + }, + { + __typename: "User", + email: "laura.stone@example.com", + firstName: "Laura", + id: "VXNlcjo5", + lastName: "Stone", + orders: { + __typename: "OrderCountableConnection", + totalCount: 1 + } + }, + { + __typename: "User", + email: "william.miller@example.com", + firstName: "William", + id: "VXNlcjoxMA==", + lastName: "Miller", + orders: { + __typename: "OrderCountableConnection", + totalCount: 0 + } + }, + { + __typename: "User", + email: "donald.solomon@example.com", + firstName: "Donald", + id: "VXNlcjoxMQ==", + lastName: "Solomon", + orders: { + __typename: "OrderCountableConnection", + totalCount: 0 + } + }, + { + __typename: "User", + email: "anthony.young@example.com", + firstName: "Anthony", + id: "VXNlcjoxMg==", + lastName: "Young", + orders: { + __typename: "OrderCountableConnection", + totalCount: 0 + } + }, + { + __typename: "User", + email: "sharon.hanson@example.com", + firstName: "Hanson", + id: "VXNlcjoxMw==", + lastName: "Sharon", + orders: { + __typename: "OrderCountableConnection", + totalCount: 0 + } + }, + { + __typename: "User", + email: "laura.jensen@example.com", + firstName: "Laura", + id: "VXNlcjoxNA==", + lastName: "Jensen", + orders: { + __typename: "OrderCountableConnection", + totalCount: 1 + } + }, + { + __typename: "User", + email: "mark.lee@example.com", + firstName: "Mark", + id: "VXNlcjoxNQ==", + lastName: "Lee", + orders: { + __typename: "OrderCountableConnection", + totalCount: 1 + } + }, + { + __typename: "User", + email: "david.lawson@example.com", + firstName: "David", + id: "VXNlcjoxNg==", + lastName: "Lawson", + orders: { + __typename: "OrderCountableConnection", + totalCount: 2 + } + }, + { + __typename: "User", + email: "david.lawson@example.com", + firstName: "David", + id: "VXNlcjoxNg==", + lastName: "Lawson", + orders: { + __typename: "OrderCountableConnection", + totalCount: 2 + } + }, + { + __typename: "User", + email: "faith.smith@example.com", + firstName: "Faith", + id: "VXNlcjoxNw==", + lastName: "Smith", + orders: { + __typename: "OrderCountableConnection", + totalCount: 0 + } + }, + { + __typename: "User", + email: "john.jones@example.com", + firstName: "John", + id: "VXNlcjoxOA==", + lastName: "Jones", + orders: { + __typename: "OrderCountableConnection", + totalCount: 0 + } + }, + { + __typename: "User", + email: "ronald.fisher@example.com", + firstName: "Ronald", + id: "VXNlcjoxOQ==", + lastName: "Fisher", + orders: { + __typename: "OrderCountableConnection", + totalCount: 0 + } + }, + { + __typename: "User", + email: "jason.gray@example.com", + firstName: "Jason", + id: "VXNlcjoyMA==", + lastName: "Gray", + orders: { + __typename: "OrderCountableConnection", + totalCount: 0 + } + }, + { + __typename: "User", + email: "admin@example.com", + firstName: "Tom", + id: "VXNlcjoyMQ==", + lastName: "Cooper", + orders: { + __typename: "OrderCountableConnection", + totalCount: 6 + } + } +]; +export const customer: CustomerDetails_user & CustomerAddresses_user = { + __typename: "User", + addresses: [ + { + __typename: "Address", + city: "Port Danielshire", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "SE", + country: "Szwecja" + }, + countryArea: "", + firstName: "Elizabeth", + id: "QWRkcmVzczoy", + lastName: "Vaughn", + phone: "", + postalCode: "52203", + streetAddress1: "419 Ruiz Orchard Apt. 199", + streetAddress2: "0238 Cremin Freeway" + }, + { + __typename: "Address", + city: "West Feliciamouth", + cityArea: "Montana", + companyName: null, + country: { + __typename: "CountryDisplay", + code: "JA", + country: "Japan" + }, + countryArea: null, + firstName: "Timmy", + id: "33855", + lastName: "Macejkovic", + phone: "+41 460-907-9374", + postalCode: "15926", + streetAddress1: "0238 Cremin Freeway", + streetAddress2: null + } + ], + dateJoined: "2017-05-07T09:37:30.124154+00:00", + firstName: "Tom", + + defaultBillingAddress: { + __typename: "Address", + city: "Port Danielshire", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "SE", + country: "Szwecja" + }, + countryArea: "", + firstName: "Elizabeth", + id: "QWRkcmVzczoy", + lastName: "Vaughn", + phone: "", + postalCode: "52203", + streetAddress1: "419 Ruiz Orchard Apt. 199", + streetAddress2: "" + }, + defaultShippingAddress: { + __typename: "Address", + city: "Port Danielshire", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "SE", + country: "Szwecja" + }, + countryArea: "", + firstName: "Elizabeth", + id: "QWRkcmVzczoy", + lastName: "Vaughn", + phone: "", + postalCode: "52203", + streetAddress1: "419 Ruiz Orchard Apt. 199", + streetAddress2: "" + }, + email: "elizabeth.vaughn@example.com", + id: "VXNlcjoy", + isActive: true, + lastLogin: "2018-05-07T09:37:30.124154+00:00", + lastName: "Cooper", + lastPlacedOrder: { + __typename: "OrderCountableConnection", + edges: [ + { + __typename: "OrderCountableEdge", + node: { + __typename: "Order", + created: "2018-05-07T09:37:30.124154+00:00", + id: "T3JkZXI6MTk=" + } + } + ] + }, + note: null, + orders: { + __typename: "OrderCountableConnection", + edges: [ + { + __typename: "OrderCountableEdge", + node: { + __typename: "Order", + created: "2018-05-07T09:37:30.124154+00:00", + id: "T3JkZXI6MTk=", + number: "8234", + paymentStatus: PaymentChargeStatusEnum.FULLY_CHARGED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 1215.89, + currency: "USD" + } + } + } + } + ] + } +}; diff --git a/src/customers/index.tsx b/src/customers/index.tsx new file mode 100644 index 000000000..b06576887 --- /dev/null +++ b/src/customers/index.tsx @@ -0,0 +1,76 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { WindowTitle } from "../components/WindowTitle"; +import i18n from "../i18n"; +import { + customerAddPath, + customerAddressesPath, + CustomerAddressesUrlQueryParams, + customerListPath, + CustomerListUrlQueryParams, + customerPath, + CustomerUrlQueryParams +} from "./urls"; +import CustomerAddressesViewComponent from "./views/CustomerAddresses"; +import CustomerCreateView from "./views/CustomerCreate"; +import CustomerDetailsViewComponent from "./views/CustomerDetails"; +import CustomerListViewComponent from "./views/CustomerList"; + +const CustomerListView: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: CustomerListUrlQueryParams = qs; + return ; +}; + +interface CustomerDetailsRouteParams { + id: string; +} +const CustomerDetailsView: React.StatelessComponent< + RouteComponentProps +> = ({ location, match }) => { + const qs = parseQs(location.search.substr(1)); + const params: CustomerUrlQueryParams = qs; + + return ( + + ); +}; + +interface CustomerAddressesRouteParams { + id: string; +} +const CustomerAddressesView: React.StatelessComponent< + RouteComponentProps +> = ({ match }) => { + const qs = parseQs(location.search.substr(1)); + const params: CustomerAddressesUrlQueryParams = qs; + + return ( + + ); +}; + +export const CustomerSection: React.StatelessComponent<{}> = () => ( + <> + + + + + + + + +); diff --git a/src/customers/mutations.ts b/src/customers/mutations.ts new file mode 100644 index 000000000..1c80da368 --- /dev/null +++ b/src/customers/mutations.ts @@ -0,0 +1,188 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { fragmentAddress } from "../orders/queries"; +import { customerAddressesFragment, customerDetailsFragment } from "./queries"; +import { + BulkRemoveCustomers, + BulkRemoveCustomersVariables +} from "./types/BulkRemoveCustomers"; +import { + CreateCustomer, + CreateCustomerVariables +} from "./types/CreateCustomer"; +import { + CreateCustomerAddress, + CreateCustomerAddressVariables +} from "./types/CreateCustomerAddress"; +import { + RemoveCustomer, + RemoveCustomerVariables +} from "./types/RemoveCustomer"; +import { + RemoveCustomerAddress, + RemoveCustomerAddressVariables +} from "./types/RemoveCustomerAddress"; +import { + SetCustomerDefaultAddress, + SetCustomerDefaultAddressVariables +} from "./types/SetCustomerDefaultAddress"; +import { + UpdateCustomer, + UpdateCustomerVariables +} from "./types/UpdateCustomer"; +import { + UpdateCustomerAddress, + UpdateCustomerAddressVariables +} from "./types/UpdateCustomerAddress"; + +const updateCustomer = gql` + ${customerDetailsFragment} + mutation UpdateCustomer($id: ID!, $input: CustomerInput!) { + customerUpdate(id: $id, input: $input) { + errors { + field + message + } + user { + ...CustomerDetailsFragment + } + } + } +`; +export const TypedUpdateCustomerMutation = TypedMutation< + UpdateCustomer, + UpdateCustomerVariables +>(updateCustomer); + +const createCustomer = gql` + mutation CreateCustomer($input: UserCreateInput!) { + customerCreate(input: $input) { + errors { + field + message + } + user { + id + } + } + } +`; +export const TypedCreateCustomerMutation = TypedMutation< + CreateCustomer, + CreateCustomerVariables +>(createCustomer); + +const removeCustomer = gql` + mutation RemoveCustomer($id: ID!) { + customerDelete(id: $id) { + errors { + field + message + } + } + } +`; +export const TypedRemoveCustomerMutation = TypedMutation< + RemoveCustomer, + RemoveCustomerVariables +>(removeCustomer); + +const setCustomerDefaultAddress = gql` + ${customerAddressesFragment} + mutation SetCustomerDefaultAddress( + $addressId: ID! + $userId: ID! + $type: AddressTypeEnum! + ) { + addressSetDefault(addressId: $addressId, userId: $userId, type: $type) { + errors { + field + message + } + user { + ...CustomerAddressesFragment + } + } + } +`; +export const TypedSetCustomerDefaultAddressMutation = TypedMutation< + SetCustomerDefaultAddress, + SetCustomerDefaultAddressVariables +>(setCustomerDefaultAddress); + +const createCustomerAddress = gql` + ${customerAddressesFragment} + ${fragmentAddress} + mutation CreateCustomerAddress($id: ID!, $input: AddressInput!) { + addressCreate(userId: $id, input: $input) { + errors { + field + message + } + address { + ...AddressFragment + } + user { + ...CustomerAddressesFragment + } + } + } +`; +export const TypedCreateCustomerAddressMutation = TypedMutation< + CreateCustomerAddress, + CreateCustomerAddressVariables +>(createCustomerAddress); + +const updateCustomerAddress = gql` + ${fragmentAddress} + mutation UpdateCustomerAddress($id: ID!, $input: AddressInput!) { + addressUpdate(id: $id, input: $input) { + errors { + field + message + } + address { + ...AddressFragment + } + } + } +`; +export const TypedUpdateCustomerAddressMutation = TypedMutation< + UpdateCustomerAddress, + UpdateCustomerAddressVariables +>(updateCustomerAddress); + +const removeCustomerAddress = gql` + ${customerAddressesFragment} + mutation RemoveCustomerAddress($id: ID!) { + addressDelete(id: $id) { + errors { + field + message + } + user { + ...CustomerAddressesFragment + } + } + } +`; +export const TypedRemoveCustomerAddressMutation = TypedMutation< + RemoveCustomerAddress, + RemoveCustomerAddressVariables +>(removeCustomerAddress); + +export const bulkRemoveCustomers = gql` + mutation BulkRemoveCustomers($ids: [ID]!) { + customerBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedBulkRemoveCustomers = TypedMutation< + BulkRemoveCustomers, + BulkRemoveCustomersVariables +>(bulkRemoveCustomers); diff --git a/src/customers/queries.ts b/src/customers/queries.ts new file mode 100644 index 000000000..9030ecbdf --- /dev/null +++ b/src/customers/queries.ts @@ -0,0 +1,153 @@ +import gql from "graphql-tag"; + +import { fragmentAddress } from "../orders/queries"; +import { TypedQuery } from "../queries"; +import { + CustomerAddresses, + CustomerAddressesVariables +} from "./types/CustomerAddresses"; +import { CustomerCreateData } from "./types/CustomerCreateData"; +import { + CustomerDetails, + CustomerDetailsVariables +} from "./types/CustomerDetails"; +import { ListCustomers, ListCustomersVariables } from "./types/ListCustomers"; + +export const customerFragment = gql` + fragment CustomerFragment on User { + id + email + firstName + lastName + } +`; + +export const customerDetailsFragment = gql` + ${customerFragment} + ${fragmentAddress} + fragment CustomerDetailsFragment on User { + ...CustomerFragment + dateJoined + lastLogin + defaultShippingAddress { + ...AddressFragment + } + defaultBillingAddress { + ...AddressFragment + } + note + isActive + } +`; + +export const customerAddressesFragment = gql` + ${customerFragment} + ${fragmentAddress} + fragment CustomerAddressesFragment on User { + ...CustomerFragment + addresses { + ...AddressFragment + } + defaultBillingAddress { + id + } + defaultShippingAddress { + id + } + } +`; + +const customerList = gql` + ${customerFragment} + query ListCustomers( + $after: String + $before: String + $first: Int + $last: Int + ) { + customers(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + ...CustomerFragment + orders { + totalCount + } + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + } +`; +export const TypedCustomerListQuery = TypedQuery< + ListCustomers, + ListCustomersVariables +>(customerList); + +const customerDetails = gql` + ${customerDetailsFragment} + query CustomerDetails($id: ID!) { + user(id: $id) { + ...CustomerDetailsFragment + orders(last: 5) { + edges { + node { + id + created + number + paymentStatus + total { + gross { + currency + amount + } + } + } + } + } + lastPlacedOrder: orders(last: 1) { + edges { + node { + id + created + } + } + } + } + } +`; +export const TypedCustomerDetailsQuery = TypedQuery< + CustomerDetails, + CustomerDetailsVariables +>(customerDetails); + +const customerAddresses = gql` + ${customerAddressesFragment} + query CustomerAddresses($id: ID!) { + user(id: $id) { + ...CustomerAddressesFragment + } + } +`; +export const TypedCustomerAddressesQuery = TypedQuery< + CustomerAddresses, + CustomerAddressesVariables +>(customerAddresses); + +const customerCreateData = gql` + query CustomerCreateData { + shop { + countries { + code + country + } + } + } +`; +export const TypedCustomerCreateDataQuery = TypedQuery( + customerCreateData +); diff --git a/src/customers/types.ts b/src/customers/types.ts new file mode 100644 index 000000000..1eee8acac --- /dev/null +++ b/src/customers/types.ts @@ -0,0 +1,33 @@ +export interface AddressTypeInput { + city: string; + cityArea?: string; + companyName?: string; + country: { + label: string; + value: string; + }; + countryArea?: string; + firstName: string; + lastName: string; + phone: string; + postalCode: string; + streetAddress1: string; + streetAddress2?: string; +} +export interface AddressType { + id: string; + city: string; + cityArea?: string; + companyName?: string; + country: { + code: string; + country: string; + }; + countryArea?: string; + firstName: string; + lastName: string; + phone: string; + postalCode: string; + streetAddress1: string; + streetAddress2?: string; +} diff --git a/src/customers/types/BulkRemoveCustomers.ts b/src/customers/types/BulkRemoveCustomers.ts new file mode 100644 index 000000000..06251bbbc --- /dev/null +++ b/src/customers/types/BulkRemoveCustomers.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: BulkRemoveCustomers +// ==================================================== + +export interface BulkRemoveCustomers_customerBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface BulkRemoveCustomers_customerBulkDelete { + __typename: "CustomerBulkDelete"; + errors: BulkRemoveCustomers_customerBulkDelete_errors[] | null; +} + +export interface BulkRemoveCustomers { + customerBulkDelete: BulkRemoveCustomers_customerBulkDelete | null; +} + +export interface BulkRemoveCustomersVariables { + ids: (string | null)[]; +} diff --git a/src/customers/types/CreateCustomer.ts b/src/customers/types/CreateCustomer.ts new file mode 100644 index 000000000..a816a40d0 --- /dev/null +++ b/src/customers/types/CreateCustomer.ts @@ -0,0 +1,34 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { UserCreateInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: CreateCustomer +// ==================================================== + +export interface CreateCustomer_customerCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CreateCustomer_customerCreate_user { + __typename: "User"; + id: string; +} + +export interface CreateCustomer_customerCreate { + __typename: "CustomerCreate"; + errors: CreateCustomer_customerCreate_errors[] | null; + user: CreateCustomer_customerCreate_user | null; +} + +export interface CreateCustomer { + customerCreate: CreateCustomer_customerCreate | null; +} + +export interface CreateCustomerVariables { + input: UserCreateInput; +} diff --git a/src/customers/types/CreateCustomerAddress.ts b/src/customers/types/CreateCustomerAddress.ts new file mode 100644 index 000000000..f49e42228 --- /dev/null +++ b/src/customers/types/CreateCustomerAddress.ts @@ -0,0 +1,96 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AddressInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: CreateCustomerAddress +// ==================================================== + +export interface CreateCustomerAddress_addressCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CreateCustomerAddress_addressCreate_address_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface CreateCustomerAddress_addressCreate_address { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: CreateCustomerAddress_addressCreate_address_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface CreateCustomerAddress_addressCreate_user_addresses_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface CreateCustomerAddress_addressCreate_user_addresses { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: CreateCustomerAddress_addressCreate_user_addresses_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface CreateCustomerAddress_addressCreate_user_defaultBillingAddress { + __typename: "Address"; + id: string; +} + +export interface CreateCustomerAddress_addressCreate_user_defaultShippingAddress { + __typename: "Address"; + id: string; +} + +export interface CreateCustomerAddress_addressCreate_user { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + addresses: (CreateCustomerAddress_addressCreate_user_addresses | null)[] | null; + defaultBillingAddress: CreateCustomerAddress_addressCreate_user_defaultBillingAddress | null; + defaultShippingAddress: CreateCustomerAddress_addressCreate_user_defaultShippingAddress | null; +} + +export interface CreateCustomerAddress_addressCreate { + __typename: "AddressCreate"; + errors: CreateCustomerAddress_addressCreate_errors[] | null; + address: CreateCustomerAddress_addressCreate_address | null; + user: CreateCustomerAddress_addressCreate_user | null; +} + +export interface CreateCustomerAddress { + addressCreate: CreateCustomerAddress_addressCreate | null; +} + +export interface CreateCustomerAddressVariables { + id: string; + input: AddressInput; +} diff --git a/src/customers/types/CustomerAddresses.ts b/src/customers/types/CustomerAddresses.ts new file mode 100644 index 000000000..b95d46a28 --- /dev/null +++ b/src/customers/types/CustomerAddresses.ts @@ -0,0 +1,58 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: CustomerAddresses +// ==================================================== + +export interface CustomerAddresses_user_addresses_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface CustomerAddresses_user_addresses { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: CustomerAddresses_user_addresses_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface CustomerAddresses_user_defaultBillingAddress { + __typename: "Address"; + id: string; +} + +export interface CustomerAddresses_user_defaultShippingAddress { + __typename: "Address"; + id: string; +} + +export interface CustomerAddresses_user { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + addresses: (CustomerAddresses_user_addresses | null)[] | null; + defaultBillingAddress: CustomerAddresses_user_defaultBillingAddress | null; + defaultShippingAddress: CustomerAddresses_user_defaultShippingAddress | null; +} + +export interface CustomerAddresses { + user: CustomerAddresses_user | null; +} + +export interface CustomerAddressesVariables { + id: string; +} diff --git a/src/customers/types/CustomerAddressesFragment.ts b/src/customers/types/CustomerAddressesFragment.ts new file mode 100644 index 000000000..07fd6c695 --- /dev/null +++ b/src/customers/types/CustomerAddressesFragment.ts @@ -0,0 +1,50 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: CustomerAddressesFragment +// ==================================================== + +export interface CustomerAddressesFragment_addresses_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface CustomerAddressesFragment_addresses { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: CustomerAddressesFragment_addresses_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface CustomerAddressesFragment_defaultBillingAddress { + __typename: "Address"; + id: string; +} + +export interface CustomerAddressesFragment_defaultShippingAddress { + __typename: "Address"; + id: string; +} + +export interface CustomerAddressesFragment { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + addresses: (CustomerAddressesFragment_addresses | null)[] | null; + defaultBillingAddress: CustomerAddressesFragment_defaultBillingAddress | null; + defaultShippingAddress: CustomerAddressesFragment_defaultShippingAddress | null; +} diff --git a/src/customers/types/CustomerCreateData.ts b/src/customers/types/CustomerCreateData.ts new file mode 100644 index 000000000..2f5029892 --- /dev/null +++ b/src/customers/types/CustomerCreateData.ts @@ -0,0 +1,22 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: CustomerCreateData +// ==================================================== + +export interface CustomerCreateData_shop_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface CustomerCreateData_shop { + __typename: "Shop"; + countries: (CustomerCreateData_shop_countries | null)[]; +} + +export interface CustomerCreateData { + shop: CustomerCreateData_shop | null; +} diff --git a/src/customers/types/CustomerDetails.ts b/src/customers/types/CustomerDetails.ts new file mode 100644 index 000000000..84cd2e038 --- /dev/null +++ b/src/customers/types/CustomerDetails.ts @@ -0,0 +1,123 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PaymentChargeStatusEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: CustomerDetails +// ==================================================== + +export interface CustomerDetails_user_defaultShippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface CustomerDetails_user_defaultShippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: CustomerDetails_user_defaultShippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface CustomerDetails_user_defaultBillingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface CustomerDetails_user_defaultBillingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: CustomerDetails_user_defaultBillingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface CustomerDetails_user_orders_edges_node_total_gross { + __typename: "Money"; + currency: string; + amount: number; +} + +export interface CustomerDetails_user_orders_edges_node_total { + __typename: "TaxedMoney"; + gross: CustomerDetails_user_orders_edges_node_total_gross; +} + +export interface CustomerDetails_user_orders_edges_node { + __typename: "Order"; + id: string; + created: any; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + total: CustomerDetails_user_orders_edges_node_total | null; +} + +export interface CustomerDetails_user_orders_edges { + __typename: "OrderCountableEdge"; + node: CustomerDetails_user_orders_edges_node; +} + +export interface CustomerDetails_user_orders { + __typename: "OrderCountableConnection"; + edges: CustomerDetails_user_orders_edges[]; +} + +export interface CustomerDetails_user_lastPlacedOrder_edges_node { + __typename: "Order"; + id: string; + created: any; +} + +export interface CustomerDetails_user_lastPlacedOrder_edges { + __typename: "OrderCountableEdge"; + node: CustomerDetails_user_lastPlacedOrder_edges_node; +} + +export interface CustomerDetails_user_lastPlacedOrder { + __typename: "OrderCountableConnection"; + edges: CustomerDetails_user_lastPlacedOrder_edges[]; +} + +export interface CustomerDetails_user { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + dateJoined: any; + lastLogin: any | null; + defaultShippingAddress: CustomerDetails_user_defaultShippingAddress | null; + defaultBillingAddress: CustomerDetails_user_defaultBillingAddress | null; + note: string | null; + isActive: boolean; + orders: CustomerDetails_user_orders | null; + lastPlacedOrder: CustomerDetails_user_lastPlacedOrder | null; +} + +export interface CustomerDetails { + user: CustomerDetails_user | null; +} + +export interface CustomerDetailsVariables { + id: string; +} diff --git a/src/customers/types/CustomerDetailsFragment.ts b/src/customers/types/CustomerDetailsFragment.ts new file mode 100644 index 000000000..cd2b1b0e8 --- /dev/null +++ b/src/customers/types/CustomerDetailsFragment.ts @@ -0,0 +1,65 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: CustomerDetailsFragment +// ==================================================== + +export interface CustomerDetailsFragment_defaultShippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface CustomerDetailsFragment_defaultShippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: CustomerDetailsFragment_defaultShippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface CustomerDetailsFragment_defaultBillingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface CustomerDetailsFragment_defaultBillingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: CustomerDetailsFragment_defaultBillingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface CustomerDetailsFragment { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + dateJoined: any; + lastLogin: any | null; + defaultShippingAddress: CustomerDetailsFragment_defaultShippingAddress | null; + defaultBillingAddress: CustomerDetailsFragment_defaultBillingAddress | null; + note: string | null; + isActive: boolean; +} diff --git a/src/customers/types/CustomerFragment.ts b/src/customers/types/CustomerFragment.ts new file mode 100644 index 000000000..f945af27f --- /dev/null +++ b/src/customers/types/CustomerFragment.ts @@ -0,0 +1,15 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: CustomerFragment +// ==================================================== + +export interface CustomerFragment { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; +} diff --git a/src/customers/types/ListCustomers.ts b/src/customers/types/ListCustomers.ts new file mode 100644 index 000000000..aeaf81931 --- /dev/null +++ b/src/customers/types/ListCustomers.ts @@ -0,0 +1,51 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: ListCustomers +// ==================================================== + +export interface ListCustomers_customers_edges_node_orders { + __typename: "OrderCountableConnection"; + totalCount: number | null; +} + +export interface ListCustomers_customers_edges_node { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + orders: ListCustomers_customers_edges_node_orders | null; +} + +export interface ListCustomers_customers_edges { + __typename: "UserCountableEdge"; + node: ListCustomers_customers_edges_node; +} + +export interface ListCustomers_customers_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface ListCustomers_customers { + __typename: "UserCountableConnection"; + edges: ListCustomers_customers_edges[]; + pageInfo: ListCustomers_customers_pageInfo; +} + +export interface ListCustomers { + customers: ListCustomers_customers | null; +} + +export interface ListCustomersVariables { + after?: string | null; + before?: string | null; + first?: number | null; + last?: number | null; +} diff --git a/src/customers/types/RemoveCustomer.ts b/src/customers/types/RemoveCustomer.ts new file mode 100644 index 000000000..70a93326d --- /dev/null +++ b/src/customers/types/RemoveCustomer.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: RemoveCustomer +// ==================================================== + +export interface RemoveCustomer_customerDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface RemoveCustomer_customerDelete { + __typename: "CustomerDelete"; + errors: RemoveCustomer_customerDelete_errors[] | null; +} + +export interface RemoveCustomer { + customerDelete: RemoveCustomer_customerDelete | null; +} + +export interface RemoveCustomerVariables { + id: string; +} diff --git a/src/customers/types/RemoveCustomerAddress.ts b/src/customers/types/RemoveCustomerAddress.ts new file mode 100644 index 000000000..a4f6cd9ee --- /dev/null +++ b/src/customers/types/RemoveCustomerAddress.ts @@ -0,0 +1,70 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: RemoveCustomerAddress +// ==================================================== + +export interface RemoveCustomerAddress_addressDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface RemoveCustomerAddress_addressDelete_user_addresses_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface RemoveCustomerAddress_addressDelete_user_addresses { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: RemoveCustomerAddress_addressDelete_user_addresses_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface RemoveCustomerAddress_addressDelete_user_defaultBillingAddress { + __typename: "Address"; + id: string; +} + +export interface RemoveCustomerAddress_addressDelete_user_defaultShippingAddress { + __typename: "Address"; + id: string; +} + +export interface RemoveCustomerAddress_addressDelete_user { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + addresses: (RemoveCustomerAddress_addressDelete_user_addresses | null)[] | null; + defaultBillingAddress: RemoveCustomerAddress_addressDelete_user_defaultBillingAddress | null; + defaultShippingAddress: RemoveCustomerAddress_addressDelete_user_defaultShippingAddress | null; +} + +export interface RemoveCustomerAddress_addressDelete { + __typename: "AddressDelete"; + errors: RemoveCustomerAddress_addressDelete_errors[] | null; + user: RemoveCustomerAddress_addressDelete_user | null; +} + +export interface RemoveCustomerAddress { + addressDelete: RemoveCustomerAddress_addressDelete | null; +} + +export interface RemoveCustomerAddressVariables { + id: string; +} diff --git a/src/customers/types/SetCustomerDefaultAddress.ts b/src/customers/types/SetCustomerDefaultAddress.ts new file mode 100644 index 000000000..e2732c8c7 --- /dev/null +++ b/src/customers/types/SetCustomerDefaultAddress.ts @@ -0,0 +1,74 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AddressTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: SetCustomerDefaultAddress +// ==================================================== + +export interface SetCustomerDefaultAddress_addressSetDefault_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface SetCustomerDefaultAddress_addressSetDefault_user_addresses_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface SetCustomerDefaultAddress_addressSetDefault_user_addresses { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: SetCustomerDefaultAddress_addressSetDefault_user_addresses_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface SetCustomerDefaultAddress_addressSetDefault_user_defaultBillingAddress { + __typename: "Address"; + id: string; +} + +export interface SetCustomerDefaultAddress_addressSetDefault_user_defaultShippingAddress { + __typename: "Address"; + id: string; +} + +export interface SetCustomerDefaultAddress_addressSetDefault_user { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + addresses: (SetCustomerDefaultAddress_addressSetDefault_user_addresses | null)[] | null; + defaultBillingAddress: SetCustomerDefaultAddress_addressSetDefault_user_defaultBillingAddress | null; + defaultShippingAddress: SetCustomerDefaultAddress_addressSetDefault_user_defaultShippingAddress | null; +} + +export interface SetCustomerDefaultAddress_addressSetDefault { + __typename: "AddressSetDefault"; + errors: SetCustomerDefaultAddress_addressSetDefault_errors[] | null; + user: SetCustomerDefaultAddress_addressSetDefault_user | null; +} + +export interface SetCustomerDefaultAddress { + addressSetDefault: SetCustomerDefaultAddress_addressSetDefault | null; +} + +export interface SetCustomerDefaultAddressVariables { + addressId: string; + userId: string; + type: AddressTypeEnum; +} diff --git a/src/customers/types/UpdateCustomer.ts b/src/customers/types/UpdateCustomer.ts new file mode 100644 index 000000000..32be22048 --- /dev/null +++ b/src/customers/types/UpdateCustomer.ts @@ -0,0 +1,88 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { CustomerInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: UpdateCustomer +// ==================================================== + +export interface UpdateCustomer_customerUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface UpdateCustomer_customerUpdate_user_defaultShippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface UpdateCustomer_customerUpdate_user_defaultShippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: UpdateCustomer_customerUpdate_user_defaultShippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface UpdateCustomer_customerUpdate_user_defaultBillingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface UpdateCustomer_customerUpdate_user_defaultBillingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: UpdateCustomer_customerUpdate_user_defaultBillingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface UpdateCustomer_customerUpdate_user { + __typename: "User"; + id: string; + email: string; + firstName: string; + lastName: string; + dateJoined: any; + lastLogin: any | null; + defaultShippingAddress: UpdateCustomer_customerUpdate_user_defaultShippingAddress | null; + defaultBillingAddress: UpdateCustomer_customerUpdate_user_defaultBillingAddress | null; + note: string | null; + isActive: boolean; +} + +export interface UpdateCustomer_customerUpdate { + __typename: "CustomerUpdate"; + errors: UpdateCustomer_customerUpdate_errors[] | null; + user: UpdateCustomer_customerUpdate_user | null; +} + +export interface UpdateCustomer { + customerUpdate: UpdateCustomer_customerUpdate | null; +} + +export interface UpdateCustomerVariables { + id: string; + input: CustomerInput; +} diff --git a/src/customers/types/UpdateCustomerAddress.ts b/src/customers/types/UpdateCustomerAddress.ts new file mode 100644 index 000000000..4cf3ea5c3 --- /dev/null +++ b/src/customers/types/UpdateCustomerAddress.ts @@ -0,0 +1,52 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AddressInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: UpdateCustomerAddress +// ==================================================== + +export interface UpdateCustomerAddress_addressUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface UpdateCustomerAddress_addressUpdate_address_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface UpdateCustomerAddress_addressUpdate_address { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: UpdateCustomerAddress_addressUpdate_address_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface UpdateCustomerAddress_addressUpdate { + __typename: "AddressUpdate"; + errors: UpdateCustomerAddress_addressUpdate_errors[] | null; + address: UpdateCustomerAddress_addressUpdate_address | null; +} + +export interface UpdateCustomerAddress { + addressUpdate: UpdateCustomerAddress_addressUpdate | null; +} + +export interface UpdateCustomerAddressVariables { + id: string; + input: AddressInput; +} diff --git a/src/customers/urls.ts b/src/customers/urls.ts new file mode 100644 index 000000000..53662c0f5 --- /dev/null +++ b/src/customers/urls.ts @@ -0,0 +1,35 @@ +import { stringify as stringifyQs } from "qs"; +import * as urlJoin from "url-join"; + +import { BulkAction, Dialog, Pagination, SingleAction } from "../types"; + +export const customerSection = "/customers/"; + +export const customerListPath = customerSection; +export type CustomerListUrlDialog = "remove"; +export type CustomerListUrlQueryParams = BulkAction & + Dialog & + Pagination; +export const customerListUrl = (params?: CustomerListUrlQueryParams) => + customerListPath + "?" + stringifyQs(params); + +export const customerPath = (id: string) => urlJoin(customerSection, id); +export type CustomerUrlDialog = "remove"; +export type CustomerUrlQueryParams = Dialog; +export const customerUrl = (id: string, params?: CustomerUrlQueryParams) => + customerPath(encodeURIComponent(id)) + "?" + stringifyQs(params); + +export const customerAddPath = urlJoin(customerSection, "add"); +export const customerAddUrl = customerAddPath; + +export const customerAddressesPath = (id: string) => + urlJoin(customerPath(id), "addresses"); +export type CustomerAddressesUrlDialog = "add" | "edit" | "remove"; +export type CustomerAddressesUrlQueryParams = Dialog< + CustomerAddressesUrlDialog +> & + SingleAction; +export const customerAddressesUrl = ( + id: string, + params?: CustomerAddressesUrlQueryParams +) => customerAddressesPath(encodeURIComponent(id)) + "?" + stringifyQs(params); diff --git a/src/customers/views/CustomerAddresses.tsx b/src/customers/views/CustomerAddresses.tsx new file mode 100644 index 000000000..5e968036b --- /dev/null +++ b/src/customers/views/CustomerAddresses.tsx @@ -0,0 +1,251 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import CustomerAddressDialog from "../components/CustomerAddressDialog"; +import CustomerAddressListPage from "../components/CustomerAddressListPage"; +import { + TypedCreateCustomerAddressMutation, + TypedRemoveCustomerAddressMutation, + TypedSetCustomerDefaultAddressMutation, + TypedUpdateCustomerAddressMutation +} from "../mutations"; +import { TypedCustomerAddressesQuery } from "../queries"; +import { CreateCustomerAddress } from "../types/CreateCustomerAddress"; +import { RemoveCustomerAddress } from "../types/RemoveCustomerAddress"; +import { SetCustomerDefaultAddress } from "../types/SetCustomerDefaultAddress"; +import { UpdateCustomerAddress } from "../types/UpdateCustomerAddress"; +import { + customerAddressesUrl, + CustomerAddressesUrlDialog, + CustomerAddressesUrlQueryParams, + customerUrl +} from "../urls"; + +interface CustomerAddressesProps { + id: string; + params: CustomerAddressesUrlQueryParams; +} + +const CustomerAddresses: React.FC = ({ + id, + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const shop = useShop(); + + const closeModal = () => navigate(customerAddressesUrl(id), true); + const openModal = (action: CustomerAddressesUrlDialog, addressId?: string) => + navigate(customerAddressesUrl(id, { action, id: addressId })); + + const handleSetAddressAsDefault = (data: SetCustomerDefaultAddress) => { + if (data.addressSetDefault.errors.length === 0) { + closeModal(); + notify({ + text: i18n.t("Set address as default", { + context: "notification" + }) + }); + } + }; + + const handleAddressCreate = (data: CreateCustomerAddress) => { + if (data.addressCreate.errors.length === 0) { + closeModal(); + } + }; + + const handleAddressUpdate = (data: UpdateCustomerAddress) => { + if (data.addressUpdate.errors.length === 0) { + closeModal(); + notify({ + text: i18n.t("Updated address", { + context: "notification" + }) + }); + } + }; + + const handleAddressRemove = (data: RemoveCustomerAddress) => { + if (data.addressDelete.errors.length === 0) { + closeModal(); + notify({ + text: i18n.t("Removed address", { + context: "notification" + }) + }); + } + }; + + return ( + + {setCustomerDefaultAddress => ( + + {(createCustomerAddress, createCustomerAddressOpts) => ( + + {(updateCustomerAddress, updateCustomerAddressOpts) => ( + + {(removeCustomerAddress, removeCustomerAddressOpts) => ( + + {customerData => { + const createAddressTransitionState = getMutationState( + createCustomerAddressOpts.called, + createCustomerAddressOpts.loading, + maybe( + () => + createCustomerAddressOpts.data.addressCreate + .errors, + [] + ) + ); + + const updateAddressTransitionState = getMutationState( + updateCustomerAddressOpts.called, + updateCustomerAddressOpts.loading, + maybe( + () => + updateCustomerAddressOpts.data.addressUpdate + .errors, + [] + ) + ); + + const removeAddressTransitionState = getMutationState( + removeCustomerAddressOpts.called, + removeCustomerAddressOpts.loading, + maybe( + () => + removeCustomerAddressOpts.data.addressDelete + .errors, + [] + ) + ); + return ( + <> + customerData.data.user.email)} + /> + customerData.data.user)} + disabled={customerData.loading} + onAdd={() => openModal("add")} + onBack={() => navigate(customerUrl(id))} + onEdit={addressId => openModal("edit", addressId)} + onRemove={addressId => + openModal("remove", addressId) + } + onSetAsDefault={(addressId, type) => + setCustomerDefaultAddress({ + variables: { addressId, type, userId: id } + }) + } + /> + + shop.countries.map(country => ({ + code: country.code, + label: country.country + })), + [] + )} + errors={maybe( + () => + createCustomerAddressOpts.data.addressCreate + .errors, + [] + )} + open={params.action === "add"} + variant="create" + onClose={closeModal} + onConfirm={formData => + createCustomerAddress({ + variables: { + id, + input: { + ...formData, + country: formData.country.value + } + } + }) + } + /> + + customerData.data.user.addresses.find( + addr => addr.id === params.id + ) + )} + confirmButtonState={updateAddressTransitionState} + countries={[]} + errors={maybe( + () => + updateCustomerAddressOpts.data.addressUpdate + .errors, + [] + )} + open={params.action === "edit"} + variant="edit" + onClose={closeModal} + onConfirm={formData => + updateCustomerAddress({ + variables: { + id: params.id, + input: { + ...formData, + country: formData.country.value + } + } + }) + } + /> + + removeCustomerAddress({ + variables: { + id: params.id + } + }) + } + > + + {i18n.t( + "Are you sure you want to remove this address from users address book?" + )} + + + + ); + }} + + )} + + )} + + )} + + )} + + ); +}; +export default CustomerAddresses; diff --git a/src/customers/views/CustomerCreate.tsx b/src/customers/views/CustomerCreate.tsx new file mode 100644 index 000000000..62d83e07d --- /dev/null +++ b/src/customers/views/CustomerCreate.tsx @@ -0,0 +1,95 @@ +import * as React from "react"; + +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../i18n"; +import { maybe } from "../../misc"; +import CustomerCreatePage from "../components/CustomerCreatePage"; +import { TypedCreateCustomerMutation } from "../mutations"; +import { TypedCustomerCreateDataQuery } from "../queries"; +import { CreateCustomer } from "../types/CreateCustomer"; +import { customerListUrl, customerUrl } from "../urls"; + +export const CustomerCreate: React.StatelessComponent<{}> = () => { + const navigate = useNavigator(); + const notify = useNotifier(); + + const handleCreateCustomerSuccess = (data: CreateCustomer) => { + if (data.customerCreate.errors.length === 0) { + notify({ + text: i18n.t("Customer created", { + context: "notification" + }) + }); + navigate(customerUrl(data.customerCreate.user.id)); + } + }; + return ( + + {({ data, loading }) => ( + + {(createCustomer, createCustomerOpts) => ( + <> + + data.shop.countries, [])} + disabled={loading || createCustomerOpts.loading} + errors={maybe(() => { + const errs = createCustomerOpts.data.customerCreate.errors; + return errs.map(err => + err.field.split(":").length > 1 + ? { + ...err, + field: err.field.split(":")[1] + } + : err + ); + }, [])} + saveButtonBar={ + createCustomerOpts.loading ? "loading" : "default" + } + onBack={() => navigate(customerListUrl())} + onSubmit={formData => { + const address = { + city: formData.city, + cityArea: formData.cityArea, + companyName: formData.companyName, + country: formData.country, + countryArea: formData.countryArea, + firstName: formData.firstName, + lastName: formData.lastName, + phone: formData.phone, + postalCode: formData.postalCode, + streetAddress1: formData.streetAddress1, + streetAddress2: formData.streetAddress2 + }; + createCustomer({ + variables: { + input: { + defaultBillingAddress: { + ...address, + country: address.country.value + }, + defaultShippingAddress: { + ...address, + country: address.country.value + }, + email: formData.email, + firstName: formData.customerFirstName, + lastName: formData.customerLastName, + note: formData.note, + sendPasswordEmail: true + } + } + }); + }} + /> + + )} + + )} + + ); +}; +export default CustomerCreate; diff --git a/src/customers/views/CustomerDetails.tsx b/src/customers/views/CustomerDetails.tsx new file mode 100644 index 000000000..e6e9ab6aa --- /dev/null +++ b/src/customers/views/CustomerDetails.tsx @@ -0,0 +1,166 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import { orderListUrl, orderUrl } from "../../orders/urls"; +import CustomerDetailsPage from "../components/CustomerDetailsPage/CustomerDetailsPage"; +import { + TypedRemoveCustomerMutation, + TypedUpdateCustomerMutation +} from "../mutations"; +import { TypedCustomerDetailsQuery } from "../queries"; +import { RemoveCustomer } from "../types/RemoveCustomer"; +import { UpdateCustomer } from "../types/UpdateCustomer"; +import { + customerAddressesUrl, + customerListUrl, + customerUrl, + CustomerUrlQueryParams +} from "../urls"; + +interface CustomerDetailsViewProps { + id: string; + params: CustomerUrlQueryParams; +} + +export const CustomerDetailsView: React.StatelessComponent< + CustomerDetailsViewProps +> = ({ id, params }) => { + const navigate = useNavigator(); + const notify = useNotifier(); + + const handleCustomerUpdateSuccess = (data: UpdateCustomer) => { + if (data.customerUpdate.errors.length === 0) { + notify({ + text: i18n.t("Customer updated", { + context: "notification" + }) + }); + } + }; + const handleCustomerRemoveSuccess = (data: RemoveCustomer) => { + if (data.customerDelete.errors.length === 0) { + notify({ + text: i18n.t("Customer removed", { + context: "notification" + }) + }); + navigate(customerListUrl()); + } + }; + return ( + + {(removeCustomer, removeCustomerOpts) => ( + + {(updateCustomer, updateCustomerOpts) => ( + + {customerDetails => { + const formTransitionState = getMutationState( + updateCustomerOpts.called, + updateCustomerOpts.loading, + maybe(() => updateCustomerOpts.data.customerUpdate.errors) + ); + const removeTransitionState = getMutationState( + removeCustomerOpts.called, + removeCustomerOpts.loading, + maybe(() => removeCustomerOpts.data.customerDelete.errors) + ); + + return ( + <> + customerDetails.data.user.email)} + /> + updateCustomerOpts.data.customerUpdate.errors + )} + saveButtonBar={formTransitionState} + onAddressManageClick={() => + navigate(customerAddressesUrl(id)) + } + onBack={() => navigate(customerListUrl())} + onRowClick={id => navigate(orderUrl(id))} + onSubmit={formData => + updateCustomer({ + variables: { + id, + input: { + email: formData.email, + firstName: formData.firstName, + isActive: formData.isActive, + lastName: formData.lastName, + note: formData.note + } + } + }) + } + onDelete={() => + navigate( + customerUrl(id, { + action: "remove" + }) + ) + } + onViewAllOrdersClick={() => + navigate( + orderListUrl({ + email: maybe(() => customerDetails.data.user.email) + }) + ) + } + /> + navigate(customerUrl(id), true)} + onConfirm={() => removeCustomer()} + title={i18n.t("Remove customer", { + context: "modal title" + })} + variant="delete" + open={params.action === "remove"} + > + {{ email }}?", + { + context: "modal content", + email: maybe( + () => customerDetails.data.user.email, + "..." + ) + } + ) + }} + /> + + + ); + }} + + )} + + )} + + ); +}; +export default CustomerDetailsView; diff --git a/src/customers/views/CustomerList.tsx b/src/customers/views/CustomerList.tsx new file mode 100644 index 000000000..6961261af --- /dev/null +++ b/src/customers/views/CustomerList.tsx @@ -0,0 +1,153 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { PAGINATE_BY } from "../../config"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import CustomerListPage from "../components/CustomerListPage"; +import { TypedBulkRemoveCustomers } from "../mutations"; +import { TypedCustomerListQuery } from "../queries"; +import { BulkRemoveCustomers } from "../types/BulkRemoveCustomers"; +import { + customerAddUrl, + customerListUrl, + CustomerListUrlQueryParams, + customerUrl +} from "../urls"; + +interface CustomerListProps { + params: CustomerListUrlQueryParams; +} + +export const CustomerList: React.StatelessComponent = ({ + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const closeModal = () => + navigate( + customerListUrl({ + ...params, + action: undefined, + ids: undefined + }), + true + ); + + const paginationState = createPaginationState(PAGINATE_BY, params); + + return ( + + {({ data, loading, refetch }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.customers.pageInfo), + paginationState, + params + ); + + const handleBulkCustomerDelete = (data: BulkRemoveCustomers) => { + if (data.customerBulkDelete.errors.length === 0) { + notify({ + text: i18n.t("Customers removed") + }); + reset(); + refetch(); + closeModal(); + } + }; + + return ( + + {(bulkRemoveCustomers, bulkRemoveCustomersOpts) => { + const removeTransitionState = getMutationState( + bulkRemoveCustomersOpts.called, + bulkRemoveCustomersOpts.loading, + maybe( + () => bulkRemoveCustomersOpts.data.customerBulkDelete.errors + ) + ); + + return ( + <> + + data.customers.edges.map(edge => edge.node) + )} + disabled={loading} + pageInfo={pageInfo} + onAdd={() => navigate(customerAddUrl)} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRowClick={id => () => navigate(customerUrl(id))} + toolbar={ + + navigate( + customerListUrl({ + action: "remove", + ids: listElements + }) + ) + } + > + + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + /> + + bulkRemoveCustomers({ + variables: { + ids: params.ids + } + }) + } + variant="delete" + title={i18n.t("Remove customers")} + > + {{ number }} customers?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + ); + }} + + ); + }} + + ); +}; +export default CustomerList; diff --git a/src/discounts/components/DiscountCategories/DiscountCategories.tsx b/src/discounts/components/DiscountCategories/DiscountCategories.tsx new file mode 100644 index 000000000..a608481f5 --- /dev/null +++ b/src/discounts/components/DiscountCategories/DiscountCategories.tsx @@ -0,0 +1,173 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import IconButton from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Checkbox from "@saleor/components/Checkbox"; +import Skeleton from "@saleor/components/Skeleton"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { SaleDetails_sale } from "../../types/SaleDetails"; +import { VoucherDetails_voucher } from "../../types/VoucherDetails"; + +export interface DiscountCategoriesProps extends ListProps, ListActions { + discount: SaleDetails_sale | VoucherDetails_voucher; + onCategoryAssign: () => void; + onCategoryUnassign: (id: string) => void; +} + +const styles = (theme: Theme) => + createStyles({ + iconCell: { + "&:last-child": { + paddingRight: 0 + }, + width: 48 + theme.spacing.unit / 2 + }, + tableRow: { + cursor: "pointer" + }, + textRight: { + textAlign: "right" + }, + wideColumn: { + width: "60%" + } + }); +const DiscountCategories = withStyles(styles, { + name: "DiscountCategories" +})( + ({ + discount: sale, + classes, + disabled, + pageInfo, + onCategoryAssign, + onCategoryUnassign, + onRowClick, + onPreviousPage, + onNextPage, + toolbar, + toggle, + toggleAll, + selected, + isChecked + }: DiscountCategoriesProps & WithStyles) => ( + + sale.name) + })} + toolbar={ + + } + /> + + sale.categories.edges.map(edge => edge.node))} + toggleAll={toggleAll} + toolbar={toolbar} + > + <> + + + {i18n.t("Category name")} + + + {i18n.t("Products")} + + + + + + + + + + + {renderCollection( + maybe(() => sale.categories.edges.map(edge => edge.node)), + category => { + const isSelected = category ? isChecked(category.id) : false; + + return ( + + + toggle(category.id)} + /> + + + {maybe(() => category.name, )} + + + {maybe( + () => category.products.totalCount, + + )} + + + { + event.stopPropagation(); + onCategoryUnassign(category.id); + }} + > + + + + + ); + }, + () => ( + + + {i18n.t("No categories found")} + + + ) + )} + +
+
+ ) +); +DiscountCategories.displayName = "DiscountCategories"; +export default DiscountCategories; diff --git a/src/discounts/components/DiscountCategories/index.ts b/src/discounts/components/DiscountCategories/index.ts new file mode 100644 index 000000000..00e781deb --- /dev/null +++ b/src/discounts/components/DiscountCategories/index.ts @@ -0,0 +1,2 @@ +export { default } from "./DiscountCategories"; +export * from "./DiscountCategories"; diff --git a/src/discounts/components/DiscountCollections/DiscountCollections.tsx b/src/discounts/components/DiscountCollections/DiscountCollections.tsx new file mode 100644 index 000000000..ec1f7900e --- /dev/null +++ b/src/discounts/components/DiscountCollections/DiscountCollections.tsx @@ -0,0 +1,171 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import IconButton from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Checkbox from "@saleor/components/Checkbox"; +import Skeleton from "@saleor/components/Skeleton"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { SaleDetails_sale } from "../../types/SaleDetails"; +import { VoucherDetails_voucher } from "../../types/VoucherDetails"; + +export interface DiscountCollectionsProps extends ListProps, ListActions { + discount: SaleDetails_sale | VoucherDetails_voucher; + onCollectionAssign: () => void; + onCollectionUnassign: (id: string) => void; +} + +const styles = (theme: Theme) => + createStyles({ + iconCell: { + "&:last-child": { + paddingRight: 0 + }, + width: 48 + theme.spacing.unit / 2 + }, + tableRow: { + cursor: "pointer" + }, + textRight: { + textAlign: "right" + }, + wideColumn: { + width: "60%" + } + }); +const DiscountCollections = withStyles(styles, { + name: "DiscountCollections" +})( + ({ + discount: sale, + classes, + disabled, + pageInfo, + onCollectionAssign, + onCollectionUnassign, + onRowClick, + onPreviousPage, + onNextPage, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: DiscountCollectionsProps & WithStyles) => ( + + sale.name) + })} + toolbar={ + + } + /> + + sale.collections.edges.map(edge => edge.node))} + toggleAll={toggleAll} + toolbar={toolbar} + > + + {i18n.t("Collection name")} + + + {i18n.t("Products")} + + + + + + + + + {renderCollection( + maybe(() => sale.collections.edges.map(edge => edge.node)), + collection => { + const isSelected = collection ? isChecked(collection.id) : false; + return ( + + + toggle(collection.id)} + /> + + + {maybe( + () => collection.name, + + )} + + + {maybe( + () => collection.products.totalCount, + + )} + + + { + event.stopPropagation(); + onCollectionUnassign(collection.id); + }} + > + + + + + ); + }, + () => ( + + + {i18n.t("No collections found")} + + + ) + )} + +
+
+ ) +); +DiscountCollections.displayName = "DiscountCollections"; +export default DiscountCollections; diff --git a/src/discounts/components/DiscountCollections/index.ts b/src/discounts/components/DiscountCollections/index.ts new file mode 100644 index 000000000..5cd22c3a1 --- /dev/null +++ b/src/discounts/components/DiscountCollections/index.ts @@ -0,0 +1,2 @@ +export { default } from "./DiscountCollections"; +export * from "./DiscountCollections"; diff --git a/src/discounts/components/DiscountCountrySelectDialog/DiscountCountrySelectDialog.tsx b/src/discounts/components/DiscountCountrySelectDialog/DiscountCountrySelectDialog.tsx new file mode 100644 index 000000000..3a5aadaec --- /dev/null +++ b/src/discounts/components/DiscountCountrySelectDialog/DiscountCountrySelectDialog.tsx @@ -0,0 +1,190 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import { filter } from "fuzzaldrin"; +import * as React from "react"; + +import Checkbox from "@saleor/components/Checkbox"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import FormSpacer from "@saleor/components/FormSpacer"; +import Hr from "@saleor/components/Hr"; +// tslint:disable no-submodule-imports +import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo"; +import i18n from "../../../i18n"; + +interface FormData { + allCountries: boolean; + countries: string[]; + query: string; +} + +export interface DiscountCountrySelectDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + countries: ShopInfo_shop_countries[]; + initial: string[]; + open: boolean; + onClose: () => void; + onConfirm: (data: FormData) => void; +} + +const styles = (theme: Theme) => + createStyles({ + checkboxCell: { + paddingLeft: 0 + }, + container: { + maxHeight: 500 + }, + heading: { + marginBottom: theme.spacing.unit * 2, + marginTop: theme.spacing.unit * 2 + }, + wideCell: { + width: "100%" + } + }); +const DiscountCountrySelectDialog = withStyles(styles, { + name: "DiscountCountrySelectDialog" +})( + ({ + classes, + confirmButtonState, + onClose, + countries, + open, + initial, + onConfirm + }: DiscountCountrySelectDialogProps & WithStyles) => { + const initialForm: FormData = { + allCountries: true, + countries: initial, + query: "" + }; + return ( + +
+ {({ data, change }) => { + const countrySelectionMap = countries.reduce((acc, country) => { + acc[country.code] = !!data.countries.find( + selectedCountries => selectedCountries === country.code + ); + return acc; + }, {}); + + return ( + <> + {i18n.t("Assign Countries")} + + + {i18n.t( + "Choose countries, you want voucher to be limited to, from the list below" + )} + + + change(event, () => fetch(data.query))} + label={i18n.t("Search Countries", { + context: "country search input label" + })} + placeholder={i18n.t("Search by country name", { + context: "country search input placeholder" + })} + fullWidth + /> + +
+ + + {i18n.t("Countries A to Z", { + context: "country selection" + })} + + + + {filter(countries, data.query, { + key: "country" + }).map(country => { + const isChecked = countrySelectionMap[country.code]; + + return ( + + + {country.country} + + + + isChecked + ? change({ + target: { + name: "countries" as keyof FormData, + value: data.countries.filter( + selectedCountries => + selectedCountries !== country.code + ) + } + } as any) + : change({ + target: { + name: "countries" as keyof FormData, + value: [ + ...data.countries, + country.code + ] + } + } as any) + } + /> + + + ); + })} + +
+
+ + + + {i18n.t("Assign countries", { context: "button" })} + + + + ); + }} +
+
+ ); + } +); +DiscountCountrySelectDialog.displayName = "DiscountCountrySelectDialog"; +export default DiscountCountrySelectDialog; diff --git a/src/discounts/components/DiscountCountrySelectDialog/index.ts b/src/discounts/components/DiscountCountrySelectDialog/index.ts new file mode 100644 index 000000000..cbbee8a48 --- /dev/null +++ b/src/discounts/components/DiscountCountrySelectDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from './DiscountCountrySelectDialog'; +export * from './DiscountCountrySelectDialog'; \ No newline at end of file diff --git a/src/discounts/components/DiscountProducts/DiscountProducts.tsx b/src/discounts/components/DiscountProducts/DiscountProducts.tsx new file mode 100644 index 000000000..3df6478f1 --- /dev/null +++ b/src/discounts/components/DiscountProducts/DiscountProducts.tsx @@ -0,0 +1,199 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import IconButton from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Checkbox from "@saleor/components/Checkbox"; +import Skeleton from "@saleor/components/Skeleton"; +import StatusLabel from "@saleor/components/StatusLabel"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { SaleDetails_sale } from "../../types/SaleDetails"; +import { VoucherDetails_voucher } from "../../types/VoucherDetails"; + +export interface SaleProductsProps extends ListProps, ListActions { + discount: SaleDetails_sale | VoucherDetails_voucher; + onProductAssign: () => void; + onProductUnassign: (id: string) => void; +} + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colName: {}, + colPublished: { + width: 150 + }, + colType: { + width: 200 + } + }, + colName: {}, + colPublished: {}, + colType: {}, + iconCell: { + "&:last-child": { + paddingRight: 0 + }, + width: 48 + theme.spacing.unit / 2 + }, + tableRow: { + cursor: "pointer" + } + }); +const DiscountProducts = withStyles(styles, { + name: "DiscountProducts" +})( + ({ + discount: sale, + classes, + disabled, + pageInfo, + onRowClick, + onPreviousPage, + onProductAssign, + onProductUnassign, + onNextPage, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: SaleProductsProps & WithStyles) => ( + + sale.name) + })} + toolbar={ + + } + /> + + sale.products.edges.map(edge => edge.node))} + toggleAll={toggleAll} + toolbar={toolbar} + > + + + + {i18n.t("Product name")} + + + {i18n.t("Product Type")} + + + {i18n.t("Published")} + + + + + + + + + + {renderCollection( + maybe(() => sale.products.edges.map(edge => edge.node)), + product => { + const isSelected = product ? isChecked(product.id) : false; + return ( + + + toggle(product.id)} + /> + + product.thumbnail.url)} + /> + + {maybe(() => product.name, )} + + + {maybe( + () => product.productType.name, + + )} + + + {product && product.isPublished !== undefined ? ( + + ) : ( + + )} + + + { + event.stopPropagation(); + onProductUnassign(product.id); + }} + > + + + + + ); + }, + () => ( + + {i18n.t("No products found")} + + ) + )} + +
+
+ ) +); +DiscountProducts.displayName = "DiscountProducts"; +export default DiscountProducts; diff --git a/src/discounts/components/DiscountProducts/index.ts b/src/discounts/components/DiscountProducts/index.ts new file mode 100644 index 000000000..acd26089a --- /dev/null +++ b/src/discounts/components/DiscountProducts/index.ts @@ -0,0 +1,2 @@ +export { default } from "./DiscountProducts"; +export * from "./DiscountProducts"; diff --git a/src/discounts/components/SaleCreatePage/SaleCreatePage.tsx b/src/discounts/components/SaleCreatePage/SaleCreatePage.tsx new file mode 100644 index 000000000..d5dd1945d --- /dev/null +++ b/src/discounts/components/SaleCreatePage/SaleCreatePage.tsx @@ -0,0 +1,85 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { UserError } from "../../../types"; +import { SaleType } from "../../../types/globalTypes"; +import SaleInfo from "../SaleInfo"; +import SalePricing from "../SalePricing"; + +export interface FormData { + name: string; + startDate: string; + endDate: string; + value: string; + type: SaleType; +} + +export interface SaleCreatePageProps { + defaultCurrency: string; + disabled: boolean; + errors: UserError[]; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onSubmit: (data: FormData) => void; +} + +const SaleCreatePage: React.StatelessComponent = ({ + defaultCurrency, + disabled, + errors, + onSubmit, + saveButtonBarState, + onBack +}) => { + const initialForm: FormData = { + endDate: "", + name: "", + startDate: "", + type: SaleType.FIXED, + value: "" + }; + return ( +
+ {({ change, data, errors: formErrors, hasChanged, submit }) => ( + + {i18n.t("Sales")} + + +
+ + + +
+
+ +
+ )} +
+ ); +}; +SaleCreatePage.displayName = "SaleCreatePage"; +export default SaleCreatePage; diff --git a/src/discounts/components/SaleCreatePage/index.ts b/src/discounts/components/SaleCreatePage/index.ts new file mode 100644 index 000000000..5621f967a --- /dev/null +++ b/src/discounts/components/SaleCreatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SaleCreatePage"; +export * from "./SaleCreatePage"; diff --git a/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx b/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx new file mode 100644 index 000000000..d760c43f0 --- /dev/null +++ b/src/discounts/components/SaleDetailsPage/SaleDetailsPage.tsx @@ -0,0 +1,238 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { Tab, TabContainer } from "@saleor/components/Tab"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { ListProps, TabListActions, UserError } from "../../../types"; +import { SaleType } from "../../../types/globalTypes"; +import { SaleDetails_sale } from "../../types/SaleDetails"; +import DiscountCategories from "../DiscountCategories"; +import DiscountCollections from "../DiscountCollections"; +import DiscountProducts from "../DiscountProducts"; +import SaleInfo from "../SaleInfo"; +import SalePricing from "../SalePricing"; +import SaleSummary from "../SaleSummary"; + +export interface FormData { + name: string; + startDate: string; + endDate: string; + value: string; + type: SaleType; +} + +export enum SaleDetailsPageTab { + categories = "categories", + collections = "collections", + products = "products" +} +export function saleDetailsPageTab(tab: string): SaleDetailsPageTab { + return tab === SaleDetailsPageTab.products + ? SaleDetailsPageTab.products + : tab === SaleDetailsPageTab.collections + ? SaleDetailsPageTab.collections + : SaleDetailsPageTab.categories; +} + +export interface SaleDetailsPageProps + extends Pick>, + TabListActions< + "categoryListToolbar" | "collectionListToolbar" | "productListToolbar" + > { + activeTab: SaleDetailsPageTab; + defaultCurrency: string; + errors: UserError[]; + sale: SaleDetails_sale; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onCategoryAssign: () => void; + onCategoryUnassign: (id: string) => void; + onCategoryClick: (id: string) => () => void; + onCollectionAssign: () => void; + onCollectionUnassign: (id: string) => void; + onCollectionClick: (id: string) => () => void; + onProductAssign: () => void; + onProductUnassign: (id: string) => void; + onProductClick: (id: string) => () => void; + onRemove: () => void; + onSubmit: (data: FormData) => void; + onTabClick: (index: SaleDetailsPageTab) => void; +} + +const CategoriesTab = Tab(SaleDetailsPageTab.categories); +const CollectionsTab = Tab(SaleDetailsPageTab.collections); +const ProductsTab = Tab(SaleDetailsPageTab.products); + +const SaleDetailsPage: React.StatelessComponent = ({ + activeTab, + defaultCurrency, + disabled, + errors, + onRemove, + onSubmit, + onTabClick, + pageInfo, + sale, + saveButtonBarState, + onBack, + onCategoryAssign, + onCategoryUnassign, + onCategoryClick, + onCollectionAssign, + onCollectionUnassign, + onCollectionClick, + onNextPage, + onPreviousPage, + onProductAssign, + onProductUnassign, + onProductClick, + categoryListToolbar, + collectionListToolbar, + productListToolbar, + isChecked, + selected, + toggle, + toggleAll +}) => { + const initialForm: FormData = { + endDate: maybe(() => (sale.endDate ? sale.endDate : ""), ""), + name: maybe(() => sale.name, ""), + startDate: maybe(() => sale.startDate, ""), + type: maybe(() => sale.type, SaleType.FIXED), + value: maybe(() => sale.value.toString(), "") + }; + return ( +
+ {({ change, data, errors: formErrors, hasChanged, submit }) => ( + + {i18n.t("Sales")} + sale.name)} /> + +
+ + + + + + + {i18n.t("Categories ({{ number }})", { + number: maybe( + () => sale.categories.totalCount.toString(), + "…" + ) + })} + + + {i18n.t("Collections ({{ number }})", { + number: maybe( + () => sale.collections.totalCount.toString(), + "…" + ) + })} + + + {i18n.t("Products ({{ number }})", { + number: maybe( + () => sale.products.totalCount.toString(), + "…" + ) + })} + + + + {activeTab === SaleDetailsPageTab.categories ? ( + + ) : activeTab === SaleDetailsPageTab.collections ? ( + + ) : ( + + )} +
+
+ +
+
+ +
+ )} +
+ ); +}; +SaleDetailsPage.displayName = "SaleDetailsPage"; +export default SaleDetailsPage; diff --git a/src/discounts/components/SaleDetailsPage/index.ts b/src/discounts/components/SaleDetailsPage/index.ts new file mode 100644 index 000000000..32c43a08b --- /dev/null +++ b/src/discounts/components/SaleDetailsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SaleDetailsPage"; +export * from "./SaleDetailsPage"; diff --git a/src/discounts/components/SaleInfo/SaleInfo.tsx b/src/discounts/components/SaleInfo/SaleInfo.tsx new file mode 100644 index 000000000..606cf94a6 --- /dev/null +++ b/src/discounts/components/SaleInfo/SaleInfo.tsx @@ -0,0 +1,62 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + WithStyles, + withStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import i18n from "../../../i18n"; +import { FormData } from "../SaleDetailsPage"; + +export interface SaleInfoProps { + data: FormData; + disabled: boolean; + errors: { + name?: string; + }; + onChange: (event: React.ChangeEvent) => void; +} + +const styles = (theme: Theme) => + createStyles({ + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridTemplateColumns: "3fr 1fr" + } + }); + +const SaleInfo = withStyles(styles, { + name: "SaleInfo" +})( + ({ + classes, + data, + disabled, + errors, + onChange + }: SaleInfoProps & WithStyles) => ( + + + + + + + ) +); +SaleInfo.displayName = "SaleInfo"; +export default SaleInfo; diff --git a/src/discounts/components/SaleInfo/index.ts b/src/discounts/components/SaleInfo/index.ts new file mode 100644 index 000000000..2abfa07d8 --- /dev/null +++ b/src/discounts/components/SaleInfo/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SaleInfo"; +export * from "./SaleInfo"; diff --git a/src/discounts/components/SaleList/SaleList.tsx b/src/discounts/components/SaleList/SaleList.tsx new file mode 100644 index 000000000..80a174b36 --- /dev/null +++ b/src/discounts/components/SaleList/SaleList.tsx @@ -0,0 +1,197 @@ +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + WithStyles, + withStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import Checkbox from "@saleor/components/Checkbox"; +import Date from "@saleor/components/Date"; +import Money from "@saleor/components/Money"; +import Percent from "@saleor/components/Percent"; +import Skeleton from "@saleor/components/Skeleton"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { SaleType } from "../../../types/globalTypes"; +import { SaleList_sales_edges_node } from "../../types/SaleList"; + +export interface SaleListProps extends ListProps, ListActions { + defaultCurrency: string; + sales: SaleList_sales_edges_node[]; +} + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colEnd: { + width: 250 + }, + colName: {}, + colStart: { + width: 250 + }, + colValue: { + width: 200 + } + }, + colEnd: { + textAlign: "right" + }, + colName: {}, + colStart: { + textAlign: "right" + }, + colValue: { + textAlign: "right" + }, + tableRow: { + cursor: "pointer" + } + }); + +const SaleList = withStyles(styles, { + name: "SaleList" +})( + ({ + classes, + defaultCurrency, + disabled, + onNextPage, + onPreviousPage, + onRowClick, + pageInfo, + sales, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: SaleListProps & WithStyles) => ( + + + + + {i18n.t("Name", { + context: "sale list table header" + })} + + + {i18n.t("Starts", { + context: "sale list table header" + })} + + + {i18n.t("Ends", { + context: "sale list table header" + })} + + + {i18n.t("Value", { + context: "sale list table header" + })} + + + + + + + + + {renderCollection( + sales, + sale => { + const isSelected = sale ? isChecked(sale.id) : false; + + return ( + + + toggle(sale.id)} + /> + + + {maybe(() => sale.name, )} + + + {sale && sale.startDate ? ( + + ) : ( + + )} + + + {sale && sale.endDate ? ( + + ) : sale && sale.endDate === null ? ( + "-" + ) : ( + + )} + + + {sale && sale.type && sale.value ? ( + sale.type === SaleType.FIXED ? ( + + ) : ( + + ) + ) : ( + + )} + + + ); + }, + () => ( + + {i18n.t("No sales found")} + + ) + )} + +
+
+ ) +); +SaleList.displayName = "SaleList"; +export default SaleList; diff --git a/src/discounts/components/SaleList/index.ts b/src/discounts/components/SaleList/index.ts new file mode 100644 index 000000000..20d8fef01 --- /dev/null +++ b/src/discounts/components/SaleList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SaleList"; +export * from "./SaleList"; diff --git a/src/discounts/components/SaleListPage/SaleListPage.tsx b/src/discounts/components/SaleListPage/SaleListPage.tsx new file mode 100644 index 000000000..0d49e9c22 --- /dev/null +++ b/src/discounts/components/SaleListPage/SaleListPage.tsx @@ -0,0 +1,32 @@ +import Button from "@material-ui/core/Button"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { ListActions, PageListProps } from "../../../types"; +import { SaleList_sales_edges_node } from "../../types/SaleList"; +import SaleList from "../SaleList"; + +export interface SaleListPageProps extends PageListProps, ListActions { + defaultCurrency: string; + sales: SaleList_sales_edges_node[]; +} + +const SaleListPage: React.StatelessComponent = ({ + onAdd, + ...listProps +}) => ( + + + + + + +); +SaleListPage.displayName = "SaleListPage"; +export default SaleListPage; diff --git a/src/discounts/components/SaleListPage/index.ts b/src/discounts/components/SaleListPage/index.ts new file mode 100644 index 000000000..59dd2585a --- /dev/null +++ b/src/discounts/components/SaleListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SaleListPage"; +export * from "./SaleListPage"; diff --git a/src/discounts/components/SalePricing/SalePricing.tsx b/src/discounts/components/SalePricing/SalePricing.tsx new file mode 100644 index 000000000..45eb60472 --- /dev/null +++ b/src/discounts/components/SalePricing/SalePricing.tsx @@ -0,0 +1,117 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + WithStyles, + withStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Hr from "@saleor/components/Hr"; +import TextFieldWithChoice from "@saleor/components/TextFieldWithChoice"; +import i18n from "../../../i18n"; +import { FormErrors } from "../../../types"; +import { SaleType } from "../../../types/globalTypes"; +import { FormData } from "../SaleDetailsPage"; + +export interface SalePricingProps { + data: FormData; + defaultCurrency: string; + disabled: boolean; + errors: FormErrors<"startDate" | "endDate" | "value">; + onChange: (event: React.ChangeEvent) => void; +} + +const styles = (theme: Theme) => + createStyles({ + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridTemplateColumns: "1fr 1fr" + }, + subheading: { + gridColumnEnd: "span 2", + marginBottom: theme.spacing.unit * 2 + } + }); + +const SalePricing = withStyles(styles, { + name: "SalePricing" +})( + ({ + classes, + data, + defaultCurrency, + disabled, + errors, + onChange + }: SalePricingProps & WithStyles) => ( + + + + + +
+ + + {i18n.t("Time Frame")} + + + + +
+ ) +); +SalePricing.displayName = "SalePricing"; +export default SalePricing; diff --git a/src/discounts/components/SalePricing/index.ts b/src/discounts/components/SalePricing/index.ts new file mode 100644 index 000000000..347c08adc --- /dev/null +++ b/src/discounts/components/SalePricing/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SalePricing"; +export * from "./SalePricing"; diff --git a/src/discounts/components/SaleSummary/SaleSummary.tsx b/src/discounts/components/SaleSummary/SaleSummary.tsx new file mode 100644 index 000000000..5cfa73db8 --- /dev/null +++ b/src/discounts/components/SaleSummary/SaleSummary.tsx @@ -0,0 +1,82 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardSpacer from "@saleor/components/CardSpacer"; +import CardTitle from "@saleor/components/CardTitle"; +import Date from "@saleor/components/Date"; +import FormSpacer from "@saleor/components/FormSpacer"; +import Hr from "@saleor/components/Hr"; +import Money from "@saleor/components/Money"; +import Percent from "@saleor/components/Percent"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { SaleType } from "../../../types/globalTypes"; +import { SaleDetails_sale } from "../../types/SaleDetails"; + +export interface SaleSummaryProps { + defaultCurrency: string; + sale: SaleDetails_sale; +} + +const SaleSummary: React.StatelessComponent = ({ + defaultCurrency, + sale +}) => ( + + + + {i18n.t("Name")} + + {maybe(() => sale.name, )} + + + + {i18n.t("Value")} + + {maybe( + () => + sale.type === SaleType.FIXED ? ( + + ) : ( + + ), + + )} + + + +
+ + + {i18n.t("Start Date")} + + {maybe( + () => ( + + ), + + )} + + + + {i18n.t("End Date")} + + {maybe( + () => + sale.endDate === null ? "-" : , + + )} + +
+
+); +SaleSummary.displayName = "SaleSummary"; +export default SaleSummary; diff --git a/src/discounts/components/SaleSummary/index.ts b/src/discounts/components/SaleSummary/index.ts new file mode 100644 index 000000000..6e0a510f5 --- /dev/null +++ b/src/discounts/components/SaleSummary/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SaleSummary"; +export * from "./SaleSummary"; diff --git a/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx b/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx new file mode 100644 index 000000000..46147595f --- /dev/null +++ b/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx @@ -0,0 +1,101 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { UserError } from "../../../types"; +import { + VoucherDiscountValueType, + VoucherType +} from "../../../types/globalTypes"; +import VoucherInfo from "../VoucherInfo"; +import VoucherOptions from "../VoucherOptions"; + +export interface FormData { + applyOncePerOrder: boolean; + code: string; + discountType: VoucherDiscountValueType; + endDate: string; + minAmountSpent: number; + name: string; + startDate: string; + type: VoucherType; + usageLimit: number; + value: number; +} + +export interface VoucherCreatePageProps { + defaultCurrency: string; + disabled: boolean; + errors: UserError[]; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onSubmit: (data: FormData) => void; +} + +const VoucherCreatePage: React.StatelessComponent = ({ + defaultCurrency, + disabled, + errors, + saveButtonBarState, + onBack, + onSubmit +}) => { + const initialForm: FormData = { + applyOncePerOrder: false, + code: "", + discountType: VoucherDiscountValueType.FIXED, + endDate: "", + minAmountSpent: 0, + name: "", + startDate: "", + type: VoucherType.VALUE, + usageLimit: 0, + value: 0 + }; + + return ( +
+ {({ change, data, errors: formErrors, hasChanged, submit }) => ( + + {i18n.t("Vouchers")} + + +
+ + + + +
+
+ +
+ )} +
+ ); +}; +VoucherCreatePage.displayName = "VoucherCreatePage"; +export default VoucherCreatePage; diff --git a/src/discounts/components/VoucherCreatePage/index.ts b/src/discounts/components/VoucherCreatePage/index.ts new file mode 100644 index 000000000..b38cb8083 --- /dev/null +++ b/src/discounts/components/VoucherCreatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from './VoucherCreatePage'; +export * from './VoucherCreatePage'; \ No newline at end of file diff --git a/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx b/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx new file mode 100644 index 000000000..fec9980d7 --- /dev/null +++ b/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx @@ -0,0 +1,290 @@ +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import CountryList from "@saleor/components/CountryList"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { Tab, TabContainer } from "@saleor/components/Tab"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { ListProps, TabListActions, UserError } from "../../../types"; +import { + VoucherDiscountValueType, + VoucherType +} from "../../../types/globalTypes"; +import { VoucherDetails_voucher } from "../../types/VoucherDetails"; +import DiscountCategories from "../DiscountCategories"; +import DiscountCollections from "../DiscountCollections"; +import DiscountProducts from "../DiscountProducts"; +import VoucherInfo from "../VoucherInfo"; +import VoucherOptions from "../VoucherOptions"; +import VoucherSummary from "../VoucherSummary"; + +export enum VoucherDetailsPageTab { + categories = "categories", + collections = "collections", + products = "products" +} +export function voucherDetailsPageTab(tab: string): VoucherDetailsPageTab { + return tab === VoucherDetailsPageTab.products + ? VoucherDetailsPageTab.products + : tab === VoucherDetailsPageTab.collections + ? VoucherDetailsPageTab.collections + : VoucherDetailsPageTab.categories; +} + +export interface FormData { + applyOncePerOrder: boolean; + code: string; + discountType: VoucherDiscountValueType; + endDate: string; + minAmountSpent: number; + name: string; + startDate: string; + type: VoucherType; + usageLimit: number; + value: number; +} + +export interface VoucherDetailsPageProps + extends Pick>, + TabListActions< + "categoryListToolbar" | "collectionListToolbar" | "productListToolbar" + > { + activeTab: VoucherDetailsPageTab; + defaultCurrency: string; + errors: UserError[]; + saveButtonBarState: ConfirmButtonTransitionState; + voucher: VoucherDetails_voucher; + onBack: () => void; + onCategoryAssign: () => void; + onCategoryUnassign: (id: string) => void; + onCategoryClick: (id: string) => () => void; + onCollectionAssign: () => void; + onCollectionUnassign: (id: string) => void; + onCollectionClick: (id: string) => () => void; + onCountryAssign: () => void; + onCountryUnassign: (code: string) => void; + onProductAssign: () => void; + onProductUnassign: (id: string) => void; + onProductClick: (id: string) => () => void; + onRemove: () => void; + onSubmit: (data: FormData) => void; + onTabClick: (index: VoucherDetailsPageTab) => void; +} + +const CategoriesTab = Tab(VoucherDetailsPageTab.categories); +const CollectionsTab = Tab(VoucherDetailsPageTab.collections); +const ProductsTab = Tab(VoucherDetailsPageTab.products); + +const VoucherDetailsPage: React.StatelessComponent = ({ + activeTab, + defaultCurrency, + disabled, + errors, + pageInfo, + saveButtonBarState, + voucher, + onBack, + onCategoryAssign, + onCategoryClick, + onCategoryUnassign, + onCountryAssign, + onCountryUnassign, + onCollectionAssign, + onCollectionClick, + onCollectionUnassign, + onNextPage, + onPreviousPage, + onProductAssign, + onProductClick, + onProductUnassign, + onTabClick, + onRemove, + onSubmit, + toggle, + toggleAll, + selected, + isChecked, + categoryListToolbar, + collectionListToolbar, + productListToolbar +}) => { + const initialForm: FormData = { + applyOncePerOrder: maybe(() => voucher.applyOncePerOrder, false), + code: maybe(() => voucher.code, ""), + discountType: maybe( + () => voucher.discountValueType, + VoucherDiscountValueType.FIXED + ), + endDate: maybe(() => voucher.endDate, ""), + minAmountSpent: maybe(() => voucher.minAmountSpent.amount, 0), + name: maybe(() => voucher.name, ""), + startDate: maybe(() => voucher.startDate, ""), + type: maybe(() => voucher.type, VoucherType.VALUE), + usageLimit: maybe(() => voucher.usageLimit || 0, 0), + value: maybe(() => voucher.discountValue, 0) + }; + + return ( +
+ {({ change, data, errors: formErrors, hasChanged, submit }) => ( + + {i18n.t("Vouchers")} + voucher.name)} /> + +
+ + + + + {data.type === VoucherType.CATEGORY || + data.type === VoucherType.COLLECTION || + data.type === VoucherType.PRODUCT ? ( + <> + + + {i18n.t("Categories ({{ number }})", { + number: maybe( + () => voucher.categories.totalCount.toString(), + "…" + ) + })} + + + {i18n.t("Collections ({{ number }})", { + number: maybe( + () => voucher.collections.totalCount.toString(), + "…" + ) + })} + + + {i18n.t("Products ({{ number }})", { + number: maybe( + () => voucher.products.totalCount.toString(), + "…" + ) + })} + + + + {activeTab === VoucherDetailsPageTab.categories ? ( + + ) : activeTab === VoucherDetailsPageTab.collections ? ( + + ) : ( + + )} + + ) : data.type === VoucherType.SHIPPING ? ( + voucher.countries)} + disabled={disabled} + emptyText={i18n.t("Voucher applies to all countries")} + title={ + <> + {i18n.t("Countries assigned to {{ voucherName }}", { + voucherName: maybe(() => voucher.name) + })} + + {i18n.t("Vouchers limited to these countries")} + + + } + onCountryAssign={onCountryAssign} + onCountryUnassign={onCountryUnassign} + /> + ) : null} +
+
+ +
+
+ +
+ )} +
+ ); +}; +VoucherDetailsPage.displayName = "VoucherDetailsPage"; + +export default VoucherDetailsPage; diff --git a/src/discounts/components/VoucherDetailsPage/index.ts b/src/discounts/components/VoucherDetailsPage/index.ts new file mode 100644 index 000000000..d165924b6 --- /dev/null +++ b/src/discounts/components/VoucherDetailsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./VoucherDetailsPage"; +export * from "./VoucherDetailsPage"; diff --git a/src/discounts/components/VoucherInfo/VoucherInfo.tsx b/src/discounts/components/VoucherInfo/VoucherInfo.tsx new file mode 100644 index 000000000..7395fe33f --- /dev/null +++ b/src/discounts/components/VoucherInfo/VoucherInfo.tsx @@ -0,0 +1,101 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import FormSpacer from "@saleor/components/FormSpacer"; +import SingleSelectField from "@saleor/components/SingleSelectField"; +import i18n from "../../../i18n"; +import { FormErrors } from "../../../types"; +import { VoucherType } from "../../../types/globalTypes"; +import { translateVoucherTypes } from "../../translations"; +import { FormData } from "../VoucherDetailsPage"; + +interface VoucherInfoProps { + data: FormData; + errors: FormErrors<"name" | "code" | "type">; + disabled: boolean; + variant: "create" | "update"; + onChange: (event: React.ChangeEvent) => void; +} + +const styles = (theme: Theme) => + createStyles({ + nameInput: { + gridColumnEnd: "span 2" + }, + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridTemplateColumns: "1fr 1fr" + } + }); + +const VoucherInfo = withStyles(styles, { + name: "VoucherInfo" +})( + ({ + classes, + data, + disabled, + errors, + variant, + onChange + }: VoucherInfoProps & WithStyles) => { + const translatedVoucherTypes = translateVoucherTypes(); + const voucherTypeChoices = Object.values(VoucherType).map(type => ({ + label: translatedVoucherTypes[type], + value: type + })); + + return ( + + + + + +
+ + +
+
+
+ ); + } +); +export default VoucherInfo; diff --git a/src/discounts/components/VoucherInfo/index.ts b/src/discounts/components/VoucherInfo/index.ts new file mode 100644 index 000000000..0f852b910 --- /dev/null +++ b/src/discounts/components/VoucherInfo/index.ts @@ -0,0 +1,2 @@ +export { default } from "./VoucherInfo"; +export * from "./VoucherInfo"; diff --git a/src/discounts/components/VoucherList/VoucherList.tsx b/src/discounts/components/VoucherList/VoucherList.tsx new file mode 100644 index 000000000..f18df8d5a --- /dev/null +++ b/src/discounts/components/VoucherList/VoucherList.tsx @@ -0,0 +1,243 @@ +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + WithStyles, + withStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import Checkbox from "@saleor/components/Checkbox"; +import Date from "@saleor/components/Date"; +import Money from "@saleor/components/Money"; +import Percent from "@saleor/components/Percent"; +import Skeleton from "@saleor/components/Skeleton"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { VoucherDiscountValueType } from "../../../types/globalTypes"; +import { VoucherList_vouchers_edges_node } from "../../types/VoucherList"; + +export interface VoucherListProps extends ListProps, ListActions { + defaultCurrency: string; + vouchers: VoucherList_vouchers_edges_node[]; +} + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colEnd: { + width: 180 + }, + colMinSpent: { + width: 150 + }, + colName: {}, + colStart: { + width: 180 + }, + colUses: { + width: 150 + }, + colValue: { + width: 150 + } + }, + colEnd: { + textAlign: "right" + }, + colMinSpent: { + textAlign: "right" + }, + colName: {}, + colStart: { + textAlign: "right" + }, + colUses: { + textAlign: "right" + }, + colValue: { + textAlign: "right" + }, + tableRow: { + cursor: "pointer" + }, + textRight: { + textAlign: "right" + } + }); + +const VoucherList = withStyles(styles, { + name: "VoucherList" +})( + ({ + classes, + defaultCurrency, + disabled, + onNextPage, + onPreviousPage, + onRowClick, + pageInfo, + vouchers, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: VoucherListProps & WithStyles) => ( + + + + + {i18n.t("Name", { + context: "voucher list table header" + })} + + + {i18n.t("Min. Spent", { + context: "voucher list table header" + })} + + + {i18n.t("Starts", { + context: "voucher list table header" + })} + + + {i18n.t("Ends", { + context: "voucher list table header" + })} + + + {i18n.t("Value", { + context: "voucher list table header" + })} + + + {i18n.t("Uses", { + context: "voucher list table header" + })} + + + + + + + + + {renderCollection( + vouchers, + voucher => { + const isSelected = voucher ? isChecked(voucher.id) : false; + + return ( + + + toggle(voucher.id)} + /> + + + {maybe(() => voucher.name, )} + + + {voucher && voucher.minAmountSpent ? ( + + ) : voucher && voucher.minAmountSpent === null ? ( + "-" + ) : ( + + )} + + + {voucher && voucher.startDate ? ( + + ) : ( + + )} + + + {voucher && voucher.endDate ? ( + + ) : voucher && voucher.endDate === null ? ( + "-" + ) : ( + + )} + + + {voucher && + voucher.discountValueType && + voucher.discountValue ? ( + voucher.discountValueType === + VoucherDiscountValueType.FIXED ? ( + + ) : ( + + ) + ) : ( + + )} + + + {voucher && voucher.usageLimit ? ( + voucher.usageLimit + ) : voucher && voucher.usageLimit === null ? ( + "-" + ) : ( + + )} + + + ); + }, + () => ( + + {i18n.t("No vouchers found")} + + ) + )} + +
+
+ ) +); +VoucherList.displayName = "VoucherList"; +export default VoucherList; diff --git a/src/discounts/components/VoucherList/index.ts b/src/discounts/components/VoucherList/index.ts new file mode 100644 index 000000000..c84409632 --- /dev/null +++ b/src/discounts/components/VoucherList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./VoucherList"; +export * from "./VoucherList"; diff --git a/src/discounts/components/VoucherListPage/VoucherListPage.tsx b/src/discounts/components/VoucherListPage/VoucherListPage.tsx new file mode 100644 index 000000000..cf40fff3f --- /dev/null +++ b/src/discounts/components/VoucherListPage/VoucherListPage.tsx @@ -0,0 +1,56 @@ +import Button from "@material-ui/core/Button"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { ListActions, PageListProps } from "../../../types"; +import { VoucherList_vouchers_edges_node } from "../../types/VoucherList"; +import VoucherList from "../VoucherList"; + +export interface VoucherListPageProps extends PageListProps, ListActions { + defaultCurrency: string; + vouchers: VoucherList_vouchers_edges_node[]; +} + +const VoucherListPage: React.StatelessComponent = ({ + defaultCurrency, + disabled, + onAdd, + onNextPage, + onPreviousPage, + onRowClick, + pageInfo, + vouchers, + isChecked, + selected, + toggle, + toggleAll, + toolbar +}) => ( + + + + + + +); +VoucherListPage.displayName = "VoucherListPage"; +export default VoucherListPage; diff --git a/src/discounts/components/VoucherListPage/index.ts b/src/discounts/components/VoucherListPage/index.ts new file mode 100644 index 000000000..84b3fa702 --- /dev/null +++ b/src/discounts/components/VoucherListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./VoucherListPage"; +export * from "./VoucherListPage"; diff --git a/src/discounts/components/VoucherOptions/VoucherOptions.tsx b/src/discounts/components/VoucherOptions/VoucherOptions.tsx new file mode 100644 index 000000000..c9bde716b --- /dev/null +++ b/src/discounts/components/VoucherOptions/VoucherOptions.tsx @@ -0,0 +1,177 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import ControlledSwitch from "@saleor/components/ControlledSwitch"; +import FormSpacer from "@saleor/components/FormSpacer"; +import Hr from "@saleor/components/Hr"; +import TextFieldWithChoice from "@saleor/components/TextFieldWithChoice"; +import i18n from "../../../i18n"; +import { FormErrors } from "../../../types"; +import { VoucherDiscountValueType } from "../../../types/globalTypes"; +import { FormData } from "../VoucherDetailsPage"; + +interface VoucherOptionsProps { + data: FormData; + defaultCurrency: string; + disabled: boolean; + errors: FormErrors< + | "discountType" + | "discountValue" + | "endDate" + | "minAmountSpent" + | "startDate" + | "usageLimit" + >; + onChange: (event: React.ChangeEvent) => void; +} + +const styles = (theme: Theme) => + createStyles({ + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridTemplateColumns: "1fr 1fr" + } + }); + +const VoucherOptions = withStyles(styles, { + name: "VoucherOptions" +})( + ({ + classes, + data, + defaultCurrency, + disabled, + errors, + onChange + }: VoucherOptionsProps & WithStyles) => ( + + + + + + +
+ + + {i18n.t("Discount Specific Information")} + + +
+ +
+ + + {i18n.t("Only once per order", { + context: "voucher application" + })} + + {i18n.t( + "If this option is disabled, discount will be counted for every eligible product" + )} + + + } + onChange={onChange} + name={"applyOncePerOrder" as keyof FormData} + disabled={disabled} + /> +
+
+ + {i18n.t("Time Frame")} + +
+ + +
+
+
+ ) +); +export default VoucherOptions; diff --git a/src/discounts/components/VoucherOptions/index.ts b/src/discounts/components/VoucherOptions/index.ts new file mode 100644 index 000000000..3b2411d35 --- /dev/null +++ b/src/discounts/components/VoucherOptions/index.ts @@ -0,0 +1,2 @@ +export { default } from "./VoucherOptions"; +export * from "./VoucherOptions"; diff --git a/src/discounts/components/VoucherSummary/VoucherSummary.tsx b/src/discounts/components/VoucherSummary/VoucherSummary.tsx new file mode 100644 index 000000000..e3035f126 --- /dev/null +++ b/src/discounts/components/VoucherSummary/VoucherSummary.tsx @@ -0,0 +1,126 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardSpacer from "@saleor/components/CardSpacer"; +import CardTitle from "@saleor/components/CardTitle"; +import Date from "@saleor/components/Date"; +import FormSpacer from "@saleor/components/FormSpacer"; +import Hr from "@saleor/components/Hr"; +import Money from "@saleor/components/Money"; +import Percent from "@saleor/components/Percent"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { VoucherDiscountValueType } from "../../../types/globalTypes"; +import { translateVoucherTypes } from "../../translations"; +import { VoucherDetails_voucher } from "../../types/VoucherDetails"; + +export interface VoucherSummaryProps { + defaultCurrency: string; + voucher: VoucherDetails_voucher; +} + +const VoucherSummary: React.StatelessComponent = ({ + defaultCurrency, + voucher +}) => { + const translatedVoucherTypes = translateVoucherTypes(); + + return ( + + + + {i18n.t("Name")} + + {maybe(() => voucher.name, )} + + + + {i18n.t("Applies to")} + + {maybe( + () => translatedVoucherTypes[voucher.type], + + )} + + + + {i18n.t("Value")} + + {maybe( + () => + voucher.discountValueType === VoucherDiscountValueType.FIXED ? ( + + ) : ( + + ), + + )} + + + +
+ + + {i18n.t("Start Date")} + + {maybe( + () => ( + + ), + + )} + + + + {i18n.t("End Date")} + + {maybe( + () => + voucher.endDate === null ? ( + "-" + ) : ( + + ), + + )} + + + +
+ + + {i18n.t("Min. Order Value")} + + {maybe( + () => + voucher.minAmountSpent ? ( + + ) : ( + "-" + ), + + )} + + + + {i18n.t("Usage Limit")} + + {maybe( + () => (voucher.usageLimit === null ? "-" : voucher.usageLimit), + + )} + +
+
+ ); +}; +VoucherSummary.displayName = "VoucherSummary"; +export default VoucherSummary; diff --git a/src/discounts/components/VoucherSummary/index.ts b/src/discounts/components/VoucherSummary/index.ts new file mode 100644 index 000000000..a7c1bebc1 --- /dev/null +++ b/src/discounts/components/VoucherSummary/index.ts @@ -0,0 +1,2 @@ +export { default } from "./VoucherSummary"; +export * from "./VoucherSummary"; diff --git a/src/discounts/fixtures.ts b/src/discounts/fixtures.ts new file mode 100644 index 000000000..7f4cef125 --- /dev/null +++ b/src/discounts/fixtures.ts @@ -0,0 +1,303 @@ +import * as placeholderImage from "@assets/images/placeholder60x60.png"; +import { + SaleType, + VoucherDiscountValueType, + VoucherType +} from "../types/globalTypes"; +import { SaleDetails_sale } from "./types/SaleDetails"; +import { SaleList_sales_edges_node } from "./types/SaleList"; +import { VoucherDetails_voucher } from "./types/VoucherDetails"; +import { VoucherList_vouchers_edges_node } from "./types/VoucherList"; + +export const saleList: SaleList_sales_edges_node[] = [ + { + __typename: "Sale" as "Sale", + endDate: null, + id: "U2FsZTo0", + name: "Happy front day!", + startDate: "2019-01-03", + type: "PERCENTAGE" as SaleType, + value: 40 + }, + { + __typename: "Sale" as "Sale", + endDate: null, + id: "U2FsZTo1", + name: "Happy minute day!", + startDate: "2019-01-03", + type: "FIXED" as SaleType, + value: 30 + }, + { + __typename: "Sale" as "Sale", + endDate: null, + id: "U2FsZTox", + name: "Happy class day!", + startDate: "2019-01-03", + type: "PERCENTAGE" as SaleType, + value: 10 + }, + { + __typename: "Sale" as "Sale", + endDate: null, + id: "U2FsZToy", + name: "Happy human day!", + startDate: "2019-01-03", + type: "PERCENTAGE" as SaleType, + value: 20 + }, + { + __typename: "Sale" as "Sale", + endDate: null, + id: "U2FsZToz", + name: "Happy year day!", + startDate: "2019-01-03", + type: "PERCENTAGE" as SaleType, + value: 10 + } +]; + +export const voucherList: VoucherList_vouchers_edges_node[] = [ + { + __typename: "Voucher" as "Voucher", + countries: [ + { + __typename: "CountryDisplay", + code: "DE", + country: "Germany" + } + ], + discountValue: 100, + discountValueType: "PERCENTAGE" as VoucherDiscountValueType, + endDate: null, + id: "Vm91Y2hlcjox", + minAmountSpent: null, + name: "Free shipping", + startDate: "2019-01-03", + usageLimit: null + }, + { + __typename: "Voucher" as "Voucher", + countries: [], + discountValue: 25, + discountValueType: "FIXED" as VoucherDiscountValueType, + endDate: null, + id: "Vm91Y2hlcjoy", + minAmountSpent: { + __typename: "Money" as "Money", + amount: 200, + currency: "USD" + }, + name: "Big order discount", + startDate: "2019-01-03", + usageLimit: 150 + } +]; + +export const sale: SaleDetails_sale = { + __typename: "Sale", + categories: { + __typename: "CategoryCountableConnection", + edges: [ + { + __typename: "CategoryCountableEdge", + node: { + __typename: "Category", + id: "U2FsZTo1=", + name: "Apparel", + products: { + __typename: "ProductCountableConnection", + totalCount: 18 + } + } + } + ], + pageInfo: { + __typename: "PageInfo", + endCursor: null, + hasNextPage: false, + hasPreviousPage: false, + startCursor: null + }, + totalCount: 2 + }, + collections: { + __typename: "CollectionCountableConnection", + edges: [ + { + __typename: "CollectionCountableEdge", + node: { + __typename: "Collection", + id: "U2FsZBo4=", + name: "Winter Collection", + products: { + __typename: "ProductCountableConnection", + totalCount: 110 + } + } + } + ], + pageInfo: { + __typename: "PageInfo", + endCursor: null, + hasNextPage: false, + hasPreviousPage: false, + startCursor: null + }, + totalCount: 4 + }, + endDate: null, + id: "U2FsZTo1", + name: "Happy minute day!", + products: { + __typename: "ProductCountableConnection", + edges: [ + { + __typename: "ProductCountableEdge", + node: { + __typename: "Product", + id: "UHJvZHVjdDo3MQ==", + isPublished: true, + name: "Orange Juice", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6OQ==", + name: "Juice" + }, + thumbnail: { + __typename: "Image", + url: placeholderImage + } + } + }, + { + __typename: "ProductCountableEdge", + node: { + __typename: "Product", + id: "UHJvZHVjdDo3Mw==", + isPublished: true, + name: "Carrot Juice", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6OQ==", + name: "Juice" + }, + thumbnail: { + __typename: "Image", + url: placeholderImage + } + } + }, + { + __typename: "ProductCountableEdge", + node: { + __typename: "Product", + id: "UHJvZHVjdDo3OQ==", + isPublished: true, + name: "Bean Juice", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6OQ==", + name: "Juice" + }, + thumbnail: { + __typename: "Image", + url: placeholderImage + } + } + }, + { + __typename: "ProductCountableEdge", + node: { + __typename: "Product", + id: "UHJvZHVjdDoxMTU=", + isPublished: true, + name: "Black Hoodie", + productType: { + __typename: "ProductType", + id: "UHJvZHVjdFR5cGU6MTQ=", + name: "Top (clothing)" + }, + thumbnail: { + __typename: "Image", + url: placeholderImage + } + } + } + ], + pageInfo: { + __typename: "PageInfo", + endCursor: "YXJyYXljb25uZWN0aW9uOjM=", + hasNextPage: false, + hasPreviousPage: false, + startCursor: "YXJyYXljb25uZWN0aW9uOjA=" + }, + totalCount: 4 + }, + startDate: "2019-01-03", + type: "PERCENTAGE" as SaleType, + value: 30 +}; + +export const voucherDetails: VoucherDetails_voucher = { + __typename: "Voucher", + applyOncePerOrder: false, + categories: { + __typename: "CategoryCountableConnection", + edges: [], + pageInfo: { + __typename: "PageInfo", + endCursor: "YXJyYXljb25uZWN0aW9uOjM=", + hasNextPage: false, + hasPreviousPage: false, + startCursor: "YXJyYXljb25uZWN0aW9uOjA=" + }, + totalCount: 0 + }, + code: "DISCOUNT", + collections: { + __typename: "CollectionCountableConnection", + edges: [], + pageInfo: { + __typename: "PageInfo", + endCursor: "YXJyYXljb25uZWN0aW9uOjM=", + hasNextPage: false, + hasPreviousPage: false, + startCursor: "YXJyYXljb25uZWN0aW9uOjA=" + }, + totalCount: 0 + }, + countries: [ + { + __typename: "CountryDisplay", + code: "DE", + country: "Germany" + } + ], + discountValue: 25, + discountValueType: VoucherDiscountValueType.FIXED, + endDate: null, + id: "Vm91Y2hlcjoy", + minAmountSpent: { + __typename: "Money", + amount: 200, + currency: "USD" + }, + name: "Big order discount", + products: { + __typename: "ProductCountableConnection", + edges: [], + pageInfo: { + __typename: "PageInfo", + endCursor: "YXJyYXljb25uZWN0aW9uOjM=", + hasNextPage: false, + hasPreviousPage: false, + startCursor: "YXJyYXljb25uZWN0aW9uOjA=" + }, + totalCount: 0 + }, + startDate: "2018-11-27", + type: VoucherType.VALUE, + usageLimit: null, + used: 0 +}; diff --git a/src/discounts/index.tsx b/src/discounts/index.tsx new file mode 100644 index 000000000..40d4ba0b8 --- /dev/null +++ b/src/discounts/index.tsx @@ -0,0 +1,89 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { WindowTitle } from "../components/WindowTitle"; +import i18n from "../i18n"; +import { saleDetailsPageTab } from "./components/SaleDetailsPage"; +import { voucherDetailsPageTab } from "./components/VoucherDetailsPage"; +import { + saleAddPath, + saleListPath, + SaleListUrlQueryParams, + salePath, + SaleUrlQueryParams, + voucherAddPath, + voucherListPath, + VoucherListUrlQueryParams, + voucherPath, + VoucherUrlQueryParams +} from "./urls"; +import SaleCreateView from "./views/SaleCreate"; +import SaleDetailsViewComponent from "./views/SaleDetails"; +import SaleListViewComponent from "./views/SaleList"; +import VoucherCreateView from "./views/VoucherCreate"; +import VoucherDetailsViewComponent from "./views/VoucherDetails"; +import VoucherListViewComponent from "./views/VoucherList"; + +const SaleListView: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: SaleListUrlQueryParams = qs; + return ; +}; + +const SaleDetailsView: React.StatelessComponent< + RouteComponentProps<{ id: string }> +> = ({ match, location }) => { + const { activeTab, ...qs } = parseQs(location.search.substr(1)); + const params: SaleUrlQueryParams = { + ...qs, + activeTab: saleDetailsPageTab(activeTab) + }; + return ( + + ); +}; + +const VoucherListView: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: VoucherListUrlQueryParams = qs; + return ; +}; + +const VoucherDetailsView: React.StatelessComponent< + RouteComponentProps<{ id: string }> +> = ({ match, location }) => { + const { activeTab, ...qs } = parseQs(location.search.substr(1)); + const params: VoucherUrlQueryParams = { + ...qs, + activeTab: voucherDetailsPageTab(activeTab) + }; + return ( + + ); +}; + +export const DiscountSection: React.StatelessComponent<{}> = () => ( + <> + + + + + + + + + + +); +export default DiscountSection; diff --git a/src/discounts/mutations.ts b/src/discounts/mutations.ts new file mode 100644 index 000000000..0a3529b52 --- /dev/null +++ b/src/discounts/mutations.ts @@ -0,0 +1,276 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { + saleDetailsFragment, + saleFragment, + voucherDetailsFragment, + voucherFragment +} from "./queries"; +import { + SaleBulkDelete, + SaleBulkDeleteVariables +} from "./types/SaleBulkDelete"; +import { + SaleCataloguesAdd, + SaleCataloguesAddVariables +} from "./types/SaleCataloguesAdd"; +import { + SaleCataloguesRemove, + SaleCataloguesRemoveVariables +} from "./types/SaleCataloguesRemove"; +import { SaleCreate, SaleCreateVariables } from "./types/SaleCreate"; +import { SaleDelete, SaleDeleteVariables } from "./types/SaleDelete"; +import { SaleUpdate, SaleUpdateVariables } from "./types/SaleUpdate"; +import { + VoucherBulkDelete, + VoucherBulkDeleteVariables +} from "./types/VoucherBulkDelete"; +import { + VoucherCataloguesAdd, + VoucherCataloguesAddVariables +} from "./types/VoucherCataloguesAdd"; +import { + VoucherCataloguesRemove, + VoucherCataloguesRemoveVariables +} from "./types/VoucherCataloguesRemove"; +import { VoucherCreate, VoucherCreateVariables } from "./types/VoucherCreate"; +import { VoucherDelete, VoucherDeleteVariables } from "./types/VoucherDelete"; +import { VoucherUpdate, VoucherUpdateVariables } from "./types/VoucherUpdate"; + +const saleUpdate = gql` + ${saleFragment} + mutation SaleUpdate($input: SaleInput!, $id: ID!) { + saleUpdate(id: $id, input: $input) { + errors { + field + message + } + sale { + ...SaleFragment + } + } + } +`; +export const TypedSaleUpdate = TypedMutation( + saleUpdate +); + +const saleCataloguesAdd = gql` + ${saleDetailsFragment} + mutation SaleCataloguesAdd( + $input: CatalogueInput! + $id: ID! + $after: String + $before: String + $first: Int + $last: Int + ) { + saleCataloguesAdd(id: $id, input: $input) { + errors { + field + message + } + sale { + ...SaleDetailsFragment + } + } + } +`; +export const TypedSaleCataloguesAdd = TypedMutation< + SaleCataloguesAdd, + SaleCataloguesAddVariables +>(saleCataloguesAdd); + +const saleCataloguesRemove = gql` + ${saleDetailsFragment} + mutation SaleCataloguesRemove( + $input: CatalogueInput! + $id: ID! + $after: String + $before: String + $first: Int + $last: Int + ) { + saleCataloguesRemove(id: $id, input: $input) { + errors { + field + message + } + sale { + ...SaleDetailsFragment + } + } + } +`; +export const TypedSaleCataloguesRemove = TypedMutation< + SaleCataloguesRemove, + SaleCataloguesRemoveVariables +>(saleCataloguesRemove); + +const saleCreate = gql` + ${saleFragment} + mutation SaleCreate($input: SaleInput!) { + saleCreate(input: $input) { + errors { + field + message + } + sale { + ...SaleFragment + } + } + } +`; +export const TypedSaleCreate = TypedMutation( + saleCreate +); + +const saleDelete = gql` + mutation SaleDelete($id: ID!) { + saleDelete(id: $id) { + errors { + field + message + } + } + } +`; +export const TypedSaleDelete = TypedMutation( + saleDelete +); + +const saleBulkDelete = gql` + mutation SaleBulkDelete($ids: [ID]!) { + saleBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedSaleBulkDelete = TypedMutation< + SaleBulkDelete, + SaleBulkDeleteVariables +>(saleBulkDelete); + +const voucherUpdate = gql` + ${voucherFragment} + mutation VoucherUpdate($input: VoucherInput!, $id: ID!) { + voucherUpdate(id: $id, input: $input) { + errors { + field + message + } + voucher { + ...VoucherFragment + } + } + } +`; +export const TypedVoucherUpdate = TypedMutation< + VoucherUpdate, + VoucherUpdateVariables +>(voucherUpdate); + +const voucherCataloguesAdd = gql` + ${voucherDetailsFragment} + mutation VoucherCataloguesAdd( + $input: CatalogueInput! + $id: ID! + $after: String + $before: String + $first: Int + $last: Int + ) { + voucherCataloguesAdd(id: $id, input: $input) { + errors { + field + message + } + voucher { + ...VoucherDetailsFragment + } + } + } +`; +export const TypedVoucherCataloguesAdd = TypedMutation< + VoucherCataloguesAdd, + VoucherCataloguesAddVariables +>(voucherCataloguesAdd); + +const voucherCataloguesRemove = gql` + ${voucherDetailsFragment} + mutation VoucherCataloguesRemove( + $input: CatalogueInput! + $id: ID! + $after: String + $before: String + $first: Int + $last: Int + ) { + voucherCataloguesRemove(id: $id, input: $input) { + errors { + field + message + } + voucher { + ...VoucherDetailsFragment + } + } + } +`; +export const TypedVoucherCataloguesRemove = TypedMutation< + VoucherCataloguesRemove, + VoucherCataloguesRemoveVariables +>(voucherCataloguesRemove); + +const voucherCreate = gql` + ${voucherFragment} + mutation VoucherCreate($input: VoucherInput!) { + voucherCreate(input: $input) { + errors { + field + message + } + voucher { + ...VoucherFragment + } + } + } +`; +export const TypedVoucherCreate = TypedMutation< + VoucherCreate, + VoucherCreateVariables +>(voucherCreate); + +const voucherDelete = gql` + mutation VoucherDelete($id: ID!) { + voucherDelete(id: $id) { + errors { + field + message + } + } + } +`; +export const TypedVoucherDelete = TypedMutation< + VoucherDelete, + VoucherDeleteVariables +>(voucherDelete); + +const voucherBulkDelete = gql` + mutation VoucherBulkDelete($ids: [ID]!) { + voucherBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedVoucherBulkDelete = TypedMutation< + VoucherBulkDelete, + VoucherBulkDeleteVariables +>(voucherBulkDelete); diff --git a/src/discounts/queries.ts b/src/discounts/queries.ts new file mode 100644 index 000000000..e5905952b --- /dev/null +++ b/src/discounts/queries.ts @@ -0,0 +1,237 @@ +import gql from "graphql-tag"; + +import { pageInfoFragment, TypedQuery } from "../queries"; +import { SaleDetails, SaleDetailsVariables } from "./types/SaleDetails"; +import { SaleList, SaleListVariables } from "./types/SaleList"; +import { + VoucherDetails, + VoucherDetailsVariables +} from "./types/VoucherDetails"; +import { VoucherList, VoucherListVariables } from "./types/VoucherList"; + +export const saleFragment = gql` + fragment SaleFragment on Sale { + id + name + type + startDate + endDate + value + } +`; + +export const saleDetailsFragment = gql` + ${pageInfoFragment} + ${saleFragment} + fragment SaleDetailsFragment on Sale { + ...SaleFragment + products(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + isPublished + productType { + id + name + } + thumbnail { + url + } + } + } + pageInfo { + ...PageInfoFragment + } + totalCount + } + categories(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + products { + totalCount + } + } + } + pageInfo { + ...PageInfoFragment + } + totalCount + } + collections(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + products { + totalCount + } + } + } + pageInfo { + ...PageInfoFragment + } + totalCount + } + } +`; + +export const voucherFragment = gql` + fragment VoucherFragment on Voucher { + id + name + startDate + endDate + usageLimit + discountValueType + discountValue + countries { + code + country + } + minAmountSpent { + currency + amount + } + } +`; + +export const voucherDetailsFragment = gql` + ${pageInfoFragment} + ${voucherFragment} + fragment VoucherDetailsFragment on Voucher { + ...VoucherFragment + type + code + usageLimit + used + applyOncePerOrder + products(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + productType { + id + name + } + isPublished + thumbnail { + url + } + } + } + totalCount + pageInfo { + ...PageInfoFragment + } + } + collections(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + products { + totalCount + } + } + } + totalCount + pageInfo { + ...PageInfoFragment + } + } + categories(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + id + name + products { + totalCount + } + } + } + totalCount + pageInfo { + ...PageInfoFragment + } + } + } +`; + +export const saleList = gql` + ${pageInfoFragment} + ${saleFragment} + query SaleList($after: String, $before: String, $first: Int, $last: Int) { + sales(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + ...SaleFragment + } + } + pageInfo { + ...PageInfoFragment + } + } + } +`; +export const TypedSaleList = TypedQuery(saleList); + +export const voucherList = gql` + ${pageInfoFragment} + ${voucherFragment} + query VoucherList($after: String, $before: String, $first: Int, $last: Int) { + vouchers(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + ...VoucherFragment + } + } + pageInfo { + ...PageInfoFragment + } + } + } +`; +export const TypedVoucherList = TypedQuery( + voucherList +); + +export const saleDetails = gql` + ${saleDetailsFragment} + query SaleDetails( + $id: ID! + $after: String + $before: String + $first: Int + $last: Int + ) { + sale(id: $id) { + ...SaleDetailsFragment + } + } +`; +export const TypedSaleDetails = TypedQuery( + saleDetails +); + +const voucherDetails = gql` + ${voucherDetailsFragment} + query VoucherDetails( + $id: ID! + $after: String + $before: String + $first: Int + $last: Int + ) { + voucher(id: $id) { + ...VoucherDetailsFragment + } + } +`; +export const TypedVoucherDetails = TypedQuery< + VoucherDetails, + VoucherDetailsVariables +>(voucherDetails); diff --git a/src/discounts/translations.ts b/src/discounts/translations.ts new file mode 100644 index 000000000..b6f6af8e5 --- /dev/null +++ b/src/discounts/translations.ts @@ -0,0 +1,10 @@ +import i18n from "../i18n"; +import { VoucherType } from "../types/globalTypes"; + +export const translateVoucherTypes = () => ({ + [VoucherType.CATEGORY]: i18n.t("Selected Categories"), + [VoucherType.COLLECTION]: i18n.t("Selected Collections"), + [VoucherType.PRODUCT]: i18n.t("Selected Products"), + [VoucherType.SHIPPING]: i18n.t("Shipment"), + [VoucherType.VALUE]: i18n.t("All Products") +}); diff --git a/src/discounts/types/SaleBulkDelete.ts b/src/discounts/types/SaleBulkDelete.ts new file mode 100644 index 000000000..e02fcbac0 --- /dev/null +++ b/src/discounts/types/SaleBulkDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: SaleBulkDelete +// ==================================================== + +export interface SaleBulkDelete_saleBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface SaleBulkDelete_saleBulkDelete { + __typename: "SaleBulkDelete"; + errors: SaleBulkDelete_saleBulkDelete_errors[] | null; +} + +export interface SaleBulkDelete { + saleBulkDelete: SaleBulkDelete_saleBulkDelete | null; +} + +export interface SaleBulkDeleteVariables { + ids: (string | null)[]; +} diff --git a/src/discounts/types/SaleCataloguesAdd.ts b/src/discounts/types/SaleCataloguesAdd.ts new file mode 100644 index 000000000..3f1302316 --- /dev/null +++ b/src/discounts/types/SaleCataloguesAdd.ts @@ -0,0 +1,151 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { CatalogueInput, SaleType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: SaleCataloguesAdd +// ==================================================== + +export interface SaleCataloguesAdd_saleCataloguesAdd_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_products_edges_node { + __typename: "Product"; + id: string; + name: string; + isPublished: boolean; + productType: SaleCataloguesAdd_saleCataloguesAdd_sale_products_edges_node_productType; + thumbnail: SaleCataloguesAdd_saleCataloguesAdd_sale_products_edges_node_thumbnail | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_products_edges { + __typename: "ProductCountableEdge"; + node: SaleCataloguesAdd_saleCataloguesAdd_sale_products_edges_node; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_products { + __typename: "ProductCountableConnection"; + edges: SaleCataloguesAdd_saleCataloguesAdd_sale_products_edges[]; + pageInfo: SaleCataloguesAdd_saleCataloguesAdd_sale_products_pageInfo; + totalCount: number | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_categories_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_categories_edges_node { + __typename: "Category"; + id: string; + name: string; + products: SaleCataloguesAdd_saleCataloguesAdd_sale_categories_edges_node_products | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_categories_edges { + __typename: "CategoryCountableEdge"; + node: SaleCataloguesAdd_saleCataloguesAdd_sale_categories_edges_node; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_categories_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_categories { + __typename: "CategoryCountableConnection"; + edges: SaleCataloguesAdd_saleCataloguesAdd_sale_categories_edges[]; + pageInfo: SaleCataloguesAdd_saleCataloguesAdd_sale_categories_pageInfo; + totalCount: number | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_collections_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_collections_edges_node { + __typename: "Collection"; + id: string; + name: string; + products: SaleCataloguesAdd_saleCataloguesAdd_sale_collections_edges_node_products | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_collections_edges { + __typename: "CollectionCountableEdge"; + node: SaleCataloguesAdd_saleCataloguesAdd_sale_collections_edges_node; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_collections_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale_collections { + __typename: "CollectionCountableConnection"; + edges: SaleCataloguesAdd_saleCataloguesAdd_sale_collections_edges[]; + pageInfo: SaleCataloguesAdd_saleCataloguesAdd_sale_collections_pageInfo; + totalCount: number | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd_sale { + __typename: "Sale"; + id: string; + name: string; + type: SaleType; + startDate: any; + endDate: any | null; + value: number; + products: SaleCataloguesAdd_saleCataloguesAdd_sale_products | null; + categories: SaleCataloguesAdd_saleCataloguesAdd_sale_categories | null; + collections: SaleCataloguesAdd_saleCataloguesAdd_sale_collections | null; +} + +export interface SaleCataloguesAdd_saleCataloguesAdd { + __typename: "SaleAddCatalogues"; + errors: SaleCataloguesAdd_saleCataloguesAdd_errors[] | null; + sale: SaleCataloguesAdd_saleCataloguesAdd_sale | null; +} + +export interface SaleCataloguesAdd { + saleCataloguesAdd: SaleCataloguesAdd_saleCataloguesAdd | null; +} + +export interface SaleCataloguesAddVariables { + input: CatalogueInput; + id: string; + after?: string | null; + before?: string | null; + first?: number | null; + last?: number | null; +} diff --git a/src/discounts/types/SaleCataloguesRemove.ts b/src/discounts/types/SaleCataloguesRemove.ts new file mode 100644 index 000000000..96746e461 --- /dev/null +++ b/src/discounts/types/SaleCataloguesRemove.ts @@ -0,0 +1,151 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { CatalogueInput, SaleType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: SaleCataloguesRemove +// ==================================================== + +export interface SaleCataloguesRemove_saleCataloguesRemove_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_products_edges_node { + __typename: "Product"; + id: string; + name: string; + isPublished: boolean; + productType: SaleCataloguesRemove_saleCataloguesRemove_sale_products_edges_node_productType; + thumbnail: SaleCataloguesRemove_saleCataloguesRemove_sale_products_edges_node_thumbnail | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_products_edges { + __typename: "ProductCountableEdge"; + node: SaleCataloguesRemove_saleCataloguesRemove_sale_products_edges_node; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_products { + __typename: "ProductCountableConnection"; + edges: SaleCataloguesRemove_saleCataloguesRemove_sale_products_edges[]; + pageInfo: SaleCataloguesRemove_saleCataloguesRemove_sale_products_pageInfo; + totalCount: number | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_categories_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_categories_edges_node { + __typename: "Category"; + id: string; + name: string; + products: SaleCataloguesRemove_saleCataloguesRemove_sale_categories_edges_node_products | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_categories_edges { + __typename: "CategoryCountableEdge"; + node: SaleCataloguesRemove_saleCataloguesRemove_sale_categories_edges_node; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_categories_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_categories { + __typename: "CategoryCountableConnection"; + edges: SaleCataloguesRemove_saleCataloguesRemove_sale_categories_edges[]; + pageInfo: SaleCataloguesRemove_saleCataloguesRemove_sale_categories_pageInfo; + totalCount: number | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_collections_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_collections_edges_node { + __typename: "Collection"; + id: string; + name: string; + products: SaleCataloguesRemove_saleCataloguesRemove_sale_collections_edges_node_products | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_collections_edges { + __typename: "CollectionCountableEdge"; + node: SaleCataloguesRemove_saleCataloguesRemove_sale_collections_edges_node; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_collections_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale_collections { + __typename: "CollectionCountableConnection"; + edges: SaleCataloguesRemove_saleCataloguesRemove_sale_collections_edges[]; + pageInfo: SaleCataloguesRemove_saleCataloguesRemove_sale_collections_pageInfo; + totalCount: number | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove_sale { + __typename: "Sale"; + id: string; + name: string; + type: SaleType; + startDate: any; + endDate: any | null; + value: number; + products: SaleCataloguesRemove_saleCataloguesRemove_sale_products | null; + categories: SaleCataloguesRemove_saleCataloguesRemove_sale_categories | null; + collections: SaleCataloguesRemove_saleCataloguesRemove_sale_collections | null; +} + +export interface SaleCataloguesRemove_saleCataloguesRemove { + __typename: "SaleRemoveCatalogues"; + errors: SaleCataloguesRemove_saleCataloguesRemove_errors[] | null; + sale: SaleCataloguesRemove_saleCataloguesRemove_sale | null; +} + +export interface SaleCataloguesRemove { + saleCataloguesRemove: SaleCataloguesRemove_saleCataloguesRemove | null; +} + +export interface SaleCataloguesRemoveVariables { + input: CatalogueInput; + id: string; + after?: string | null; + before?: string | null; + first?: number | null; + last?: number | null; +} diff --git a/src/discounts/types/SaleCreate.ts b/src/discounts/types/SaleCreate.ts new file mode 100644 index 000000000..0f30617fc --- /dev/null +++ b/src/discounts/types/SaleCreate.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { SaleInput, SaleType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: SaleCreate +// ==================================================== + +export interface SaleCreate_saleCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface SaleCreate_saleCreate_sale { + __typename: "Sale"; + id: string; + name: string; + type: SaleType; + startDate: any; + endDate: any | null; + value: number; +} + +export interface SaleCreate_saleCreate { + __typename: "SaleCreate"; + errors: SaleCreate_saleCreate_errors[] | null; + sale: SaleCreate_saleCreate_sale | null; +} + +export interface SaleCreate { + saleCreate: SaleCreate_saleCreate | null; +} + +export interface SaleCreateVariables { + input: SaleInput; +} diff --git a/src/discounts/types/SaleDelete.ts b/src/discounts/types/SaleDelete.ts new file mode 100644 index 000000000..b11575381 --- /dev/null +++ b/src/discounts/types/SaleDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: SaleDelete +// ==================================================== + +export interface SaleDelete_saleDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface SaleDelete_saleDelete { + __typename: "SaleDelete"; + errors: SaleDelete_saleDelete_errors[] | null; +} + +export interface SaleDelete { + saleDelete: SaleDelete_saleDelete | null; +} + +export interface SaleDeleteVariables { + id: string; +} diff --git a/src/discounts/types/SaleDetails.ts b/src/discounts/types/SaleDetails.ts new file mode 100644 index 000000000..938563606 --- /dev/null +++ b/src/discounts/types/SaleDetails.ts @@ -0,0 +1,138 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { SaleType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: SaleDetails +// ==================================================== + +export interface SaleDetails_sale_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface SaleDetails_sale_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface SaleDetails_sale_products_edges_node { + __typename: "Product"; + id: string; + name: string; + isPublished: boolean; + productType: SaleDetails_sale_products_edges_node_productType; + thumbnail: SaleDetails_sale_products_edges_node_thumbnail | null; +} + +export interface SaleDetails_sale_products_edges { + __typename: "ProductCountableEdge"; + node: SaleDetails_sale_products_edges_node; +} + +export interface SaleDetails_sale_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleDetails_sale_products { + __typename: "ProductCountableConnection"; + edges: SaleDetails_sale_products_edges[]; + pageInfo: SaleDetails_sale_products_pageInfo; + totalCount: number | null; +} + +export interface SaleDetails_sale_categories_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface SaleDetails_sale_categories_edges_node { + __typename: "Category"; + id: string; + name: string; + products: SaleDetails_sale_categories_edges_node_products | null; +} + +export interface SaleDetails_sale_categories_edges { + __typename: "CategoryCountableEdge"; + node: SaleDetails_sale_categories_edges_node; +} + +export interface SaleDetails_sale_categories_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleDetails_sale_categories { + __typename: "CategoryCountableConnection"; + edges: SaleDetails_sale_categories_edges[]; + pageInfo: SaleDetails_sale_categories_pageInfo; + totalCount: number | null; +} + +export interface SaleDetails_sale_collections_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface SaleDetails_sale_collections_edges_node { + __typename: "Collection"; + id: string; + name: string; + products: SaleDetails_sale_collections_edges_node_products | null; +} + +export interface SaleDetails_sale_collections_edges { + __typename: "CollectionCountableEdge"; + node: SaleDetails_sale_collections_edges_node; +} + +export interface SaleDetails_sale_collections_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleDetails_sale_collections { + __typename: "CollectionCountableConnection"; + edges: SaleDetails_sale_collections_edges[]; + pageInfo: SaleDetails_sale_collections_pageInfo; + totalCount: number | null; +} + +export interface SaleDetails_sale { + __typename: "Sale"; + id: string; + name: string; + type: SaleType; + startDate: any; + endDate: any | null; + value: number; + products: SaleDetails_sale_products | null; + categories: SaleDetails_sale_categories | null; + collections: SaleDetails_sale_collections | null; +} + +export interface SaleDetails { + sale: SaleDetails_sale | null; +} + +export interface SaleDetailsVariables { + id: string; + after?: string | null; + before?: string | null; + first?: number | null; + last?: number | null; +} diff --git a/src/discounts/types/SaleDetailsFragment.ts b/src/discounts/types/SaleDetailsFragment.ts new file mode 100644 index 000000000..be8362a70 --- /dev/null +++ b/src/discounts/types/SaleDetailsFragment.ts @@ -0,0 +1,126 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { SaleType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: SaleDetailsFragment +// ==================================================== + +export interface SaleDetailsFragment_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface SaleDetailsFragment_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface SaleDetailsFragment_products_edges_node { + __typename: "Product"; + id: string; + name: string; + isPublished: boolean; + productType: SaleDetailsFragment_products_edges_node_productType; + thumbnail: SaleDetailsFragment_products_edges_node_thumbnail | null; +} + +export interface SaleDetailsFragment_products_edges { + __typename: "ProductCountableEdge"; + node: SaleDetailsFragment_products_edges_node; +} + +export interface SaleDetailsFragment_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleDetailsFragment_products { + __typename: "ProductCountableConnection"; + edges: SaleDetailsFragment_products_edges[]; + pageInfo: SaleDetailsFragment_products_pageInfo; + totalCount: number | null; +} + +export interface SaleDetailsFragment_categories_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface SaleDetailsFragment_categories_edges_node { + __typename: "Category"; + id: string; + name: string; + products: SaleDetailsFragment_categories_edges_node_products | null; +} + +export interface SaleDetailsFragment_categories_edges { + __typename: "CategoryCountableEdge"; + node: SaleDetailsFragment_categories_edges_node; +} + +export interface SaleDetailsFragment_categories_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleDetailsFragment_categories { + __typename: "CategoryCountableConnection"; + edges: SaleDetailsFragment_categories_edges[]; + pageInfo: SaleDetailsFragment_categories_pageInfo; + totalCount: number | null; +} + +export interface SaleDetailsFragment_collections_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface SaleDetailsFragment_collections_edges_node { + __typename: "Collection"; + id: string; + name: string; + products: SaleDetailsFragment_collections_edges_node_products | null; +} + +export interface SaleDetailsFragment_collections_edges { + __typename: "CollectionCountableEdge"; + node: SaleDetailsFragment_collections_edges_node; +} + +export interface SaleDetailsFragment_collections_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleDetailsFragment_collections { + __typename: "CollectionCountableConnection"; + edges: SaleDetailsFragment_collections_edges[]; + pageInfo: SaleDetailsFragment_collections_pageInfo; + totalCount: number | null; +} + +export interface SaleDetailsFragment { + __typename: "Sale"; + id: string; + name: string; + type: SaleType; + startDate: any; + endDate: any | null; + value: number; + products: SaleDetailsFragment_products | null; + categories: SaleDetailsFragment_categories | null; + collections: SaleDetailsFragment_collections | null; +} diff --git a/src/discounts/types/SaleFragment.ts b/src/discounts/types/SaleFragment.ts new file mode 100644 index 000000000..ef6a4ff0e --- /dev/null +++ b/src/discounts/types/SaleFragment.ts @@ -0,0 +1,19 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { SaleType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: SaleFragment +// ==================================================== + +export interface SaleFragment { + __typename: "Sale"; + id: string; + name: string; + type: SaleType; + startDate: any; + endDate: any | null; + value: number; +} diff --git a/src/discounts/types/SaleList.ts b/src/discounts/types/SaleList.ts new file mode 100644 index 000000000..0667b9b72 --- /dev/null +++ b/src/discounts/types/SaleList.ts @@ -0,0 +1,49 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { SaleType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: SaleList +// ==================================================== + +export interface SaleList_sales_edges_node { + __typename: "Sale"; + id: string; + name: string; + type: SaleType; + startDate: any; + endDate: any | null; + value: number; +} + +export interface SaleList_sales_edges { + __typename: "SaleCountableEdge"; + node: SaleList_sales_edges_node; +} + +export interface SaleList_sales_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SaleList_sales { + __typename: "SaleCountableConnection"; + edges: SaleList_sales_edges[]; + pageInfo: SaleList_sales_pageInfo; +} + +export interface SaleList { + sales: SaleList_sales | null; +} + +export interface SaleListVariables { + after?: string | null; + before?: string | null; + first?: number | null; + last?: number | null; +} diff --git a/src/discounts/types/SaleUpdate.ts b/src/discounts/types/SaleUpdate.ts new file mode 100644 index 000000000..ca835efb5 --- /dev/null +++ b/src/discounts/types/SaleUpdate.ts @@ -0,0 +1,40 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { SaleInput, SaleType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: SaleUpdate +// ==================================================== + +export interface SaleUpdate_saleUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface SaleUpdate_saleUpdate_sale { + __typename: "Sale"; + id: string; + name: string; + type: SaleType; + startDate: any; + endDate: any | null; + value: number; +} + +export interface SaleUpdate_saleUpdate { + __typename: "SaleUpdate"; + errors: SaleUpdate_saleUpdate_errors[] | null; + sale: SaleUpdate_saleUpdate_sale | null; +} + +export interface SaleUpdate { + saleUpdate: SaleUpdate_saleUpdate | null; +} + +export interface SaleUpdateVariables { + input: SaleInput; + id: string; +} diff --git a/src/discounts/types/VoucherBulkDelete.ts b/src/discounts/types/VoucherBulkDelete.ts new file mode 100644 index 000000000..ac3277e75 --- /dev/null +++ b/src/discounts/types/VoucherBulkDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: VoucherBulkDelete +// ==================================================== + +export interface VoucherBulkDelete_voucherBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface VoucherBulkDelete_voucherBulkDelete { + __typename: "VoucherBulkDelete"; + errors: VoucherBulkDelete_voucherBulkDelete_errors[] | null; +} + +export interface VoucherBulkDelete { + voucherBulkDelete: VoucherBulkDelete_voucherBulkDelete | null; +} + +export interface VoucherBulkDeleteVariables { + ids: (string | null)[]; +} diff --git a/src/discounts/types/VoucherCataloguesAdd.ts b/src/discounts/types/VoucherCataloguesAdd.ts new file mode 100644 index 000000000..f005d2e19 --- /dev/null +++ b/src/discounts/types/VoucherCataloguesAdd.ts @@ -0,0 +1,170 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { CatalogueInput, VoucherDiscountValueType, VoucherType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: VoucherCataloguesAdd +// ==================================================== + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_minAmountSpent { + __typename: "Money"; + currency: string; + amount: number; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products_edges_node { + __typename: "Product"; + id: string; + name: string; + productType: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products_edges_node_productType; + isPublished: boolean; + thumbnail: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products_edges_node_thumbnail | null; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products_edges { + __typename: "ProductCountableEdge"; + node: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products_edges_node; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products { + __typename: "ProductCountableConnection"; + edges: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products_edges[]; + totalCount: number | null; + pageInfo: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products_pageInfo; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_collections_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_collections_edges_node { + __typename: "Collection"; + id: string; + name: string; + products: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_collections_edges_node_products | null; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_collections_edges { + __typename: "CollectionCountableEdge"; + node: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_collections_edges_node; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_collections_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_collections { + __typename: "CollectionCountableConnection"; + edges: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_collections_edges[]; + totalCount: number | null; + pageInfo: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_collections_pageInfo; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_categories_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_categories_edges_node { + __typename: "Category"; + id: string; + name: string; + products: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_categories_edges_node_products | null; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_categories_edges { + __typename: "CategoryCountableEdge"; + node: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_categories_edges_node; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_categories_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher_categories { + __typename: "CategoryCountableConnection"; + edges: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_categories_edges[]; + totalCount: number | null; + pageInfo: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_categories_pageInfo; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher { + __typename: "Voucher"; + id: string; + name: string | null; + startDate: any; + endDate: any | null; + usageLimit: number | null; + discountValueType: VoucherDiscountValueType; + discountValue: number; + countries: (VoucherCataloguesAdd_voucherCataloguesAdd_voucher_countries | null)[] | null; + minAmountSpent: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_minAmountSpent | null; + type: VoucherType; + code: string; + used: number; + applyOncePerOrder: boolean; + products: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products | null; + collections: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_collections | null; + categories: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_categories | null; +} + +export interface VoucherCataloguesAdd_voucherCataloguesAdd { + __typename: "VoucherAddCatalogues"; + errors: VoucherCataloguesAdd_voucherCataloguesAdd_errors[] | null; + voucher: VoucherCataloguesAdd_voucherCataloguesAdd_voucher | null; +} + +export interface VoucherCataloguesAdd { + voucherCataloguesAdd: VoucherCataloguesAdd_voucherCataloguesAdd | null; +} + +export interface VoucherCataloguesAddVariables { + input: CatalogueInput; + id: string; + after?: string | null; + before?: string | null; + first?: number | null; + last?: number | null; +} diff --git a/src/discounts/types/VoucherCataloguesRemove.ts b/src/discounts/types/VoucherCataloguesRemove.ts new file mode 100644 index 000000000..417934c69 --- /dev/null +++ b/src/discounts/types/VoucherCataloguesRemove.ts @@ -0,0 +1,170 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { CatalogueInput, VoucherDiscountValueType, VoucherType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: VoucherCataloguesRemove +// ==================================================== + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_minAmountSpent { + __typename: "Money"; + currency: string; + amount: number; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products_edges_node { + __typename: "Product"; + id: string; + name: string; + productType: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products_edges_node_productType; + isPublished: boolean; + thumbnail: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products_edges_node_thumbnail | null; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products_edges { + __typename: "ProductCountableEdge"; + node: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products_edges_node; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products { + __typename: "ProductCountableConnection"; + edges: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products_edges[]; + totalCount: number | null; + pageInfo: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products_pageInfo; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_collections_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_collections_edges_node { + __typename: "Collection"; + id: string; + name: string; + products: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_collections_edges_node_products | null; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_collections_edges { + __typename: "CollectionCountableEdge"; + node: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_collections_edges_node; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_collections_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_collections { + __typename: "CollectionCountableConnection"; + edges: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_collections_edges[]; + totalCount: number | null; + pageInfo: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_collections_pageInfo; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_categories_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_categories_edges_node { + __typename: "Category"; + id: string; + name: string; + products: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_categories_edges_node_products | null; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_categories_edges { + __typename: "CategoryCountableEdge"; + node: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_categories_edges_node; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_categories_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher_categories { + __typename: "CategoryCountableConnection"; + edges: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_categories_edges[]; + totalCount: number | null; + pageInfo: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_categories_pageInfo; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher { + __typename: "Voucher"; + id: string; + name: string | null; + startDate: any; + endDate: any | null; + usageLimit: number | null; + discountValueType: VoucherDiscountValueType; + discountValue: number; + countries: (VoucherCataloguesRemove_voucherCataloguesRemove_voucher_countries | null)[] | null; + minAmountSpent: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_minAmountSpent | null; + type: VoucherType; + code: string; + used: number; + applyOncePerOrder: boolean; + products: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products | null; + collections: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_collections | null; + categories: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_categories | null; +} + +export interface VoucherCataloguesRemove_voucherCataloguesRemove { + __typename: "VoucherRemoveCatalogues"; + errors: VoucherCataloguesRemove_voucherCataloguesRemove_errors[] | null; + voucher: VoucherCataloguesRemove_voucherCataloguesRemove_voucher | null; +} + +export interface VoucherCataloguesRemove { + voucherCataloguesRemove: VoucherCataloguesRemove_voucherCataloguesRemove | null; +} + +export interface VoucherCataloguesRemoveVariables { + input: CatalogueInput; + id: string; + after?: string | null; + before?: string | null; + first?: number | null; + last?: number | null; +} diff --git a/src/discounts/types/VoucherCreate.ts b/src/discounts/types/VoucherCreate.ts new file mode 100644 index 000000000..eca02664f --- /dev/null +++ b/src/discounts/types/VoucherCreate.ts @@ -0,0 +1,54 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { VoucherInput, VoucherDiscountValueType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: VoucherCreate +// ==================================================== + +export interface VoucherCreate_voucherCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface VoucherCreate_voucherCreate_voucher_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface VoucherCreate_voucherCreate_voucher_minAmountSpent { + __typename: "Money"; + currency: string; + amount: number; +} + +export interface VoucherCreate_voucherCreate_voucher { + __typename: "Voucher"; + id: string; + name: string | null; + startDate: any; + endDate: any | null; + usageLimit: number | null; + discountValueType: VoucherDiscountValueType; + discountValue: number; + countries: (VoucherCreate_voucherCreate_voucher_countries | null)[] | null; + minAmountSpent: VoucherCreate_voucherCreate_voucher_minAmountSpent | null; +} + +export interface VoucherCreate_voucherCreate { + __typename: "VoucherCreate"; + errors: VoucherCreate_voucherCreate_errors[] | null; + voucher: VoucherCreate_voucherCreate_voucher | null; +} + +export interface VoucherCreate { + voucherCreate: VoucherCreate_voucherCreate | null; +} + +export interface VoucherCreateVariables { + input: VoucherInput; +} diff --git a/src/discounts/types/VoucherDelete.ts b/src/discounts/types/VoucherDelete.ts new file mode 100644 index 000000000..7a0fc7f4c --- /dev/null +++ b/src/discounts/types/VoucherDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: VoucherDelete +// ==================================================== + +export interface VoucherDelete_voucherDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface VoucherDelete_voucherDelete { + __typename: "VoucherDelete"; + errors: VoucherDelete_voucherDelete_errors[] | null; +} + +export interface VoucherDelete { + voucherDelete: VoucherDelete_voucherDelete | null; +} + +export interface VoucherDeleteVariables { + id: string; +} diff --git a/src/discounts/types/VoucherDetails.ts b/src/discounts/types/VoucherDetails.ts new file mode 100644 index 000000000..dae5f8b1a --- /dev/null +++ b/src/discounts/types/VoucherDetails.ts @@ -0,0 +1,157 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { VoucherDiscountValueType, VoucherType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: VoucherDetails +// ==================================================== + +export interface VoucherDetails_voucher_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface VoucherDetails_voucher_minAmountSpent { + __typename: "Money"; + currency: string; + amount: number; +} + +export interface VoucherDetails_voucher_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface VoucherDetails_voucher_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface VoucherDetails_voucher_products_edges_node { + __typename: "Product"; + id: string; + name: string; + productType: VoucherDetails_voucher_products_edges_node_productType; + isPublished: boolean; + thumbnail: VoucherDetails_voucher_products_edges_node_thumbnail | null; +} + +export interface VoucherDetails_voucher_products_edges { + __typename: "ProductCountableEdge"; + node: VoucherDetails_voucher_products_edges_node; +} + +export interface VoucherDetails_voucher_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherDetails_voucher_products { + __typename: "ProductCountableConnection"; + edges: VoucherDetails_voucher_products_edges[]; + totalCount: number | null; + pageInfo: VoucherDetails_voucher_products_pageInfo; +} + +export interface VoucherDetails_voucher_collections_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface VoucherDetails_voucher_collections_edges_node { + __typename: "Collection"; + id: string; + name: string; + products: VoucherDetails_voucher_collections_edges_node_products | null; +} + +export interface VoucherDetails_voucher_collections_edges { + __typename: "CollectionCountableEdge"; + node: VoucherDetails_voucher_collections_edges_node; +} + +export interface VoucherDetails_voucher_collections_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherDetails_voucher_collections { + __typename: "CollectionCountableConnection"; + edges: VoucherDetails_voucher_collections_edges[]; + totalCount: number | null; + pageInfo: VoucherDetails_voucher_collections_pageInfo; +} + +export interface VoucherDetails_voucher_categories_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface VoucherDetails_voucher_categories_edges_node { + __typename: "Category"; + id: string; + name: string; + products: VoucherDetails_voucher_categories_edges_node_products | null; +} + +export interface VoucherDetails_voucher_categories_edges { + __typename: "CategoryCountableEdge"; + node: VoucherDetails_voucher_categories_edges_node; +} + +export interface VoucherDetails_voucher_categories_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherDetails_voucher_categories { + __typename: "CategoryCountableConnection"; + edges: VoucherDetails_voucher_categories_edges[]; + totalCount: number | null; + pageInfo: VoucherDetails_voucher_categories_pageInfo; +} + +export interface VoucherDetails_voucher { + __typename: "Voucher"; + id: string; + name: string | null; + startDate: any; + endDate: any | null; + usageLimit: number | null; + discountValueType: VoucherDiscountValueType; + discountValue: number; + countries: (VoucherDetails_voucher_countries | null)[] | null; + minAmountSpent: VoucherDetails_voucher_minAmountSpent | null; + type: VoucherType; + code: string; + used: number; + applyOncePerOrder: boolean; + products: VoucherDetails_voucher_products | null; + collections: VoucherDetails_voucher_collections | null; + categories: VoucherDetails_voucher_categories | null; +} + +export interface VoucherDetails { + voucher: VoucherDetails_voucher | null; +} + +export interface VoucherDetailsVariables { + id: string; + after?: string | null; + before?: string | null; + first?: number | null; + last?: number | null; +} diff --git a/src/discounts/types/VoucherDetailsFragment.ts b/src/discounts/types/VoucherDetailsFragment.ts new file mode 100644 index 000000000..b34b7d793 --- /dev/null +++ b/src/discounts/types/VoucherDetailsFragment.ts @@ -0,0 +1,145 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { VoucherDiscountValueType, VoucherType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: VoucherDetailsFragment +// ==================================================== + +export interface VoucherDetailsFragment_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface VoucherDetailsFragment_minAmountSpent { + __typename: "Money"; + currency: string; + amount: number; +} + +export interface VoucherDetailsFragment_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface VoucherDetailsFragment_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface VoucherDetailsFragment_products_edges_node { + __typename: "Product"; + id: string; + name: string; + productType: VoucherDetailsFragment_products_edges_node_productType; + isPublished: boolean; + thumbnail: VoucherDetailsFragment_products_edges_node_thumbnail | null; +} + +export interface VoucherDetailsFragment_products_edges { + __typename: "ProductCountableEdge"; + node: VoucherDetailsFragment_products_edges_node; +} + +export interface VoucherDetailsFragment_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherDetailsFragment_products { + __typename: "ProductCountableConnection"; + edges: VoucherDetailsFragment_products_edges[]; + totalCount: number | null; + pageInfo: VoucherDetailsFragment_products_pageInfo; +} + +export interface VoucherDetailsFragment_collections_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface VoucherDetailsFragment_collections_edges_node { + __typename: "Collection"; + id: string; + name: string; + products: VoucherDetailsFragment_collections_edges_node_products | null; +} + +export interface VoucherDetailsFragment_collections_edges { + __typename: "CollectionCountableEdge"; + node: VoucherDetailsFragment_collections_edges_node; +} + +export interface VoucherDetailsFragment_collections_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherDetailsFragment_collections { + __typename: "CollectionCountableConnection"; + edges: VoucherDetailsFragment_collections_edges[]; + totalCount: number | null; + pageInfo: VoucherDetailsFragment_collections_pageInfo; +} + +export interface VoucherDetailsFragment_categories_edges_node_products { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface VoucherDetailsFragment_categories_edges_node { + __typename: "Category"; + id: string; + name: string; + products: VoucherDetailsFragment_categories_edges_node_products | null; +} + +export interface VoucherDetailsFragment_categories_edges { + __typename: "CategoryCountableEdge"; + node: VoucherDetailsFragment_categories_edges_node; +} + +export interface VoucherDetailsFragment_categories_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherDetailsFragment_categories { + __typename: "CategoryCountableConnection"; + edges: VoucherDetailsFragment_categories_edges[]; + totalCount: number | null; + pageInfo: VoucherDetailsFragment_categories_pageInfo; +} + +export interface VoucherDetailsFragment { + __typename: "Voucher"; + id: string; + name: string | null; + startDate: any; + endDate: any | null; + usageLimit: number | null; + discountValueType: VoucherDiscountValueType; + discountValue: number; + countries: (VoucherDetailsFragment_countries | null)[] | null; + minAmountSpent: VoucherDetailsFragment_minAmountSpent | null; + type: VoucherType; + code: string; + used: number; + applyOncePerOrder: boolean; + products: VoucherDetailsFragment_products | null; + collections: VoucherDetailsFragment_collections | null; + categories: VoucherDetailsFragment_categories | null; +} diff --git a/src/discounts/types/VoucherFragment.ts b/src/discounts/types/VoucherFragment.ts new file mode 100644 index 000000000..c8d8aab47 --- /dev/null +++ b/src/discounts/types/VoucherFragment.ts @@ -0,0 +1,34 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { VoucherDiscountValueType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: VoucherFragment +// ==================================================== + +export interface VoucherFragment_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface VoucherFragment_minAmountSpent { + __typename: "Money"; + currency: string; + amount: number; +} + +export interface VoucherFragment { + __typename: "Voucher"; + id: string; + name: string | null; + startDate: any; + endDate: any | null; + usageLimit: number | null; + discountValueType: VoucherDiscountValueType; + discountValue: number; + countries: (VoucherFragment_countries | null)[] | null; + minAmountSpent: VoucherFragment_minAmountSpent | null; +} diff --git a/src/discounts/types/VoucherList.ts b/src/discounts/types/VoucherList.ts new file mode 100644 index 000000000..cce0df721 --- /dev/null +++ b/src/discounts/types/VoucherList.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { VoucherDiscountValueType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: VoucherList +// ==================================================== + +export interface VoucherList_vouchers_edges_node_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface VoucherList_vouchers_edges_node_minAmountSpent { + __typename: "Money"; + currency: string; + amount: number; +} + +export interface VoucherList_vouchers_edges_node { + __typename: "Voucher"; + id: string; + name: string | null; + startDate: any; + endDate: any | null; + usageLimit: number | null; + discountValueType: VoucherDiscountValueType; + discountValue: number; + countries: (VoucherList_vouchers_edges_node_countries | null)[] | null; + minAmountSpent: VoucherList_vouchers_edges_node_minAmountSpent | null; +} + +export interface VoucherList_vouchers_edges { + __typename: "VoucherCountableEdge"; + node: VoucherList_vouchers_edges_node; +} + +export interface VoucherList_vouchers_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface VoucherList_vouchers { + __typename: "VoucherCountableConnection"; + edges: VoucherList_vouchers_edges[]; + pageInfo: VoucherList_vouchers_pageInfo; +} + +export interface VoucherList { + vouchers: VoucherList_vouchers | null; +} + +export interface VoucherListVariables { + after?: string | null; + before?: string | null; + first?: number | null; + last?: number | null; +} diff --git a/src/discounts/types/VoucherUpdate.ts b/src/discounts/types/VoucherUpdate.ts new file mode 100644 index 000000000..2dd2521b2 --- /dev/null +++ b/src/discounts/types/VoucherUpdate.ts @@ -0,0 +1,55 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { VoucherInput, VoucherDiscountValueType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: VoucherUpdate +// ==================================================== + +export interface VoucherUpdate_voucherUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface VoucherUpdate_voucherUpdate_voucher_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface VoucherUpdate_voucherUpdate_voucher_minAmountSpent { + __typename: "Money"; + currency: string; + amount: number; +} + +export interface VoucherUpdate_voucherUpdate_voucher { + __typename: "Voucher"; + id: string; + name: string | null; + startDate: any; + endDate: any | null; + usageLimit: number | null; + discountValueType: VoucherDiscountValueType; + discountValue: number; + countries: (VoucherUpdate_voucherUpdate_voucher_countries | null)[] | null; + minAmountSpent: VoucherUpdate_voucherUpdate_voucher_minAmountSpent | null; +} + +export interface VoucherUpdate_voucherUpdate { + __typename: "VoucherUpdate"; + errors: VoucherUpdate_voucherUpdate_errors[] | null; + voucher: VoucherUpdate_voucherUpdate_voucher | null; +} + +export interface VoucherUpdate { + voucherUpdate: VoucherUpdate_voucherUpdate | null; +} + +export interface VoucherUpdateVariables { + input: VoucherInput; + id: string; +} diff --git a/src/discounts/urls.ts b/src/discounts/urls.ts new file mode 100644 index 000000000..a33556ed8 --- /dev/null +++ b/src/discounts/urls.ts @@ -0,0 +1,61 @@ +import { stringify as stringifyQs } from "qs"; +import * as urlJoin from "url-join"; + +import { ActiveTab, BulkAction, Dialog, Pagination } from "../types"; +import { SaleDetailsPageTab } from "./components/SaleDetailsPage"; +import { VoucherDetailsPageTab } from "./components/VoucherDetailsPage"; + +export const discountSection = "/discounts/"; + +export const saleSection = urlJoin(discountSection, "sales"); +export const saleListPath = saleSection; +export type SaleListUrlDialog = "remove"; +export type SaleListUrlQueryParams = BulkAction & + Dialog & + Pagination; +export const saleListUrl = (params?: SaleListUrlQueryParams) => + saleListPath + "?" + stringifyQs(params); +export const salePath = (id: string) => urlJoin(saleSection, id); +export type SaleUrlDialog = + | "assign-category" + | "assign-collection" + | "assign-product" + | "unassign-category" + | "unassign-collection" + | "unassign-product" + | "remove"; +export type SaleUrlQueryParams = Pagination & + BulkAction & + Dialog & + ActiveTab; +export const saleUrl = (id: string, params?: SaleUrlQueryParams) => + salePath(encodeURIComponent(id)) + "?" + stringifyQs(params); +export const saleAddPath = urlJoin(saleSection, "add"); +export const saleAddUrl = saleAddPath; + +export const voucherSection = urlJoin(discountSection, "vouchers"); +export const voucherListPath = voucherSection; +export type VoucherListUrlDialog = "remove"; +export type VoucherListUrlQueryParams = BulkAction & + Dialog & + Pagination; +export const voucherListUrl = (params?: VoucherListUrlQueryParams) => + voucherListPath + "?" + stringifyQs(params); +export const voucherPath = (id: string) => urlJoin(voucherSection, id); +export type VoucherUrlDialog = + | "assign-category" + | "assign-collection" + | "assign-country" + | "assign-product" + | "unassign-category" + | "unassign-collection" + | "unassign-product" + | "remove"; +export type VoucherUrlQueryParams = Pagination & + BulkAction & + Dialog & + ActiveTab; +export const voucherUrl = (id: string, params?: VoucherUrlQueryParams) => + voucherPath(encodeURIComponent(id)) + "?" + stringifyQs(params); +export const voucherAddPath = urlJoin(voucherSection, "add"); +export const voucherAddUrl = voucherAddPath; diff --git a/src/discounts/views/SaleCreate.tsx b/src/discounts/views/SaleCreate.tsx new file mode 100644 index 000000000..eb5a55f80 --- /dev/null +++ b/src/discounts/views/SaleCreate.tsx @@ -0,0 +1,77 @@ +import * as React from "react"; + +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import i18n from "../../i18n"; +import { decimal, getMutationState, maybe } from "../../misc"; +import { DiscountValueTypeEnum, SaleType } from "../../types/globalTypes"; +import SaleCreatePage from "../components/SaleCreatePage"; +import { TypedSaleCreate } from "../mutations"; +import { SaleCreate } from "../types/SaleCreate"; +import { saleListUrl, saleUrl } from "../urls"; + +function discountValueTypeEnum(type: SaleType): DiscountValueTypeEnum { + return type.toString() === DiscountValueTypeEnum.FIXED + ? DiscountValueTypeEnum.FIXED + : DiscountValueTypeEnum.PERCENTAGE; +} + +export const SaleDetails: React.StatelessComponent = () => { + const navigate = useNavigator(); + const pushMessage = useNotifier(); + const shop = useShop(); + + const handleSaleCreate = (data: SaleCreate) => { + if (data.saleCreate.errors.length === 0) { + pushMessage({ + text: i18n.t("Successfully created sale", { + context: "notification" + }) + }); + navigate(saleUrl(data.saleCreate.sale.id), true); + } + }; + + return ( + + {(saleCreate, saleCreateOpts) => { + const formTransitionState = getMutationState( + saleCreateOpts.called, + saleCreateOpts.loading, + maybe(() => saleCreateOpts.data.saleCreate.errors) + ); + + return ( + <> + + shop.defaultCurrency)} + disabled={saleCreateOpts.loading} + errors={maybe(() => saleCreateOpts.data.saleCreate.errors)} + onBack={() => navigate(saleListUrl())} + onSubmit={formData => + saleCreate({ + variables: { + input: { + endDate: + formData.endDate === "" ? null : formData.endDate, + name: formData.name, + startDate: + formData.startDate === "" ? null : formData.startDate, + type: discountValueTypeEnum(formData.type), + value: decimal(formData.value) + } + } + }) + } + saveButtonBarState={formTransitionState} + /> + + ); + }} + + ); +}; +export default SaleDetails; diff --git a/src/discounts/views/SaleDetails.tsx b/src/discounts/views/SaleDetails.tsx new file mode 100644 index 000000000..b0a3c473f --- /dev/null +++ b/src/discounts/views/SaleDetails.tsx @@ -0,0 +1,548 @@ +import Button from "@material-ui/core/Button"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import AssignCategoriesDialog from "@saleor/components/AssignCategoryDialog"; +import AssignCollectionDialog from "@saleor/components/AssignCollectionDialog"; +import AssignProductDialog from "@saleor/components/AssignProductDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; +import { categoryUrl } from "../../categories/urls"; +import { collectionUrl } from "../../collections/urls"; +import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config"; +import SearchCategories from "../../containers/SearchCategories"; +import SearchCollections from "../../containers/SearchCollections"; +import SearchProducts from "../../containers/SearchProducts"; +import i18n from "../../i18n"; +import { decimal, getMutationState, maybe } from "../../misc"; +import { productUrl } from "../../products/urls"; +import { DiscountValueTypeEnum, SaleType } from "../../types/globalTypes"; +import SaleDetailsPage, { + SaleDetailsPageTab +} from "../components/SaleDetailsPage"; +import { + TypedSaleCataloguesAdd, + TypedSaleCataloguesRemove, + TypedSaleDelete, + TypedSaleUpdate +} from "../mutations"; +import { TypedSaleDetails } from "../queries"; +import { SaleCataloguesAdd } from "../types/SaleCataloguesAdd"; +import { SaleCataloguesRemove } from "../types/SaleCataloguesRemove"; +import { SaleDelete } from "../types/SaleDelete"; +import { SaleUpdate } from "../types/SaleUpdate"; +import { + saleListUrl, + saleUrl, + SaleUrlDialog, + SaleUrlQueryParams +} from "../urls"; + +interface SaleDetailsProps { + id: string; + params: SaleUrlQueryParams; +} + +function discountValueTypeEnum(type: SaleType): DiscountValueTypeEnum { + return type.toString() === DiscountValueTypeEnum.FIXED + ? DiscountValueTypeEnum.FIXED + : DiscountValueTypeEnum.PERCENTAGE; +} + +export const SaleDetails: React.StatelessComponent = ({ + id, + params +}) => { + const navigate = useNavigator(); + const paginate = usePaginator(); + const notify = useNotifier(); + const shop = useShop(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const paginationState = createPaginationState(PAGINATE_BY, params); + const changeTab = (tab: SaleDetailsPageTab) => { + reset(); + navigate( + saleUrl(id, { + activeTab: tab + }) + ); + }; + + const handleSaleDelete = (data: SaleDelete) => { + if (data.saleDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed sale", { + context: "notification" + }) + }); + navigate(saleListUrl(), true); + } + }; + + const handleSaleUpdate = (data: SaleUpdate) => { + if (data.saleUpdate.errors.length === 0) { + notify({ + text: i18n.t("Updated sale", { + context: "notification" + }) + }); + } + }; + + const closeModal = () => + navigate( + saleUrl(id, { + ...params, + action: undefined, + ids: undefined + }), + true + ); + + const openModal = (action: SaleUrlDialog, ids?: string[]) => + navigate( + saleUrl(id, { + ...params, + action, + ids + }) + ); + + const handleCatalogueAdd = (data: SaleCataloguesAdd) => { + if (data.saleCataloguesAdd.errors.length === 0) { + closeModal(); + } + }; + + const handleCatalogueRemove = (data: SaleCataloguesRemove) => { + if (data.saleCataloguesRemove.errors.length === 0) { + closeModal(); + reset(); + } + }; + + return ( + + {(saleCataloguesRemove, saleCataloguesRemoveOpts) => ( + + {(saleCataloguesAdd, saleCataloguesAddOpts) => ( + + {(saleUpdate, saleUpdateOpts) => ( + + {(saleDelete, saleDeleteOpts) => ( + + {({ data, loading }) => { + const tabPageInfo = + params.activeTab === SaleDetailsPageTab.categories + ? maybe(() => data.sale.categories.pageInfo) + : params.activeTab === + SaleDetailsPageTab.collections + ? maybe(() => data.sale.collections.pageInfo) + : maybe(() => data.sale.products.pageInfo); + const formTransitionState = getMutationState( + saleUpdateOpts.called, + saleUpdateOpts.loading, + maybe(() => saleUpdateOpts.data.saleUpdate.errors) + ); + const assignTransitionState = getMutationState( + saleCataloguesAddOpts.called, + saleCataloguesAddOpts.loading, + maybe( + () => + saleCataloguesAddOpts.data.saleCataloguesAdd + .errors + ) + ); + const unassignTransitionState = getMutationState( + saleCataloguesRemoveOpts.called, + saleCataloguesRemoveOpts.loading, + maybe( + () => + saleCataloguesRemoveOpts.data.saleCataloguesRemove + .errors + ) + ); + const removeTransitionState = getMutationState( + saleDeleteOpts.called, + saleDeleteOpts.loading, + maybe(() => saleDeleteOpts.data.saleDelete.errors) + ); + + const handleCategoriesUnassign = (ids: string[]) => + saleCataloguesRemove({ + variables: { + ...paginationState, + id, + input: { + categories: ids + } + } + }); + + const handleCollectionsUnassign = (ids: string[]) => + saleCataloguesRemove({ + variables: { + ...paginationState, + id, + input: { + collections: ids + } + } + }); + + const handleProductsUnassign = (ids: string[]) => + saleCataloguesRemove({ + variables: { + ...paginationState, + id, + input: { + products: ids + } + } + }); + + const { + loadNextPage, + loadPreviousPage, + pageInfo + } = paginate(tabPageInfo, paginationState, params); + + return ( + <> + + shop.defaultCurrency + )} + sale={maybe(() => data.sale)} + disabled={ + loading || saleCataloguesRemoveOpts.loading + } + errors={maybe( + () => saleUpdateOpts.data.saleUpdate.errors + )} + pageInfo={pageInfo} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onCategoryAssign={() => + openModal("assign-category") + } + onCategoryClick={id => () => + navigate(categoryUrl(id))} + onCollectionAssign={() => + openModal("assign-collection") + } + onCollectionUnassign={collectionId => + handleCollectionsUnassign([collectionId]) + } + onCategoryUnassign={categoryId => + handleCategoriesUnassign([categoryId]) + } + onCollectionClick={id => () => + navigate(collectionUrl(id))} + onProductAssign={() => + openModal("assign-product") + } + onProductUnassign={productId => + handleProductsUnassign([productId]) + } + onProductClick={id => () => + navigate(productUrl(id))} + activeTab={params.activeTab} + onBack={() => navigate(saleListUrl())} + onTabClick={changeTab} + onSubmit={formData => + saleUpdate({ + variables: { + id, + input: { + endDate: + formData.endDate === "" + ? null + : formData.endDate, + name: formData.name, + startDate: + formData.startDate === "" + ? null + : formData.startDate, + type: discountValueTypeEnum( + formData.type + ), + value: decimal(formData.value) + } + } + }) + } + onRemove={() => openModal("remove")} + saveButtonBarState={formTransitionState} + categoryListToolbar={ + + } + collectionListToolbar={ + + } + productListToolbar={ + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + /> + + {({ + search: searchProducts, + result: searchProductsOpts + }) => ( + + saleCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + products: formData.products.map( + product => product.id + ) + } + } + }) + } + products={maybe(() => + searchProductsOpts.data.products.edges + .map(edge => edge.node) + .filter( + suggestedProduct => suggestedProduct.id + ) + )} + /> + )} + + + {({ + search: searchCategories, + result: searchCategoriesOpts + }) => ( + + searchCategoriesOpts.data.categories.edges + .map(edge => edge.node) + .filter( + suggestedCategory => + suggestedCategory.id + ) + )} + confirmButtonState={assignTransitionState} + open={params.action === "assign-category"} + onFetch={searchCategories} + loading={searchCategoriesOpts.loading} + onClose={closeModal} + onSubmit={formData => + saleCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + categories: formData.categories.map( + product => product.id + ) + } + } + }) + } + /> + )} + + + {({ + search: searchCollections, + result: searchCollectionsOpts + }) => ( + + searchCollectionsOpts.data.collections.edges + .map(edge => edge.node) + .filter( + suggestedCategory => + suggestedCategory.id + ) + )} + confirmButtonState={assignTransitionState} + open={params.action === "assign-collection"} + onFetch={searchCollections} + loading={searchCollectionsOpts.loading} + onClose={closeModal} + onSubmit={formData => + saleCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + collections: formData.collections.map( + product => product.id + ) + } + } + }) + } + /> + )} + + + handleCategoriesUnassign(params.ids) + } + > + {{ saleName }} categories?", + { + saleName: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + handleCollectionsUnassign(params.ids) + } + > + {{ saleName }} collections?", + { + saleName: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + handleProductsUnassign(params.ids) + } + > + {{ saleName }} products?", + { + saleName: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + saleDelete({ + variables: { id } + }) + } + > + {{ saleName }}?", + { + saleName: maybe( + () => data.sale.name, + "..." + ) + } + ) + }} + /> + + + ); + }} + + )} + + )} + + )} + + )} + + ); +}; +export default SaleDetails; diff --git a/src/discounts/views/SaleList.tsx b/src/discounts/views/SaleList.tsx new file mode 100644 index 000000000..97e1a302e --- /dev/null +++ b/src/discounts/views/SaleList.tsx @@ -0,0 +1,146 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; +import { PAGINATE_BY } from "../../config"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import SaleListPage from "../components/SaleListPage"; +import { TypedSaleBulkDelete } from "../mutations"; +import { TypedSaleList } from "../queries"; +import { SaleBulkDelete } from "../types/SaleBulkDelete"; +import { + saleAddUrl, + saleListUrl, + SaleListUrlQueryParams, + saleUrl +} from "../urls"; + +interface SaleListProps { + params: SaleListUrlQueryParams; +} + +export const SaleList: React.StatelessComponent = ({ + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const shop = useShop(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const closeModal = () => navigate(saleListUrl(), true); + + const paginationState = createPaginationState(PAGINATE_BY, params); + + return ( + + {({ data, loading, refetch }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.sales.pageInfo), + paginationState, + params + ); + + const handleSaleBulkDelete = (data: SaleBulkDelete) => { + if (data.saleBulkDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed sales") + }); + reset(); + closeModal(); + refetch(); + } + }; + + return ( + + {(saleBulkDelete, saleBulkDeleteOpts) => { + const bulkRemoveTransitionState = getMutationState( + saleBulkDeleteOpts.called, + saleBulkDeleteOpts.loading, + maybe(() => saleBulkDeleteOpts.data.saleBulkDelete.errors) + ); + const onSaleBulkDelete = () => + saleBulkDelete({ + variables: { + ids: params.ids + } + }); + + return ( + <> + + shop.defaultCurrency)} + sales={maybe(() => data.sales.edges.map(edge => edge.node))} + disabled={loading} + pageInfo={pageInfo} + onAdd={() => navigate(saleAddUrl)} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRowClick={id => () => navigate(saleUrl(id))} + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + toolbar={ + + navigate( + saleListUrl({ + action: "remove", + ids: listElements + }) + ) + } + > + + + } + /> + + {{ number }} sales?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + ); + }} + + ); + }} + + ); +}; +export default SaleList; diff --git a/src/discounts/views/VoucherCreate.tsx b/src/discounts/views/VoucherCreate.tsx new file mode 100644 index 000000000..00efa1210 --- /dev/null +++ b/src/discounts/views/VoucherCreate.tsx @@ -0,0 +1,88 @@ +import * as React from "react"; + +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import i18n from "../../i18n"; +import { decimal, getMutationState, maybe } from "../../misc"; +import { + DiscountValueTypeEnum, + VoucherDiscountValueType, + VoucherTypeEnum +} from "../../types/globalTypes"; +import VoucherCreatePage from "../components/VoucherCreatePage"; +import { TypedVoucherCreate } from "../mutations"; +import { VoucherCreate } from "../types/VoucherCreate"; +import { voucherListUrl, voucherUrl } from "../urls"; + +function discountValueTypeEnum( + type: VoucherDiscountValueType +): DiscountValueTypeEnum { + return type.toString() === DiscountValueTypeEnum.FIXED + ? DiscountValueTypeEnum.FIXED + : DiscountValueTypeEnum.PERCENTAGE; +} + +export const VoucherDetails: React.StatelessComponent = () => { + const navigate = useNavigator(); + const notify = useNotifier(); + const shop = useShop(); + + const handleVoucherCreate = (data: VoucherCreate) => { + if (data.voucherCreate.errors.length === 0) { + notify({ + text: i18n.t("Successfully created voucher", { + context: "notification" + }) + }); + navigate(voucherUrl(data.voucherCreate.voucher.id), true); + } + }; + + return ( + + {(voucherCreate, voucherCreateOpts) => { + const formTransitionState = getMutationState( + voucherCreateOpts.called, + voucherCreateOpts.loading, + maybe(() => voucherCreateOpts.data.voucherCreate.errors) + ); + + return ( + <> + + shop.defaultCurrency)} + disabled={voucherCreateOpts.loading} + errors={maybe(() => voucherCreateOpts.data.voucherCreate.errors)} + onBack={() => navigate(voucherListUrl())} + onSubmit={formData => + voucherCreate({ + variables: { + input: { + code: formData.code, + discountValue: decimal(formData.value), + discountValueType: discountValueTypeEnum( + formData.discountType + ), + endDate: + formData.endDate === "" ? null : formData.endDate, + minAmountSpent: formData.minAmountSpent, + name: formData.name, + startDate: + formData.startDate === "" ? null : formData.startDate, + type: VoucherTypeEnum[formData.type] + } + } + }) + } + saveButtonBarState={formTransitionState} + /> + + ); + }} + + ); +}; +export default VoucherDetails; diff --git a/src/discounts/views/VoucherDetails.tsx b/src/discounts/views/VoucherDetails.tsx new file mode 100644 index 000000000..b3ef7ec5e --- /dev/null +++ b/src/discounts/views/VoucherDetails.tsx @@ -0,0 +1,625 @@ +import Button from "@material-ui/core/Button"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import AssignCategoriesDialog from "@saleor/components/AssignCategoryDialog"; +import AssignCollectionDialog from "@saleor/components/AssignCollectionDialog"; +import AssignProductDialog from "@saleor/components/AssignProductDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; +import { categoryUrl } from "../../categories/urls"; +import { collectionUrl } from "../../collections/urls"; +import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config"; +import SearchCategories from "../../containers/SearchCategories"; +import SearchCollections from "../../containers/SearchCollections"; +import SearchProducts from "../../containers/SearchProducts"; +import i18n from "../../i18n"; +import { decimal, getMutationState, maybe } from "../../misc"; +import { productUrl } from "../../products/urls"; +import { + DiscountValueTypeEnum, + VoucherDiscountValueType +} from "../../types/globalTypes"; +import DiscountCountrySelectDialog from "../components/DiscountCountrySelectDialog"; +import VoucherDetailsPage, { + VoucherDetailsPageTab +} from "../components/VoucherDetailsPage"; +import { + TypedVoucherCataloguesAdd, + TypedVoucherCataloguesRemove, + TypedVoucherDelete, + TypedVoucherUpdate +} from "../mutations"; +import { TypedVoucherDetails } from "../queries"; +import { VoucherCataloguesAdd } from "../types/VoucherCataloguesAdd"; +import { VoucherCataloguesRemove } from "../types/VoucherCataloguesRemove"; +import { VoucherDelete } from "../types/VoucherDelete"; +import { VoucherUpdate } from "../types/VoucherUpdate"; +import { + voucherListUrl, + voucherUrl, + VoucherUrlDialog, + VoucherUrlQueryParams +} from "../urls"; + +interface VoucherDetailsProps { + id: string; + params: VoucherUrlQueryParams; +} + +function discountValueTypeEnum( + type: VoucherDiscountValueType +): DiscountValueTypeEnum { + return type.toString() === DiscountValueTypeEnum.FIXED + ? DiscountValueTypeEnum.FIXED + : DiscountValueTypeEnum.PERCENTAGE; +} + +export const VoucherDetails: React.StatelessComponent = ({ + id, + params +}) => { + const navigate = useNavigator(); + const paginate = usePaginator(); + const notify = useNotifier(); + const shop = useShop(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const paginationState = createPaginationState(PAGINATE_BY, params); + const changeTab = (tab: VoucherDetailsPageTab) => { + reset(); + navigate( + voucherUrl(id, { + activeTab: tab + }) + ); + }; + + const handleVoucherDelete = (data: VoucherDelete) => { + if (data.voucherDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed voucher", { + context: "notification" + }) + }); + navigate(voucherListUrl(), true); + } + }; + + const handleVoucherUpdate = (data: VoucherUpdate) => { + if (data.voucherUpdate.errors.length === 0) { + closeModal(); + notify({ + text: i18n.t("Updated voucher", { + context: "notification" + }) + }); + } + }; + + const closeModal = () => + navigate( + voucherUrl(id, { + ...params, + action: undefined + }), + true + ); + + const openModal = (action: VoucherUrlDialog, ids?: string[]) => + navigate( + voucherUrl(id, { + ...params, + action, + ids + }) + ); + + const handleCatalogueAdd = (data: VoucherCataloguesAdd) => { + if (data.voucherCataloguesAdd.errors.length === 0) { + closeModal(); + } + }; + + const handleCatalogueRemove = (data: VoucherCataloguesRemove) => { + if (data.voucherCataloguesRemove.errors.length === 0) { + closeModal(); + reset(); + } + }; + + return ( + + {(voucherCataloguesRemove, voucherCataloguesRemoveOpts) => ( + + {(voucherCataloguesAdd, voucherCataloguesAddOpts) => ( + + {(voucherUpdate, voucherUpdateOpts) => ( + + {(voucherDelete, voucherDeleteOpts) => ( + + {({ data, loading }) => { + const tabPageInfo = + params.activeTab === VoucherDetailsPageTab.categories + ? maybe(() => data.voucher.categories.pageInfo) + : params.activeTab === + VoucherDetailsPageTab.collections + ? maybe(() => data.voucher.collections.pageInfo) + : maybe(() => data.voucher.products.pageInfo); + const formTransitionState = getMutationState( + voucherUpdateOpts.called, + voucherUpdateOpts.loading, + maybe( + () => voucherUpdateOpts.data.voucherUpdate.errors + ) + ); + const assignTransitionState = getMutationState( + voucherCataloguesAddOpts.called, + voucherCataloguesAddOpts.loading, + maybe( + () => + voucherCataloguesAddOpts.data.voucherCataloguesAdd + .errors + ) + ); + const unassignTransitionState = getMutationState( + voucherCataloguesRemoveOpts.called, + voucherCataloguesRemoveOpts.loading, + maybe( + () => + voucherCataloguesRemoveOpts.data + .voucherCataloguesRemove.errors + ) + ); + const removeTransitionState = getMutationState( + voucherDeleteOpts.called, + voucherDeleteOpts.loading, + maybe( + () => voucherDeleteOpts.data.voucherDelete.errors + ) + ); + + const handleCategoriesUnassign = (ids: string[]) => + voucherCataloguesRemove({ + variables: { + ...paginationState, + id, + input: { + categories: ids + } + } + }); + + const handleCollectionsUnassign = (ids: string[]) => + voucherCataloguesRemove({ + variables: { + ...paginationState, + id, + input: { + collections: ids + } + } + }); + + const handleProductsUnassign = (ids: string[]) => + voucherCataloguesRemove({ + variables: { + ...paginationState, + id, + input: { + products: ids + } + } + }); + + const { + loadNextPage, + loadPreviousPage, + pageInfo + } = paginate(tabPageInfo, paginationState, params); + + return ( + <> + + shop.defaultCurrency + )} + voucher={maybe(() => data.voucher)} + disabled={ + loading || voucherCataloguesRemoveOpts.loading + } + errors={maybe( + () => + voucherUpdateOpts.data.voucherUpdate.errors + )} + pageInfo={pageInfo} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onCategoryAssign={() => + openModal("assign-category") + } + onCategoryClick={id => () => + navigate(categoryUrl(id))} + onCollectionAssign={() => + openModal("assign-collection") + } + onCollectionUnassign={collectionId => + voucherCataloguesRemove({ + variables: { + ...paginationState, + id, + input: { + collections: [collectionId] + } + } + }) + } + onCountryAssign={() => + openModal("assign-country") + } + onCountryUnassign={countryCode => + voucherUpdate({ + variables: { + ...paginationState, + id, + input: { + countries: data.voucher.countries + .filter( + country => + country.code !== countryCode + ) + .map(country => country.code) + } + } + }) + } + onCategoryUnassign={categoryId => + voucherCataloguesRemove({ + variables: { + ...paginationState, + id, + input: { + categories: [categoryId] + } + } + }) + } + onCollectionClick={id => () => + navigate(collectionUrl(id))} + onProductAssign={() => + openModal("assign-product") + } + onProductUnassign={productId => + voucherCataloguesRemove({ + variables: { + ...paginationState, + id, + input: { + products: [productId] + } + } + }) + } + onProductClick={id => () => + navigate(productUrl(id))} + activeTab={params.activeTab} + onBack={() => navigate(voucherListUrl())} + onTabClick={changeTab} + onSubmit={formData => + voucherUpdate({ + variables: { + id, + input: { + discountValue: decimal(formData.value), + discountValueType: discountValueTypeEnum( + formData.discountType + ), + endDate: + formData.endDate === "" + ? null + : formData.endDate, + name: formData.name, + startDate: + formData.startDate === "" + ? null + : formData.startDate + } + } + }) + } + onRemove={() => openModal("remove")} + saveButtonBarState={formTransitionState} + categoryListToolbar={ + + } + collectionListToolbar={ + + } + productListToolbar={ + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + /> + + {({ + search: searchCategories, + result: searchCategoriesOpts + }) => ( + + searchCategoriesOpts.data.categories.edges + .map(edge => edge.node) + .filter( + suggestedCategory => + suggestedCategory.id + ) + )} + confirmButtonState={assignTransitionState} + open={params.action === "assign-category"} + onFetch={searchCategories} + loading={searchCategoriesOpts.loading} + onClose={closeModal} + onSubmit={formData => + voucherCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + categories: formData.categories.map( + product => product.id + ) + } + } + }) + } + /> + )} + + + {({ + search: searchCollections, + result: searchCollectionsOpts + }) => ( + + searchCollectionsOpts.data.collections.edges + .map(edge => edge.node) + .filter( + suggestedCategory => + suggestedCategory.id + ) + )} + confirmButtonState={assignTransitionState} + open={params.action === "assign-collection"} + onFetch={searchCollections} + loading={searchCollectionsOpts.loading} + onClose={closeModal} + onSubmit={formData => + voucherCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + collections: formData.collections.map( + product => product.id + ) + } + } + }) + } + /> + )} + + shop.countries, [])} + onClose={() => navigate(voucherUrl(id))} + onConfirm={formData => + voucherUpdate({ + variables: { + id, + input: { + countries: formData.countries + } + } + }) + } + open={params.action === "assign-country"} + initial={maybe( + () => + data.voucher.countries.map( + country => country.code + ), + [] + )} + /> + + {({ + search: searchProducts, + result: searchProductsOpts + }) => ( + + voucherCataloguesAdd({ + variables: { + ...paginationState, + id, + input: { + products: formData.products.map( + product => product.id + ) + } + } + }) + } + products={maybe(() => + searchProductsOpts.data.products.edges + .map(edge => edge.node) + .filter( + suggestedProduct => suggestedProduct.id + ) + )} + /> + )} + + + handleCategoriesUnassign(params.ids) + } + > + {{ saleName }} categories?", + { + saleName: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + handleCollectionsUnassign(params.ids) + } + > + {{ saleName }} collections?", + { + saleName: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + handleProductsUnassign(params.ids) + } + > + {{ saleName }} products?", + { + saleName: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + voucherDelete({ + variables: { id } + }) + } + > + {{ voucherName }}?", + { + voucherName: maybe( + () => data.voucher.name, + "..." + ) + } + ) + }} + /> + + + ); + }} + + )} + + )} + + )} + + )} + + ); +}; +export default VoucherDetails; diff --git a/src/discounts/views/VoucherList.tsx b/src/discounts/views/VoucherList.tsx new file mode 100644 index 000000000..e8ca0d404 --- /dev/null +++ b/src/discounts/views/VoucherList.tsx @@ -0,0 +1,147 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; +import { PAGINATE_BY } from "../../config"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import VoucherListPage from "../components/VoucherListPage"; +import { TypedVoucherBulkDelete } from "../mutations"; +import { TypedVoucherList } from "../queries"; +import { VoucherBulkDelete } from "../types/VoucherBulkDelete"; +import { + voucherAddUrl, + voucherListUrl, + VoucherListUrlQueryParams, + voucherUrl +} from "../urls"; + +interface VoucherListProps { + params: VoucherListUrlQueryParams; +} + +export const VoucherList: React.StatelessComponent = ({ + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const shop = useShop(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const closeModal = () => navigate(voucherListUrl(), true); + + const paginationState = createPaginationState(PAGINATE_BY, params); + + return ( + + {({ data, loading, refetch }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.vouchers.pageInfo), + paginationState, + params + ); + + const handleVoucherBulkDelete = (data: VoucherBulkDelete) => { + if (data.voucherBulkDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed vouchers") + }); + reset(); + closeModal(); + refetch(); + } + }; + + return ( + + {(voucherBulkDelete, voucherBulkDeleteOpts) => { + const bulkRemoveTransitionState = getMutationState( + voucherBulkDeleteOpts.called, + voucherBulkDeleteOpts.loading, + maybe(() => voucherBulkDeleteOpts.data.voucherBulkDelete.errors) + ); + const onVoucherBulkDelete = () => + voucherBulkDelete({ + variables: { + ids: params.ids + } + }); + return ( + <> + + shop.defaultCurrency)} + vouchers={maybe(() => + data.vouchers.edges.map(edge => edge.node) + )} + disabled={loading} + pageInfo={pageInfo} + onAdd={() => navigate(voucherAddUrl)} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRowClick={id => () => navigate(voucherUrl(id))} + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + toolbar={ + + navigate( + voucherListUrl({ + action: "remove", + ids: listElements + }) + ) + } + > + + + } + /> + + {{ number }} vouchers?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + ); + }} + + ); + }} + + ); +}; +export default VoucherList; diff --git a/src/fixtures.ts b/src/fixtures.ts new file mode 100644 index 000000000..ef1d1aeec --- /dev/null +++ b/src/fixtures.ts @@ -0,0 +1,125 @@ +import { Filter } from "./components/TableFilter"; +import { FilterPageProps, ListActions, PageListProps } from "./types"; + +const pageInfo = { + hasNextPage: true, + hasPreviousPage: false +}; +export const pageListProps: { [key: string]: PageListProps } = { + default: { + disabled: false, + onAdd: undefined, + onNextPage: undefined, + onPreviousPage: undefined, + onRowClick: () => undefined, + pageInfo + }, + loading: { + disabled: true, + onAdd: undefined, + onNextPage: undefined, + onPreviousPage: undefined, + onRowClick: () => undefined, + pageInfo + } +}; +export const listActionsProps: ListActions = { + isChecked: () => undefined, + selected: 0, + toggle: () => undefined, + toggleAll: () => undefined, + toolbar: null +}; + +export const countries = [ + { code: "AF", label: "Afghanistan" }, + { code: "AX", label: "Åland Islands" }, + { code: "AL", label: "Albania" }, + { code: "DZ", label: "Algeria" }, + { code: "AS", label: "American Samoa" } +]; + +export const filterPageProps: FilterPageProps<{}> = { + currencySymbol: "USD", + currentTab: 0, + filterTabs: [ + { + data: {}, + name: "Tab X" + } + ], + filtersList: [], + initialSearch: "", + onAll: () => undefined, + onFilterAdd: () => undefined, + onFilterDelete: () => undefined, + onFilterSave: () => undefined, + onSearchChange: () => undefined, + onTabChange: () => undefined +}; + +export const filters: Filter[] = [ + { + label: "Property X is ", + onClick: () => undefined + }, + { + label: "Property Y is ", + onClick: () => undefined + }, + { + label: "Property Z is ", + onClick: () => undefined + }, + { + label: "Property X is ", + onClick: () => undefined + }, + { + label: "Property Y is ", + onClick: () => undefined + }, + { + label: "Property Z is ", + onClick: () => undefined + }, + { + label: "Property X is ", + onClick: () => undefined + }, + { + label: "Property Y is ", + onClick: () => undefined + }, + { + label: "Property Z is ", + onClick: () => undefined + }, + { + label: "Property X is ", + onClick: () => undefined + }, + { + label: "Property Y is ", + onClick: () => undefined + }, + { + label: "Property Z is ", + onClick: () => undefined + }, + { + label: "Property X is ", + onClick: () => undefined + }, + { + label: "Property Y is ", + onClick: () => undefined + }, + { + label: "Property Z is ", + onClick: () => undefined + } +].map((filter, filterIndex) => ({ + ...filter, + label: filter.label + filterIndex +})); diff --git a/src/home/components/HomeActivityCard/HomeActivityCard.tsx b/src/home/components/HomeActivityCard/HomeActivityCard.tsx new file mode 100644 index 000000000..f28f72ded --- /dev/null +++ b/src/home/components/HomeActivityCard/HomeActivityCard.tsx @@ -0,0 +1,74 @@ +import Card from "@material-ui/core/Card"; +import List from "@material-ui/core/List"; +import ListItem from "@material-ui/core/ListItem"; +import ListItemText from "@material-ui/core/ListItemText"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import { DateTime } from "@saleor/components/Date"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { renderCollection } from "../../../misc"; +import { Home_activities_edges_node } from "../../types/Home"; +import { getActivityMessage } from "./activityMessages"; + +const styles = createStyles({ + loadingProducts: { + paddingBottom: "10px", + paddingTop: "10px" + }, + noProducts: { + paddingBottom: "16px", + paddingTop: "16px" + } +}); + +interface HomeProductListCardProps extends WithStyles { + activities: Home_activities_edges_node[]; +} + +const HomeProductListCard = withStyles(styles, { name: "HomeProductListCard" })( + ({ classes, activities }: HomeProductListCardProps) => { + return ( + + + + {renderCollection( + activities, + (activity, activityId) => ( + + {activity ? ( + {getActivityMessage(activity)} + } + secondary={} + /> + ) : ( + + + + + + )} + + ), + () => ( + + {i18n.t("No activities found")} + } + /> + + ) + )} + + + ); + } +); +HomeProductListCard.displayName = "HomeProductListCard"; +export default HomeProductListCard; diff --git a/src/home/components/HomeActivityCard/activityMessages.ts b/src/home/components/HomeActivityCard/activityMessages.ts new file mode 100644 index 000000000..b195ccdc2 --- /dev/null +++ b/src/home/components/HomeActivityCard/activityMessages.ts @@ -0,0 +1,26 @@ +import i18n from "../../../i18n"; +import { OrderEventsEnum } from "../../../types/globalTypes"; +import { Home_activities_edges_node } from "../../types/Home"; + +export const getActivityMessage = (activity: Home_activities_edges_node) => { + switch (activity.type) { + case OrderEventsEnum.ORDER_FULLY_PAID: + return i18n.t("Order #{{ orderId }} was fully paid", { + orderId: activity.orderNumber + }); + case OrderEventsEnum.PLACED: + return i18n.t("Order #{{ orderId }} was placed", { + orderId: activity.orderNumber + }); + case OrderEventsEnum.PLACED_FROM_DRAFT: + return i18n.t( + "Order #{{ orderId }} was placed from draft by {{ user }}", + { + orderId: activity.orderNumber, + user: activity.user.email + } + ); + default: + return activity.message; + } +}; diff --git a/src/home/components/HomeActivityCard/index.ts b/src/home/components/HomeActivityCard/index.ts new file mode 100644 index 000000000..bec23d02f --- /dev/null +++ b/src/home/components/HomeActivityCard/index.ts @@ -0,0 +1,2 @@ +export { default } from "./HomeActivityCard"; +export * from "./HomeActivityCard"; diff --git a/src/home/components/HomeAnalyticsCard/HomeAnalyticsCard.tsx b/src/home/components/HomeAnalyticsCard/HomeAnalyticsCard.tsx new file mode 100644 index 000000000..faafc0a2e --- /dev/null +++ b/src/home/components/HomeAnalyticsCard/HomeAnalyticsCard.tsx @@ -0,0 +1,93 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { IconProps } from "@material-ui/core/Icon"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import i18n from "../../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + cardContent: { + "&:last-child": { + paddingBottom: 16 + }, + display: "grid", + gridColumnGap: theme.spacing.unit * 3 + "px", + gridTemplateColumns: "1fr 64px" + }, + cardSpacing: { + [theme.breakpoints.down("sm")]: { + marginBottom: theme.spacing.unit + }, + marginBottom: theme.spacing.unit * 3 + }, + cardSubtitle: { + color: theme.palette.text.secondary, + height: "20px", + lineHeight: 0.9 + }, + cardTitle: { + fontWeight: 600 as 600 + }, + icon: { + color: theme.palette.primary.contrastText, + fontSize: 54, + margin: ".5rem .3rem" + }, + iconBackground: { + backgroundColor: theme.palette.background.default, + borderRadius: "8px", + color: "white", + fontSize: "54px", + height: "100%", + padding: "10px 5px 0px 5px", + width: "100%" + }, + value: { + textAlign: "right" + } + }); + +interface HomeAnalyticsCardProps extends WithStyles { + icon: React.ReactElement; + title: string; + children?: React.ReactNode; +} + +const HomeAnalyticsCard = withStyles(styles, { name: "HomeAnalyticsCard" })( + ({ children, classes, title, icon }: HomeAnalyticsCardProps) => ( + + +
+ + {title} + + + {i18n.t("Today")} + + + {children} + +
+
{icon}
+
+
+ ) +); +HomeAnalyticsCard.displayName = "HomeAnalyticsCard"; +export default HomeAnalyticsCard; diff --git a/src/home/components/HomeAnalyticsCard/index.ts b/src/home/components/HomeAnalyticsCard/index.ts new file mode 100644 index 000000000..209b4b54e --- /dev/null +++ b/src/home/components/HomeAnalyticsCard/index.ts @@ -0,0 +1,2 @@ +export { default } from "./HomeAnalyticsCard"; +export * from "./HomeAnalyticsCard"; diff --git a/src/home/components/HomeHeader/HomeHeader.tsx b/src/home/components/HomeHeader/HomeHeader.tsx new file mode 100644 index 000000000..ff692eb2a --- /dev/null +++ b/src/home/components/HomeHeader/HomeHeader.tsx @@ -0,0 +1,53 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + headerContainer: { + marginBottom: theme.spacing.unit * 3 + }, + pageHeader: { + fontWeight: 600 as 600 + }, + subtitle: { + color: theme.typography.caption.color + } + }); + +interface HomeOrdersCardProps extends WithStyles { + userName: string; +} + +const HomeOrdersCard = withStyles(styles, { name: "HomeOrdersCard" })( + ({ classes, userName }: HomeOrdersCardProps) => { + return ( +
+ + {userName ? ( + i18n.t("Hello there, {{userName}}", { userName }) + ) : ( + + )} + + + {userName ? ( + i18n.t("Here is some information we gathered about your store") + ) : ( + + )} + +
+ ); + } +); +HomeOrdersCard.displayName = "HomeOrdersCard"; +export default HomeOrdersCard; diff --git a/src/home/components/HomeHeader/index.ts b/src/home/components/HomeHeader/index.ts new file mode 100644 index 000000000..be3bc03ae --- /dev/null +++ b/src/home/components/HomeHeader/index.ts @@ -0,0 +1,2 @@ +export { default } from "./HomeHeader"; +export * from "./HomeHeader"; diff --git a/src/home/components/HomeNotificationTable/HomeNotificationTable.tsx b/src/home/components/HomeNotificationTable/HomeNotificationTable.tsx new file mode 100644 index 000000000..752ca3032 --- /dev/null +++ b/src/home/components/HomeNotificationTable/HomeNotificationTable.tsx @@ -0,0 +1,128 @@ +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import KeyboardArrowRight from "@material-ui/icons/KeyboardArrowRight"; +import * as React from "react"; + +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + arrowIcon: { + width: theme.spacing.unit * 4 + }, + tableRow: { + cursor: "pointer" + } + }); + +interface HomeNotificationTableProps extends WithStyles { + ordersToCapture: number; + ordersToFulfill: number; + productsOutOfStock: number; + onOrdersToFulfillClick: () => void; + onOrdersToCaptureClick: () => void; + onProductsOutOfStockClick: () => void; +} + +const HomeNotificationTable = withStyles(styles, { + name: "HomeNotificationTable" +})( + ({ + classes, + onOrdersToCaptureClick, + onOrdersToFulfillClick, + onProductsOutOfStockClick, + ordersToCapture, + ordersToFulfill, + productsOutOfStock + }: HomeNotificationTableProps) => { + return ( + + + + + + {ordersToFulfill === undefined ? ( + + ) : ordersToFulfill === 0 ? ( + + {i18n.t("No orders ready to fulfill")} + + ) : ( + {{ amount }} Orders are ready to fulfill", + { amount: ordersToFulfill } + ) + }} + /> + )} + + + + + + + + {ordersToCapture === undefined ? ( + + ) : ordersToCapture === 0 ? ( + + {i18n.t("No payments waiting for capture")} + + ) : ( + {{ amount }} Payments to capture", + { amount: ordersToCapture } + ) + }} + /> + )} + + + + + + + + {productsOutOfStock === undefined ? ( + + ) : productsOutOfStock === 0 ? ( + {i18n.t("No products out of stock")} + ) : ( + {{ amount }} Products out of stock", + { amount: productsOutOfStock } + ) + }} + /> + )} + + + + + + +
+
+ ); + } +); +HomeNotificationTable.displayName = "HomeNotificationTable"; +export default HomeNotificationTable; diff --git a/src/home/components/HomeNotificationTable/index.ts b/src/home/components/HomeNotificationTable/index.ts new file mode 100644 index 000000000..5f13ce2da --- /dev/null +++ b/src/home/components/HomeNotificationTable/index.ts @@ -0,0 +1,2 @@ +export { default } from "./HomeNotificationTable"; +export * from "./HomeNotificationTable"; diff --git a/src/home/components/HomePage/HomePage.tsx b/src/home/components/HomePage/HomePage.tsx new file mode 100644 index 000000000..af26fe46f --- /dev/null +++ b/src/home/components/HomePage/HomePage.tsx @@ -0,0 +1,123 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import CardSpacer from "@saleor/components/CardSpacer"; +import Container from "@saleor/components/Container"; +import Grid from "@saleor/components/Grid"; +import Money from "@saleor/components/Money"; +import Skeleton from "@saleor/components/Skeleton"; +import Orders from "../../../icons/Orders"; +import Sales from "../../../icons/Sales"; +import { + Home_activities_edges_node, + Home_productTopToday_edges_node, + Home_salesToday_gross +} from "../../types/Home"; +import HomeActivityCard from "../HomeActivityCard"; +import HomeAnalyticsCard from "../HomeAnalyticsCard"; +import HomeHeader from "../HomeHeader"; +import HomeNotificationTable from "../HomeNotificationTable/HomeNotificationTable"; +import HomeProductListCard from "../HomeProductListCard"; + +const styles = (theme: Theme) => + createStyles({ + cardContainer: { + display: "grid", + gridColumnGap: `${theme.spacing.unit * 3}px`, + gridTemplateColumns: "1fr 1fr", + [theme.breakpoints.down("sm")]: { + gridColumnGap: `${theme.spacing.unit}px` + }, + [theme.breakpoints.down("xs")]: { + gridTemplateColumns: "1fr" + } + } + }); + +export interface HomePageProps extends WithStyles { + activities: Home_activities_edges_node[]; + orders: number; + ordersToCapture: number; + ordersToFulfill: number; + productsOutOfStock: number; + sales: Home_salesToday_gross; + topProducts: Home_productTopToday_edges_node[]; + userName: string; + onOrdersToCaptureClick: () => void; + onOrdersToFulfillClick: () => void; + onProductClick: (productId: string, variantId: string) => void; + onProductsOutOfStockClick: () => void; +} + +const HomePage = withStyles(styles, { name: "HomePage" })( + ({ + classes, + userName, + orders, + sales, + topProducts, + onProductClick, + activities, + onOrdersToCaptureClick, + onOrdersToFulfillClick, + onProductsOutOfStockClick, + ordersToCapture, + ordersToFulfill, + productsOutOfStock + }: HomePageProps) => ( + + + + +
+
+ } + > + {sales ? ( + + ) : ( + + )} + + } + > + {orders === undefined ? ( + + ) : ( + orders + )} + +
+ + + + +
+
+ +
+
+
+ ) +); +HomePage.displayName = "HomePage"; +export default HomePage; diff --git a/src/home/components/HomePage/index.ts b/src/home/components/HomePage/index.ts new file mode 100644 index 000000000..60f729a6c --- /dev/null +++ b/src/home/components/HomePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./HomePage"; +export * from "./HomePage"; diff --git a/src/home/components/HomeProductListCard/HomeProductListCard.tsx b/src/home/components/HomeProductListCard/HomeProductListCard.tsx new file mode 100644 index 000000000..d6783210a --- /dev/null +++ b/src/home/components/HomeProductListCard/HomeProductListCard.tsx @@ -0,0 +1,130 @@ +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import * as classNames from "classnames"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Money from "@saleor/components/Money"; +import Skeleton from "@saleor/components/Skeleton"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { Home_productTopToday_edges_node } from "../../types/Home"; + +const styles = (theme: Theme) => + createStyles({ + avatarProps: { + height: 64, + width: 64 + }, + avatarSpacing: { + paddingBottom: theme.spacing.unit * 2, + paddingTop: theme.spacing.unit * 2 + }, + noProducts: { + paddingBottom: 20, + paddingTop: 20 + }, + tableRow: { + cursor: "pointer" + } + }); + +interface HomeProductListProps extends WithStyles { + topProducts: Home_productTopToday_edges_node[]; + onRowClick: (productId: string, variantId: string) => void; +} + +export const HomeProductList = withStyles(styles, { name: "HomeProductList" })( + ({ classes, topProducts, onRowClick }: HomeProductListProps) => ( + + + + + {renderCollection( + topProducts, + variant => ( + onRowClick(variant.product.id, variant.id) + : undefined + } + > + variant.product.thumbnail.url)} + avatarProps={classes.avatarProps} + /> + + + {variant ? ( + <> + + {variant.product.name} + + + {maybe(() => + variant.attributes + .map(attribute => attribute.value) + .sort((a, b) => + a.sortOrder > b.sortOrder ? 1 : -1 + ) + .map(attribute => attribute.name) + .join(" / ") + )} + + + {i18n.t("{{ordersCount}} Orders", { + ordersCount: variant.quantityOrdered + })} + + + ) : ( + + )} + + + + + {maybe( + () => ( + + ), + + )} + + + + ), + () => ( + + + {i18n.t("No products found")} + + + ) + )} + +
+
+ ) +); + +HomeProductList.displayName = "HomeProductList"; +export default HomeProductList; diff --git a/src/home/components/HomeProductListCard/index.ts b/src/home/components/HomeProductListCard/index.ts new file mode 100644 index 000000000..139cd4fe3 --- /dev/null +++ b/src/home/components/HomeProductListCard/index.ts @@ -0,0 +1,2 @@ +export { default } from "./HomeProductListCard"; +export * from "./HomeProductListCard"; diff --git a/src/home/components/HomeScreen.tsx b/src/home/components/HomeScreen.tsx new file mode 100644 index 000000000..9c30edce0 --- /dev/null +++ b/src/home/components/HomeScreen.tsx @@ -0,0 +1,40 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../i18n"; + +interface HomeScreenProps { + user: { + email: string; + }; +} + +export const HomeScreen: React.StatelessComponent = ({ + user +}) => ( + + + + + + + {i18n.t( + "The new dashboard and the GraphQL API are preview-quality software." + )} + + + {i18n.t( + "The GraphQL API is beta quality. It is not fully optimized and some mutations or queries may be missing." + )} + + + + +); diff --git a/src/home/fixtures.ts b/src/home/fixtures.ts new file mode 100644 index 000000000..16bb183f9 --- /dev/null +++ b/src/home/fixtures.ts @@ -0,0 +1,340 @@ +import { OrderEventsEnum } from "../types/globalTypes"; +import { Home } from "./types/Home"; + +export const shop: (placeholderImage: string) => Home = ( + placeholderImage: string +) => ({ + activities: { + __typename: "OrderEventCountableConnection", + edges: [ + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-09-14T16:10:27.137126+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDoxOA==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.PLACED_FROM_DRAFT, + user: { + __typename: "User", + email: "admin@example.com", + id: "VXNlcjoyMQ==" + } + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-03T13:28:46.325279+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDozNQ==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.PLACED, + user: null + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-03T13:29:01.837496+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDozNw==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.ORDER_FULLY_PAID, + user: null + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-04T01:01:51.243723+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo1OA==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.PLACED_FROM_DRAFT, + user: { + __typename: "User", + email: "admin@example.com", + id: "VXNlcjoyMQ==" + } + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-04T19:36:18.831561+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo2Nw==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.PLACED_FROM_DRAFT, + user: { + __typename: "User", + email: "admin@example.com", + id: "VXNlcjoyMQ==" + } + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-04T19:38:01.420365+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo2OA==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.PLACED_FROM_DRAFT, + user: { + __typename: "User", + email: "admin@example.com", + id: "VXNlcjoyMQ==" + } + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-05T12:30:57.268592+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo3MQ==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.PLACED_FROM_DRAFT, + user: { + __typename: "User", + email: "admin@example.com", + id: "VXNlcjoyMQ==" + } + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-08T09:50:42.622253+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo3Mw==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.PLACED, + user: null + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-12T15:51:11.665838+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo3Nw==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.PLACED_FROM_DRAFT, + user: { + __typename: "User", + email: "admin@example.com", + id: "VXNlcjoyMQ==" + } + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-25T11:25:58.843860+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo3OA==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.PLACED, + user: null + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-26T09:34:57.580167+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo4MA==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.PLACED, + user: null + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-26T09:38:02.440061+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo4Mg==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.ORDER_FULLY_PAID, + user: null + } + }, + { + __typename: "OrderEventCountableEdge", + node: { + __typename: "OrderEvent", + amount: null, + composedId: null, + date: "2018-10-26T09:38:02.467443+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDo4NA==", + message: null, + orderNumber: "15", + oversoldItems: null, + quantity: null, + type: OrderEventsEnum.ORDER_FULLY_PAID, + user: null + } + } + ] + }, + ordersToCapture: { + __typename: "OrderCountableConnection", + totalCount: 0 + }, + ordersToFulfill: { + __typename: "OrderCountableConnection", + totalCount: 1 + }, + ordersToday: { + __typename: "OrderCountableConnection", + totalCount: 1 + }, + productTopToday: { + __typename: "ProductVariantCountableConnection", + edges: [ + { + __typename: "ProductVariantCountableEdge", + node: { + __typename: "ProductVariant", + attributes: [ + { + __typename: "SelectedAttribute", + value: { + __typename: "AttributeValue", + id: "QXR0cmlidXRlVmFsdWU6OTI=", + name: "XS", + sortOrder: 0 + } + } + ], + id: "UHJvZHVjdFZhcmlhbnQ6NDM=", + product: { + __typename: "Product", + basePrice: { + __typename: "Money", + amount: 37.65, + currency: "USD" + }, + id: "UHJvZHVjdDo4", + name: "Gardner-Martin", + thumbnail: { + __typename: "Image", + url: placeholderImage + } + }, + quantityOrdered: 1, + revenue: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 37.65, + currency: "USD" + } + } + } + } + ] + }, + productsOutOfStock: { + __typename: "ProductCountableConnection", + totalCount: 0 + }, + salesToday: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 57.15, + currency: "USD" + } + } +}); diff --git a/src/home/index.tsx b/src/home/index.tsx new file mode 100644 index 000000000..e7520f23f --- /dev/null +++ b/src/home/index.tsx @@ -0,0 +1,7 @@ +import * as React from "react"; + +import HomePage from "./views"; + +const Component = () => ; + +export default Component; diff --git a/src/home/queries.ts b/src/home/queries.ts new file mode 100644 index 000000000..8e5011fdf --- /dev/null +++ b/src/home/queries.ts @@ -0,0 +1,77 @@ +import gql from "graphql-tag"; + +import { TypedQuery } from "../queries"; +import { Home } from "./types/Home"; + +const home = gql` + query Home { + salesToday: ordersTotal(period: TODAY) { + gross { + amount + currency + } + } + ordersToday: orders(created: TODAY) { + totalCount + } + ordersToFulfill: orders(status: READY_TO_FULFILL) { + totalCount + } + ordersToCapture: orders(status: READY_TO_CAPTURE) { + totalCount + } + productsOutOfStock: products(stockAvailability: OUT_OF_STOCK) { + totalCount + } + productTopToday: reportProductSales(period: TODAY, first: 5) { + edges { + node { + id + revenue(period: TODAY) { + gross { + amount + currency + } + } + attributes { + value { + id + name + sortOrder + } + } + product { + id + name + thumbnail { + url + } + } + quantityOrdered + } + } + } + activities: homepageEvents(last: 10) { + edges { + node { + amount + composedId + date + email + emailType + id + message + orderNumber + oversoldItems + quantity + type + user { + id + email + } + } + } + } + } +`; +export const HomePageQuery = TypedQuery(home); diff --git a/src/home/types/Home.ts b/src/home/types/Home.ts new file mode 100644 index 000000000..9400d0adc --- /dev/null +++ b/src/home/types/Home.ts @@ -0,0 +1,136 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: Home +// ==================================================== + +export interface Home_salesToday_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface Home_salesToday { + __typename: "TaxedMoney"; + gross: Home_salesToday_gross; +} + +export interface Home_ordersToday { + __typename: "OrderCountableConnection"; + totalCount: number | null; +} + +export interface Home_ordersToFulfill { + __typename: "OrderCountableConnection"; + totalCount: number | null; +} + +export interface Home_ordersToCapture { + __typename: "OrderCountableConnection"; + totalCount: number | null; +} + +export interface Home_productsOutOfStock { + __typename: "ProductCountableConnection"; + totalCount: number | null; +} + +export interface Home_productTopToday_edges_node_revenue_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface Home_productTopToday_edges_node_revenue { + __typename: "TaxedMoney"; + gross: Home_productTopToday_edges_node_revenue_gross; +} + +export interface Home_productTopToday_edges_node_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + sortOrder: number | null; +} + +export interface Home_productTopToday_edges_node_attributes { + __typename: "SelectedAttribute"; + value: Home_productTopToday_edges_node_attributes_value; +} + +export interface Home_productTopToday_edges_node_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface Home_productTopToday_edges_node_product { + __typename: "Product"; + id: string; + name: string; + thumbnail: Home_productTopToday_edges_node_product_thumbnail | null; +} + +export interface Home_productTopToday_edges_node { + __typename: "ProductVariant"; + id: string; + revenue: Home_productTopToday_edges_node_revenue | null; + attributes: Home_productTopToday_edges_node_attributes[]; + product: Home_productTopToday_edges_node_product; + quantityOrdered: number | null; +} + +export interface Home_productTopToday_edges { + __typename: "ProductVariantCountableEdge"; + node: Home_productTopToday_edges_node; +} + +export interface Home_productTopToday { + __typename: "ProductVariantCountableConnection"; + edges: Home_productTopToday_edges[]; +} + +export interface Home_activities_edges_node_user { + __typename: "User"; + id: string; + email: string; +} + +export interface Home_activities_edges_node { + __typename: "OrderEvent"; + amount: number | null; + composedId: string | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + id: string; + message: string | null; + orderNumber: string | null; + oversoldItems: (string | null)[] | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: Home_activities_edges_node_user | null; +} + +export interface Home_activities_edges { + __typename: "OrderEventCountableEdge"; + node: Home_activities_edges_node; +} + +export interface Home_activities { + __typename: "OrderEventCountableConnection"; + edges: Home_activities_edges[]; +} + +export interface Home { + salesToday: Home_salesToday | null; + ordersToday: Home_ordersToday | null; + ordersToFulfill: Home_ordersToFulfill | null; + ordersToCapture: Home_ordersToCapture | null; + productsOutOfStock: Home_productsOutOfStock | null; + productTopToday: Home_productTopToday | null; + activities: Home_activities | null; +} diff --git a/src/home/views/index.tsx b/src/home/views/index.tsx new file mode 100644 index 000000000..b0a06a884 --- /dev/null +++ b/src/home/views/index.tsx @@ -0,0 +1,62 @@ +import * as React from "react"; + +import useNavigator from "@saleor/hooks/useNavigator"; +import useUser from "@saleor/hooks/useUser"; +import { getUserName, maybe } from "../../misc"; +import { orderListUrl } from "../../orders/urls"; +import { productListUrl, productVariantEditUrl } from "../../products/urls"; +import { OrderStatusFilter, StockAvailability } from "../../types/globalTypes"; +import HomePage from "../components/HomePage"; +import { HomePageQuery } from "../queries"; + +const HomeSection = () => { + const navigate = useNavigator(); + const { user } = useUser(); + + return ( + + {({ data }) => ( + + data.activities.edges.map(edge => edge.node).reverse() + )} + orders={maybe(() => data.ordersToday.totalCount)} + sales={maybe(() => data.salesToday.gross)} + topProducts={maybe(() => + data.productTopToday.edges.map(edge => edge.node) + )} + onProductClick={(productId, variantId) => + navigate(productVariantEditUrl(productId, variantId)) + } + onOrdersToCaptureClick={() => + navigate( + orderListUrl({ + status: OrderStatusFilter.READY_TO_CAPTURE + }) + ) + } + onOrdersToFulfillClick={() => + navigate( + orderListUrl({ + status: OrderStatusFilter.READY_TO_FULFILL + }) + ) + } + onProductsOutOfStockClick={() => + navigate( + productListUrl({ + status: StockAvailability.OUT_OF_STOCK + }) + ) + } + ordersToCapture={maybe(() => data.ordersToCapture.totalCount)} + ordersToFulfill={maybe(() => data.ordersToFulfill.totalCount)} + productsOutOfStock={maybe(() => data.productsOutOfStock.totalCount)} + userName={getUserName(user, true)} + /> + )} + + ); +}; + +export default HomeSection; diff --git a/src/hooks/useBulkActions.ts b/src/hooks/useBulkActions.ts new file mode 100644 index 000000000..986308782 --- /dev/null +++ b/src/hooks/useBulkActions.ts @@ -0,0 +1,45 @@ +import { useState } from "react"; +import { Node } from "../types"; + +function useBulkActions(initial: string[] = []) { + const [listElements, setListElements] = useState(initial); + + function isSelected(id: string) { + return !!listElements.find(listElement => listElement === id); + } + + function add(id: string) { + setListElements([...listElements, id]); + } + + function remove(id: string) { + setListElements(listElements.filter(listElement => listElement !== id)); + } + + function reset() { + setListElements([]); + } + + function toggle(id: string) { + isSelected(id) ? remove(id) : add(id); + } + + function toggleAll(items: Node[], selected: number) { + const allItems = items.map(item => item.id); + reset(); + if (selected !== allItems.length) { + setListElements(allItems); + } + } + + return { + add, + isSelected, + listElements, + remove, + reset, + toggle, + toggleAll + }; +} +export default useBulkActions; diff --git a/src/hooks/useDateLocalize.ts b/src/hooks/useDateLocalize.ts new file mode 100644 index 000000000..88426f520 --- /dev/null +++ b/src/hooks/useDateLocalize.ts @@ -0,0 +1,15 @@ +import * as moment from "moment-timezone"; +import { useContext } from "react"; + +import { LocaleContext } from "@saleor/components/Locale"; + +function useDateLocalize(): (date: string) => string { + const locale = useContext(LocaleContext); + + return (date: string) => + moment(date) + .locale(locale) + .format("ll"); +} + +export default useDateLocalize; diff --git a/src/hooks/useLocale.ts b/src/hooks/useLocale.ts new file mode 100644 index 000000000..1f1487603 --- /dev/null +++ b/src/hooks/useLocale.ts @@ -0,0 +1,9 @@ +import { useContext } from "react"; + +import { LocaleContext } from "@saleor/components/Locale"; + +function useLocale() { + const themeInfo = useContext(LocaleContext); + return themeInfo; +} +export default useLocale; diff --git a/src/hooks/useNavigator.ts b/src/hooks/useNavigator.ts new file mode 100644 index 000000000..180b1d1bb --- /dev/null +++ b/src/hooks/useNavigator.ts @@ -0,0 +1,21 @@ +import useRouter from "use-react-router"; + +export type UseNavigatorResult = ( + url: string, + replace?: boolean, + preserveQs?: boolean +) => void; +function useNavigator(): UseNavigatorResult { + const { + location: { search }, + history + } = useRouter(); + + return (url: string, replace = false, preserveQs = false) => { + const targetUrl = preserveQs ? url + search : url; + replace ? history.replace(targetUrl) : history.push(targetUrl); + window.scrollTo({ top: 0, behavior: "smooth" }); + }; +} + +export default useNavigator; diff --git a/src/hooks/useNotifier.ts b/src/hooks/useNotifier.ts new file mode 100644 index 000000000..6f18707e9 --- /dev/null +++ b/src/hooks/useNotifier.ts @@ -0,0 +1,10 @@ +import { useContext } from "react"; + +import { IMessageContext, MessageContext } from "@saleor/components/messages"; + +export type UseNotifierResult = IMessageContext; +function useNotifier(): UseNotifierResult { + const notify = useContext(MessageContext); + return notify; +} +export default useNotifier; diff --git a/src/hooks/usePaginator.ts b/src/hooks/usePaginator.ts new file mode 100644 index 000000000..8c67a736a --- /dev/null +++ b/src/hooks/usePaginator.ts @@ -0,0 +1,85 @@ +import { stringify as stringifyQs } from "qs"; + +import { Pagination } from "../types"; +import useNavigator from "./useNavigator"; + +export interface PageInfo { + endCursor: string; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string; +} + +export interface PaginationState { + after?: string; + before?: string; + first?: number; + last?: number; +} + +export function createPaginationState( + paginateBy: number, + queryString: Pagination +): PaginationState { + return queryString && (queryString.before || queryString.after) + ? queryString.after + ? { + after: queryString.after, + first: paginateBy + } + : { + before: queryString.before, + last: paginateBy + } + : { + first: paginateBy + }; +} + +function usePaginator() { + const navigate = useNavigator(); + + function paginate( + pageInfo: PageInfo, + paginationState: PaginationState, + queryString: Pagination + ) { + const loadNextPage = () => + navigate( + "?" + + stringifyQs({ + ...queryString, + after: pageInfo.endCursor, + before: undefined + }), + true + ); + + const loadPreviousPage = () => + navigate( + "?" + + stringifyQs({ + ...queryString, + after: undefined, + before: pageInfo.startCursor + }), + true + ); + + const newPageInfo = pageInfo + ? { + ...pageInfo, + hasNextPage: !!paginationState.before || pageInfo.hasNextPage, + hasPreviousPage: !!paginationState.after || pageInfo.hasPreviousPage + } + : undefined; + + return { + loadNextPage, + loadPreviousPage, + pageInfo: newPageInfo + }; + } + return paginate; +} +export default usePaginator; diff --git a/src/hooks/useScroll.ts b/src/hooks/useScroll.ts new file mode 100644 index 000000000..355ae5e5e --- /dev/null +++ b/src/hooks/useScroll.ts @@ -0,0 +1,25 @@ +// tslint:disable:no-submodule-imports +import * as throttle from "lodash/throttle"; +import { useEffect, useState } from "react"; + +function getPosition() { + return { + x: window.pageXOffset, + y: window.pageYOffset + }; +} + +function useScroll() { + const [scroll, setScroll] = useState(getPosition); + + useEffect(() => { + const handleScroll = throttle(() => setScroll(getPosition()), 250); + + window.addEventListener("scroll", handleScroll); + + return () => window.removeEventListener("scroll", handleScroll); + }, []); + + return scroll; +} +export default useScroll; diff --git a/src/hooks/useShop.ts b/src/hooks/useShop.ts new file mode 100644 index 000000000..22c333e2b --- /dev/null +++ b/src/hooks/useShop.ts @@ -0,0 +1,8 @@ +import { useContext } from "react"; + +import { shopContext } from "@saleor/components/Shop"; + +function useShop() { + return useContext(shopContext); +} +export default useShop; diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts new file mode 100644 index 000000000..409b09f3d --- /dev/null +++ b/src/hooks/useTheme.ts @@ -0,0 +1,9 @@ +import { useContext } from "react"; + +import { ThemeContext } from "@saleor/components/Theme"; + +function useTheme() { + const themeInfo = useContext(ThemeContext); + return themeInfo; +} +export default useTheme; diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts new file mode 100644 index 000000000..13e6c3fd0 --- /dev/null +++ b/src/hooks/useUser.ts @@ -0,0 +1,9 @@ +import { useContext } from "react"; + +import { UserContext } from "../auth"; + +function useUser() { + const user = useContext(UserContext); + return user; +} +export default useUser; diff --git a/src/i18n.ts b/src/i18n.ts new file mode 100644 index 000000000..d15b0883b --- /dev/null +++ b/src/i18n.ts @@ -0,0 +1,18 @@ +import * as i18n from "i18next"; +import * as LanguageDetector from "i18next-browser-languagedetector"; +import * as XHR from "i18next-xhr-backend"; + +i18n.use(XHR); +i18n.use(LanguageDetector); +i18n.init({ + defaultNS: "dashboard", + fallbackLng: "en", + interpolation: { + escapeValue: false + }, + keySeparator: false, + ns: ["dashboard"], + nsSeparator: false +}); + +export default i18n; diff --git a/src/icons/AccountCircle.tsx b/src/icons/AccountCircle.tsx new file mode 100644 index 000000000..49eae5c1e --- /dev/null +++ b/src/icons/AccountCircle.tsx @@ -0,0 +1,20 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const AccountCircle = createSvgIcon( + <> + + + + + + +); +AccountCircle.displayName = "AccountCircle"; +export default AccountCircle; diff --git a/src/icons/ArrowDropdown.tsx b/src/icons/ArrowDropdown.tsx new file mode 100644 index 000000000..e8f324da3 --- /dev/null +++ b/src/icons/ArrowDropdown.tsx @@ -0,0 +1,10 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const NoPhoto = createSvgIcon( + + + +); +NoPhoto.displayName = "NoPhoto"; +export default NoPhoto; diff --git a/src/icons/Ballot.tsx b/src/icons/Ballot.tsx new file mode 100644 index 000000000..d5dfb8afe --- /dev/null +++ b/src/icons/Ballot.tsx @@ -0,0 +1,17 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Ballot = createSvgIcon( + <> + + + + + + + + + +); +Ballot.displayName = "Ballot"; +export default Ballot; diff --git a/src/icons/BoldIcon.tsx b/src/icons/BoldIcon.tsx new file mode 100644 index 000000000..ae22592b2 --- /dev/null +++ b/src/icons/BoldIcon.tsx @@ -0,0 +1,10 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const BoldIcon = createSvgIcon( + <> + + +); +BoldIcon.displayName = "BoldIcon"; +export default BoldIcon; diff --git a/src/icons/Calendar.tsx b/src/icons/Calendar.tsx new file mode 100644 index 000000000..a67c5e60e --- /dev/null +++ b/src/icons/Calendar.tsx @@ -0,0 +1,28 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Calendar = createSvgIcon( + <> + + + + + + + + +); +Calendar.displayName = "Calendar"; +export default Calendar; diff --git a/src/icons/Draggable.tsx b/src/icons/Draggable.tsx new file mode 100644 index 000000000..948ef738e --- /dev/null +++ b/src/icons/Draggable.tsx @@ -0,0 +1,31 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Draggable = createSvgIcon( + <> + + + + + + + + +); +Draggable.displayName = "Draggable"; +export default Draggable; diff --git a/src/icons/Folder.tsx b/src/icons/Folder.tsx new file mode 100644 index 000000000..f9e6bdb5d --- /dev/null +++ b/src/icons/Folder.tsx @@ -0,0 +1,12 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Folder = createSvgIcon( + <> + + + + +); +Folder.displayName = "Folder"; +export default Folder; diff --git a/src/icons/HeaderOne.tsx b/src/icons/HeaderOne.tsx new file mode 100644 index 000000000..31409752f --- /dev/null +++ b/src/icons/HeaderOne.tsx @@ -0,0 +1,11 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const HeaderOne = createSvgIcon( + <> + + + +); +HeaderOne.displayName = "HeaderOne"; +export default HeaderOne; diff --git a/src/icons/HeaderThree.tsx b/src/icons/HeaderThree.tsx new file mode 100644 index 000000000..8544d68ec --- /dev/null +++ b/src/icons/HeaderThree.tsx @@ -0,0 +1,11 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const HeaderThree = createSvgIcon( + <> + + + +); +HeaderThree.displayName = "HeaderThree"; +export default HeaderThree; diff --git a/src/icons/HeaderTwo.tsx b/src/icons/HeaderTwo.tsx new file mode 100644 index 000000000..8a9b4d289 --- /dev/null +++ b/src/icons/HeaderTwo.tsx @@ -0,0 +1,11 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const HeaderTwo = createSvgIcon( + <> + + + +); +HeaderTwo.displayName = "HeaderTwo"; +export default HeaderTwo; diff --git a/src/icons/Home.tsx b/src/icons/Home.tsx new file mode 100644 index 000000000..1e574e556 --- /dev/null +++ b/src/icons/Home.tsx @@ -0,0 +1,12 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Home = createSvgIcon( + <> + + + + +); +Home.displayName = "Home"; +export default Home; diff --git a/src/icons/Image.tsx b/src/icons/Image.tsx new file mode 100644 index 000000000..3ff31d962 --- /dev/null +++ b/src/icons/Image.tsx @@ -0,0 +1,26 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Image = createSvgIcon( + <> + + + + + + + + +); +Image.displayName = "Image"; +export default Image; diff --git a/src/icons/ItalicIcon.tsx b/src/icons/ItalicIcon.tsx new file mode 100644 index 000000000..ced567f02 --- /dev/null +++ b/src/icons/ItalicIcon.tsx @@ -0,0 +1,10 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const ItalicIcon = createSvgIcon( + <> + + +); +ItalicIcon.displayName = "ItalicIcon"; +export default ItalicIcon; diff --git a/src/icons/LinkIcon.tsx b/src/icons/LinkIcon.tsx new file mode 100644 index 000000000..adfd37b6f --- /dev/null +++ b/src/icons/LinkIcon.tsx @@ -0,0 +1,10 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const LinkIcon = createSvgIcon( + <> + + +); +LinkIcon.displayName = "LinkIcon"; +export default LinkIcon; diff --git a/src/icons/LocalShipping.tsx b/src/icons/LocalShipping.tsx new file mode 100644 index 000000000..b0440c68e --- /dev/null +++ b/src/icons/LocalShipping.tsx @@ -0,0 +1,12 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const LocalShipping = createSvgIcon( + <> + + + + +); +LocalShipping.displayName = "LocalShipping"; +export default LocalShipping; diff --git a/src/icons/Monetization.tsx b/src/icons/Monetization.tsx new file mode 100644 index 000000000..1dd34af67 --- /dev/null +++ b/src/icons/Monetization.tsx @@ -0,0 +1,14 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Monetization = createSvgIcon( + <> + + + + + + +); +Monetization.displayName = "Monetization"; +export default Monetization; diff --git a/src/icons/Moon.tsx b/src/icons/Moon.tsx new file mode 100644 index 000000000..88df92b0f --- /dev/null +++ b/src/icons/Moon.tsx @@ -0,0 +1,24 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Moon = createSvgIcon( + <> + + + + +); +Moon.displayName = "Moon"; +export default Moon; diff --git a/src/icons/Navigation.tsx b/src/icons/Navigation.tsx new file mode 100644 index 000000000..57b83ec11 --- /dev/null +++ b/src/icons/Navigation.tsx @@ -0,0 +1,45 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Navigation = createSvgIcon( + <> + + + + + + + + + + + + + +); +Navigation.displayName = "Navigation"; +export default Navigation; diff --git a/src/icons/NoPhoto.tsx b/src/icons/NoPhoto.tsx new file mode 100644 index 000000000..60f61c2ab --- /dev/null +++ b/src/icons/NoPhoto.tsx @@ -0,0 +1,10 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const NoPhoto = createSvgIcon( + + + +); +NoPhoto.displayName = "NoPhoto"; +export default NoPhoto; diff --git a/src/icons/OrderedListIcon.tsx b/src/icons/OrderedListIcon.tsx new file mode 100644 index 000000000..e203dc794 --- /dev/null +++ b/src/icons/OrderedListIcon.tsx @@ -0,0 +1,10 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const OrderedListIcon = createSvgIcon( + <> + + +); +OrderedListIcon.displayName = "OrderedListIcon"; +export default OrderedListIcon; diff --git a/src/icons/Orders.tsx b/src/icons/Orders.tsx new file mode 100644 index 000000000..264a652f3 --- /dev/null +++ b/src/icons/Orders.tsx @@ -0,0 +1,28 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Orders = createSvgIcon( + <> + + + + + + + + +); +Orders.displayName = "Orders"; +export default Orders; diff --git a/src/icons/Pages.tsx b/src/icons/Pages.tsx new file mode 100644 index 000000000..cf4be3c29 --- /dev/null +++ b/src/icons/Pages.tsx @@ -0,0 +1,28 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Pages = createSvgIcon( + <> + + + + + + + + +); +Pages.displayName = "Pages"; +export default Pages; diff --git a/src/icons/ProductTypes.tsx b/src/icons/ProductTypes.tsx new file mode 100644 index 000000000..57d3b88f7 --- /dev/null +++ b/src/icons/ProductTypes.tsx @@ -0,0 +1,28 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const ProductTypes = createSvgIcon( + <> + + + + + + + + +); +ProductTypes.displayName = "ProductTypes"; +export default ProductTypes; diff --git a/src/icons/QuotationIcon.tsx b/src/icons/QuotationIcon.tsx new file mode 100644 index 000000000..16e855053 --- /dev/null +++ b/src/icons/QuotationIcon.tsx @@ -0,0 +1,10 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const QuotationIcon = createSvgIcon( + <> + + +); +QuotationIcon.displayName = "QuotationIcon"; +export default QuotationIcon; diff --git a/src/icons/Sales.tsx b/src/icons/Sales.tsx new file mode 100644 index 000000000..dc85268a7 --- /dev/null +++ b/src/icons/Sales.tsx @@ -0,0 +1,28 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Sales = createSvgIcon( + <> + + + + + + + + +); +Sales.displayName = "Sales"; +export default Sales; diff --git a/src/icons/ShippingMethods.tsx b/src/icons/ShippingMethods.tsx new file mode 100644 index 000000000..b695a80d6 --- /dev/null +++ b/src/icons/ShippingMethods.tsx @@ -0,0 +1,28 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const ShippingMethods = createSvgIcon( + <> + + + + + + + + +); +ShippingMethods.displayName = "ShippingMethods"; +export default ShippingMethods; diff --git a/src/icons/Shop.tsx b/src/icons/Shop.tsx new file mode 100644 index 000000000..397a69410 --- /dev/null +++ b/src/icons/Shop.tsx @@ -0,0 +1,14 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Shop = createSvgIcon( + <> + + + + + + +); +Shop.displayName = "Shop"; +export default Shop; diff --git a/src/icons/SiteSettings.tsx b/src/icons/SiteSettings.tsx new file mode 100644 index 000000000..fc7d50bad --- /dev/null +++ b/src/icons/SiteSettings.tsx @@ -0,0 +1,28 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const SiteSettings = createSvgIcon( + <> + + + + + + + + +); +SiteSettings.displayName = "SiteSettings"; +export default SiteSettings; diff --git a/src/icons/StaffMembers.tsx b/src/icons/StaffMembers.tsx new file mode 100644 index 000000000..1a3072e0d --- /dev/null +++ b/src/icons/StaffMembers.tsx @@ -0,0 +1,28 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const StaffMembers = createSvgIcon( + <> + + + + + + + + +); +StaffMembers.displayName = "StaffMembers"; +export default StaffMembers; diff --git a/src/icons/StoreMall.tsx b/src/icons/StoreMall.tsx new file mode 100644 index 000000000..bec5a200c --- /dev/null +++ b/src/icons/StoreMall.tsx @@ -0,0 +1,12 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const StoreMall = createSvgIcon( + <> + + + + +); +StoreMall.displayName = "StoreMall"; +export default StoreMall; diff --git a/src/icons/StrikethroughIcon.tsx b/src/icons/StrikethroughIcon.tsx new file mode 100644 index 000000000..93f8286fc --- /dev/null +++ b/src/icons/StrikethroughIcon.tsx @@ -0,0 +1,10 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const HeaderOne = createSvgIcon( + <> + + +); +HeaderOne.displayName = "HeaderOne"; +export default HeaderOne; diff --git a/src/icons/Sun.tsx b/src/icons/Sun.tsx new file mode 100644 index 000000000..ff870b2f9 --- /dev/null +++ b/src/icons/Sun.tsx @@ -0,0 +1,14 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Sun = createSvgIcon( + <> + + +); +Sun.displayName = "Sun"; +export default Sun; diff --git a/src/icons/Taxes.tsx b/src/icons/Taxes.tsx new file mode 100644 index 000000000..bfc3ce334 --- /dev/null +++ b/src/icons/Taxes.tsx @@ -0,0 +1,28 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Taxes = createSvgIcon( + <> + + + + + + + + +); +Taxes.displayName = "Taxes"; +export default Taxes; diff --git a/src/icons/Truck.tsx b/src/icons/Truck.tsx new file mode 100644 index 000000000..edfe088ed --- /dev/null +++ b/src/icons/Truck.tsx @@ -0,0 +1,10 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Truck = createSvgIcon( + <> + + +); +Truck.displayName = "Truck"; +export default Truck; diff --git a/src/icons/UnorderedListIcon.tsx b/src/icons/UnorderedListIcon.tsx new file mode 100644 index 000000000..f62a439d3 --- /dev/null +++ b/src/icons/UnorderedListIcon.tsx @@ -0,0 +1,10 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const UnorderedListIcon = createSvgIcon( + <> + + +); +UnorderedListIcon.displayName = "UnorderedListIcon"; +export default UnorderedListIcon; diff --git a/src/icons/Unstyled.tsx b/src/icons/Unstyled.tsx new file mode 100644 index 000000000..c5993628a --- /dev/null +++ b/src/icons/Unstyled.tsx @@ -0,0 +1,14 @@ +import createSvgIcon from "@material-ui/icons/utils/createSvgIcon"; +import * as React from "react"; + +export const Unstyled = createSvgIcon( + <> + + +); +Unstyled.displayName = "Unstyled"; +export default Unstyled; diff --git a/src/index.html b/src/index.html new file mode 100644 index 000000000..44ad4a630 --- /dev/null +++ b/src/index.html @@ -0,0 +1,11 @@ + + + + + <%= htmlWebpackPlugin.options.title %> + + + +
+ + \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 000000000..229fbe5c8 --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,236 @@ +import { defaultDataIdFromObject, InMemoryCache } from "apollo-cache-inmemory"; +import { ApolloClient } from "apollo-client"; +import { ApolloLink } from "apollo-link"; +import { BatchHttpLink } from "apollo-link-batch-http"; +import { setContext } from "apollo-link-context"; +import { ErrorResponse, onError } from "apollo-link-error"; +import { createUploadLink } from "apollo-upload-client"; +import * as React from "react"; +import { ApolloProvider } from "react-apollo"; +import { render } from "react-dom"; +import { BrowserRouter, Route, Switch } from "react-router-dom"; + +import { getAuthToken, removeAuthToken } from "./auth"; +import AuthProvider from "./auth/AuthProvider"; +import LoginLoading from "./auth/components/LoginLoading/LoginLoading"; +import SectionRoute from "./auth/components/SectionRoute"; +import { hasPermission } from "./auth/misc"; +import Login from "./auth/views/Login"; +import CategorySection from "./categories"; +import CollectionSection from "./collections"; +import { AppProgressProvider } from "./components/AppProgress"; +// import { ConfirmFormLeaveDialog } from "./components/ConfirmFormLeaveDialog"; +import { DateProvider } from "./components/Date"; +import { FormProvider } from "./components/Form"; +import { LocaleProvider } from "./components/Locale"; +import { MessageManager } from "./components/messages"; +import { ShopProvider } from "./components/Shop"; +import ThemeProvider from "./components/Theme"; +import { WindowTitle } from "./components/WindowTitle"; +import { API_URI, APP_MOUNT_URI } from "./config"; +import ConfigurationSection, { configurationMenu } from "./configuration"; +import { CustomerSection } from "./customers"; +import DiscountSection from "./discounts"; +import HomePage from "./home"; +import i18n from "./i18n"; +import NavigationSection from "./navigation"; +import { navigationSection } from "./navigation/urls"; +import { NotFound } from "./NotFound"; +import OrdersSection from "./orders"; +import PageSection from "./pages"; +import ProductSection from "./products"; +import ProductTypesSection from "./productTypes"; +import ShippingSection from "./shipping"; +import SiteSettingsSection from "./siteSettings"; +import StaffSection from "./staff"; +import TaxesSection from "./taxes"; +import TranslationsSection from "./translations"; +import { PermissionEnum } from "./types/globalTypes"; + +interface ResponseError extends ErrorResponse { + networkError?: Error & { + statusCode?: number; + bodyText?: string; + }; +} + +const invalidTokenLink = onError((error: ResponseError) => { + if (error.networkError && error.networkError.statusCode === 401) { + removeAuthToken(); + } +}); + +const authLink = setContext((_, context) => { + const authToken = getAuthToken(); + return { + ...context, + headers: { + ...context.headers, + Authorization: authToken ? `JWT ${authToken}` : null + } + }; +}); + +const linkOptions = { + credentials: "same-origin", + uri: API_URI +}; +const uploadLink = createUploadLink(linkOptions); +const batchLink = new BatchHttpLink(linkOptions); + +const link = ApolloLink.split( + operation => operation.getContext().useBatching, + batchLink, + uploadLink +); + +const apolloClient = new ApolloClient({ + cache: new InMemoryCache({ + dataIdFromObject: (obj: any) => { + // We need to set manually shop's ID, since it is singleton and + // API does not return its ID + if (obj.__typename === "Shop") { + return "shop"; + } + return defaultDataIdFromObject(obj); + } + }), + link: invalidTokenLink.concat(authLink.concat(link)) +}); + +const App: React.FC = () => { + const isDark = localStorage.getItem("theme") === "true"; + + return ( + + + + + + + + + + + {/* FIXME: #3424 */} + {/* */} + + {({ + hasToken, + isAuthenticated, + tokenAuthLoading, + tokenVerifyLoading, + user + }) => { + return isAuthenticated && + !tokenAuthLoading && + !tokenVerifyLoading ? ( + + + + + + + + + + + + + + + + + {configurationMenu.filter(menuItem => + hasPermission(menuItem.permission, user) + ).length > 0 && ( + + )} + + + ) : hasToken && tokenVerifyLoading ? ( + + ) : ( + + ); + }} + + + + + + + + + + + ); +}; + +render(, document.querySelector("#dashboard-app")); diff --git a/src/misc.ts b/src/misc.ts new file mode 100644 index 000000000..c41a3b0e7 --- /dev/null +++ b/src/misc.ts @@ -0,0 +1,238 @@ +import * as urlJoin from "url-join"; + +import { MutationFn, MutationResult } from "react-apollo"; +import { ConfirmButtonTransitionState } from "./components/ConfirmButton/ConfirmButton"; +import { APP_MOUNT_URI } from "./config"; +import { AddressType } from "./customers/types"; +import i18n from "./i18n"; +import { PartialMutationProviderOutput, UserError } from "./types"; +import { + AuthorizationKeyType, + OrderStatus, + PaymentChargeStatusEnum, + TaxRateType +} from "./types/globalTypes"; + +export type RequireAtLeastOne = Pick< + T, + Exclude +> & + { [K in Keys]-?: Required> }[Keys]; + +export type RequireOnlyOne = Pick< + T, + Exclude +> & + { + [K in Keys]-?: Required> & + Partial, undefined>> + }[Keys]; + +export function renderCollection( + collection: T[], + renderItem: ( + item: T | undefined, + index: number | undefined, + collection: T[] + ) => any, + renderEmpty?: (collection: T[]) => any +) { + if (collection === undefined) { + return renderItem(undefined, undefined, collection); + } + if (collection.length === 0) { + return !!renderEmpty ? renderEmpty(collection) : null; + } + return collection.map(renderItem); +} + +export function decimal(value: string | number) { + if (typeof value === "string") { + return value === "" ? null : value; + } + return value; +} + +export const removeDoubleSlashes = (url: string) => + url.replace(/([^:]\/)\/+/g, "$1"); + +export const transformPaymentStatus = (status: string) => { + switch (status) { + case PaymentChargeStatusEnum.PARTIALLY_CHARGED: + return { localized: i18n.t("Partially paid"), status: "error" }; + case PaymentChargeStatusEnum.FULLY_CHARGED: + return { localized: i18n.t("Fully paid"), status: "success" }; + case PaymentChargeStatusEnum.PARTIALLY_REFUNDED: + return { localized: i18n.t("Partially refunded"), status: "error" }; + case PaymentChargeStatusEnum.FULLY_REFUNDED: + return { localized: i18n.t("Fully refunded"), status: "success" }; + default: + return { localized: i18n.t("Unpaid"), status: "error" }; + } +}; + +export const transformOrderStatus = (status: string) => { + switch (status) { + case OrderStatus.FULFILLED: + return { localized: i18n.t("Fulfilled"), status: "success" }; + case OrderStatus.PARTIALLY_FULFILLED: + return { localized: i18n.t("Partially fulfilled"), status: "neutral" }; + case OrderStatus.UNFULFILLED: + return { localized: i18n.t("Unfulfilled"), status: "error" }; + case OrderStatus.CANCELED: + return { localized: i18n.t("Cancelled"), status: "error" }; + case OrderStatus.DRAFT: + return { localized: i18n.t("Draft"), status: "error" }; + } + return { + localized: status, + status: "error" + }; +}; + +export const transformAddressToForm = (data: AddressType) => ({ + city: maybe(() => data.city, ""), + cityArea: maybe(() => data.cityArea, ""), + companyName: maybe(() => data.companyName, ""), + country: { + label: maybe(() => data.country.country, ""), + value: maybe(() => data.country.code, "") + }, + countryArea: maybe(() => data.countryArea, ""), + firstName: maybe(() => data.firstName, ""), + lastName: maybe(() => data.lastName, ""), + phone: maybe(() => data.phone, ""), + postalCode: maybe(() => data.postalCode, ""), + streetAddress1: maybe(() => data.streetAddress1, ""), + streetAddress2: maybe(() => data.streetAddress2, "") +}); + +export const translatedTaxRates = () => ({ + [TaxRateType.ACCOMMODATION]: i18n.t("Accommodation"), + [TaxRateType.ADMISSION_TO_CULTURAL_EVENTS]: i18n.t( + "Admission to cultural events" + ), + [TaxRateType.ADMISSION_TO_ENTERTAINMENT_EVENTS]: i18n.t( + "Admission to entertainment events" + ), + [TaxRateType.ADMISSION_TO_SPORTING_EVENTS]: i18n.t( + "Admission to sporting events" + ), + [TaxRateType.ADVERTISING]: i18n.t("Advertising"), + [TaxRateType.AGRICULTURAL_SUPPLIES]: i18n.t("Agricultural supplies"), + [TaxRateType.BABY_FOODSTUFFS]: i18n.t("Baby foodstuffs"), + [TaxRateType.BIKES]: i18n.t("Bikes"), + [TaxRateType.BOOKS]: i18n.t("Books"), + [TaxRateType.CHILDRENS_CLOTHING]: i18n.t("Children's clothing"), + [TaxRateType.DOMESTIC_FUEL]: i18n.t("Domestic fuel"), + [TaxRateType.DOMESTIC_SERVICES]: i18n.t("Domestic services"), + [TaxRateType.E_BOOKS]: i18n.t("E-books"), + [TaxRateType.FOODSTUFFS]: i18n.t("Foodstuffs"), + [TaxRateType.HOTELS]: i18n.t("Hotels"), + [TaxRateType.MEDICAL]: i18n.t("Medical"), + [TaxRateType.NEWSPAPERS]: i18n.t("Newspapers"), + [TaxRateType.PASSENGER_TRANSPORT]: i18n.t("Passenger transport"), + [TaxRateType.PHARMACEUTICALS]: i18n.t("Pharmaceuticals"), + [TaxRateType.PROPERTY_RENOVATIONS]: i18n.t("Property renovations"), + [TaxRateType.RESTAURANTS]: i18n.t("Restaurants"), + [TaxRateType.SOCIAL_HOUSING]: i18n.t("Social housing"), + [TaxRateType.STANDARD]: i18n.t("Standard"), + [TaxRateType.WATER]: i18n.t("Water") +}); + +export const translatedAuthorizationKeyTypes = () => ({ + [AuthorizationKeyType.FACEBOOK]: i18n.t("Facebook"), + [AuthorizationKeyType.GOOGLE_OAUTH2]: i18n.t("Google OAuth2") +}); + +export function maybe(exp: () => T, d?: T) { + try { + const result = exp(); + return result === undefined ? d : result; + } catch { + return d; + } +} + +export function only(obj: T, key: keyof T): boolean { + return Object.keys(obj).every(objKey => + objKey === key ? obj[key] !== undefined : obj[key] === undefined + ); +} + +export function empty(obj: object): boolean { + return Object.keys(obj).every(key => obj[key] === undefined); +} + +export function hasErrors(errorList: UserError[] | null): boolean { + return !( + errorList === undefined || + errorList === null || + errorList.length === 0 + ); +} + +export function getMutationState( + called: boolean, + loading: boolean, + ...errorList: UserError[][] +): ConfirmButtonTransitionState { + if (loading) { + return "loading"; + } + if (called) { + return errorList.map(hasErrors).reduce((acc, curr) => acc || curr, false) + ? "error" + : "success"; + } + return "default"; +} + +export function getMutationProviderData( + mutateFn: MutationFn, + opts: MutationResult +): PartialMutationProviderOutput { + return { + mutate: variables => mutateFn({ variables }), + opts + }; +} + +interface User { + email: string; + firstName?: string; + lastName?: string; +} + +export function getUserName(user?: User, returnEmail?: boolean) { + return user && (user.email || (user.firstName && user.lastName)) + ? user.firstName && user.lastName + ? [user.firstName, user.lastName].join(" ") + : returnEmail + ? user.email + : user.email.split("@")[0] + : undefined; +} + +export function getUserInitials(user?: User) { + return user && (user.email || (user.firstName && user.lastName)) + ? (user.firstName && user.lastName + ? user.firstName[0] + user.lastName[0] + : user.email.slice(0, 2) + ).toUpperCase() + : undefined; +} + +export function createHref(url: string) { + return urlJoin(APP_MOUNT_URI, url); +} + +interface AnyEvent { + stopPropagation: () => void; +} +export function stopPropagation(cb: () => void) { + return (event: AnyEvent) => { + event.stopPropagation(); + cb(); + }; +} diff --git a/src/mutations.tsx b/src/mutations.tsx new file mode 100644 index 000000000..b4689bfea --- /dev/null +++ b/src/mutations.tsx @@ -0,0 +1,62 @@ +import { ApolloError } from "apollo-client"; +import { DocumentNode } from "graphql"; +import * as React from "react"; +import { + Mutation, + MutationFn, + MutationResult, + MutationUpdaterFn +} from "react-apollo"; + +import useNotifier from "./hooks/useNotifier"; +import i18n from "./i18n"; + +export interface TypedMutationInnerProps { + children: ( + mutateFn: MutationFn, + result: MutationResult + ) => React.ReactNode; + onCompleted?: (data: TData) => void; + onError?: (error: ApolloError) => void; + variables?: TVariables; +} + +export function TypedMutation( + mutation: DocumentNode, + update?: MutationUpdaterFn +) { + class StrictTypedMutation extends Mutation {} + return (props: TypedMutationInnerProps) => { + const notify = useNotifier(); + // Obviously, this is workaround to the problem described here: + // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/32588 + const { + children, + onCompleted, + onError, + variables + } = props as JSX.LibraryManagedAttributes< + typeof StrictTypedMutation, + typeof props + >; + return ( + { + const msg = i18n.t("Something went wrong: {{ message }}", { + message: err.message + }); + notify({ text: msg }); + if (onError) { + onError(err); + } + }} + variables={variables} + update={update} + > + {children} + + ); + }; +} diff --git a/src/navigation/components/MenuCreateDialog/MenuCreateDialog.tsx b/src/navigation/components/MenuCreateDialog/MenuCreateDialog.tsx new file mode 100644 index 000000000..1620b5b19 --- /dev/null +++ b/src/navigation/components/MenuCreateDialog/MenuCreateDialog.tsx @@ -0,0 +1,79 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import i18n from "../../../i18n"; + +export interface MenuCreateDialogFormData { + name: string; +} + +export interface MenuCreateDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + disabled: boolean; + open: boolean; + onClose: () => void; + onConfirm: (data: MenuCreateDialogFormData) => void; +} + +const initialForm: MenuCreateDialogFormData = { + name: "" +}; + +const MenuCreateDialog: React.FC = ({ + confirmButtonState, + disabled, + onClose, + onConfirm, + open +}) => ( + + + {i18n.t("Add Menu", { + context: "create menu modal window title" + })} + +
+ {({ change, data, errors: formErrors, submit }) => ( + <> + + + + + + + {i18n.t("Create")} + + + + )} +
+
+); + +MenuCreateDialog.displayName = "MenuCreateDialog"; +export default MenuCreateDialog; diff --git a/src/navigation/components/MenuCreateDialog/index.ts b/src/navigation/components/MenuCreateDialog/index.ts new file mode 100644 index 000000000..afef4b52e --- /dev/null +++ b/src/navigation/components/MenuCreateDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from './MenuCreateDialog'; +export * from './MenuCreateDialog'; \ No newline at end of file diff --git a/src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx b/src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx new file mode 100644 index 000000000..4ce143bb4 --- /dev/null +++ b/src/navigation/components/MenuDetailsPage/MenuDetailsPage.tsx @@ -0,0 +1,126 @@ +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { MenuDetails_menu } from "../../types/MenuDetails"; +import { MenuItemType } from "../MenuItemDialog"; +import MenuItems, { TreeOperation } from "../MenuItems"; +import MenuProperties from "../MenuProperties"; +import { computeTree } from "./tree"; + +export interface MenuDetailsFormData { + name: string; +} + +export interface MenuDetailsSubmitData extends MenuDetailsFormData { + operations: TreeOperation[]; +} + +export interface MenuDetailsPageProps { + saveButtonState: ConfirmButtonTransitionState; + disabled: boolean; + menu: MenuDetails_menu; + onBack: () => void; + onDelete: () => void; + onItemAdd: () => void; + onItemClick: (id: string, type: MenuItemType) => void; + onItemEdit: (id: string) => void; + onSubmit: (data: MenuDetailsSubmitData) => Promise; +} + +const MenuDetailsPage: React.StatelessComponent = ({ + disabled, + menu, + saveButtonState, + onBack, + onDelete, + onItemAdd, + onItemClick, + onItemEdit, + onSubmit +}) => { + const initialForm: MenuDetailsFormData = { + name: maybe(() => menu.name, "") + }; + + const [treeOperations, setTreeOperations] = React.useState( + [] + ); + + const handleSubmit = async (data: MenuDetailsFormData) => { + if ( + await onSubmit({ + name: data.name, + operations: treeOperations + }) + ) { + setTreeOperations([]); + } + }; + + const handleChange = (operation: TreeOperation) => { + if (!!operation) { + setTreeOperations([...treeOperations, operation]); + } + }; + + return ( +
+ {({ change, data, hasChanged, submit }) => ( + + {i18n.t("Navigation")} + +
+ {i18n.t("Navigation")} + + {i18n.t( + "Creating the navigation structure is done by dragging and dropping. Simply create a new menu item and then drag it into its destined place. You can move items inside one another to create a tree structure and drag items up and down to create a hierarchy" + )} + +
+
+ + + 0} + items={maybe(() => + computeTree(menu.items, [...treeOperations]) + )} + onChange={handleChange} + onItemAdd={onItemAdd} + onItemClick={onItemClick} + onItemEdit={onItemEdit} + onUndo={() => + setTreeOperations( + treeOperations.slice(0, treeOperations.length - 1) + ) + } + /> +
+
+ +
+ )} +
+ ); +}; +MenuDetailsPage.displayName = "MenuDetailsPage"; +export default MenuDetailsPage; diff --git a/src/navigation/components/MenuDetailsPage/__snapshots__/tree.test.ts.snap b/src/navigation/components/MenuDetailsPage/__snapshots__/tree.test.ts.snap new file mode 100644 index 000000000..496636b91 --- /dev/null +++ b/src/navigation/components/MenuDetailsPage/__snapshots__/tree.test.ts.snap @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Properly computes trees # 1`] = ` +" +Accessories +··Jewelry +··Glasses +Groceries +Apparel" +`; + +exports[`Properly computes trees # 2`] = ` +" +Groceries +··Accessories +····Jewelry +······Glasses +Apparel" +`; + +exports[`Properly computes trees # 3`] = ` +" +Apparel +··Groceries +····Accessories +······Jewelry +········Glasses" +`; + +exports[`Properly computes trees # 4`] = ` +" +Accessories +Glasses +Jewelry +··Groceries +····Apparel" +`; + +exports[`Properly computes trees # 5`] = ` +" +Jewelry +··Groceries +Glasses +··Apparel +····Accessories" +`; + +exports[`Properly computes trees # 6`] = ` +" +Groceries +Apparel" +`; + +exports[`Properly computes trees # 7`] = ` +" +Apparel" +`; diff --git a/src/navigation/components/MenuDetailsPage/index.ts b/src/navigation/components/MenuDetailsPage/index.ts new file mode 100644 index 000000000..3ebbd4695 --- /dev/null +++ b/src/navigation/components/MenuDetailsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from './MenuDetailsPage'; +export * from './MenuDetailsPage'; \ No newline at end of file diff --git a/src/navigation/components/MenuDetailsPage/tree.test.ts b/src/navigation/components/MenuDetailsPage/tree.test.ts new file mode 100644 index 000000000..5464565a3 --- /dev/null +++ b/src/navigation/components/MenuDetailsPage/tree.test.ts @@ -0,0 +1,185 @@ +import { menu } from "../../fixtures"; +import { MenuDetails_menu_items } from "../../types/MenuDetails"; +import { TreeOperation } from "../MenuItems"; +import { computeTree } from "./tree"; + +// Readability FTW +function innerTreeToString( + tree: MenuDetails_menu_items, + level: number +): string { + return ( + "\n" + + "··".repeat(level) + + tree.name + + tree.children.reduce( + (acc, node) => acc + innerTreeToString(node, level + 1), + "" + ) + ); +} +function treeToString(tree: MenuDetails_menu_items[]): string { + return tree.reduce((acc, node) => acc + innerTreeToString(node, 0), ""); +} + +describe("Properly computes trees", () => { + const testTable: TreeOperation[][] = [ + [], + [ + { id: "1glasses", parentId: "0jewelry", sortOrder: 0, type: "move" }, + { + id: "2accessories", + parentId: "3groceries", + sortOrder: 0, + type: "move" + } + ], + [ + { id: "1glasses", parentId: "0jewelry", sortOrder: 0, type: "move" }, + { + id: "2accessories", + parentId: "3groceries", + sortOrder: 0, + type: "move" + }, + { + id: "3groceries", + parentId: "4apparel", + sortOrder: 0, + type: "move" + } + ], + [ + { id: "0jewelry", sortOrder: 1, type: "move" }, + { id: "1glasses", sortOrder: 1, type: "move" }, + { + id: "4apparel", + parentId: "3groceries", + sortOrder: 0, + type: "move" + }, + { + id: "3groceries", + parentId: "0jewelry", + sortOrder: 0, + type: "move" + }, + { id: "0jewelry", parentId: "1glasses", sortOrder: 0, type: "move" }, + { + id: "1glasses", + parentId: "2accessories", + sortOrder: 0, + type: "move" + }, + { id: "1glasses", sortOrder: 1, type: "move" }, + { id: "0jewelry", sortOrder: 2, type: "move" } + ], + [ + { id: "1glasses", sortOrder: 1, type: "move" }, + { id: "1glasses", parentId: "0jewelry", sortOrder: 0, type: "move" }, + { id: "0jewelry", sortOrder: 1, type: "move" }, + { + id: "0jewelry", + parentId: "2accessories", + sortOrder: 0, + type: "move" + }, + { id: "3groceries", sortOrder: 0, type: "move" }, + { + id: "2accessories", + parentId: "3groceries", + sortOrder: 0, + type: "move" + }, + { id: "2accessories", sortOrder: 1, type: "move" }, + { id: "0jewelry", sortOrder: 2, type: "move" }, + { id: "1glasses", sortOrder: 3, type: "move" }, + { id: "4apparel", sortOrder: 0, type: "move" }, + { id: "1glasses", sortOrder: 1, type: "move" }, + { id: "2accessories", sortOrder: 0, type: "move" }, + { + id: "4apparel", + parentId: "2accessories", + sortOrder: 0, + type: "move" + }, + { + id: "3groceries", + parentId: "1glasses", + sortOrder: 0, + type: "move" + }, + { id: "0jewelry", sortOrder: 0, type: "move" }, + { + id: "0jewelry", + parentId: "2accessories", + sortOrder: 0, + type: "move" + }, + { + id: "4apparel", + parentId: "2accessories", + sortOrder: 0, + type: "move" + }, + { + id: "0jewelry", + parentId: "2accessories", + sortOrder: 0, + type: "move" + }, + { + id: "1glasses", + parentId: "2accessories", + sortOrder: 2, + type: "move" + }, + { + id: "0jewelry", + parentId: "2accessories", + sortOrder: 2, + type: "move" + }, + { + id: "1glasses", + parentId: "2accessories", + sortOrder: 2, + type: "move" + }, + { + id: "4apparel", + parentId: "2accessories", + sortOrder: 2, + type: "move" + }, + { + id: "3groceries", + parentId: "0jewelry", + sortOrder: 0, + type: "move" + }, + { id: "4apparel", parentId: "1glasses", sortOrder: 0, type: "move" }, + { id: "1glasses", sortOrder: 1, type: "move" }, + { id: "0jewelry", sortOrder: 1, type: "move" }, + { + id: "2accessories", + parentId: "4apparel", + sortOrder: 0, + type: "move" + } + ], + [{ id: "2accessories", type: "remove" }], + [ + { id: "2accessories", type: "remove" }, + { id: "4apparel", type: "move", sortOrder: 0 }, + { id: "3groceries", type: "remove" } + ] + ]; + + testTable.forEach(testData => + it("#", () => { + const computedTree = computeTree(menu.items, testData); + expect(treeToString(computedTree)).toMatchSnapshot(); + }) + ); +}); diff --git a/src/navigation/components/MenuDetailsPage/tree.ts b/src/navigation/components/MenuDetailsPage/tree.ts new file mode 100644 index 000000000..82658aeaa --- /dev/null +++ b/src/navigation/components/MenuDetailsPage/tree.ts @@ -0,0 +1,134 @@ +import { MenuDetails_menu_items } from "../../types/MenuDetails"; +import { TreeOperation } from "../MenuItems"; + +export function findNode(tree: MenuDetails_menu_items[], id: string): number[] { + const foundNodeIndex = tree.findIndex(node => node.id === id); + if (tree.length === 0) { + return [null]; + } + if (foundNodeIndex !== -1) { + return [foundNodeIndex]; + } + const nodeMap = tree.map((node, nodeIndex) => [ + nodeIndex, + ...findNode(node.children, id) + ]); + return nodeMap.find(path => path[path.length - 1] !== null) || [null]; +} + +export function getNode( + tree: MenuDetails_menu_items[], + path: number[] +): MenuDetails_menu_items { + if (path.length === 1) { + return tree[path[0]]; + } + return getNode([...tree[path[0]].children], path.slice(1)); +} + +function removeNode( + tree: MenuDetails_menu_items[], + path: number[] +): MenuDetails_menu_items[] { + const removeIndex = path[0]; + + if (path.length === 1) { + return [...tree.slice(0, removeIndex), ...tree.slice(removeIndex + 1)]; + } + + const newTree = [...tree]; + newTree[removeIndex] = { + ...tree[path[0]], + children: removeNode(tree[path[0]].children, path.slice(1)) + }; + + return newTree; +} + +function insertNode( + tree: MenuDetails_menu_items[], + path: number[], + node: MenuDetails_menu_items, + position: number +): MenuDetails_menu_items[] { + if (path.length === 0) { + return [...tree.slice(0, position), node, ...tree.slice(position)]; + } + + if (path[0] in tree) { + tree[path[0]].children = insertNode( + tree[path[0]].children, + path.slice(1), + node, + position + ); + } + return tree; +} + +function removeNodeAndChildren( + tree: MenuDetails_menu_items[], + operation: TreeOperation +): MenuDetails_menu_items[] { + const sourcePath = findNode(tree, operation.id); + const node = getNode(tree, sourcePath); + + if (node.children) { + const treeAfterChildrenRemoval = node.children.reduce( + (acc, child) => + removeNodeAndChildren(acc, { + id: child.id, + type: "remove" + }), + tree + ); + + return removeNode(treeAfterChildrenRemoval, sourcePath); + } + + return removeNode(tree, sourcePath); +} + +function permuteNode( + tree: MenuDetails_menu_items[], + permutation: TreeOperation +): MenuDetails_menu_items[] { + const sourcePath = findNode(tree, permutation.id); + const node = getNode(tree, sourcePath); + + const treeAfterRemoval = removeNode(tree, sourcePath); + + const targetPath = permutation.parentId + ? findNode(treeAfterRemoval, permutation.parentId) + : []; + + const treeAfterInsertion = insertNode( + treeAfterRemoval, + targetPath, + node, + permutation.sortOrder + ); + + return treeAfterInsertion; +} + +function executeOperation( + tree: MenuDetails_menu_items[], + operation: TreeOperation +): MenuDetails_menu_items[] { + return operation.type === "move" + ? permuteNode(tree, operation) + : removeNodeAndChildren(tree, operation); +} + +export function computeTree( + tree: MenuDetails_menu_items[], + operations: TreeOperation[] +) { + const newTree = operations.reduce( + (acc, operation) => executeOperation(acc, operation), + // FIXME: 😡 + JSON.parse(JSON.stringify(tree)) + ); + return newTree; +} diff --git a/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx b/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx new file mode 100644 index 000000000..6cb3f59ec --- /dev/null +++ b/src/navigation/components/MenuItemDialog/MenuItemDialog.tsx @@ -0,0 +1,268 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import TextField from "@material-ui/core/TextField"; +import * as isUrl from "is-url"; +import * as React from "react"; + +import AutocompleteSelectMenu from "@saleor/components/AutocompleteSelectMenu"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import FormSpacer from "@saleor/components/FormSpacer"; +import { SearchCategories_categories_edges_node } from "../../../containers/SearchCategories/types/SearchCategories"; +import { SearchCollections_collections_edges_node } from "../../../containers/SearchCollections/types/SearchCollections"; +import { SearchPages_pages_edges_node } from "../../../containers/SearchPages/types/SearchPages"; +import i18n from "../../../i18n"; +import { getMenuItemByValue, IMenu } from "../../../utils/menu"; + +export type MenuItemType = "category" | "collection" | "link" | "page"; +export interface MenuItemData { + id: string; + type: MenuItemType; +} + +export interface MenuItemDialogFormData extends MenuItemData { + name: string; +} + +export interface MenuItemDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + disabled: boolean; + initial?: MenuItemDialogFormData; + initialDisplayValue?: string; + loading: boolean; + open: boolean; + collections: SearchCollections_collections_edges_node[]; + categories: SearchCategories_categories_edges_node[]; + pages: SearchPages_pages_edges_node[]; + onClose: () => void; + onSubmit: (data: MenuItemDialogFormData) => void; + onQueryChange: (query: string) => void; +} + +const defaultInitial: MenuItemDialogFormData = { + id: "", + name: "", + type: "category" +}; + +function getMenuItemData(value: string): MenuItemData { + const [type, ...idParts] = value.split(":"); + return { + id: idParts.join(":"), + type: type as MenuItemType + }; +} + +function getDisplayValue(menu: IMenu, value: string): string { + const menuItemData = getMenuItemData(value); + if (menuItemData.type === "link") { + return menuItemData.id; + } + return getMenuItemByValue(menu, value).label.toString(); +} + +const MenuItemDialog: React.StatelessComponent = ({ + confirmButtonState, + disabled, + initial, + initialDisplayValue, + loading, + onClose, + onSubmit, + onQueryChange, + open, + categories, + collections, + pages +}) => { + const [displayValue, setDisplayValue] = React.useState( + initialDisplayValue || "" + ); + const [url, setUrl] = React.useState(undefined); + + // Refresh initial display value if changed + React.useEffect(() => setDisplayValue(initialDisplayValue), [ + initialDisplayValue + ]); + + // Reset input state after closing dialog + React.useEffect(() => { + setDisplayValue(initialDisplayValue); + setUrl(undefined); + }, [open]); + + let options: IMenu = []; + + if (categories.length > 0) { + options = [ + ...options, + { + children: categories.map(category => ({ + children: [], + data: {}, + label: category.name, + value: "category:" + category.id + })), + data: {}, + label: i18n.t("Categories") + } + ]; + } + + if (collections.length > 0) { + options = [ + ...options, + { + children: collections.map(collection => ({ + children: [], + data: {}, + label: collection.name, + value: "collection:" + collection.id + })), + data: {}, + label: i18n.t("Collections") + } + ]; + } + + if (pages.length > 0) { + options = [ + ...options, + { + children: pages.map(page => ({ + children: [], + data: {}, + label: page.title, + value: "page:" + page.id + })), + data: {}, + label: i18n.t("Pages") + } + ]; + } + + if (url) { + options = [ + { + children: [], + data: {}, + label: ( +
{{ url }}", { + context: "add link to navigation", + url + }) + }} + /> + ), + value: "link:" + url + } + ]; + } + + const handleQueryChange = (query: string) => { + if (isUrl(query)) { + setUrl(query); + } else if (isUrl("http://" + query)) { + setUrl("http://" + query); + } else if (url) { + setUrl(undefined); + } + onQueryChange(query); + }; + + return ( + + + {i18n.t("Add Item", { + context: "create new menu item" + })} + +
+ {({ change, data, submit }) => { + const handleSelectChange = (event: React.ChangeEvent) => { + const value = event.target.value; + const menuItemData = getMenuItemData(value); + change( + { + target: { + name: "id", + value: menuItemData.id + } + } as any, + () => + change( + { + target: { + name: "type", + value: menuItemData.type + } + } as any, + () => setDisplayValue(getDisplayValue(options, value)) + ) + ); + }; + + return ( + <> + + + + + + + + + {i18n.t("Submit", { context: "button" })} + + + + ); + }} + +
+ ); +}; +MenuItemDialog.displayName = "MenuItemDialog"; +export default MenuItemDialog; diff --git a/src/navigation/components/MenuItemDialog/index.ts b/src/navigation/components/MenuItemDialog/index.ts new file mode 100644 index 000000000..843bfb062 --- /dev/null +++ b/src/navigation/components/MenuItemDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./MenuItemDialog"; +export * from "./MenuItemDialog"; diff --git a/src/navigation/components/MenuItems/MenuItems.tsx b/src/navigation/components/MenuItems/MenuItems.tsx new file mode 100644 index 000000000..715e29e65 --- /dev/null +++ b/src/navigation/components/MenuItems/MenuItems.tsx @@ -0,0 +1,279 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardActions from "@material-ui/core/CardActions"; +import IconButton from "@material-ui/core/IconButton"; +import Paper from "@material-ui/core/Paper"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import DeleteIcon from "@material-ui/icons/Delete"; +import EditIcon from "@material-ui/icons/Edit"; +import classNames from "classnames"; +import * as React from "react"; +import SortableTree, { NodeRendererProps, TreeItem } from "react-sortable-tree"; + +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; +import useTheme from "@saleor/hooks/useTheme"; +import i18n from "../../../i18n"; +import Draggable from "../../../icons/Draggable"; +import { MenuDetails_menu_items } from "../../types/MenuDetails"; +import { MenuItemType } from "../MenuItemDialog"; +import { getDiff, getNodeData, getNodeQuantity, TreeOperation } from "./tree"; + +const NODE_HEIGHT = 56; +const NODE_MARGIN = 40; + +export interface MenuItemsProps { + canUndo: boolean; + items: MenuDetails_menu_items[]; + onChange: (operation: TreeOperation) => void; + onItemAdd: () => void; + onItemClick: (id: string, type: MenuItemType) => void; + onItemEdit: (id: string) => void; + onUndo: () => void; +} + +const styles = (theme: Theme) => + createStyles({ + actions: { + flexDirection: "row" + }, + container: { + background: theme.palette.grey[200] + }, + darkContainer: { + background: `${theme.palette.grey[800]} !important` + }, + deleteButton: { + marginRight: theme.spacing.unit + }, + dragIcon: { + cursor: "grab" + }, + nodeTitle: { + cursor: "pointer", + marginLeft: theme.spacing.unit * 7 + }, + root: { + "& .rst__collapseButton": { + display: "none" + }, + "& .rst__node": { + "&:first-of-type": { + "& $row": { + borderTop: `1px ${theme.overrides.MuiCard.root.borderColor} solid` + } + } + } + }, + row: { + alignItems: "center", + background: theme.palette.background.paper, + borderBottom: `1px ${theme.overrides.MuiCard.root.borderColor} solid`, + borderRadius: 0, + display: "flex", + flexDirection: "row", + height: NODE_HEIGHT, + justifyContent: "flex-start", + paddingLeft: theme.spacing.unit * 3 + }, + rowContainer: { + "& > *": { + opacity: 1, + transition: `opacity ${theme.transitions.duration.standard}ms` + }, + transition: `margin ${theme.transitions.duration.standard}ms` + }, + rowContainerDragged: { + "&$rowContainer": { + "&:before": { + background: theme.palette.background.paper, + border: `1px solid ${theme.palette.primary.main}`, + borderRadius: "100%", + content: "''", + height: 7, + left: 0, + position: "absolute", + top: -3, + width: 7 + }, + borderTop: `1px solid ${theme.palette.primary.main}`, + height: 0, + position: "relative", + top: -1 + } + }, + rowContainerPlaceholder: { + opacity: 0 + }, + spacer: { + flex: 1 + } + }); + +const Placeholder = withStyles(styles, { + name: "Placeholder" +})(({ classes }: WithStyles) => ( + + + {i18n.t("Add new menu item to begin creating menu")} + + +)); + +const Node = withStyles(styles, { + name: "Node" +})( + ({ + classes, + node, + path, + connectDragPreview, + connectDragSource, + isDragging + }: NodeRendererProps & WithStyles) => { + const draggedClassName = classNames( + classes.rowContainer, + classes.rowContainerDragged + ); + const defaultClassName = isDragging + ? draggedClassName + : classes.rowContainer; + const placeholderClassName = classNames( + classes.rowContainer, + classes.rowContainerPlaceholder + ); + + const [className, setClassName] = React.useState(defaultClassName); + React.useEffect(() => setClassName(defaultClassName), [isDragging]); + + const handleDragStart = () => { + setClassName(placeholderClassName); + setTimeout(() => setClassName(defaultClassName), 0); + }; + + return connectDragPreview( +
+ + {connectDragSource( +
+ +
+ )} + + {node.title} + +
+ + + + + + node.onChange({ + id: node.id as any, + type: "remove" + }) + } + > + + + +
+ ); + } +); + +const MenuItems = withStyles(styles, { name: "MenuItems" })( + ({ + canUndo, + classes, + items, + onChange, + onItemAdd, + onItemClick, + onItemEdit, + onUndo + }: MenuItemsProps & WithStyles) => { + const { isDark } = useTheme(); + + return ( + + + {i18n.t("Undo")} + + } + /> +
+ {items === undefined ? ( + + ) : ( + ({ + className: classes.row, + style: { + marginLeft: NODE_MARGIN * (path.length - 1) + } + })} + isVirtualized={false} + rowHeight={NODE_HEIGHT} + treeData={items.map(item => + getNodeData(item, onChange, onItemClick, onItemEdit) + )} + theme={{ + nodeContentRenderer: Node as any + }} + onChange={newTree => + onChange( + getDiff( + items.map(item => + getNodeData(item, onChange, onItemClick, onItemEdit) + ), + newTree as TreeItem[] + ) + ) + } + placeholderRenderer={Placeholder as any} + /> + )} +
+ + + +
+ ); + } +); +MenuItems.displayName = "MenuItems"; +export default MenuItems; diff --git a/src/navigation/components/MenuItems/__snapshots__/tree.test.ts.snap b/src/navigation/components/MenuItems/__snapshots__/tree.test.ts.snap new file mode 100644 index 000000000..f9bd083a0 --- /dev/null +++ b/src/navigation/components/MenuItems/__snapshots__/tree.test.ts.snap @@ -0,0 +1,28 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Properly computes diffs # 1`] = ` +Object { + "id": "1glasses", + "parentId": "0jewelry", + "sortOrder": 0, + "type": "move", +} +`; + +exports[`Properly computes diffs # 2`] = ` +Object { + "id": "1glasses", + "parentId": "2accessories", + "sortOrder": 0, + "type": "move", +} +`; + +exports[`Properly computes diffs # 3`] = ` +Object { + "id": "2accessories", + "parentId": "4apparel", + "sortOrder": 0, + "type": "move", +} +`; diff --git a/src/navigation/components/MenuItems/index.ts b/src/navigation/components/MenuItems/index.ts new file mode 100644 index 000000000..8f13d0b5a --- /dev/null +++ b/src/navigation/components/MenuItems/index.ts @@ -0,0 +1,3 @@ +export { default } from "./MenuItems"; +export * from "./MenuItems"; +export * from "./tree"; diff --git a/src/navigation/components/MenuItems/tree.test.ts b/src/navigation/components/MenuItems/tree.test.ts new file mode 100644 index 000000000..992790cd4 --- /dev/null +++ b/src/navigation/components/MenuItems/tree.test.ts @@ -0,0 +1,88 @@ +import { + addNodeUnderParent, + find, + insertNode, + removeNode, + TreeItem +} from "react-sortable-tree"; + +import { getDiff } from "./tree"; + +const originalTree: TreeItem[] = [ + { + children: [ + { children: [], expanded: true, id: "0jewelry", title: "Jewelry" }, + { children: [], expanded: true, id: "1glasses", title: "Glasses" } + ], + expanded: true, + id: "2accessories", + title: "Accessories" + }, + { children: [], expanded: true, id: "3groceries", title: "Groceries" }, + { children: [], expanded: true, id: "4apparel", title: "Apparel" } +]; + +function getNodeKey(node: any) { + return node.treeIndex; +} + +function moveNode( + tree: TreeItem[], + src: string, + target: string, + asChild: boolean +) { + const { matches: srcNodeCandidates } = find({ + getNodeKey, + searchMethod: ({ node }) => node.id === src, + treeData: tree + }); + const srcNodeData = srcNodeCandidates[0]; + + const treeAfterRemoval = removeNode({ + getNodeKey, + path: srcNodeData.path, + treeData: tree + }).treeData; + + const { matches: targetNodeCandidates } = find({ + getNodeKey, + searchMethod: ({ node }) => node.id === target, + treeData: treeAfterRemoval + }); + const targetNodeData = targetNodeCandidates[0]; + + const treeAfterInsertion = asChild + ? addNodeUnderParent({ + addAsFirstChild: true, + getNodeKey, + ignoreCollapsed: false, + newNode: srcNodeData.node, + parentKey: targetNodeData.treeIndex, + treeData: treeAfterRemoval + }).treeData + : insertNode({ + depth: targetNodeData.path.length, + getNodeKey, + minimumTreeIndex: targetNodeData.treeIndex, + newNode: srcNodeData.node, + treeData: treeAfterRemoval + }).treeData; + + return treeAfterInsertion as TreeItem[]; +} + +describe("Properly computes diffs", () => { + const testTable = [ + moveNode(originalTree, "1glasses", "0jewelry", true), + moveNode(originalTree, "1glasses", "0jewelry", false), + moveNode(originalTree, "2accessories", "4apparel", true) + ]; + + testTable.forEach(testData => + it("#", () => { + const diff = getDiff(originalTree, testData); + expect(diff).toMatchSnapshot(); + }) + ); +}); diff --git a/src/navigation/components/MenuItems/tree.ts b/src/navigation/components/MenuItems/tree.ts new file mode 100644 index 000000000..4923d2be4 --- /dev/null +++ b/src/navigation/components/MenuItems/tree.ts @@ -0,0 +1,117 @@ +import { getPatch } from "fast-array-diff"; +import { TreeItem } from "react-sortable-tree"; + +import { MenuDetails_menu_items } from "../../types/MenuDetails"; +import { MenuItemType } from "../MenuItemDialog"; + +export type TreeOperationType = "move" | "remove"; +export interface TreeOperation { + id: string; + type: TreeOperationType; + parentId?: string; + sortOrder?: number; +} + +export const unknownTypeError = Error("Unknown type"); + +function treeToMap(tree: TreeItem[], parent: string): Record { + const childrenList = tree.map(node => node.id); + const childrenMaps = tree.map(node => ({ + id: node.id, + mappedNodes: treeToMap(node.children as TreeItem[], node.id) + })); + + return { + [parent]: childrenList, + ...childrenMaps.reduce( + (acc, childMap) => ({ + ...acc, + ...childMap.mappedNodes + }), + {} + ) + }; +} + +export function getItemType(item: MenuDetails_menu_items): MenuItemType { + if (item.category) { + return "category"; + } else if (item.collection) { + return "collection"; + } else if (item.page) { + return "page"; + } else if (item.url) { + return "link"; + } else { + throw unknownTypeError; + } +} + +export function getItemId(item: MenuDetails_menu_items): string { + if (item.category) { + return item.category.id; + } else if (item.collection) { + return item.collection.id; + } else if (item.page) { + return item.page.id; + } else if (item.url) { + return item.url; + } else { + throw unknownTypeError; + } +} + +export function getDiff( + originalTree: TreeItem[], + newTree: TreeItem[] +): TreeOperation { + const originalMap = treeToMap(originalTree, "root"); + const newMap = treeToMap(newTree, "root"); + + const diff: TreeOperation[] = Object.keys(newMap).map(key => { + const originalNode = originalMap[key]; + const newNode = newMap[key]; + + const patch = getPatch(originalNode, newNode); + + if (patch.length > 0) { + const addedNode = patch.find(operation => operation.type === "add"); + if (!!addedNode) { + return { + id: addedNode.items[0], + parentId: key === "root" ? undefined : key, + sortOrder: addedNode.newPos, + type: "move" as TreeOperationType + }; + } + } + }); + + return diff.find(d => !!d); +} + +export function getNodeData( + item: MenuDetails_menu_items, + onChange: (operation: TreeOperation) => void, + onClick: (id: string, type: MenuItemType) => void, + onEdit: (id: string) => void +): TreeItem { + return { + children: item.children.map(child => + getNodeData(child, onChange, onClick, onEdit) + ), + expanded: true, + id: item.id, + onChange, + onClick: () => onClick(getItemId(item), getItemType(item)), + onEdit: () => onEdit(item.id), + title: item.name + }; +} + +export function getNodeQuantity(items: MenuDetails_menu_items[]): number { + return items.reduce( + (acc, curr) => acc + getNodeQuantity(curr.children), + items.length + ); +} diff --git a/src/navigation/components/MenuList/MenuList.tsx b/src/navigation/components/MenuList/MenuList.tsx new file mode 100644 index 000000000..2fb39843d --- /dev/null +++ b/src/navigation/components/MenuList/MenuList.tsx @@ -0,0 +1,143 @@ +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import Checkbox from "@saleor/components/Checkbox"; +import IconButtonTableCell from "@saleor/components/IconButtonTableCell"; +import Skeleton from "@saleor/components/Skeleton"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { MenuList_menus_edges_node } from "../../types/MenuList"; + +export interface MenuListProps extends ListProps, ListActions { + menus: MenuList_menus_edges_node[]; + onDelete: (id: string) => void; +} + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colItems: { + width: 200 + }, + colTitle: {} + }, + colItems: { + textAlign: "right" + }, + colTitle: {}, + row: { + cursor: "pointer" + } + }); +const MenuList = withStyles(styles, { name: "MenuList" })( + ({ + classes, + disabled, + isChecked, + menus, + onDelete, + onNextPage, + onPreviousPage, + onRowClick, + pageInfo, + selected, + toggle, + toggleAll, + toolbar + }: MenuListProps & WithStyles) => ( + + + + + {i18n.t("Menu Title", { context: "object" })} + + + {i18n.t("Items", { context: "number of menu items" })} + + + + + + + + + {renderCollection( + menus, + menu => { + const isSelected = menu ? isChecked(menu.id) : false; + + return ( + + + toggle(menu.id)} + /> + + + {maybe(() => menu.name, )} + + + {maybe( + () => menu.items.length, + + )} + + onDelete(menu.id)} + > + + + + ); + }, + () => ( + + {i18n.t("No menus found")} + + ) + )} + +
+
+ ) +); +MenuList.displayName = "MenuList"; +export default MenuList; diff --git a/src/navigation/components/MenuList/index.ts b/src/navigation/components/MenuList/index.ts new file mode 100644 index 000000000..298313288 --- /dev/null +++ b/src/navigation/components/MenuList/index.ts @@ -0,0 +1,2 @@ +export { default } from './MenuList'; +export * from './MenuList'; \ No newline at end of file diff --git a/src/navigation/components/MenuListPage/MenuListPage.tsx b/src/navigation/components/MenuListPage/MenuListPage.tsx new file mode 100644 index 000000000..49c3df930 --- /dev/null +++ b/src/navigation/components/MenuListPage/MenuListPage.tsx @@ -0,0 +1,41 @@ +import Button from "@material-ui/core/Button"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { ListActions, PageListProps } from "../../../types"; +import { MenuList_menus_edges_node } from "../../types/MenuList"; +import MenuList from "../MenuList"; + +export interface MenuListPageProps extends PageListProps, ListActions { + menus: MenuList_menus_edges_node[]; + onBack: () => void; + onDelete: (id: string) => void; +} + +const MenuListPage: React.StatelessComponent = ({ + disabled, + onAdd, + onBack, + ...listProps +}) => ( + + {i18n.t("Configuration")} + + + + + +); +MenuListPage.displayName = "MenuListPage"; +export default MenuListPage; diff --git a/src/navigation/components/MenuListPage/index.ts b/src/navigation/components/MenuListPage/index.ts new file mode 100644 index 000000000..eac89a2b2 --- /dev/null +++ b/src/navigation/components/MenuListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from './MenuListPage'; +export * from './MenuListPage'; \ No newline at end of file diff --git a/src/navigation/components/MenuProperties/MenuProperties.tsx b/src/navigation/components/MenuProperties/MenuProperties.tsx new file mode 100644 index 000000000..15436c793 --- /dev/null +++ b/src/navigation/components/MenuProperties/MenuProperties.tsx @@ -0,0 +1,36 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import i18n from "../../../i18n"; +import { MenuDetailsFormData } from "../MenuDetailsPage"; + +export interface MenuPropertiesProps { + data: MenuDetailsFormData; + disabled: boolean; + onChange: (event: React.ChangeEvent) => void; +} + +const MenuProperties: React.StatelessComponent = ({ + data, + disabled, + onChange +}) => ( + + + + + + +); +MenuProperties.displayName = "MenuProperties"; +export default MenuProperties; diff --git a/src/navigation/components/MenuProperties/index.ts b/src/navigation/components/MenuProperties/index.ts new file mode 100644 index 000000000..cbbaabac0 --- /dev/null +++ b/src/navigation/components/MenuProperties/index.ts @@ -0,0 +1,2 @@ +export { default } from './MenuProperties'; +export * from './MenuProperties'; \ No newline at end of file diff --git a/src/navigation/fixtures.ts b/src/navigation/fixtures.ts new file mode 100644 index 000000000..b21e5b2b5 --- /dev/null +++ b/src/navigation/fixtures.ts @@ -0,0 +1,113 @@ +import { MenuDetails_menu } from "./types/MenuDetails"; +import { MenuList_menus_edges_node } from "./types/MenuList"; + +export const menuList: MenuList_menus_edges_node[] = [ + { + __typename: "Menu", + id: "TWVudTox", + items: [ + { id: "TWVudUl0ZW06MQ==", __typename: "MenuItem" }, + { id: "TWVudUl0ZW06Mg==", __typename: "MenuItem" }, + { id: "TWVudUl0ZW06Mw==", __typename: "MenuItem" } + ], + name: "navbar" + }, + { + __typename: "Menu", + id: "TWVudToy", + items: [ + { id: "TWVudUl0ZW06NA==", __typename: "MenuItem" }, + { id: "TWVudUl0ZW06Nw==", __typename: "MenuItem" } + ], + name: "footer" + } +]; + +export const menu: MenuDetails_menu = { + __typename: "Menu", + id: "TWVudTox", + items: [ + { + __typename: "MenuItem", + category: { + __typename: "Category", + id: "Q2F0ZWdvcnk6Nw==", + name: "Accessories" + }, + children: [ + { + __typename: "MenuItem", + category: { + __typename: "Category", + id: "Q2F0ZWdvcnk6OAX==", + name: "Jewelry" + }, + children: [], + collection: null, + id: "0jewelry", + level: 0, + name: "Jewelry", + page: null, + sortOrder: 0, + url: null + }, + { + __typename: "MenuItem", + category: { + __typename: "Category", + id: "Q2F0ZWdvcnk6OQX==", + name: "Glasses" + }, + children: [], + collection: null, + id: "1glasses", + level: 0, + name: "Glasses", + page: null, + sortOrder: 1, + url: null + } + ], + collection: null, + id: "2accessories", + level: 0, + name: "Accessories", + page: null, + sortOrder: 0, + url: null + }, + { + __typename: "MenuItem", + category: { + __typename: "Category", + id: "Q2F0ZWdvcnk6OA==", + name: "Groceries" + }, + children: [], + collection: null, + id: "3groceries", + level: 0, + name: "Groceries", + page: null, + sortOrder: 1, + url: null + }, + { + __typename: "MenuItem", + category: { + __typename: "Category", + id: "Q2F0ZWdvcnk6OQ==", + name: "Apparel" + }, + children: [], + collection: null, + id: "4apparel", + level: 0, + name: "Apparel", + page: null, + sortOrder: 2, + url: null + } + ], + name: "navbar" +}; diff --git a/src/navigation/index.tsx b/src/navigation/index.tsx new file mode 100644 index 000000000..46ea8411c --- /dev/null +++ b/src/navigation/index.tsx @@ -0,0 +1,34 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { menuListPath, menuPath } from "./urls"; +import MenuDetailsComponent from "./views/MenuDetails"; +import MenuListComponent from "./views/MenuList"; + +const MenuList: React.FC> = ({ location }) => { + const qs = parseQs(location.search.substr(1)); + return ; +}; + +const MenuDetails: React.FC> = ({ + location, + match +}) => { + const qs = parseQs(location.search.substr(1)); + return ( + + ); +}; + +const NavigationRouter: React.FC = () => ( + + + + +); + +export default NavigationRouter; diff --git a/src/navigation/mutations.ts b/src/navigation/mutations.ts new file mode 100644 index 000000000..e678c93ae --- /dev/null +++ b/src/navigation/mutations.ts @@ -0,0 +1,143 @@ +import gql from "graphql-tag"; +import { TypedMutation } from "../mutations"; +import { menuItemFragment, menuItemNestedFragment } from "./queries"; +import { + MenuBulkDelete, + MenuBulkDeleteVariables +} from "./types/MenuBulkDelete"; +import { MenuCreate, MenuCreateVariables } from "./types/MenuCreate"; +import { MenuDelete, MenuDeleteVariables } from "./types/MenuDelete"; +import { + MenuItemCreate, + MenuItemCreateVariables +} from "./types/MenuItemCreate"; +import { + MenuItemUpdate, + MenuItemUpdateVariables +} from "./types/MenuItemUpdate"; +import { MenuUpdate, MenuUpdateVariables } from "./types/MenuUpdate"; + +const menuCreate = gql` + mutation MenuCreate($input: MenuCreateInput!) { + menuCreate(input: $input) { + errors { + field + message + } + menu { + id + } + } + } +`; +export const MenuCreateMutation = TypedMutation< + MenuCreate, + MenuCreateVariables +>(menuCreate); + +const menuBulkDelete = gql` + mutation MenuBulkDelete($ids: [ID]!) { + menuBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const MenuBulkDeleteMutation = TypedMutation< + MenuBulkDelete, + MenuBulkDeleteVariables +>(menuBulkDelete); + +const menuDelete = gql` + mutation MenuDelete($id: ID!) { + menuDelete(id: $id) { + errors { + field + message + } + } + } +`; +export const MenuDeleteMutation = TypedMutation< + MenuDelete, + MenuDeleteVariables +>(menuDelete); + +const menuItemCreate = gql` + ${menuItemNestedFragment} + mutation MenuItemCreate($input: MenuItemCreateInput!) { + menuItemCreate(input: $input) { + errors { + field + message + } + menuItem { + menu { + id + items { + ...MenuItemNestedFragment + } + } + } + } + } +`; +export const MenuItemCreateMutation = TypedMutation< + MenuItemCreate, + MenuItemCreateVariables +>(menuItemCreate); + +const menuUpdate = gql` + mutation MenuUpdate( + $id: ID! + $name: String! + $moves: [MenuItemMoveInput]! + $removeIds: [ID]! + ) { + menuUpdate(id: $id, input: { name: $name }) { + errors { + field + message + } + } + + menuItemMove(menu: $id, moves: $moves) { + errors { + field + message + } + } + + menuItemBulkDelete(ids: $removeIds) { + errors { + field + message + } + } + } +`; +export const MenuUpdateMutation = TypedMutation< + MenuUpdate, + MenuUpdateVariables +>(menuUpdate); + +const menuItemUpdate = gql` + ${menuItemFragment} + mutation MenuItemUpdate($id: ID!, $input: MenuItemInput!) { + menuItemUpdate(id: $id, input: $input) { + errors { + field + message + } + menuItem { + ...MenuItemFragment + } + } + } +`; +export const MenuItemUpdateMutation = TypedMutation< + MenuItemUpdate, + MenuItemUpdateVariables +>(menuItemUpdate); diff --git a/src/navigation/queries.ts b/src/navigation/queries.ts new file mode 100644 index 000000000..bb26c976b --- /dev/null +++ b/src/navigation/queries.ts @@ -0,0 +1,103 @@ +import gql from "graphql-tag"; +import { pageInfoFragment, TypedQuery } from "../queries"; +import { MenuDetails, MenuDetailsVariables } from "./types/MenuDetails"; +import { MenuList, MenuListVariables } from "./types/MenuList"; + +export const menuFragment = gql` + fragment MenuFragment on Menu { + id + name + items { + id + } + } +`; + +export const menuItemFragment = gql` + fragment MenuItemFragment on MenuItem { + category { + id + name + } + collection { + id + name + } + id + level + name + page { + id + title + } + sortOrder + url + } +`; + +// GraphQL does not support recurive fragments +export const menuItemNestedFragment = gql` + ${menuItemFragment} + fragment MenuItemNestedFragment on MenuItem { + ...MenuItemFragment + children { + ...MenuItemFragment + children { + ...MenuItemFragment + children { + ...MenuItemFragment + children { + ...MenuItemFragment + children { + ...MenuItemFragment + children { + ...MenuItemFragment + } + } + } + } + } + } + } +`; + +export const menuDetailsFragment = gql` + ${menuItemNestedFragment} + fragment MenuDetailsFragment on Menu { + id + items { + ...MenuItemNestedFragment + } + name + } +`; + +const menuList = gql` + ${menuFragment} + ${pageInfoFragment} + query MenuList($first: Int, $after: String, $last: Int, $before: String) { + menus(first: $first, after: $after, before: $before, last: $last) { + edges { + node { + ...MenuFragment + } + } + pageInfo { + ...PageInfoFragment + } + } + } +`; +export const MenuListQuery = TypedQuery(menuList); + +const menuDetails = gql` + ${menuDetailsFragment} + query MenuDetails($id: ID!) { + menu(id: $id) { + ...MenuDetailsFragment + } + } +`; +export const MenuDetailsQuery = TypedQuery( + menuDetails +); diff --git a/src/navigation/types/MenuBulkDelete.ts b/src/navigation/types/MenuBulkDelete.ts new file mode 100644 index 000000000..b253b78b9 --- /dev/null +++ b/src/navigation/types/MenuBulkDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: MenuBulkDelete +// ==================================================== + +export interface MenuBulkDelete_menuBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface MenuBulkDelete_menuBulkDelete { + __typename: "MenuBulkDelete"; + errors: MenuBulkDelete_menuBulkDelete_errors[] | null; +} + +export interface MenuBulkDelete { + menuBulkDelete: MenuBulkDelete_menuBulkDelete | null; +} + +export interface MenuBulkDeleteVariables { + ids: (string | null)[]; +} diff --git a/src/navigation/types/MenuCreate.ts b/src/navigation/types/MenuCreate.ts new file mode 100644 index 000000000..77613e784 --- /dev/null +++ b/src/navigation/types/MenuCreate.ts @@ -0,0 +1,34 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { MenuCreateInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: MenuCreate +// ==================================================== + +export interface MenuCreate_menuCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface MenuCreate_menuCreate_menu { + __typename: "Menu"; + id: string; +} + +export interface MenuCreate_menuCreate { + __typename: "MenuCreate"; + errors: MenuCreate_menuCreate_errors[] | null; + menu: MenuCreate_menuCreate_menu | null; +} + +export interface MenuCreate { + menuCreate: MenuCreate_menuCreate | null; +} + +export interface MenuCreateVariables { + input: MenuCreateInput; +} diff --git a/src/navigation/types/MenuDelete.ts b/src/navigation/types/MenuDelete.ts new file mode 100644 index 000000000..c5cf072b5 --- /dev/null +++ b/src/navigation/types/MenuDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: MenuDelete +// ==================================================== + +export interface MenuDelete_menuDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface MenuDelete_menuDelete { + __typename: "MenuDelete"; + errors: MenuDelete_menuDelete_errors[] | null; +} + +export interface MenuDelete { + menuDelete: MenuDelete_menuDelete | null; +} + +export interface MenuDeleteVariables { + id: string; +} diff --git a/src/navigation/types/MenuDetails.ts b/src/navigation/types/MenuDetails.ts new file mode 100644 index 000000000..8fd223984 --- /dev/null +++ b/src/navigation/types/MenuDetails.ts @@ -0,0 +1,238 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: MenuDetails +// ==================================================== + +export interface MenuDetails_menu_items_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetails_menu_items_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetails_menu_items_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetails_menu_items_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetails_menu_items_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetails_menu_items_children_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetails_menu_items_children_children_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_children_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetails_menu_items_children_children_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetails_menu_items_children_children_children_children_children_children { + __typename: "MenuItem"; + category: MenuDetails_menu_items_children_children_children_children_children_children_category | null; + collection: MenuDetails_menu_items_children_children_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetails_menu_items_children_children_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; +} + +export interface MenuDetails_menu_items_children_children_children_children_children { + __typename: "MenuItem"; + category: MenuDetails_menu_items_children_children_children_children_children_category | null; + collection: MenuDetails_menu_items_children_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetails_menu_items_children_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetails_menu_items_children_children_children_children_children_children | null)[] | null; +} + +export interface MenuDetails_menu_items_children_children_children_children { + __typename: "MenuItem"; + category: MenuDetails_menu_items_children_children_children_children_category | null; + collection: MenuDetails_menu_items_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetails_menu_items_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetails_menu_items_children_children_children_children_children | null)[] | null; +} + +export interface MenuDetails_menu_items_children_children_children { + __typename: "MenuItem"; + category: MenuDetails_menu_items_children_children_children_category | null; + collection: MenuDetails_menu_items_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetails_menu_items_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetails_menu_items_children_children_children_children | null)[] | null; +} + +export interface MenuDetails_menu_items_children_children { + __typename: "MenuItem"; + category: MenuDetails_menu_items_children_children_category | null; + collection: MenuDetails_menu_items_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetails_menu_items_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetails_menu_items_children_children_children | null)[] | null; +} + +export interface MenuDetails_menu_items_children { + __typename: "MenuItem"; + category: MenuDetails_menu_items_children_category | null; + collection: MenuDetails_menu_items_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetails_menu_items_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetails_menu_items_children_children | null)[] | null; +} + +export interface MenuDetails_menu_items { + __typename: "MenuItem"; + category: MenuDetails_menu_items_category | null; + collection: MenuDetails_menu_items_collection | null; + id: string; + level: number; + name: string; + page: MenuDetails_menu_items_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetails_menu_items_children | null)[] | null; +} + +export interface MenuDetails_menu { + __typename: "Menu"; + id: string; + items: (MenuDetails_menu_items | null)[] | null; + name: string; +} + +export interface MenuDetails { + menu: MenuDetails_menu | null; +} + +export interface MenuDetailsVariables { + id: string; +} diff --git a/src/navigation/types/MenuDetailsFragment.ts b/src/navigation/types/MenuDetailsFragment.ts new file mode 100644 index 000000000..1f1d4d545 --- /dev/null +++ b/src/navigation/types/MenuDetailsFragment.ts @@ -0,0 +1,230 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: MenuDetailsFragment +// ==================================================== + +export interface MenuDetailsFragment_items_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetailsFragment_items_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetailsFragment_items_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetailsFragment_items_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetailsFragment_items_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetailsFragment_items_children_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetailsFragment_items_children_children_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_children_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuDetailsFragment_items_children_children_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuDetailsFragment_items_children_children_children_children_children_children { + __typename: "MenuItem"; + category: MenuDetailsFragment_items_children_children_children_children_children_children_category | null; + collection: MenuDetailsFragment_items_children_children_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetailsFragment_items_children_children_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; +} + +export interface MenuDetailsFragment_items_children_children_children_children_children { + __typename: "MenuItem"; + category: MenuDetailsFragment_items_children_children_children_children_children_category | null; + collection: MenuDetailsFragment_items_children_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetailsFragment_items_children_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetailsFragment_items_children_children_children_children_children_children | null)[] | null; +} + +export interface MenuDetailsFragment_items_children_children_children_children { + __typename: "MenuItem"; + category: MenuDetailsFragment_items_children_children_children_children_category | null; + collection: MenuDetailsFragment_items_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetailsFragment_items_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetailsFragment_items_children_children_children_children_children | null)[] | null; +} + +export interface MenuDetailsFragment_items_children_children_children { + __typename: "MenuItem"; + category: MenuDetailsFragment_items_children_children_children_category | null; + collection: MenuDetailsFragment_items_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetailsFragment_items_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetailsFragment_items_children_children_children_children | null)[] | null; +} + +export interface MenuDetailsFragment_items_children_children { + __typename: "MenuItem"; + category: MenuDetailsFragment_items_children_children_category | null; + collection: MenuDetailsFragment_items_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetailsFragment_items_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetailsFragment_items_children_children_children | null)[] | null; +} + +export interface MenuDetailsFragment_items_children { + __typename: "MenuItem"; + category: MenuDetailsFragment_items_children_category | null; + collection: MenuDetailsFragment_items_children_collection | null; + id: string; + level: number; + name: string; + page: MenuDetailsFragment_items_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetailsFragment_items_children_children | null)[] | null; +} + +export interface MenuDetailsFragment_items { + __typename: "MenuItem"; + category: MenuDetailsFragment_items_category | null; + collection: MenuDetailsFragment_items_collection | null; + id: string; + level: number; + name: string; + page: MenuDetailsFragment_items_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuDetailsFragment_items_children | null)[] | null; +} + +export interface MenuDetailsFragment { + __typename: "Menu"; + id: string; + items: (MenuDetailsFragment_items | null)[] | null; + name: string; +} diff --git a/src/navigation/types/MenuFragment.ts b/src/navigation/types/MenuFragment.ts new file mode 100644 index 000000000..9b6f6fe99 --- /dev/null +++ b/src/navigation/types/MenuFragment.ts @@ -0,0 +1,19 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: MenuFragment +// ==================================================== + +export interface MenuFragment_items { + __typename: "MenuItem"; + id: string; +} + +export interface MenuFragment { + __typename: "Menu"; + id: string; + name: string; + items: (MenuFragment_items | null)[] | null; +} diff --git a/src/navigation/types/MenuItemCreate.ts b/src/navigation/types/MenuItemCreate.ts new file mode 100644 index 000000000..b993b610c --- /dev/null +++ b/src/navigation/types/MenuItemCreate.ts @@ -0,0 +1,256 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { MenuItemCreateInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: MenuItemCreate +// ==================================================== + +export interface MenuItemCreate_menuItemCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_children { + __typename: "MenuItem"; + category: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_children_category | null; + collection: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children { + __typename: "MenuItem"; + category: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_category | null; + collection: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children_children | null)[] | null; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children { + __typename: "MenuItem"; + category: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_category | null; + collection: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children_children | null)[] | null; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children { + __typename: "MenuItem"; + category: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_category | null; + collection: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children_children | null)[] | null; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children { + __typename: "MenuItem"; + category: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_category | null; + collection: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children_children | null)[] | null; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items_children { + __typename: "MenuItem"; + category: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_category | null; + collection: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemCreate_menuItemCreate_menuItem_menu_items_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemCreate_menuItemCreate_menuItem_menu_items_children_children | null)[] | null; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu_items { + __typename: "MenuItem"; + category: MenuItemCreate_menuItemCreate_menuItem_menu_items_category | null; + collection: MenuItemCreate_menuItemCreate_menuItem_menu_items_collection | null; + id: string; + level: number; + name: string; + page: MenuItemCreate_menuItemCreate_menuItem_menu_items_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemCreate_menuItemCreate_menuItem_menu_items_children | null)[] | null; +} + +export interface MenuItemCreate_menuItemCreate_menuItem_menu { + __typename: "Menu"; + id: string; + items: (MenuItemCreate_menuItemCreate_menuItem_menu_items | null)[] | null; +} + +export interface MenuItemCreate_menuItemCreate_menuItem { + __typename: "MenuItem"; + menu: MenuItemCreate_menuItemCreate_menuItem_menu; +} + +export interface MenuItemCreate_menuItemCreate { + __typename: "MenuItemCreate"; + errors: MenuItemCreate_menuItemCreate_errors[] | null; + menuItem: MenuItemCreate_menuItemCreate_menuItem | null; +} + +export interface MenuItemCreate { + menuItemCreate: MenuItemCreate_menuItemCreate | null; +} + +export interface MenuItemCreateVariables { + input: MenuItemCreateInput; +} diff --git a/src/navigation/types/MenuItemFragment.ts b/src/navigation/types/MenuItemFragment.ts new file mode 100644 index 000000000..9d7a261e0 --- /dev/null +++ b/src/navigation/types/MenuItemFragment.ts @@ -0,0 +1,37 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: MenuItemFragment +// ==================================================== + +export interface MenuItemFragment_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemFragment_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemFragment_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemFragment { + __typename: "MenuItem"; + category: MenuItemFragment_category | null; + collection: MenuItemFragment_collection | null; + id: string; + level: number; + name: string; + page: MenuItemFragment_page | null; + sortOrder: number | null; + url: string | null; +} diff --git a/src/navigation/types/MenuItemNestedFragment.ts b/src/navigation/types/MenuItemNestedFragment.ts new file mode 100644 index 000000000..4559855b4 --- /dev/null +++ b/src/navigation/types/MenuItemNestedFragment.ts @@ -0,0 +1,223 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: MenuItemNestedFragment +// ==================================================== + +export interface MenuItemNestedFragment_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemNestedFragment_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemNestedFragment_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemNestedFragment_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemNestedFragment_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemNestedFragment_children_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemNestedFragment_children_children_children_children_children_children_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_children_children_children_children_children_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemNestedFragment_children_children_children_children_children_children_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemNestedFragment_children_children_children_children_children_children { + __typename: "MenuItem"; + category: MenuItemNestedFragment_children_children_children_children_children_children_category | null; + collection: MenuItemNestedFragment_children_children_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemNestedFragment_children_children_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; +} + +export interface MenuItemNestedFragment_children_children_children_children_children { + __typename: "MenuItem"; + category: MenuItemNestedFragment_children_children_children_children_children_category | null; + collection: MenuItemNestedFragment_children_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemNestedFragment_children_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemNestedFragment_children_children_children_children_children_children | null)[] | null; +} + +export interface MenuItemNestedFragment_children_children_children_children { + __typename: "MenuItem"; + category: MenuItemNestedFragment_children_children_children_children_category | null; + collection: MenuItemNestedFragment_children_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemNestedFragment_children_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemNestedFragment_children_children_children_children_children | null)[] | null; +} + +export interface MenuItemNestedFragment_children_children_children { + __typename: "MenuItem"; + category: MenuItemNestedFragment_children_children_children_category | null; + collection: MenuItemNestedFragment_children_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemNestedFragment_children_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemNestedFragment_children_children_children_children | null)[] | null; +} + +export interface MenuItemNestedFragment_children_children { + __typename: "MenuItem"; + category: MenuItemNestedFragment_children_children_category | null; + collection: MenuItemNestedFragment_children_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemNestedFragment_children_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemNestedFragment_children_children_children | null)[] | null; +} + +export interface MenuItemNestedFragment_children { + __typename: "MenuItem"; + category: MenuItemNestedFragment_children_category | null; + collection: MenuItemNestedFragment_children_collection | null; + id: string; + level: number; + name: string; + page: MenuItemNestedFragment_children_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemNestedFragment_children_children | null)[] | null; +} + +export interface MenuItemNestedFragment { + __typename: "MenuItem"; + category: MenuItemNestedFragment_category | null; + collection: MenuItemNestedFragment_collection | null; + id: string; + level: number; + name: string; + page: MenuItemNestedFragment_page | null; + sortOrder: number | null; + url: string | null; + children: (MenuItemNestedFragment_children | null)[] | null; +} diff --git a/src/navigation/types/MenuItemUpdate.ts b/src/navigation/types/MenuItemUpdate.ts new file mode 100644 index 000000000..d3c46bd07 --- /dev/null +++ b/src/navigation/types/MenuItemUpdate.ts @@ -0,0 +1,60 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { MenuItemInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: MenuItemUpdate +// ==================================================== + +export interface MenuItemUpdate_menuItemUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface MenuItemUpdate_menuItemUpdate_menuItem_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface MenuItemUpdate_menuItemUpdate_menuItem_collection { + __typename: "Collection"; + id: string; + name: string; +} + +export interface MenuItemUpdate_menuItemUpdate_menuItem_page { + __typename: "Page"; + id: string; + title: string; +} + +export interface MenuItemUpdate_menuItemUpdate_menuItem { + __typename: "MenuItem"; + category: MenuItemUpdate_menuItemUpdate_menuItem_category | null; + collection: MenuItemUpdate_menuItemUpdate_menuItem_collection | null; + id: string; + level: number; + name: string; + page: MenuItemUpdate_menuItemUpdate_menuItem_page | null; + sortOrder: number | null; + url: string | null; +} + +export interface MenuItemUpdate_menuItemUpdate { + __typename: "MenuItemUpdate"; + errors: MenuItemUpdate_menuItemUpdate_errors[] | null; + menuItem: MenuItemUpdate_menuItemUpdate_menuItem | null; +} + +export interface MenuItemUpdate { + menuItemUpdate: MenuItemUpdate_menuItemUpdate | null; +} + +export interface MenuItemUpdateVariables { + id: string; + input: MenuItemInput; +} diff --git a/src/navigation/types/MenuList.ts b/src/navigation/types/MenuList.ts new file mode 100644 index 000000000..8e95e1110 --- /dev/null +++ b/src/navigation/types/MenuList.ts @@ -0,0 +1,49 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: MenuList +// ==================================================== + +export interface MenuList_menus_edges_node_items { + __typename: "MenuItem"; + id: string; +} + +export interface MenuList_menus_edges_node { + __typename: "Menu"; + id: string; + name: string; + items: (MenuList_menus_edges_node_items | null)[] | null; +} + +export interface MenuList_menus_edges { + __typename: "MenuCountableEdge"; + node: MenuList_menus_edges_node; +} + +export interface MenuList_menus_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface MenuList_menus { + __typename: "MenuCountableConnection"; + edges: MenuList_menus_edges[]; + pageInfo: MenuList_menus_pageInfo; +} + +export interface MenuList { + menus: MenuList_menus | null; +} + +export interface MenuListVariables { + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/navigation/types/MenuUpdate.ts b/src/navigation/types/MenuUpdate.ts new file mode 100644 index 000000000..0ab7d0d56 --- /dev/null +++ b/src/navigation/types/MenuUpdate.ts @@ -0,0 +1,55 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { MenuItemMoveInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: MenuUpdate +// ==================================================== + +export interface MenuUpdate_menuUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface MenuUpdate_menuUpdate { + __typename: "MenuUpdate"; + errors: MenuUpdate_menuUpdate_errors[] | null; +} + +export interface MenuUpdate_menuItemMove_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface MenuUpdate_menuItemMove { + __typename: "MenuItemMove"; + errors: MenuUpdate_menuItemMove_errors[] | null; +} + +export interface MenuUpdate_menuItemBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface MenuUpdate_menuItemBulkDelete { + __typename: "MenuItemBulkDelete"; + errors: MenuUpdate_menuItemBulkDelete_errors[] | null; +} + +export interface MenuUpdate { + menuUpdate: MenuUpdate_menuUpdate | null; + menuItemMove: MenuUpdate_menuItemMove | null; + menuItemBulkDelete: MenuUpdate_menuItemBulkDelete | null; +} + +export interface MenuUpdateVariables { + id: string; + name: string; + moves: (MenuItemMoveInput | null)[]; + removeIds: (string | null)[]; +} diff --git a/src/navigation/urls.ts b/src/navigation/urls.ts new file mode 100644 index 000000000..2481f46d4 --- /dev/null +++ b/src/navigation/urls.ts @@ -0,0 +1,20 @@ +import { stringify as stringifyQs } from "qs"; +import * as urlJoin from "url-join"; +import { BulkAction, Dialog, Pagination, SingleAction } from "../types"; + +export const navigationSection = "/navigation"; + +export const menuListPath = navigationSection; +export type MenuListUrlDialog = "add" | "remove" | "remove-many"; +export type MenuListUrlQueryParams = BulkAction & + Dialog & + Pagination & + SingleAction; +export const menuListUrl = (params?: MenuListUrlQueryParams) => + menuListPath + "?" + stringifyQs(params); + +export const menuPath = (id: string) => urlJoin(navigationSection, id); +export type MenuUrlDialog = "add-item" | "edit-item" | "remove"; +export type MenuUrlQueryParams = Dialog & SingleAction; +export const menuUrl = (id: string, params?: MenuUrlQueryParams) => + menuPath(encodeURIComponent(id)) + "?" + stringifyQs(params); diff --git a/src/navigation/views/MenuDetails/index.tsx b/src/navigation/views/MenuDetails/index.tsx new file mode 100644 index 000000000..c5ad9d9d1 --- /dev/null +++ b/src/navigation/views/MenuDetails/index.tsx @@ -0,0 +1,397 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import { categoryUrl } from "../../../categories/urls"; +import { collectionUrl } from "../../../collections/urls"; +import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config"; +import SearchCategories from "../../../containers/SearchCategories"; +import SearchCollections from "../../../containers/SearchCollections"; +import SearchPages from "../../../containers/SearchPages"; +import i18n from "../../../i18n"; +import { getMutationState, maybe } from "../../../misc"; +import { pageUrl } from "../../../pages/urls"; +import MenuDetailsPage, { + MenuDetailsSubmitData +} from "../../components/MenuDetailsPage"; +import { findNode, getNode } from "../../components/MenuDetailsPage/tree"; +import MenuItemDialog, { + MenuItemDialogFormData, + MenuItemType +} from "../../components/MenuItemDialog"; +import { + getItemId, + getItemType, + unknownTypeError +} from "../../components/MenuItems"; +import { + MenuDeleteMutation, + MenuItemCreateMutation, + MenuItemUpdateMutation, + MenuUpdateMutation +} from "../../mutations"; +import { MenuDetailsQuery } from "../../queries"; +import { MenuItemCreateVariables } from "../../types/MenuItemCreate"; +import { MenuItemUpdateVariables } from "../../types/MenuItemUpdate"; +import { menuListUrl, menuUrl, MenuUrlQueryParams } from "../../urls"; +import { + handleDelete, + handleItemCreate, + handleItemUpdate, + handleUpdate +} from "./successHandlers"; +import { + getInitialDisplayValue, + getMenuItemInputData, + getMoves, + getRemoveIds +} from "./utils"; + +interface MenuDetailsProps { + id: string; + params: MenuUrlQueryParams; +} + +const MenuDetails: React.FC = ({ id, params }) => { + const navigate = useNavigator(); + const notify = useNotifier(); + + const closeModal = () => + navigate( + menuUrl(id, { + ...params, + action: undefined, + id: undefined + }), + true + ); + + const handleItemClick = (id: string, type: MenuItemType) => { + switch (type) { + case "category": + navigate(categoryUrl(id)); + break; + + case "collection": + navigate(collectionUrl(id)); + break; + + case "page": + navigate(pageUrl(id)); + break; + + case "link": + window.open(id, "blank"); + break; + + default: + throw unknownTypeError; + break; + } + }; + + return ( + + {pageSearch => ( + + {categorySearch => ( + + {collectionSearch => ( + + {({ data, loading, refetch }) => { + const handleQueryChange = (query: string) => { + categorySearch.search(query); + collectionSearch.search(query); + pageSearch.search(query); + }; + + const categories = maybe( + () => + categorySearch.result.data.categories.edges.map( + edge => edge.node + ), + [] + ); + + const collections = maybe( + () => + collectionSearch.result.data.collections.edges.map( + edge => edge.node + ), + [] + ); + + const pages = maybe( + () => + pageSearch.result.data.pages.edges.map( + edge => edge.node + ), + [] + ); + + return ( + + handleDelete(data, navigate, notify) + } + > + {(menuDelete, menuDeleteOpts) => ( + + handleUpdate(data, notify, refetch) + } + > + {(menuUpdate, menuUpdateOpts) => { + const deleteState = getMutationState( + menuDeleteOpts.called, + menuDeleteOpts.loading, + maybe( + () => menuDeleteOpts.data.menuDelete.errors + ) + ); + + const updateState = getMutationState( + menuUpdateOpts.called, + menuUpdateOpts.loading, + maybe( + () => menuUpdateOpts.data.menuUpdate.errors + ), + maybe( + () => menuUpdateOpts.data.menuItemMove.errors + ) + ); + + // This is a workaround to let know + // that it should clean operation stack if mutations + // were successful + const handleSubmit = async ( + data: MenuDetailsSubmitData + ) => { + try { + const result = await menuUpdate({ + variables: { + id, + moves: getMoves(data), + name: data.name, + removeIds: getRemoveIds(data) + } + }); + if (result) { + if ( + result.data.menuItemBulkDelete.errors + .length > 0 || + result.data.menuItemMove.errors.length > + 0 || + result.data.menuUpdate.errors.length > 0 + ) { + return false; + } + } + return true; + } catch { + return false; + } + }; + + return ( + <> + data.menu)} + onBack={() => navigate(menuListUrl())} + onDelete={() => + navigate( + menuUrl(id, { + action: "remove" + }) + ) + } + onItemAdd={() => + navigate( + menuUrl(id, { + action: "add-item" + }) + ) + } + onItemClick={handleItemClick} + onItemEdit={itemId => + navigate( + menuUrl(id, { + action: "edit-item", + id: itemId + }) + ) + } + onSubmit={handleSubmit} + saveButtonState={updateState} + /> + + menuDelete({ variables: { id } }) + } + variant="delete" + title={i18n.t("Remove menu")} + > + {{ name }}?", + { + name: maybe( + () => data.menu.name, + "..." + ) + } + ) + }} + /> + + + + handleItemCreate(data, notify, closeModal) + } + > + {(menuItemCreate, menuItemCreateOpts) => { + const handleSubmit = ( + data: MenuItemDialogFormData + ) => { + const variables: MenuItemCreateVariables = { + input: { + menu: id, + ...getMenuItemInputData(data) + } + }; + + menuItemCreate({ variables }); + }; + + const formTransitionState = getMutationState( + menuItemCreateOpts.called, + menuItemCreateOpts.loading, + maybe( + () => + menuItemCreateOpts.data + .menuItemCreate.errors + ) + ); + + return ( + + ); + }} + + + handleItemUpdate( + data, + id, + navigate, + notify + ) + } + > + {(menuItemUpdate, menuItemUpdateOpts) => { + const handleSubmit = ( + data: MenuItemDialogFormData + ) => { + const variables: MenuItemUpdateVariables = { + id: params.id, + input: getMenuItemInputData(data) + }; + + menuItemUpdate({ variables }); + }; + + const menuItem = maybe(() => + getNode( + data.menu.items, + findNode(data.menu.items, params.id) + ) + ); + + const formTransitionState = getMutationState( + menuItemUpdateOpts.called, + menuItemUpdateOpts.loading, + maybe( + () => + menuItemUpdateOpts.data + .menuItemUpdate.errors + ) + ); + + const initialFormData: MenuItemDialogFormData = { + id: maybe(() => getItemId(menuItem)), + name: maybe(() => menuItem.name, "..."), + type: maybe( + () => getItemType(menuItem), + "category" + ) + }; + + return ( + + ); + }} + + + ); + }} + + )} + + ); + }} + + )} + + )} + + )} + + ); +}; +MenuDetails.displayName = "MenuDetails"; + +export default MenuDetails; diff --git a/src/navigation/views/MenuDetails/successHandlers.ts b/src/navigation/views/MenuDetails/successHandlers.ts new file mode 100644 index 000000000..995211a6f --- /dev/null +++ b/src/navigation/views/MenuDetails/successHandlers.ts @@ -0,0 +1,78 @@ +import { UseNavigatorResult } from "../../../hooks/useNavigator"; +import { UseNotifierResult } from "../../../hooks/useNotifier"; +import i18n from "../../../i18n"; +import { MenuDelete } from "../../types/MenuDelete"; +import { MenuItemCreate } from "../../types/MenuItemCreate"; +import { MenuItemUpdate } from "../../types/MenuItemUpdate"; +import { MenuUpdate } from "../../types/MenuUpdate"; +import { menuListUrl, menuUrl } from "../../urls"; + +export function handleItemCreate( + data: MenuItemCreate, + notify: UseNotifierResult, + closeModal: () => void +) { + if (data.menuItemCreate.errors.length === 0) { + closeModal(); + notify({ + text: i18n.t("Created menu item", { + context: "notification" + }) + }); + } +} + +export function handleItemUpdate( + data: MenuItemUpdate, + id: string, + navigate: UseNavigatorResult, + notify: UseNotifierResult +) { + if (data.menuItemUpdate.errors.length === 0) { + notify({ + text: i18n.t("Updated menu item", { + context: "notification" + }) + }); + navigate( + menuUrl(id, { + action: undefined, + id: undefined + }) + ); + } +} + +export function handleDelete( + data: MenuDelete, + navigate: UseNavigatorResult, + notify: UseNotifierResult +) { + if (data.menuDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed menu", { + context: "notification" + }) + }); + navigate(menuListUrl(), true); + } +} + +export function handleUpdate( + data: MenuUpdate, + notify: UseNotifierResult, + refetch: () => void +) { + if ( + data.menuItemBulkDelete.errors.length === 0 && + data.menuItemMove.errors.length === 0 && + data.menuUpdate.errors.length === 0 + ) { + notify({ + text: i18n.t("Updated menu", { + context: "notification" + }) + }); + refetch(); + } +} diff --git a/src/navigation/views/MenuDetails/utils.ts b/src/navigation/views/MenuDetails/utils.ts new file mode 100644 index 000000000..188bd357b --- /dev/null +++ b/src/navigation/views/MenuDetails/utils.ts @@ -0,0 +1,68 @@ +import { MenuItemInput, MenuItemMoveInput } from "../../../types/globalTypes"; +import { MenuDetailsSubmitData } from "../../components/MenuDetailsPage"; +import { MenuItemDialogFormData } from "../../components/MenuItemDialog"; +import { unknownTypeError } from "../../components/MenuItems"; +import { MenuDetails_menu_items } from "../../types/MenuDetails"; + +export function getMenuItemInputData( + data: MenuItemDialogFormData +): MenuItemInput { + const variables: MenuItemInput = { + name: data.name + }; + switch (data.type) { + case "category": + variables.category = data.id; + break; + + case "collection": + variables.collection = data.id; + break; + + case "page": + variables.page = data.id; + break; + + case "link": + variables.url = data.id; + break; + + default: + throw unknownTypeError; + } + + return variables; +} + +export function getInitialDisplayValue(item: MenuDetails_menu_items): string { + if (!item) { + return "..."; + } + if (item.category) { + return item.category.name; + } else if (item.collection) { + return item.collection.name; + } else if (item.page) { + return item.page.title; + } else if (item.url) { + return item.url; + } else { + throw unknownTypeError; + } +} + +export function getMoves(data: MenuDetailsSubmitData): MenuItemMoveInput[] { + return data.operations + .filter(operation => operation.type === "move") + .map(move => ({ + itemId: move.id, + parentId: move.parentId, + sortOrder: move.sortOrder + })); +} + +export function getRemoveIds(data: MenuDetailsSubmitData): string[] { + return data.operations + .filter(operation => operation.type === "remove") + .map(operation => operation.id); +} diff --git a/src/navigation/views/MenuList.tsx b/src/navigation/views/MenuList.tsx new file mode 100644 index 000000000..7e9f0a561 --- /dev/null +++ b/src/navigation/views/MenuList.tsx @@ -0,0 +1,256 @@ +import Button from "@material-ui/core/Button"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { PAGINATE_BY } from "../../config"; +import { configurationMenuUrl } from "../../configuration"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import MenuCreateDialog from "../components/MenuCreateDialog"; +import MenuListPage from "../components/MenuListPage"; +import { + MenuBulkDeleteMutation, + MenuCreateMutation, + MenuDeleteMutation +} from "../mutations"; +import { MenuListQuery } from "../queries"; +import { MenuBulkDelete } from "../types/MenuBulkDelete"; +import { MenuCreate } from "../types/MenuCreate"; +import { MenuDelete } from "../types/MenuDelete"; +import { menuListUrl, MenuListUrlQueryParams, menuUrl } from "../urls"; + +interface MenuListProps { + params: MenuListUrlQueryParams; +} +const MenuList: React.FC = ({ params }) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const closeModal = () => + navigate( + menuListUrl({ + ...params, + action: undefined, + id: undefined, + ids: undefined + }), + true + ); + + const paginationState = createPaginationState(PAGINATE_BY, params); + + return ( + + {({ data, loading, refetch }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.menus.pageInfo), + paginationState, + params + ); + + const handleCreate = (data: MenuCreate) => { + if (data.menuCreate.errors.length === 0) { + notify({ + text: i18n.t("Created menu", { + context: "notification" + }) + }); + navigate(menuUrl(data.menuCreate.menu.id)); + } + }; + + const handleBulkDelete = (data: MenuBulkDelete) => { + if (data.menuBulkDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed menus", { + context: "notification" + }) + }); + closeModal(); + reset(); + refetch(); + } + }; + + const handleDelete = (data: MenuDelete) => { + if (data.menuDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed menu", { + context: "notification" + }) + }); + closeModal(); + refetch(); + } + }; + + return ( + + {(menuCreate, menuCreateOpts) => ( + + {(menuDelete, menuDeleteOpts) => ( + + {(menuBulkDelete, menuBulkDeleteOpts) => { + const createTransitionState = getMutationState( + menuCreateOpts.called, + menuCreateOpts.loading, + maybe(() => menuCreateOpts.data.menuCreate.errors) + ); + + const deleteTransitionState = getMutationState( + menuDeleteOpts.called, + menuDeleteOpts.loading, + maybe(() => menuDeleteOpts.data.menuDelete.errors) + ); + + const bulkDeleteTransitionState = getMutationState( + menuBulkDeleteOpts.called, + menuBulkDeleteOpts.loading, + maybe( + () => menuBulkDeleteOpts.data.menuBulkDelete.errors + ) + ); + + return ( + <> + + data.menus.edges.map(edge => edge.node) + )} + onAdd={() => + navigate( + menuListUrl({ + action: "add" + }) + ) + } + onBack={() => navigate(configurationMenuUrl)} + onDelete={id => + navigate( + menuListUrl({ + action: "remove", + id + }) + ) + } + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRowClick={id => () => navigate(menuUrl(id))} + pageInfo={pageInfo} + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + toolbar={ + + } + /> + + menuCreate({ + variables: { input: formData } + }) + } + /> + + menuDelete({ + variables: { + id: params.id + } + }) + } + variant="delete" + title={i18n.t("Remove menu")} + > + {{ name }}?", + { + name: maybe( + () => + data.menus.edges.find( + edge => edge.node.id === params.id + ).node.name, + "..." + ) + } + ) + }} + /> + + + menuBulkDelete({ + variables: { + ids: params.ids + } + }) + } + variant="delete" + title={i18n.t("Remove menus")} + > + {{ number }} menus?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + ); + }} + + )} + + )} + + ); + }} + + ); +}; +export default MenuList; diff --git a/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx b/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx new file mode 100644 index 000000000..81687a3e4 --- /dev/null +++ b/src/orders/components/OrderAddressEditDialog/OrderAddressEditDialog.tsx @@ -0,0 +1,90 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import * as React from "react"; + +import AddressEdit from "@saleor/components/AddressEdit"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import { AddressTypeInput } from "../../../customers/types"; +import i18n from "../../../i18n"; +import { UserError } from "../../../types"; + +const styles = createStyles({ + overflow: { + overflowY: "visible" + } +}); + +interface OrderAddressEditDialogProps extends WithStyles { + confirmButtonState: ConfirmButtonTransitionState; + address: AddressTypeInput; + open: boolean; + errors: UserError[]; + variant: "billing" | "shipping" | string; + countries?: Array<{ + code: string; + label: string; + }>; + onClose(); + onConfirm(data: AddressTypeInput); +} + +const OrderAddressEditDialog = withStyles(styles, { + name: "OrderAddressEditDialog" +})( + ({ + address, + classes, + confirmButtonState, + open, + errors, + variant, + countries, + onClose, + onConfirm + }: OrderAddressEditDialogProps) => ( + +
+ {({ change, data, errors, submit }) => ( + <> + + {variant === "billing" + ? i18n.t("Edit billing address", { context: "title" }) + : i18n.t("Edit shipping address", { context: "title" })} + + + + + + + + {i18n.t("Confirm", { context: "button" })} + + + + )} +
+
+ ) +); +OrderAddressEditDialog.displayName = "OrderAddressEditDialog"; +export default OrderAddressEditDialog; diff --git a/src/orders/components/OrderAddressEditDialog/index.ts b/src/orders/components/OrderAddressEditDialog/index.ts new file mode 100644 index 000000000..5ae253bf8 --- /dev/null +++ b/src/orders/components/OrderAddressEditDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderAddressEditDialog"; +export * from "./OrderAddressEditDialog"; diff --git a/src/orders/components/OrderBulkCancelDialog/OrderBulkCancelDialog.tsx b/src/orders/components/OrderBulkCancelDialog/OrderBulkCancelDialog.tsx new file mode 100644 index 000000000..f9029dd82 --- /dev/null +++ b/src/orders/components/OrderBulkCancelDialog/OrderBulkCancelDialog.tsx @@ -0,0 +1,51 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; +import i18n from "../../../i18n"; + +export interface OrderBulkCancelDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + numberOfOrders: string; + open: boolean; + onClose: () => void; + onConfirm: (restock: boolean) => void; +} + +const OrderBulkCancelDialog: React.StatelessComponent< + OrderBulkCancelDialogProps +> = ({ confirmButtonState, numberOfOrders, open, onClose, onConfirm }) => { + const [restock, setRestock] = React.useState(true); + + return ( + onConfirm(restock)} + > + {{ number }} orders?", + { + number: numberOfOrders + } + ) + }} + /> + setRestock(event.target.value)} + /> + + ); +}; +OrderBulkCancelDialog.displayName = "OrderBulkCancelDialog"; +export default OrderBulkCancelDialog; diff --git a/src/orders/components/OrderBulkCancelDialog/index.ts b/src/orders/components/OrderBulkCancelDialog/index.ts new file mode 100644 index 000000000..25c157c84 --- /dev/null +++ b/src/orders/components/OrderBulkCancelDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from './OrderBulkCancelDialog'; +export * from './OrderBulkCancelDialog'; \ No newline at end of file diff --git a/src/orders/components/OrderCancelDialog/OrderCancelDialog.tsx b/src/orders/components/OrderCancelDialog/OrderCancelDialog.tsx new file mode 100644 index 000000000..ee8b15758 --- /dev/null +++ b/src/orders/components/OrderCancelDialog/OrderCancelDialog.tsx @@ -0,0 +1,104 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; +import Form from "@saleor/components/Form"; +import i18n from "../../../i18n"; + +export interface FormData { + restock: boolean; +} + +const styles = (theme: Theme) => + createStyles({ + deleteButton: { + "&:hover": { + backgroundColor: theme.palette.error.main + }, + backgroundColor: theme.palette.error.main, + color: theme.palette.error.contrastText + } + }); + +interface OrderCancelDialogProps extends WithStyles { + confirmButtonState: ConfirmButtonTransitionState; + number: string; + open: boolean; + onClose?(); + onSubmit(data: FormData); +} + +const OrderCancelDialog = withStyles(styles, { name: "OrderCancelDialog" })( + ({ + classes, + confirmButtonState, + number: orderNumber, + open, + onSubmit, + onClose + }: OrderCancelDialogProps) => ( + +
+ {({ data, change }) => { + return ( + <> + + {i18n.t("Cancel order", { context: "title" })} + + + {{ orderNumber }}?", + { orderNumber } + ) + }} + /> + + + + + + {i18n.t("Cancel order", { context: "button" })} + + + + ); + }} +
+
+ ) +); +OrderCancelDialog.displayName = "OrderCancelDialog"; +export default OrderCancelDialog; diff --git a/src/orders/components/OrderCancelDialog/index.ts b/src/orders/components/OrderCancelDialog/index.ts new file mode 100644 index 000000000..fb5e9e4cc --- /dev/null +++ b/src/orders/components/OrderCancelDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderCancelDialog"; +export * from "./OrderCancelDialog"; diff --git a/src/orders/components/OrderCustomer/OrderCustomer.tsx b/src/orders/components/OrderCustomer/OrderCustomer.tsx new file mode 100644 index 000000000..92970c79c --- /dev/null +++ b/src/orders/components/OrderCustomer/OrderCustomer.tsx @@ -0,0 +1,286 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import ExternalLink from "@saleor/components/ExternalLink"; +import Form from "@saleor/components/Form"; +import Hr from "@saleor/components/Hr"; +import Link from "@saleor/components/Link"; +import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField"; +import Skeleton from "@saleor/components/Skeleton"; +import { SearchCustomers_customers_edges_node } from "../../../containers/SearchCustomers/types/SearchCustomers"; +import { customerUrl } from "../../../customers/urls"; +import i18n from "../../../i18n"; +import { createHref, maybe } from "../../../misc"; +import { OrderDetails_order } from "../../types/OrderDetails"; + +const styles = (theme: Theme) => + createStyles({ + sectionHeader: { + alignItems: "center", + display: "flex", + marginBottom: theme.spacing.unit * 3 + }, + sectionHeaderTitle: { + flex: 1, + fontWeight: 600 as 600, + lineHeight: 1, + textTransform: "uppercase" + }, + sectionHeaderToolbar: { + marginRight: -theme.spacing.unit * 2 + }, + userEmail: { + fontWeight: 600 as 600, + marginBottom: theme.spacing.unit + } + }); + +export interface OrderCustomerProps extends WithStyles { + order: OrderDetails_order; + users?: SearchCustomers_customers_edges_node[]; + loading?: boolean; + canEditAddresses: boolean; + canEditCustomer: boolean; + fetchUsers?: (query: string) => void; + onCustomerEdit?: (data: { user?: string; userEmail?: string }) => void; + onProfileView: () => void; + onBillingAddressEdit?: () => void; + onShippingAddressEdit?: () => void; +} + +const OrderCustomer = withStyles(styles, { name: "OrderCustomer" })( + ({ + classes, + canEditAddresses, + canEditCustomer, + fetchUsers, + loading, + order, + users, + onCustomerEdit, + onBillingAddressEdit, + onProfileView, + onShippingAddressEdit + }: OrderCustomerProps) => { + const [isInEditMode, setEditModeStatus] = React.useState(false); + const toggleEditMode = () => setEditModeStatus(!isInEditMode); + + const billingAddress = maybe(() => order.billingAddress); + const shippingAddress = maybe(() => order.shippingAddress); + const user = maybe(() => order.user); + return ( + + + {i18n.t("Edit")} + + ) + } + /> + + {user === undefined ? ( + + ) : isInEditMode && canEditCustomer ? ( +
+ {({ change, data }) => { + const handleChange = (event: React.ChangeEvent) => { + change(event); + onCustomerEdit({ + [event.target.value.value.includes("@") + ? "userEmail" + : "user"]: event.target.value.value + }); + toggleEditMode(); + }; + return ( + users, []).map(user => ({ + label: user.email, + value: user.id + }))} + fetchChoices={fetchUsers} + loading={loading} + placeholder={i18n.t("Search Customers")} + onChange={handleChange} + name="query" + value={data.query} + /> + ); + }} + + ) : user === null ? ( + {i18n.t("Anonymous user")} + ) : ( + <> + + {user.email} + +
+ + {i18n.t("View Profile")} + +
+ {/* TODO: Uncomment it after adding ability to filter + orders by customer */} + {/*
+ {i18n.t("View Orders")} +
*/} + + )} +
+
+ +
+ + {i18n.t("Contact information")} + +
+ + {maybe(() => order.userEmail) === undefined ? ( + + ) : order.userEmail === null ? ( + {i18n.t("Not set")} + ) : ( + order.userEmail)}`} + typographyProps={{ color: "primary" }} + > + {maybe(() => order.userEmail)} + + )} +
+
+ +
+ + {i18n.t("Shipping Address")} + + {canEditAddresses && ( +
+ +
+ )} +
+ {shippingAddress === undefined ? ( + + ) : shippingAddress === null ? ( + {i18n.t("Not set")} + ) : ( + <> + {shippingAddress.companyName && ( + {shippingAddress.companyName} + )} + + {shippingAddress.firstName} {shippingAddress.lastName} + + + {shippingAddress.streetAddress1} +
+ {shippingAddress.streetAddress2} +
+ + {shippingAddress.postalCode} {shippingAddress.city} + {shippingAddress.cityArea + ? ", " + shippingAddress.cityArea + : ""} + + + {shippingAddress.countryArea + ? shippingAddress.countryArea + + ", " + + shippingAddress.country.country + : shippingAddress.country.country} + + {shippingAddress.phone} + + )} +
+
+ +
+ + {i18n.t("Billing Address")} + + {canEditAddresses && ( +
+ +
+ )} +
+ {billingAddress === undefined ? ( + + ) : billingAddress === null ? ( + {i18n.t("Not set")} + ) : maybe(() => shippingAddress.id) === billingAddress.id ? ( + {i18n.t("Same as shipping address")} + ) : ( + <> + {billingAddress.companyName && ( + {billingAddress.companyName} + )} + + {billingAddress.firstName} {billingAddress.lastName} + + + {billingAddress.streetAddress1} +
+ {billingAddress.streetAddress2} +
+ + {billingAddress.postalCode} {billingAddress.city} + {billingAddress.cityArea ? ", " + billingAddress.cityArea : ""} + + + {billingAddress.countryArea + ? billingAddress.countryArea + + ", " + + billingAddress.country.country + : billingAddress.country.country} + + {billingAddress.phone} + + )} +
+
+ ); + } +); +OrderCustomer.displayName = "OrderCustomer"; +export default OrderCustomer; diff --git a/src/orders/components/OrderCustomer/index.ts b/src/orders/components/OrderCustomer/index.ts new file mode 100644 index 000000000..eb0326b8c --- /dev/null +++ b/src/orders/components/OrderCustomer/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderCustomer"; +export * from "./OrderCustomer"; diff --git a/src/orders/components/OrderCustomerEditDialog/OrderCustomerEditDialog.tsx b/src/orders/components/OrderCustomerEditDialog/OrderCustomerEditDialog.tsx new file mode 100644 index 000000000..2c7b1f271 --- /dev/null +++ b/src/orders/components/OrderCustomerEditDialog/OrderCustomerEditDialog.tsx @@ -0,0 +1,110 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import { SingleAutocompleteSelectField } from "@saleor/components/SingleAutocompleteSelectField"; +import i18n from "../../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + dialog: { + overflowY: "visible" + }, + root: { + overflowY: "visible", + width: theme.breakpoints.values.sm + }, + select: { + flex: 1, + marginRight: theme.spacing.unit * 2 + }, + textRight: { + textAlign: "right" + } + }); + +interface OrderCustomerEditDialogProps extends WithStyles { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + user?: { + label: string; + value: string; + }; + users?: Array<{ + id: string; + email: string; + }>; + loading?: boolean; + fetchUsers(value: string); + onChange(event: React.ChangeEvent); + onClose?(); + onConfirm?(event: React.FormEvent); +} + +const OrderCustomerEditDialog = withStyles(styles, { + name: "OrderCustomerEditDialog" +})( + ({ + classes, + confirmButtonState, + open, + loading, + user, + users, + fetchUsers, + onChange, + onClose, + onConfirm + }: OrderCustomerEditDialogProps) => { + const choices = + !loading && users + ? users.map(v => ({ + label: v.email, + value: v.id + })) + : []; + return ( + + {i18n.t("Edit customer details")} + + + + + + + {i18n.t("Confirm", { context: "button" })} + + + + ); + } +); +OrderCustomerEditDialog.displayName = "OrderCustomerEditDialog"; +export default OrderCustomerEditDialog; diff --git a/src/orders/components/OrderCustomerEditDialog/index.ts b/src/orders/components/OrderCustomerEditDialog/index.ts new file mode 100644 index 000000000..cb32cf9f6 --- /dev/null +++ b/src/orders/components/OrderCustomerEditDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderCustomerEditDialog"; +export * from "./OrderCustomerEditDialog"; diff --git a/src/orders/components/OrderCustomerNote/OrderCustomerNote.tsx b/src/orders/components/OrderCustomerNote/OrderCustomerNote.tsx new file mode 100644 index 000000000..331473340 --- /dev/null +++ b/src/orders/components/OrderCustomerNote/OrderCustomerNote.tsx @@ -0,0 +1,36 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; + +interface OrderCustomerNoteProps { + note: string; +} + +export const OrderCustomerNote: React.StatelessComponent< + OrderCustomerNoteProps +> = ({ note }) => ( + + + + {note === undefined ? ( + + ) : note === "" ? ( + + {i18n.t("No notes from customer")} + + ) : ( + {note} + )} + + +); +export default OrderCustomerNote; diff --git a/src/orders/components/OrderCustomerNote/index.ts b/src/orders/components/OrderCustomerNote/index.ts new file mode 100644 index 000000000..d9ccde57a --- /dev/null +++ b/src/orders/components/OrderCustomerNote/index.ts @@ -0,0 +1,2 @@ +export * from "./OrderCustomerNote"; +export { default } from "./OrderCustomerNote"; diff --git a/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx b/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx new file mode 100644 index 000000000..a1d3d7f3a --- /dev/null +++ b/src/orders/components/OrderDetailsPage/OrderDetailsPage.tsx @@ -0,0 +1,178 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardMenu from "@saleor/components/CardMenu"; +import { CardSpacer } from "@saleor/components/CardSpacer"; +import { Container } from "@saleor/components/Container"; +import { DateTime } from "@saleor/components/Date"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { OrderStatus } from "../../../types/globalTypes"; +import { OrderDetails_order } from "../../types/OrderDetails"; +import OrderCustomer from "../OrderCustomer"; +import OrderCustomerNote from "../OrderCustomerNote"; +import OrderFulfillment from "../OrderFulfillment"; +import OrderHistory, { FormData as HistoryFormData } from "../OrderHistory"; +import OrderPayment from "../OrderPayment/OrderPayment"; +import OrderUnfulfilledItems from "../OrderUnfulfilledItems/OrderUnfulfilledItems"; + +const styles = (theme: Theme) => + createStyles({ + date: { + marginBottom: theme.spacing.unit * 3, + marginTop: -theme.spacing.unit * 2 + }, + header: { + marginBottom: 0 + } + }); + +export interface OrderDetailsPageProps extends WithStyles { + order: OrderDetails_order; + shippingMethods?: Array<{ + id: string; + name: string; + }>; + countries?: Array<{ + code: string; + label: string; + }>; + onBack(); + onBillingAddressEdit(); + onFulfillmentCancel(id: string); + onFulfillmentTrackingNumberUpdate(id: string); + onOrderFulfill(); + onProductClick?(id: string); + onPaymentCapture(); + onPaymentPaid(); + onPaymentRefund(); + onPaymentVoid(); + onShippingAddressEdit(); + onOrderCancel(); + onNoteAdd(data: HistoryFormData); + onProfileView(); +} + +const OrderDetailsPage = withStyles(styles, { name: "OrderDetailsPage" })( + ({ + classes, + order, + onOrderCancel, + onBack, + onBillingAddressEdit, + onFulfillmentCancel, + onFulfillmentTrackingNumberUpdate, + onNoteAdd, + onOrderFulfill, + onPaymentCapture, + onPaymentPaid, + onPaymentRefund, + onPaymentVoid, + onShippingAddressEdit, + onProfileView + }: OrderDetailsPageProps) => { + const canCancel = maybe(() => order.status) !== OrderStatus.CANCELED; + const canEditAddresses = maybe(() => order.status) !== OrderStatus.CANCELED; + const canFulfill = maybe(() => order.status) !== OrderStatus.CANCELED; + const unfulfilled = maybe(() => order.lines, []).filter( + line => line.quantityFulfilled < line.quantity + ); + + return ( + + {i18n.t("Orders")} + order.number) ? "#" + order.number : undefined} + > + {canCancel && ( + + )} + +
+ {order && order.created ? ( + + + + ) : ( + + )} +
+ +
+ {unfulfilled.length > 0 && ( + + )} + {renderCollection( + maybe(() => order.fulfillments), + (fulfillment, fulfillmentIndex) => ( + fulfillment.id, "loading")}> + {!(unfulfilled.length === 0 && fulfillmentIndex === 0) && ( + + )} + order.number)} + onOrderFulfillmentCancel={() => + onFulfillmentCancel(fulfillment.id) + } + onTrackingCodeAdd={() => + onFulfillmentTrackingNumberUpdate(fulfillment.id) + } + /> + + ) + )} + + + order.events)} + onNoteAdd={onNoteAdd} + /> +
+
+ + + order.customerNote)} /> +
+
+
+ ); + } +); +OrderDetailsPage.displayName = "OrderDetailsPage"; +export default OrderDetailsPage; diff --git a/src/orders/components/OrderDetailsPage/index.ts b/src/orders/components/OrderDetailsPage/index.ts new file mode 100644 index 000000000..ef8727941 --- /dev/null +++ b/src/orders/components/OrderDetailsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderDetailsPage"; +export * from "./OrderDetailsPage"; diff --git a/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.tsx b/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.tsx new file mode 100644 index 000000000..61704b193 --- /dev/null +++ b/src/orders/components/OrderDraftCancelDialog/OrderDraftCancelDialog.tsx @@ -0,0 +1,43 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import i18n from "../../../i18n"; + +export interface OrderDraftCancelDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + onClose: () => void; + onConfirm: () => void; + orderNumber: string; +} + +const OrderDraftCancelDialog: React.StatelessComponent< + OrderDraftCancelDialogProps +> = ({ confirmButtonState, onClose, onConfirm, open, orderNumber }) => ( + + #{{ number }}?", + { + context: "modal", + number: orderNumber + } + ) + }} + /> + +); +OrderDraftCancelDialog.displayName = "OrderDraftCancelDialog"; +export default OrderDraftCancelDialog; diff --git a/src/orders/components/OrderDraftCancelDialog/index.ts b/src/orders/components/OrderDraftCancelDialog/index.ts new file mode 100644 index 000000000..0643ddf14 --- /dev/null +++ b/src/orders/components/OrderDraftCancelDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderDraftCancelDialog"; +export * from "./OrderDraftCancelDialog"; diff --git a/src/orders/components/OrderDraftDetails/OrderDraftDetails.tsx b/src/orders/components/OrderDraftDetails/OrderDraftDetails.tsx new file mode 100644 index 000000000..17f1e478c --- /dev/null +++ b/src/orders/components/OrderDraftDetails/OrderDraftDetails.tsx @@ -0,0 +1,62 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { OrderDetails_order } from "../../types/OrderDetails"; +import OrderDraftDetailsProducts, { + FormData as OrderDraftDetailsProductsFormData +} from "../OrderDraftDetailsProducts"; +import OrderDraftDetailsSummary from "../OrderDraftDetailsSummary/OrderDraftDetailsSummary"; + +interface OrderDraftDetailsProps { + order: OrderDetails_order; + onOrderLineAdd: () => void; + onOrderLineChange: ( + id: string, + data: OrderDraftDetailsProductsFormData + ) => void; + onOrderLineRemove: (id: string) => void; + onShippingMethodEdit: () => void; +} + +const OrderDraftDetails: React.StatelessComponent = ({ + order, + onOrderLineAdd, + onOrderLineChange, + onOrderLineRemove, + onShippingMethodEdit +}) => ( + + + {i18n.t("Add products", { + context: "button" + })} + + } + /> + order.lines)} + onOrderLineChange={onOrderLineChange} + onOrderLineRemove={onOrderLineRemove} + /> + {maybe(() => order.lines.length) !== 0 && ( + + + + )} + +); +OrderDraftDetails.displayName = "OrderDraftDetails"; +export default OrderDraftDetails; diff --git a/src/orders/components/OrderDraftDetails/index.ts b/src/orders/components/OrderDraftDetails/index.ts new file mode 100644 index 000000000..02dcb0a12 --- /dev/null +++ b/src/orders/components/OrderDraftDetails/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderDraftDetails"; +export * from "./OrderDraftDetails"; diff --git a/src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx b/src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx new file mode 100644 index 000000000..1ba483fe3 --- /dev/null +++ b/src/orders/components/OrderDraftDetailsProducts/OrderDraftDetailsProducts.tsx @@ -0,0 +1,168 @@ +import IconButton from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import { DebounceForm } from "@saleor/components/DebounceForm"; +import Form from "@saleor/components/Form"; +import Money from "@saleor/components/Money"; +import Skeleton from "@saleor/components/Skeleton"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { OrderDetails_order_lines } from "../../types/OrderDetails"; + +export interface FormData { + quantity: number; +} + +const styles = (theme: Theme) => + createStyles({ + iconCell: { + "&:last-child": { + paddingRight: 0 + }, + width: 48 + theme.spacing.unit / 2 + }, + quantityField: { + "& input": { + padding: "12px 12px 10px", + textAlign: "right" + }, + width: 60 + }, + textRight: { + textAlign: "right" + } + }); + +interface OrderDraftDetailsProductsProps extends WithStyles { + lines: OrderDetails_order_lines[]; + onOrderLineChange: (id: string, data: FormData) => void; + onOrderLineRemove: (id: string) => void; +} + +const OrderDraftDetailsProducts = withStyles(styles, { + name: "OrderDraftDetailsProducts" +})( + ({ + classes, + lines, + onOrderLineChange, + onOrderLineRemove + }: OrderDraftDetailsProductsProps) => ( + + {maybe(() => !!lines.length) && ( + + + + {i18n.t("Product", { context: "table header" })} + + + {i18n.t("Quantity", { context: "table header" })} + + + {i18n.t("Price", { context: "table header" })} + + + {i18n.t("Total", { context: "table header" })} + + + + + )} + + {maybe(() => lines.length) === 0 ? ( + + + {i18n.t("No Products added to Order")} + + + ) : ( + renderCollection(lines, line => ( + + line.thumbnail.url)} /> + + {maybe(() => line.productName && line.productSku) ? ( + <> + {line.productName} + {line.productSku} + + ) : ( + + )} + + + {maybe(() => line.quantity) ? ( +
onOrderLineChange(line.id, data)} + > + {({ change, data, hasChanged, submit }) => ( + + {debounce => ( + + )} + + )} + + ) : ( + + )} +
+ + {maybe(() => line.unitPrice.net) ? ( + + ) : ( + + )} + + + {maybe(() => line.unitPrice.net && line.quantity) ? ( + + ) : ( + + )} + + + onOrderLineRemove(line.id)}> + + + +
+ )) + )} +
+
+ ) +); +OrderDraftDetailsProducts.displayName = "OrderDraftDetailsProducts"; +export default OrderDraftDetailsProducts; diff --git a/src/orders/components/OrderDraftDetailsProducts/index.ts b/src/orders/components/OrderDraftDetailsProducts/index.ts new file mode 100644 index 000000000..75f2b953f --- /dev/null +++ b/src/orders/components/OrderDraftDetailsProducts/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderDraftDetailsProducts"; +export * from "./OrderDraftDetailsProducts"; diff --git a/src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx b/src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx new file mode 100644 index 000000000..70eebafd1 --- /dev/null +++ b/src/orders/components/OrderDraftDetailsSummary/OrderDraftDetailsSummary.tsx @@ -0,0 +1,123 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import Link from "@saleor/components/Link"; +import Money from "@saleor/components/Money"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { OrderDetails_order } from "../../types/OrderDetails"; + +const styles = (theme: Theme) => + createStyles({ + root: { + ...theme.typography.body2, + lineHeight: 1.9, + width: "100%" + }, + textRight: { + textAlign: "right" + } + }); + +interface OrderDraftDetailsSummaryProps extends WithStyles { + order: OrderDetails_order; + onShippingMethodEdit: () => void; +} + +const OrderDraftDetailsSummary = withStyles(styles, { + name: "OrderDraftDetailsSummary" +})( + ({ classes, order, onShippingMethodEdit }: OrderDraftDetailsSummaryProps) => ( + + + + {maybe(() => order.subtotal) ? ( + <> + + + + ) : ( + + )} + + + {order && + order.shippingMethod !== undefined && + order.shippingMethodName !== undefined ? ( + order.shippingMethod === null ? ( + order.availableShippingMethods && + order.availableShippingMethods.length > 0 ? ( + + ) : ( + + ) + ) : ( + <> + + + + ) + ) : ( + + )} + + + {maybe(() => order.total.tax) !== undefined ? ( + <> + + + + ) : ( + + )} + + + {maybe(() => order.total.gross) !== undefined ? ( + <> + + + + ) : ( + + )} + + +
{i18n.t("Subtotal")} + + + +
+ + {i18n.t("Add shipping carrier")} + + {i18n.t("No applicable shipping carriers")} + + {order.shippingMethodName} + + + {maybe(() => order.shippingPrice) ? ( + + ) : ( + "---" + )} + + +
{i18n.t("Taxes (VAT included)")} + + + +
{i18n.t("Total")} + + + +
+ ) +); +OrderDraftDetailsSummary.displayName = "OrderDraftDetailsSummary"; +export default OrderDraftDetailsSummary; diff --git a/src/orders/components/OrderDraftDetailsSummary/index.ts b/src/orders/components/OrderDraftDetailsSummary/index.ts new file mode 100644 index 000000000..78bbd58f0 --- /dev/null +++ b/src/orders/components/OrderDraftDetailsSummary/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderDraftDetailsSummary"; +export * from "./OrderDraftDetailsSummary"; diff --git a/src/orders/components/OrderDraftFinalizeDialog/OrderDraftFinalizeDialog.tsx b/src/orders/components/OrderDraftFinalizeDialog/OrderDraftFinalizeDialog.tsx new file mode 100644 index 000000000..4238d299e --- /dev/null +++ b/src/orders/components/OrderDraftFinalizeDialog/OrderDraftFinalizeDialog.tsx @@ -0,0 +1,92 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import i18n from "../../../i18n"; + +export type OrderDraftFinalizeWarning = + | "no-shipping" + | "no-billing" + | "no-user" + | "no-shipping-method" + | "unnecessary-shipping-method"; + +export interface OrderDraftFinalizeDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + orderNumber: string; + warnings: OrderDraftFinalizeWarning[]; + onClose: () => void; + onConfirm: () => void; +} + +const warningToText = (warning: OrderDraftFinalizeWarning) => { + switch (warning) { + case "no-shipping": + return i18n.t("No shipping address"); + case "no-billing": + return i18n.t("No billing address"); + case "no-user": + return i18n.t("No user information"); + case "no-shipping-method": + return i18n.t("Some products require shipping, but no method provided"); + case "unnecessary-shipping-method": + return i18n.t("Shipping method provided, but no product requires it"); + } +}; + +const OrderDraftFinalizeDialog: React.StatelessComponent< + OrderDraftFinalizeDialogProps +> = ({ + confirmButtonState, + open, + warnings, + onClose, + onConfirm, + orderNumber +}) => ( + 0 ? i18n.t("Finalize anyway") : i18n.t("Finalize") + } + confirmButtonState={confirmButtonState} + variant={warnings.length > 0 ? "delete" : "default"} + > + + {warnings.length > 0 && ( + <> +

+ {i18n.t( + "There are missing or incorrect informations about this order:" + )} +

+
    + {warnings.map(warning => ( +
  • {warningToText(warning)}
  • + ))} +
+ + )} + #{{ number }}?", + { + context: "modal", + number: orderNumber + } + ) + }} + /> +
+
+); +OrderDraftFinalizeDialog.displayName = "OrderDraftFinalize"; +export default OrderDraftFinalizeDialog; diff --git a/src/orders/components/OrderDraftFinalizeDialog/index.ts b/src/orders/components/OrderDraftFinalizeDialog/index.ts new file mode 100644 index 000000000..8867a8bca --- /dev/null +++ b/src/orders/components/OrderDraftFinalizeDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderDraftFinalizeDialog"; +export * from "./OrderDraftFinalizeDialog"; diff --git a/src/orders/components/OrderDraftList/OrderDraftList.tsx b/src/orders/components/OrderDraftList/OrderDraftList.tsx new file mode 100644 index 000000000..b0c25797d --- /dev/null +++ b/src/orders/components/OrderDraftList/OrderDraftList.tsx @@ -0,0 +1,189 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import Checkbox from "@saleor/components/Checkbox"; +import { DateTime } from "@saleor/components/Date"; +import Money from "@saleor/components/Money"; +import Skeleton from "@saleor/components/Skeleton"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { + maybe, + renderCollection, + transformOrderStatus, + transformPaymentStatus +} from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { OrderDraftList_draftOrders_edges_node } from "../../types/OrderDraftList"; + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colCustomer: { + width: 300 + }, + colDate: { + width: 300 + }, + colNumber: { + width: 120 + }, + colTotal: {} + }, + colCustomer: {}, + colDate: {}, + colNumber: {}, + colTotal: { + textAlign: "right" + }, + link: { + cursor: "pointer" + } + }); + +interface OrderDraftListProps + extends ListProps, + ListActions, + WithStyles { + orders: OrderDraftList_draftOrders_edges_node[]; +} + +export const OrderDraftList = withStyles(styles, { name: "OrderDraftList" })( + ({ + classes, + disabled, + orders, + pageInfo, + onPreviousPage, + onNextPage, + onRowClick, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: OrderDraftListProps) => { + const orderDraftList = orders + ? orders.map(order => ({ + ...order, + paymentStatus: transformPaymentStatus(order.paymentStatus), + status: transformOrderStatus(order.status) + })) + : undefined; + return ( + + + + {i18n.t("No. of Order", { context: "table header" })} + + + {i18n.t("Date", { context: "table header" })} + + + {i18n.t("Customer", { context: "table header" })} + + + {i18n.t("Total", { context: "table header" })} + + + + + + + + + {renderCollection( + orderDraftList, + order => { + const isSelected = order ? isChecked(order.id) : false; + + return ( + + + toggle(order.id)} + /> + + + {maybe(() => order.number) ? ( + "#" + order.number + ) : ( + + )} + + + {maybe(() => order.created) ? ( + + ) : ( + + )} + + + {maybe(() => order.billingAddress) ? ( + <> + {order.billingAddress.firstName} +   + {order.billingAddress.lastName} + + ) : maybe(() => order.userEmail) !== undefined ? ( + order.userEmail + ) : ( + + )} + + + {maybe(() => order.total.gross) ? ( + + ) : ( + + )} + + + ); + }, + () => ( + + {i18n.t("No orders found")} + + ) + )} + +
+ ); + } +); +OrderDraftList.displayName = "OrderDraftList"; +export default OrderDraftList; diff --git a/src/orders/components/OrderDraftList/index.ts b/src/orders/components/OrderDraftList/index.ts new file mode 100644 index 000000000..96f0cae70 --- /dev/null +++ b/src/orders/components/OrderDraftList/index.ts @@ -0,0 +1,2 @@ +export { default } from './OrderDraftList'; +export * from './OrderDraftList'; \ No newline at end of file diff --git a/src/orders/components/OrderDraftListPage/OrderDraftListPage.tsx b/src/orders/components/OrderDraftListPage/OrderDraftListPage.tsx new file mode 100644 index 000000000..9e9d2235c --- /dev/null +++ b/src/orders/components/OrderDraftListPage/OrderDraftListPage.tsx @@ -0,0 +1,39 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { ListActions, PageListProps } from "../../../types"; +import { OrderDraftList_draftOrders_edges_node } from "../../types/OrderDraftList"; +import OrderDraftList from "../OrderDraftList"; + +export interface OrderDraftListPageProps extends PageListProps, ListActions { + orders: OrderDraftList_draftOrders_edges_node[]; +} + +const OrderDraftListPage: React.StatelessComponent = ({ + disabled, + onAdd, + ...listProps +}) => ( + + + + + + + + +); +OrderDraftListPage.displayName = "OrderDraftListPage"; +export default OrderDraftListPage; diff --git a/src/orders/components/OrderDraftListPage/index.ts b/src/orders/components/OrderDraftListPage/index.ts new file mode 100644 index 000000000..5814e7cb1 --- /dev/null +++ b/src/orders/components/OrderDraftListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from './OrderDraftListPage'; +export * from './OrderDraftListPage'; \ No newline at end of file diff --git a/src/orders/components/OrderDraftPage/OrderDraftPage.tsx b/src/orders/components/OrderDraftPage/OrderDraftPage.tsx new file mode 100644 index 000000000..074d3a65d --- /dev/null +++ b/src/orders/components/OrderDraftPage/OrderDraftPage.tsx @@ -0,0 +1,155 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardMenu from "@saleor/components/CardMenu"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import { Container } from "@saleor/components/Container"; +import { DateTime } from "@saleor/components/Date"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import Skeleton from "@saleor/components/Skeleton"; +import { SearchCustomers_customers_edges_node } from "../../../containers/SearchCustomers/types/SearchCustomers"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { DraftOrderInput } from "../../../types/globalTypes"; +import { OrderDetails_order } from "../../types/OrderDetails"; +import OrderCustomer from "../OrderCustomer"; +import OrderDraftDetails from "../OrderDraftDetails/OrderDraftDetails"; +import { FormData as OrderDraftDetailsProductsFormData } from "../OrderDraftDetailsProducts"; +import OrderHistory, { FormData as HistoryFormData } from "../OrderHistory"; + +const styles = (theme: Theme) => + createStyles({ + date: { + marginBottom: theme.spacing.unit * 3, + marginLeft: theme.spacing.unit * 7 + }, + header: { + marginBottom: 0 + } + }); + +export interface OrderDraftPageProps extends WithStyles { + disabled: boolean; + order: OrderDetails_order; + users: SearchCustomers_customers_edges_node[]; + usersLoading: boolean; + countries: Array<{ + code: string; + label: string; + }>; + saveButtonBarState: ConfirmButtonTransitionState; + fetchUsers: (query: string) => void; + onBack: () => void; + onBillingAddressEdit: () => void; + onCustomerEdit: (data: DraftOrderInput) => void; + onDraftFinalize: () => void; + onDraftRemove: () => void; + onNoteAdd: (data: HistoryFormData) => void; + onOrderLineAdd: () => void; + onOrderLineChange: ( + id: string, + data: OrderDraftDetailsProductsFormData + ) => void; + onOrderLineRemove: (id: string) => void; + onProductClick: (id: string) => void; + onShippingAddressEdit: () => void; + onShippingMethodEdit: () => void; + onProfileView: () => void; +} + +const OrderDraftPage = withStyles(styles, { name: "OrderDraftPage" })( + ({ + classes, + disabled, + fetchUsers, + saveButtonBarState, + onBack, + onBillingAddressEdit, + onCustomerEdit, + onDraftFinalize, + onDraftRemove, + onNoteAdd, + onOrderLineAdd, + onOrderLineChange, + onOrderLineRemove, + onShippingAddressEdit, + onShippingMethodEdit, + onProfileView, + order, + users, + usersLoading + }: OrderDraftPageProps) => ( + + {i18n.t("Orders")} + order.number) ? "#" + order.number : undefined} + > + + +
+ {order && order.created ? ( + + + + ) : ( + + )} +
+ +
+ + order.events)} + onNoteAdd={onNoteAdd} + /> +
+
+ +
+
+ order.canFinalize)} + onCancel={onBack} + onSave={onDraftFinalize} + labels={{ save: i18n.t("Finalize", { context: "button" }) }} + /> +
+ ) +); +OrderDraftPage.displayName = "OrderDraftPage"; +export default OrderDraftPage; diff --git a/src/orders/components/OrderDraftPage/index.ts b/src/orders/components/OrderDraftPage/index.ts new file mode 100644 index 000000000..4d4fa008b --- /dev/null +++ b/src/orders/components/OrderDraftPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderDraftPage"; +export * from "./OrderDraftPage"; diff --git a/src/orders/components/OrderFulfillment/OrderFulfillment.tsx b/src/orders/components/OrderFulfillment/OrderFulfillment.tsx new file mode 100644 index 000000000..2672675e2 --- /dev/null +++ b/src/orders/components/OrderFulfillment/OrderFulfillment.tsx @@ -0,0 +1,198 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardActions from "@material-ui/core/CardActions"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardMenu from "@saleor/components/CardMenu"; +import CardTitle from "@saleor/components/CardTitle"; +import Money from "@saleor/components/Money"; +import Skeleton from "@saleor/components/Skeleton"; +import StatusLabel from "@saleor/components/StatusLabel"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { FulfillmentStatus } from "../../../types/globalTypes"; +import { OrderDetails_order_fulfillments } from "../../types/OrderDetails"; + +const styles = (theme: Theme) => + createStyles({ + clickableRow: { + cursor: "pointer" + }, + orderNumber: { + display: "inline", + marginLeft: theme.spacing.unit + }, + statusBar: { + paddingTop: 0 + }, + textCenter: { + textAlign: "center" + }, + textRight: { + textAlign: "right" + }, + wideCell: { + width: "50%" + } + }); + +interface OrderFulfillmentProps extends WithStyles { + fulfillment: OrderDetails_order_fulfillments; + orderNumber: string; + onOrderFulfillmentCancel: () => void; + onTrackingCodeAdd: () => void; +} + +const OrderFulfillment = withStyles(styles, { name: "OrderFulfillment" })( + ({ + classes, + fulfillment, + orderNumber, + onOrderFulfillmentCancel, + onTrackingCodeAdd + }: OrderFulfillmentProps) => { + const lines = maybe(() => fulfillment.lines); + const status = maybe(() => fulfillment.status); + return ( + + + {status === FulfillmentStatus.FULFILLED + ? i18n.t("Fulfilled ({{ quantity }})", { + quantity: lines + .map(line => line.quantity) + .reduce((prev, curr) => prev + curr, 0) + }) + : i18n.t("Cancelled ({{ quantity }})", { + quantity: lines + .map(line => line.quantity) + .reduce((prev, curr) => prev + curr, 0) + })} + + {maybe( + () => `#${orderNumber}-${fulfillment.fulfillmentOrder}` + )} + + + } + status={ + status === FulfillmentStatus.FULFILLED ? "success" : "error" + } + /> + ) : ( + + ) + } + toolbar={ + maybe(() => fulfillment.status) === FulfillmentStatus.FULFILLED && ( + + ) + } + /> + + + + + {i18n.t("Product")} + + + {i18n.t("Quantity")} + + + {i18n.t("Price")} + + + {i18n.t("Total")} + + + + + {renderCollection(lines, line => ( + line.id)} + > + line.orderLine.thumbnail.url)} + /> + + {maybe(() => line.orderLine.productName) || } + + + {maybe(() => line.quantity) || } + + + {maybe(() => line.orderLine.unitPrice.gross) ? ( + + ) : ( + + )} + + + {maybe( + () => line.quantity * line.orderLine.unitPrice.gross.amount + ) ? ( + + ) : ( + + )} + + + ))} + {maybe(() => fulfillment.trackingNumber) && ( + + + {i18n.t("Tracking Number: {{ trackingNumber }}", { + trackingNumber: fulfillment.trackingNumber + })} + + + )} + +
+ {status === FulfillmentStatus.FULFILLED && !fulfillment.trackingNumber && ( + + + + )} +
+ ); + } +); +OrderFulfillment.displayName = "OrderFulfillment"; +export default OrderFulfillment; diff --git a/src/orders/components/OrderFulfillment/index.ts b/src/orders/components/OrderFulfillment/index.ts new file mode 100644 index 000000000..ca836178f --- /dev/null +++ b/src/orders/components/OrderFulfillment/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderFulfillment"; +export * from "./OrderFulfillment"; diff --git a/src/orders/components/OrderFulfillmentCancelDialog/OrderFulfillmentCancelDialog.tsx b/src/orders/components/OrderFulfillmentCancelDialog/OrderFulfillmentCancelDialog.tsx new file mode 100644 index 000000000..992db9000 --- /dev/null +++ b/src/orders/components/OrderFulfillmentCancelDialog/OrderFulfillmentCancelDialog.tsx @@ -0,0 +1,92 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; +import Form from "@saleor/components/Form"; +import i18n from "../../../i18n"; + +export interface FormData { + restock: boolean; +} + +const styles = (theme: Theme) => + createStyles({ + deleteButton: { + "&:hover": { + backgroundColor: theme.palette.error.main + }, + backgroundColor: theme.palette.error.main, + color: theme.palette.error.contrastText + } + }); + +interface OrderFulfillmentCancelDialogProps extends WithStyles { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + onClose(); + onConfirm(data: FormData); +} + +const OrderFulfillmentCancelDialog = withStyles(styles, { + name: "OrderFulfillmentCancelDialog" +})( + ({ + confirmButtonState, + classes, + open, + onConfirm, + onClose + }: OrderFulfillmentCancelDialogProps) => ( + +
+ {({ change, data, submit }) => ( + <> + + {i18n.t("Cancel fulfillment", { context: "title" })} + + + + {i18n.t("Are you sure you want to cancel this fulfillment?")} + + + + + + + {i18n.t("Cancel fulfillment", { context: "button" })} + + + + )} +
+
+ ) +); +OrderFulfillmentCancelDialog.displayName = "OrderFulfillmentCancelDialog"; +export default OrderFulfillmentCancelDialog; diff --git a/src/orders/components/OrderFulfillmentCancelDialog/index.ts b/src/orders/components/OrderFulfillmentCancelDialog/index.ts new file mode 100644 index 000000000..5243bf630 --- /dev/null +++ b/src/orders/components/OrderFulfillmentCancelDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderFulfillmentCancelDialog"; +export * from "./OrderFulfillmentCancelDialog"; diff --git a/src/orders/components/OrderFulfillmentDialog/OrderFulfillmentDialog.tsx b/src/orders/components/OrderFulfillmentDialog/OrderFulfillmentDialog.tsx new file mode 100644 index 000000000..23370da00 --- /dev/null +++ b/src/orders/components/OrderFulfillmentDialog/OrderFulfillmentDialog.tsx @@ -0,0 +1,185 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import { FormSpacer } from "@saleor/components/FormSpacer"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { OrderDetails_order_lines } from "../../types/OrderDetails"; + +export interface FormData { + lines: number[]; + trackingNumber: string; +} + +const styles = (theme: Theme) => + createStyles({ + avatarCell: { + paddingLeft: theme.spacing.unit * 2, + paddingRight: theme.spacing.unit * 3, + width: theme.spacing.unit * 5 + }, + quantityInput: { + width: "4rem" + }, + quantityInputContainer: { + paddingRight: theme.spacing.unit, + textAlign: "right" as "right" + }, + remainingQuantity: { + paddingBottom: 4 + }, + textRight: { + textAlign: "right" as "right" + } + }); + +export interface OrderFulfillmentDialogProps extends WithStyles { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + lines: OrderDetails_order_lines[]; + onClose(); + onSubmit(data: FormData); +} + +const OrderFulfillmentDialog = withStyles(styles, { + name: "OrderFulfillmentDialog" +})( + ({ + classes, + confirmButtonState, + open, + lines, + onClose, + onSubmit + }: OrderFulfillmentDialogProps) => ( + +
+ lines.map( + product => product.quantity - product.quantityFulfilled + ), + [] + ), + trackingNumber: "" + }} + onSubmit={onSubmit} + > + {({ data, change }) => { + const handleQuantityChange = ( + productIndex: number, + event: React.ChangeEvent + ) => { + const newData = data.lines; + newData[productIndex] = event.target.value; + change({ + target: { + name: "lines", + value: newData + } + } as any); + }; + return ( + <> + {i18n.t("Fulfill products")} + + + + + {i18n.t("Product name")} + {i18n.t("SKU")} + + {i18n.t("Quantity")} + + + + + {lines.map((product, productIndex) => { + const remainingQuantity = + product.quantity - product.quantityFulfilled; + return ( + + product.thumbnail.url)} + /> + {product.productName} + {product.productSku} + + + handleQuantityChange(productIndex, event) + } + error={remainingQuantity < data.lines[productIndex]} + /> + + +
+ / {remainingQuantity} +
+
+
+ ); + })} +
+
+ + + + + + + + {i18n.t("Confirm", { context: "button" })} + + + + ); + }} + +
+ ) +); +OrderFulfillmentDialog.displayName = "OrderFulfillmentDialog"; +export default OrderFulfillmentDialog; diff --git a/src/orders/components/OrderFulfillmentDialog/index.ts b/src/orders/components/OrderFulfillmentDialog/index.ts new file mode 100644 index 000000000..5a977a6c0 --- /dev/null +++ b/src/orders/components/OrderFulfillmentDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderFulfillmentDialog"; +export * from "./OrderFulfillmentDialog"; diff --git a/src/orders/components/OrderFulfillmentTrackingDialog/OrderFulfillmentTrackingDialog.tsx b/src/orders/components/OrderFulfillmentTrackingDialog/OrderFulfillmentTrackingDialog.tsx new file mode 100644 index 000000000..0f6c9e9c3 --- /dev/null +++ b/src/orders/components/OrderFulfillmentTrackingDialog/OrderFulfillmentTrackingDialog.tsx @@ -0,0 +1,65 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import i18n from "../../../i18n"; + +export interface FormData { + trackingNumber: string; +} + +interface OrderFulfillmentTrackingDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + trackingNumber: string; + onClose(); + onConfirm(data: FormData); +} + +const OrderFulfillmentTrackingDialog: React.StatelessComponent< + OrderFulfillmentTrackingDialogProps +> = ({ confirmButtonState, open, trackingNumber, onConfirm, onClose }) => ( + +
+ {({ change, data, submit }) => ( + <> + + {i18n.t("Add tracking code", { context: "title" })} + + + + + + + + {i18n.t("Confirm", { context: "button" })} + + + + )} +
+
+); +OrderFulfillmentTrackingDialog.displayName = "OrderFulfillmentTrackingDialog"; +export default OrderFulfillmentTrackingDialog; diff --git a/src/orders/components/OrderFulfillmentTrackingDialog/index.ts b/src/orders/components/OrderFulfillmentTrackingDialog/index.ts new file mode 100644 index 000000000..f5b81a505 --- /dev/null +++ b/src/orders/components/OrderFulfillmentTrackingDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderFulfillmentTrackingDialog"; +export * from "./OrderFulfillmentTrackingDialog"; diff --git a/src/orders/components/OrderHistory/OrderHistory.tsx b/src/orders/components/OrderHistory/OrderHistory.tsx new file mode 100644 index 000000000..93dda34e4 --- /dev/null +++ b/src/orders/components/OrderHistory/OrderHistory.tsx @@ -0,0 +1,208 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import Form from "@saleor/components/Form"; +import Hr from "@saleor/components/Hr"; +import Skeleton from "@saleor/components/Skeleton"; +import { + Timeline, + TimelineAddNote, + TimelineEvent, + TimelineNote +} from "@saleor/components/Timeline"; +import i18n from "../../../i18n"; +import { + OrderEventsEmailsEnum, + OrderEventsEnum +} from "../../../types/globalTypes"; +import { OrderDetails_order_events } from "../../types/OrderDetails"; + +export interface FormData { + message: string; +} + +const getEventMessage = (event: OrderDetails_order_events) => { + switch (event.type) { + case OrderEventsEnum.CANCELED: + return i18n.t("Order was cancelled", { + context: "order history message" + }); + case OrderEventsEnum.DRAFT_ADDED_PRODUCTS: + return i18n.t("Products were added to draft order", { + context: "order history message" + }); + case OrderEventsEnum.DRAFT_CREATED: + return i18n.t("Draft order was created", { + context: "order history message" + }); + case OrderEventsEnum.DRAFT_REMOVED_PRODUCTS: + return i18n.t("Products were removed from draft order", { + context: "order history message" + }); + case OrderEventsEnum.EMAIL_SENT: + switch (event.emailType) { + case OrderEventsEmailsEnum.DIGITAL_LINKS: + return i18n.t("Links to the order's digital goods were sent", { + context: "order history message" + }); + case OrderEventsEmailsEnum.FULFILLMENT_CONFIRMATION: + return i18n.t("Fulfillment confirmation was sent to customer", { + context: "order history message" + }); + case OrderEventsEmailsEnum.ORDER_CONFIRMATION: + return i18n.t("Order confirmation was sent to customer", { + context: "order history message" + }); + case OrderEventsEmailsEnum.PAYMENT_CONFIRMATION: + return i18n.t("Payment confirmation was sent to customer", { + context: "order history message" + }); + case OrderEventsEmailsEnum.SHIPPING_CONFIRMATION: + return i18n.t("Shipping details was sent to customer", { + context: "order history message" + }); + case OrderEventsEmailsEnum.TRACKING_UPDATED: + return i18n.t("Shipping tracking number was sent to customer", { + context: "order history message" + }); + } + case OrderEventsEnum.FULFILLMENT_CANCELED: + return i18n.t("Fulfillment was cancelled", { + context: "order history message" + }); + case OrderEventsEnum.FULFILLMENT_FULFILLED_ITEMS: + return i18n.t("Fulfilled {{ quantity }} items", { + context: "order history message", + quantity: event.quantity + }); + case OrderEventsEnum.FULFILLMENT_RESTOCKED_ITEMS: + return i18n.t("Restocked {{ quantity }} items", { + context: "order history message", + quantity: event.quantity + }); + case OrderEventsEnum.NOTE_ADDED: + return i18n.t("Note was added to the order", { + context: "order history message" + }); + case OrderEventsEnum.ORDER_FULLY_PAID: + return i18n.t("Order was fully paid", { + context: "order history message" + }); + case OrderEventsEnum.ORDER_MARKED_AS_PAID: + return i18n.t("Marked order as paid", { + context: "order history message" + }); + case OrderEventsEnum.OTHER: + return event.message; + case OrderEventsEnum.OVERSOLD_ITEMS: + return i18n.t("Oversold {{ quantity }} items", { + context: "order history message", + quantity: event.quantity + }); + case OrderEventsEnum.PAYMENT_CAPTURED: + return i18n.t("Payment was captured", { + context: "order history message" + }); + case OrderEventsEnum.PAYMENT_FAILED: + return i18n.t("Payment failed", { + context: "order history message" + }); + case OrderEventsEnum.PAYMENT_REFUNDED: + return i18n.t("Payment was refunded", { + context: "order history message" + }); + case OrderEventsEnum.PAYMENT_VOIDED: + return i18n.t("Payment was voided", { + context: "order history message" + }); + case OrderEventsEnum.PLACED: + return i18n.t("Order was placed", { + context: "order history message" + }); + case OrderEventsEnum.PLACED_FROM_DRAFT: + return i18n.t("Order was created from draft", { + context: "order history message" + }); + case OrderEventsEnum.TRACKING_UPDATED: + return i18n.t("Updated fulfillment group's tracking number", { + context: "order history message" + }); + case OrderEventsEnum.UPDATED_ADDRESS: + return i18n.t("Order address was updated", { + context: "order history message" + }); + } +}; + +const styles = (theme: Theme) => + createStyles({ + header: { + fontWeight: 500, + marginBottom: theme.spacing.unit + }, + root: { marginTop: theme.spacing.unit * 4 }, + user: { + marginBottom: theme.spacing.unit + } + }); + +interface OrderHistoryProps extends WithStyles { + history: OrderDetails_order_events[]; + onNoteAdd: (data: FormData) => void; +} + +const OrderHistory = withStyles(styles, { name: "OrderHistory" })( + ({ classes, history, onNoteAdd }: OrderHistoryProps) => ( +
+ + {i18n.t("Order History")} + +
+ {history ? ( + +
+ {({ change, data, submit }) => ( + + )} + + {history + .slice() + .reverse() + .map(event => { + if (event.type === OrderEventsEnum.NOTE_ADDED) { + return ( + + ); + } + return ( + + ); + })} +
+ ) : ( + + )} +
+ ) +); +OrderHistory.displayName = "OrderHistory"; +export default OrderHistory; diff --git a/src/orders/components/OrderHistory/index.ts b/src/orders/components/OrderHistory/index.ts new file mode 100644 index 000000000..271408ddf --- /dev/null +++ b/src/orders/components/OrderHistory/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderHistory"; +export * from "./OrderHistory"; diff --git a/src/orders/components/OrderList/OrderList.tsx b/src/orders/components/OrderList/OrderList.tsx new file mode 100644 index 000000000..67b0e01b5 --- /dev/null +++ b/src/orders/components/OrderList/OrderList.tsx @@ -0,0 +1,224 @@ +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import Checkbox from "@saleor/components/Checkbox"; +import { DateTime } from "@saleor/components/Date"; +import Money from "@saleor/components/Money"; +import Skeleton from "@saleor/components/Skeleton"; +import StatusLabel from "@saleor/components/StatusLabel"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { + maybe, + renderCollection, + transformOrderStatus, + transformPaymentStatus +} from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { OrderList_orders_edges_node } from "../../types/OrderList"; + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colCustomer: { + width: 220 + }, + colDate: {}, + colFulfillment: { + width: 230 + }, + colNumber: { + width: 120 + }, + colPayment: { + width: 220 + }, + colTotal: {} + }, + colCustomer: {}, + colDate: {}, + colFulfillment: {}, + colNumber: {}, + colPayment: {}, + colTotal: { + textAlign: "right" + }, + link: { + cursor: "pointer" + } + }); + +interface OrderListProps + extends ListProps, + ListActions, + WithStyles { + orders: OrderList_orders_edges_node[]; +} + +export const OrderList = withStyles(styles, { name: "OrderList" })( + ({ + classes, + disabled, + orders, + pageInfo, + onPreviousPage, + onNextPage, + onRowClick, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: OrderListProps) => { + const orderList = orders + ? orders.map(order => ({ + ...order, + paymentStatus: transformPaymentStatus(order.paymentStatus), + status: transformOrderStatus(order.status) + })) + : undefined; + return ( + + + + {i18n.t("No. of Order", { context: "table header" })} + + + {i18n.t("Date", { context: "table header" })} + + + {i18n.t("Customer", { context: "table header" })} + + + {i18n.t("Payment", { context: "table header" })} + + + {i18n.t("Fulfillment status", { context: "table header" })} + + + {i18n.t("Total", { context: "table header" })} + + + + + + + + + {renderCollection( + orderList, + order => { + const isSelected = order ? isChecked(order.id) : false; + + return ( + + + toggle(order.id)} + /> + + + {maybe(() => order.number) ? ( + "#" + order.number + ) : ( + + )} + + + {maybe(() => order.created) ? ( + + ) : ( + + )} + + + {maybe(() => order.billingAddress) ? ( + <> + {order.billingAddress.firstName} +   + {order.billingAddress.lastName} + + ) : maybe(() => order.userEmail) !== undefined ? ( + order.userEmail + ) : ( + + )} + + + {maybe(() => order.paymentStatus.status) !== undefined ? ( + order.paymentStatus.status === null ? null : ( + + ) + ) : ( + + )} + + + {maybe(() => order.status) ? ( + + ) : ( + + )} + + + {maybe(() => order.total.gross) ? ( + + ) : ( + + )} + + + ); + }, + () => ( + + {i18n.t("No orders found")} + + ) + )} + +
+ ); + } +); +OrderList.displayName = "OrderList"; +export default OrderList; diff --git a/src/orders/components/OrderList/index.ts b/src/orders/components/OrderList/index.ts new file mode 100644 index 000000000..0dea1ff58 --- /dev/null +++ b/src/orders/components/OrderList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderList"; +export * from "./OrderList"; diff --git a/src/orders/components/OrderListFilter/OrderListFilter.tsx b/src/orders/components/OrderListFilter/OrderListFilter.tsx new file mode 100644 index 000000000..6fe3b547d --- /dev/null +++ b/src/orders/components/OrderListFilter/OrderListFilter.tsx @@ -0,0 +1,128 @@ +import * as moment from "moment-timezone"; +import * as React from "react"; + +import { DateContext } from "@saleor/components/Date/DateContext"; +import { FieldType, IFilter } from "@saleor/components/Filter"; +import FilterBar from "@saleor/components/FilterBar"; +import TimezoneContext from "@saleor/components/Timezone"; +import i18n from "../../../i18n"; +import { FilterProps } from "../../../types"; +import { OrderStatusFilter } from "../../../types/globalTypes"; +import { OrderListUrlFilters } from "../../urls"; + +type OrderListFilterProps = FilterProps; + +export enum OrderFilterKeys { + date, + dateEqual, + dateRange, + dateLastWeek, + dateLastMonth, + dateLastYear, + email, + fulfillment +} + +const OrderListFilter: React.FC = props => { + const date = React.useContext(DateContext); + const tz = React.useContext(TimezoneContext); + + const filterMenu: IFilter = [ + { + children: [ + { + children: [], + data: { + fieldLabel: null, + type: FieldType.hidden, + value: (tz ? moment(date).tz(tz) : moment(date)) + .subtract(7, "days") + .toISOString() + .split("T")[0] // Remove timezone + }, + label: i18n.t("Last 7 Days"), + value: OrderFilterKeys.dateLastWeek.toString() + }, + { + children: [], + data: { + fieldLabel: null, + type: FieldType.hidden, + value: (tz ? moment(date).tz(tz) : moment(date)) + .subtract(30, "days") + .toISOString() + .split("T")[0] // Remove timezone + }, + label: i18n.t("Last 30 Days"), + value: OrderFilterKeys.dateLastMonth.toString() + }, + { + children: [], + data: { + fieldLabel: null, + type: FieldType.hidden, + value: (tz ? moment(date).tz(tz) : moment(date)) + .subtract(1, "years") + .toISOString() + .split("T")[0] // Remove timezone + }, + label: i18n.t("Last Year"), + value: OrderFilterKeys.dateLastYear.toString() + }, + { + children: [], + data: { + additionalText: i18n.t("equals"), + fieldLabel: null, + type: FieldType.date + }, + label: i18n.t("Specific Date"), + value: OrderFilterKeys.dateEqual.toString() + }, + { + children: [], + data: { + fieldLabel: i18n.t("Range"), + type: FieldType.rangeDate + }, + label: i18n.t("Range"), + value: OrderFilterKeys.dateRange.toString() + } + ], + data: { + fieldLabel: i18n.t("Date"), + type: FieldType.select + }, + label: i18n.t("Date"), + value: OrderFilterKeys.date.toString() + }, + { + children: [], + data: { + additionalText: i18n.t("is set as"), + fieldLabel: i18n.t("Status"), + options: [ + { + label: i18n.t("Fulfilled"), + value: OrderStatusFilter.FULFILLED.toString() + }, + { + label: i18n.t("Partially Fulfilled"), + value: OrderStatusFilter.PARTIALLY_FULFILLED.toString() + }, + { + label: i18n.t("Unfulfilled"), + value: OrderStatusFilter.UNFULFILLED.toString() + } + ], + type: FieldType.select + }, + label: i18n.t("Fulfillment Status"), + value: OrderFilterKeys.fulfillment.toString() + } + ]; + + return ; +}; +OrderListFilter.displayName = "OrderListFilter"; +export default OrderListFilter; diff --git a/src/orders/components/OrderListFilter/index.ts b/src/orders/components/OrderListFilter/index.ts new file mode 100644 index 000000000..108193863 --- /dev/null +++ b/src/orders/components/OrderListFilter/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderListFilter"; +export * from "./OrderListFilter"; diff --git a/src/orders/components/OrderListPage/OrderListPage.tsx b/src/orders/components/OrderListPage/OrderListPage.tsx new file mode 100644 index 000000000..9b20884cf --- /dev/null +++ b/src/orders/components/OrderListPage/OrderListPage.tsx @@ -0,0 +1,65 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "@saleor/i18n"; +import { FilterPageProps, ListActions, PageListProps } from "@saleor/types"; +import { OrderList_orders_edges_node } from "../../types/OrderList"; +import { OrderListUrlFilters } from "../../urls"; +import OrderList from "../OrderList"; +import OrderListFilter from "../OrderListFilter"; + +export interface OrderListPageProps + extends PageListProps, + ListActions, + FilterPageProps { + orders: OrderList_orders_edges_node[]; +} + +const OrderListPage: React.FC = ({ + currencySymbol, + currentTab, + filtersList, + filterTabs, + initialSearch, + onAdd, + onAll, + onSearchChange, + onFilterAdd, + onFilterSave, + onTabChange, + onFilterDelete, + ...listProps +}) => ( + + + + + + + + + +); +OrderListPage.displayName = "OrderListPage"; +export default OrderListPage; diff --git a/src/orders/components/OrderListPage/index.ts b/src/orders/components/OrderListPage/index.ts new file mode 100644 index 000000000..69c5cc429 --- /dev/null +++ b/src/orders/components/OrderListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderListPage"; +export * from "./OrderListPage"; diff --git a/src/orders/components/OrderMarkAsPaidDialog/OrderMarkAsPaidDialog.tsx b/src/orders/components/OrderMarkAsPaidDialog/OrderMarkAsPaidDialog.tsx new file mode 100644 index 000000000..dc32a3be7 --- /dev/null +++ b/src/orders/components/OrderMarkAsPaidDialog/OrderMarkAsPaidDialog.tsx @@ -0,0 +1,33 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import i18n from "../../../i18n"; + +export interface OrderMarkAsPaidDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + onClose: () => void; + onConfirm: () => void; +} + +const OrderMarkAsPaidDialog: React.StatelessComponent< + OrderMarkAsPaidDialogProps +> = ({ confirmButtonState, onClose, onConfirm, open }) => ( + + + {i18n.t("Are you sure you want to mark this order as paid?", { + context: "modal content" + })} + + +); +OrderMarkAsPaidDialog.displayName = "OrderMarkAsPaidDialog"; +export default OrderMarkAsPaidDialog; diff --git a/src/orders/components/OrderMarkAsPaidDialog/index.ts b/src/orders/components/OrderMarkAsPaidDialog/index.ts new file mode 100644 index 000000000..f63a32363 --- /dev/null +++ b/src/orders/components/OrderMarkAsPaidDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderMarkAsPaidDialog"; +export * from "./OrderMarkAsPaidDialog"; diff --git a/src/orders/components/OrderPayment/OrderPayment.tsx b/src/orders/components/OrderPayment/OrderPayment.tsx new file mode 100644 index 000000000..31638a022 --- /dev/null +++ b/src/orders/components/OrderPayment/OrderPayment.tsx @@ -0,0 +1,231 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardActions from "@material-ui/core/CardActions"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import { Hr } from "@saleor/components/Hr"; +import Money, { subtractMoney } from "@saleor/components/Money"; +import Skeleton from "@saleor/components/Skeleton"; +import StatusLabel from "@saleor/components/StatusLabel"; +import i18n from "../../../i18n"; +import { maybe, transformPaymentStatus } from "../../../misc"; +import { OrderAction, OrderStatus } from "../../../types/globalTypes"; +import { OrderDetails_order } from "../../types/OrderDetails"; + +const styles = (theme: Theme) => + createStyles({ + root: { + ...theme.typography.body2, + lineHeight: 1.9, + width: "100%" + }, + textRight: { + textAlign: "right" + }, + totalRow: { + fontWeight: 600 + } + }); + +interface OrderPaymentProps extends WithStyles { + order: OrderDetails_order; + onCapture: () => void; + onMarkAsPaid: () => void; + onRefund: () => void; + onVoid: () => void; +} + +const OrderPayment = withStyles(styles, { name: "OrderPayment" })( + ({ + classes, + order, + onCapture, + onMarkAsPaid, + onRefund, + onVoid + }: OrderPaymentProps) => { + const canCapture = maybe(() => order.actions, []).includes( + OrderAction.CAPTURE + ); + const canVoid = maybe(() => order.actions, []).includes(OrderAction.VOID); + const canRefund = maybe(() => order.actions, []).includes( + OrderAction.REFUND + ); + const canMarkAsPaid = maybe(() => order.actions, []).includes( + OrderAction.MARK_AS_PAID + ); + const payment = transformPaymentStatus(maybe(() => order.paymentStatus)); + return ( + + order.paymentStatus) === undefined ? ( + + ) : ( + + ) + } + /> + + + + + + + + + + + + + + + + + + + + + + + +
{i18n.t("Subtotal")} + {maybe(() => order.lines) === undefined ? ( + + ) : ( + i18n.t("{{ quantity }} items", { + quantity: order.lines + .map(line => line.quantity) + .reduce((curr, prev) => prev + curr, 0) + }) + )} + + {maybe(() => order.subtotal.gross) === undefined ? ( + + ) : ( + + )} +
{i18n.t("Taxes")} + {maybe(() => order.total.tax) === undefined ? ( + + ) : order.total.tax.amount > 0 ? ( + i18n.t("VAT included") + ) : ( + i18n.t("does not apply") + )} + + {maybe(() => order.total.tax) === undefined ? ( + + ) : ( + + )} +
{i18n.t("Shipping")} + {maybe(() => order.shippingMethodName) === undefined && + maybe(() => order.shippingPrice) === undefined ? ( + + ) : order.shippingMethodName === null ? ( + i18n.t("does not apply") + ) : ( + order.shippingMethodName + )} + + {maybe(() => order.shippingPrice.gross) === undefined ? ( + + ) : ( + + )} +
{i18n.t("Total")} + + {maybe(() => order.total.gross) === undefined ? ( + + ) : ( + + )} +
+
+
+ + + + + + + + + + + + + + + + +
{i18n.t("Preauthorized amount")} + {maybe(() => order.totalAuthorized.amount) === undefined ? ( + + ) : ( + + )} +
{i18n.t("Captured amount")} + {maybe(() => order.totalCaptured.amount) === undefined ? ( + + ) : ( + + )} +
{i18n.t("Outstanding Balance")} + {maybe( + () => order.total.gross.amount && order.totalCaptured.amount + ) === undefined ? ( + + ) : ( + + )} +
+
+ {maybe(() => order.status) !== OrderStatus.CANCELED && + (canCapture || canRefund || canVoid || canMarkAsPaid) && ( + <> +
+ + {canCapture && ( + + )} + {canRefund && ( + + )} + {canVoid && ( + + )} + {canMarkAsPaid && ( + + )} + + + )} +
+ ); + } +); +OrderPayment.displayName = "OrderPayment"; +export default OrderPayment; diff --git a/src/orders/components/OrderPayment/index.ts b/src/orders/components/OrderPayment/index.ts new file mode 100644 index 000000000..2a036cd60 --- /dev/null +++ b/src/orders/components/OrderPayment/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderPayment"; +export * from "./OrderPayment"; diff --git a/src/orders/components/OrderPaymentDialog/OrderPaymentDialog.tsx b/src/orders/components/OrderPaymentDialog/OrderPaymentDialog.tsx new file mode 100644 index 000000000..89a87c0fe --- /dev/null +++ b/src/orders/components/OrderPaymentDialog/OrderPaymentDialog.tsx @@ -0,0 +1,89 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import i18n from "../../../i18n"; + +export interface FormData { + amount: number; +} + +interface OrderPaymentDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + initial: number; + variant: string; + onClose: () => void; + onSubmit: (data: FormData) => void; +} + +const OrderPaymentDialog: React.StatelessComponent = ({ + confirmButtonState, + open, + initial, + variant, + onClose, + onSubmit +}) => ( + +
{ + onSubmit(data); + onClose(); + }} + > + {({ data, change, submit }) => ( + <> + + {variant === "capture" + ? i18n.t("Capture payment", { context: "title" }) + : i18n.t("Refund payment", { context: "title" })} + + + + + + + + { + onClose(); + submit(data); + }} + > + {i18n.t("Confirm", { context: "button" })} + + + + )} +
+
+); +OrderPaymentDialog.displayName = "OrderPaymentDialog"; +export default OrderPaymentDialog; diff --git a/src/orders/components/OrderPaymentDialog/index.ts b/src/orders/components/OrderPaymentDialog/index.ts new file mode 100644 index 000000000..b1897f5b5 --- /dev/null +++ b/src/orders/components/OrderPaymentDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderPaymentDialog"; +export * from "./OrderPaymentDialog"; diff --git a/src/orders/components/OrderPaymentVoidDialog/OrderPaymentVoidDialog.tsx b/src/orders/components/OrderPaymentVoidDialog/OrderPaymentVoidDialog.tsx new file mode 100644 index 000000000..06a36d9b3 --- /dev/null +++ b/src/orders/components/OrderPaymentVoidDialog/OrderPaymentVoidDialog.tsx @@ -0,0 +1,45 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import i18n from "../../../i18n"; + +interface OrderPaymentVoidDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + onClose?(); + onConfirm?(); +} + +const OrderPaymentVoidDialog: React.StatelessComponent< + OrderPaymentVoidDialogProps +> = ({ confirmButtonState, open, onConfirm, onClose }) => ( + + {i18n.t("Void payment", { context: "title" })} + + + {i18n.t("Are you sure you want to void this payment?")} + + + + + + {i18n.t("Confirm", { context: "button" })} + + + +); +OrderPaymentVoidDialog.displayName = "OrderPaymentVoidDialog"; +export default OrderPaymentVoidDialog; diff --git a/src/orders/components/OrderPaymentVoidDialog/index.ts b/src/orders/components/OrderPaymentVoidDialog/index.ts new file mode 100644 index 000000000..98765d423 --- /dev/null +++ b/src/orders/components/OrderPaymentVoidDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderPaymentVoidDialog"; +export * from "./OrderPaymentVoidDialog"; diff --git a/src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx b/src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx new file mode 100644 index 000000000..38df75cbe --- /dev/null +++ b/src/orders/components/OrderProductAddDialog/OrderProductAddDialog.tsx @@ -0,0 +1,349 @@ +import Button from "@material-ui/core/Button"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; +import * as InfiniteScroll from "react-infinite-scroller"; + +import Checkbox from "@saleor/components/Checkbox"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import Money from "@saleor/components/Money"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { + SearchOrderVariant_products_edges_node, + SearchOrderVariant_products_edges_node_variants +} from "../../types/SearchOrderVariant"; + +export interface FormData { + variants: SearchOrderVariant_products_edges_node_variants[]; + query: string; +} + +const styles = (theme: Theme) => + createStyles({ + avatar: { + paddingLeft: 0 + }, + content: { + maxHeight: 600, + overflowY: "scroll" + }, + grayText: { + color: theme.palette.text.disabled + }, + loadMoreLoaderContainer: { + alignItems: "center", + display: "flex", + height: theme.spacing.unit * 3, + justifyContent: "center" + }, + overflow: { + overflowY: "visible" + }, + productCheckboxCell: { + "&:first-child": { + paddingLeft: 0, + paddingRight: 0 + } + }, + textRight: { + textAlign: "right" + }, + variantCheckbox: { + left: theme.spacing.unit, + position: "relative" + }, + wideCell: { + width: "100%" + } + }); + +interface OrderProductAddDialogProps extends WithStyles { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + products: SearchOrderVariant_products_edges_node[]; + loading: boolean; + hasMore: boolean; + onClose: () => void; + onFetch: (value: string) => void; + onFetchMore: () => void; + onSubmit: (data: FormData) => void; +} + +const initialForm: FormData = { + query: "", + variants: [] +}; + +function hasAllVariantsSelected( + productVariants: SearchOrderVariant_products_edges_node_variants[], + selectedVariants: SearchOrderVariant_products_edges_node_variants[] +): boolean { + return productVariants.reduce( + (acc, productVariant) => + acc && + !!selectedVariants.find( + selectedVariant => selectedVariant.id === productVariant.id + ), + true + ); +} + +function isVariantSelected( + variant: SearchOrderVariant_products_edges_node_variants, + selectedVariants: SearchOrderVariant_products_edges_node_variants[] +): boolean { + return !!selectedVariants.find( + selectedVariant => selectedVariant.id === variant.id + ); +} + +const OrderProductAddDialog = withStyles(styles, { + name: "OrderProductAddDialog" +})( + ({ + classes, + confirmButtonState, + open, + loading, + hasMore, + products, + onFetch, + onFetchMore, + onClose, + onSubmit + }: OrderProductAddDialogProps) => ( + +
+ {({ data, change }) => { + const selectedVariants = products + ? products.map(product => + product.variants.map(variant => + isVariantSelected(variant, data.variants) + ) + ) + : []; + const selectedProducts = products + ? products.map(product => + hasAllVariantsSelected(product.variants, data.variants) + ) + : []; + + const onProductAdd = ( + product: SearchOrderVariant_products_edges_node, + productIndex: number + ) => + selectedProducts[productIndex] + ? change({ + target: { + name: "variants", + value: data.variants.filter( + selectedVariant => + !product.variants.find( + productVariant => + productVariant.id === selectedVariant.id + ) + ) + } + } as any) + : change({ + target: { + name: "variants", + value: [ + ...data.variants, + ...product.variants.filter( + productVariant => + !data.variants.find( + selectedVariant => + selectedVariant.id === productVariant.id + ) + ) + ] + } + } as any); + const onVariantAdd = ( + variant: SearchOrderVariant_products_edges_node_variants, + variantIndex: number, + productIndex: number + ) => + selectedVariants[productIndex][variantIndex] + ? change({ + target: { + name: "variants", + value: data.variants.filter( + selectedVariant => selectedVariant.id !== variant.id + ) + } + } as any) + : change({ + target: { + name: "variants", + value: [...data.variants, variant] + } + } as any); + + return ( + <> + {i18n.t("Add product")} + + change(event, () => onFetch(data.query))} + label={i18n.t("Search Products", { + context: "product search input label" + })} + placeholder={i18n.t( + "Search by product name, attribute, product type etc...", + { + context: "product search input placeholder" + } + )} + fullWidth + InputProps={{ + autoComplete: "off", + endAdornment: loading && + }} + /> + + + + +
+ } + threshold={10} + > + + + {renderCollection( + products, + (product, productIndex) => ( + + + + + onProductAdd(product, productIndex) + } + /> + + product.thumbnail.url)} + /> + + {maybe(() => product.name)} + + + {maybe(() => product.variants, []).map( + (variant, variantIndex) => ( + + + + + onVariantAdd( + variant, + variantIndex, + productIndex + ) + } + /> + + +
{variant.name}
+
+ {i18n.t("SKU {{ sku }}", { + sku: variant.sku + })} +
+
+ + + +
+ ) + )} +
+ ), + () => ( + + + {i18n.t("No products matching given query")} + + + ) + )} +
+
+ + + + + + {i18n.t("Confirm", { context: "button" })} + + + + ); + }} + + + ) +); +OrderProductAddDialog.displayName = "OrderProductAddDialog"; +export default OrderProductAddDialog; diff --git a/src/orders/components/OrderProductAddDialog/index.ts b/src/orders/components/OrderProductAddDialog/index.ts new file mode 100644 index 000000000..b5eb5f42c --- /dev/null +++ b/src/orders/components/OrderProductAddDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderProductAddDialog"; +export * from "./OrderProductAddDialog"; diff --git a/src/orders/components/OrderShippingMethodEditDialog/OrderShippingMethodEditDialog.tsx b/src/orders/components/OrderShippingMethodEditDialog/OrderShippingMethodEditDialog.tsx new file mode 100644 index 000000000..66803c788 --- /dev/null +++ b/src/orders/components/OrderShippingMethodEditDialog/OrderShippingMethodEditDialog.tsx @@ -0,0 +1,122 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import Money from "@saleor/components/Money"; +import { SingleSelectField } from "@saleor/components/SingleSelectField"; +import i18n from "../../../i18n"; +import { OrderDetails_order_availableShippingMethods } from "../../types/OrderDetails"; + +export interface FormData { + shippingMethod: string; +} + +const styles = (theme: Theme) => + createStyles({ + dialog: { + overflowY: "visible" + }, + menuItem: { + display: "flex", + width: "100%" + }, + root: { + overflowY: "visible", + width: theme.breakpoints.values.sm + }, + shippingMethodName: { + flex: 1, + overflowX: "hidden", + textOverflow: "ellipsis" + } + }); + +interface OrderShippingMethodEditDialogProps extends WithStyles { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + shippingMethod: string; + shippingMethods?: OrderDetails_order_availableShippingMethods[]; + onClose(); + onSubmit?(data: FormData); +} + +const OrderShippingMethodEditDialog = withStyles(styles, { + name: "OrderShippingMethodEditDialog" +})( + ({ + classes, + confirmButtonState, + open, + shippingMethod, + shippingMethods, + onClose, + onSubmit + }: OrderShippingMethodEditDialogProps) => { + const choices = shippingMethods + ? shippingMethods.map(s => ({ + label: ( +
+ {s.name} +   + + + +
+ ), + value: s.id + })) + : []; + const initialForm: FormData = { + shippingMethod + }; + return ( + + + {i18n.t("Edit shipping method", { context: "title" })} + +
+ {({ change, data }) => ( + <> + + + + + + + {i18n.t("Confirm", { context: "button" })} + + + + )} +
+
+ ); + } +); +OrderShippingMethodEditDialog.displayName = "OrderShippingMethodEditDialog"; +export default OrderShippingMethodEditDialog; diff --git a/src/orders/components/OrderShippingMethodEditDialog/index.ts b/src/orders/components/OrderShippingMethodEditDialog/index.ts new file mode 100644 index 000000000..d7c8cf902 --- /dev/null +++ b/src/orders/components/OrderShippingMethodEditDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderShippingMethodEditDialog"; +export * from "./OrderShippingMethodEditDialog"; diff --git a/src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx b/src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx new file mode 100644 index 000000000..19949f23f --- /dev/null +++ b/src/orders/components/OrderUnfulfilledItems/OrderUnfulfilledItems.tsx @@ -0,0 +1,128 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardActions from "@material-ui/core/CardActions"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Money from "@saleor/components/Money"; +import Skeleton from "@saleor/components/Skeleton"; +import StatusLabel from "@saleor/components/StatusLabel"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { OrderDetails_order_lines } from "../../types/OrderDetails"; + +const styles = createStyles({ + clickableRow: { + cursor: "pointer" + }, + textCenter: { + textAlign: "center" + }, + textRight: { + textAlign: "right" + }, + wideCell: { + width: "50%" + } +}); + +interface OrderUnfulfilledItemsProps extends WithStyles { + canFulfill: boolean; + lines: OrderDetails_order_lines[]; + onFulfill: () => void; +} + +const OrderUnfulfilledItems = withStyles(styles, { + name: "OrderUnfulfilledItems" +})(({ canFulfill, classes, lines, onFulfill }: OrderUnfulfilledItemsProps) => ( + + line.quantity - line.quantityFulfilled) + .reduce((prev, curr) => prev + curr, 0) + })} + status="error" + /> + } + /> + + + + + {i18n.t("Product")} + + + {i18n.t("Quantity")} + + {i18n.t("Price")} + {i18n.t("Total")} + + + + {lines.map(line => ( + line.id)} + > + line.thumbnail.url)} /> + + {maybe(() => line.productName) || } + + + {maybe(() => line.quantity - line.quantityFulfilled) || ( + + )} + + + {maybe(() => line.unitPrice.gross) ? ( + + ) : ( + + )} + + + {maybe( + () => + (line.quantity - line.quantityFulfilled) * + line.unitPrice.gross.amount + ) ? ( + + ) : ( + + )} + + + ))} + +
+ {canFulfill && ( + + + + )} +
+)); +OrderUnfulfilledItems.displayName = "OrderUnfulfilledItems"; +export default OrderUnfulfilledItems; diff --git a/src/orders/components/OrderUnfulfilledItems/index.ts b/src/orders/components/OrderUnfulfilledItems/index.ts new file mode 100644 index 000000000..4d7c26864 --- /dev/null +++ b/src/orders/components/OrderUnfulfilledItems/index.ts @@ -0,0 +1,2 @@ +export { default } from "./OrderUnfulfilledItems"; +export * from "./OrderUnfulfilledItems"; diff --git a/src/orders/containers/OrderOperations.tsx b/src/orders/containers/OrderOperations.tsx new file mode 100644 index 000000000..2a9297fcd --- /dev/null +++ b/src/orders/containers/OrderOperations.tsx @@ -0,0 +1,342 @@ +import * as React from "react"; + +import { getMutationProviderData } from "../../misc"; +import { PartialMutationProviderOutput } from "../../types"; +import { + TypedOrderAddNoteMutation, + TypedOrderCancelMutation, + TypedOrderCaptureMutation, + TypedOrderCreateFulfillmentMutation, + TypedOrderDraftCancelMutation, + TypedOrderDraftFinalizeMutation, + TypedOrderDraftUpdateMutation, + TypedOrderFulfillmentCancelMutation, + TypedOrderFulfillmentUpdateTrackingMutation, + TypedOrderLineDeleteMutation, + TypedOrderLinesAddMutation, + TypedOrderLineUpdateMutation, + TypedOrderMarkAsPaidMutation, + TypedOrderRefundMutation, + TypedOrderShippingMethodUpdateMutation, + TypedOrderUpdateMutation, + TypedOrderVoidMutation +} from "../mutations"; +import { OrderAddNote, OrderAddNoteVariables } from "../types/OrderAddNote"; +import { OrderCancel, OrderCancelVariables } from "../types/OrderCancel"; +import { OrderCapture, OrderCaptureVariables } from "../types/OrderCapture"; +import { + OrderCreateFulfillment, + OrderCreateFulfillmentVariables +} from "../types/OrderCreateFulfillment"; +import { + OrderDraftCancel, + OrderDraftCancelVariables +} from "../types/OrderDraftCancel"; +import { + OrderDraftFinalize, + OrderDraftFinalizeVariables +} from "../types/OrderDraftFinalize"; +import { + OrderDraftUpdate, + OrderDraftUpdateVariables +} from "../types/OrderDraftUpdate"; +import { + OrderFulfillmentCancel, + OrderFulfillmentCancelVariables +} from "../types/OrderFulfillmentCancel"; +import { + OrderFulfillmentUpdateTracking, + OrderFulfillmentUpdateTrackingVariables +} from "../types/OrderFulfillmentUpdateTracking"; +import { + OrderLineDelete, + OrderLineDeleteVariables +} from "../types/OrderLineDelete"; +import { OrderLinesAdd, OrderLinesAddVariables } from "../types/OrderLinesAdd"; +import { + OrderLineUpdate, + OrderLineUpdateVariables +} from "../types/OrderLineUpdate"; +import { + OrderMarkAsPaid, + OrderMarkAsPaidVariables +} from "../types/OrderMarkAsPaid"; +import { OrderRefund, OrderRefundVariables } from "../types/OrderRefund"; +import { + OrderShippingMethodUpdate, + OrderShippingMethodUpdateVariables +} from "../types/OrderShippingMethodUpdate"; +import { OrderUpdate, OrderUpdateVariables } from "../types/OrderUpdate"; +import { OrderVoid, OrderVoidVariables } from "../types/OrderVoid"; + +interface OrderOperationsProps { + order: string; + children: (props: { + orderAddNote: PartialMutationProviderOutput< + OrderAddNote, + OrderAddNoteVariables + >; + orderCancel: PartialMutationProviderOutput< + OrderCancel, + OrderCancelVariables + >; + orderCreateFulfillment: PartialMutationProviderOutput< + OrderCreateFulfillment, + OrderCreateFulfillmentVariables + >; + orderFulfillmentCancel: PartialMutationProviderOutput< + OrderFulfillmentCancel, + OrderFulfillmentCancelVariables + >; + orderFulfillmentUpdateTracking: PartialMutationProviderOutput< + OrderFulfillmentUpdateTracking, + OrderFulfillmentUpdateTrackingVariables + >; + orderPaymentCapture: PartialMutationProviderOutput< + OrderCapture, + OrderCaptureVariables + >; + orderPaymentRefund: PartialMutationProviderOutput< + OrderRefund, + OrderRefundVariables + >; + orderPaymentMarkAsPaid: PartialMutationProviderOutput< + OrderMarkAsPaid, + OrderMarkAsPaidVariables + >; + orderVoid: PartialMutationProviderOutput; + orderUpdate: PartialMutationProviderOutput< + OrderUpdate, + OrderUpdateVariables + >; + orderDraftCancel: PartialMutationProviderOutput< + OrderDraftCancel, + OrderDraftCancelVariables + >; + orderDraftFinalize: PartialMutationProviderOutput< + OrderDraftFinalize, + OrderDraftFinalizeVariables + >; + orderDraftUpdate: PartialMutationProviderOutput< + OrderDraftUpdate, + OrderDraftUpdateVariables + >; + orderShippingMethodUpdate: PartialMutationProviderOutput< + OrderShippingMethodUpdate, + OrderShippingMethodUpdateVariables + >; + orderLineDelete: PartialMutationProviderOutput< + OrderLineDelete, + OrderLineDeleteVariables + >; + orderLinesAdd: PartialMutationProviderOutput< + OrderLinesAdd, + OrderLinesAddVariables + >; + orderLineUpdate: PartialMutationProviderOutput< + OrderLineUpdate, + OrderLineUpdateVariables + >; + }) => React.ReactNode; + onOrderFulfillmentCancel: (data: OrderFulfillmentCancel) => void; + onOrderFulfillmentCreate: (data: OrderCreateFulfillment) => void; + onOrderFulfillmentUpdate: (data: OrderFulfillmentUpdateTracking) => void; + onOrderCancel: (data: OrderCancel) => void; + onOrderVoid: (data: OrderVoid) => void; + onOrderMarkAsPaid: (data: OrderMarkAsPaid) => void; + onNoteAdd: (data: OrderAddNote) => void; + onPaymentCapture: (data: OrderCapture) => void; + onPaymentRefund: (data: OrderRefund) => void; + onUpdate: (data: OrderUpdate) => void; + onDraftCancel: (data: OrderDraftCancel) => void; + onDraftFinalize: (data: OrderDraftFinalize) => void; + onDraftUpdate: (data: OrderDraftUpdate) => void; + onShippingMethodUpdate: (data: OrderShippingMethodUpdate) => void; + onOrderLineDelete: (data: OrderLineDelete) => void; + onOrderLinesAdd: (data: OrderLinesAdd) => void; + onOrderLineUpdate: (data: OrderLineUpdate) => void; +} + +const OrderOperations: React.StatelessComponent = ({ + children, + onDraftUpdate, + onOrderFulfillmentCreate, + onNoteAdd, + onOrderCancel, + onOrderLinesAdd, + onOrderLineDelete, + onOrderLineUpdate, + onOrderVoid, + onPaymentCapture, + onPaymentRefund, + onShippingMethodUpdate, + onUpdate, + onDraftCancel, + onDraftFinalize, + onOrderFulfillmentCancel, + onOrderFulfillmentUpdate, + onOrderMarkAsPaid +}) => ( + + {(...orderVoid) => ( + + {(...orderCancel) => ( + + {(...paymentCapture) => ( + + {(...paymentRefund) => ( + + {(...createFulfillment) => ( + + {(...addNote) => ( + + {(...update) => ( + + {(...updateDraft) => ( + + {(...updateShippingMethod) => ( + + {(...deleteOrderLine) => ( + + {(...addOrderLine) => ( + + {(...updateOrderLine) => ( + + {(...cancelFulfillment) => ( + + {( + ...updateTrackingNumber + ) => ( + + {( + ...finalizeDraft + ) => ( + + {( + ...cancelDraft + ) => ( + + {( + ...markAsPaid + ) => + children({ + orderAddNote: getMutationProviderData( + ...addNote + ), + orderCancel: getMutationProviderData( + ...orderCancel + ), + orderCreateFulfillment: getMutationProviderData( + ...createFulfillment + ), + orderDraftCancel: getMutationProviderData( + ...cancelDraft + ), + orderDraftFinalize: getMutationProviderData( + ...finalizeDraft + ), + orderDraftUpdate: getMutationProviderData( + ...updateDraft + ), + orderFulfillmentCancel: getMutationProviderData( + ...cancelFulfillment + ), + orderFulfillmentUpdateTracking: getMutationProviderData( + ...updateTrackingNumber + ), + orderLineDelete: getMutationProviderData( + ...deleteOrderLine + ), + orderLineUpdate: getMutationProviderData( + ...updateOrderLine + ), + orderLinesAdd: getMutationProviderData( + ...addOrderLine + ), + orderPaymentCapture: getMutationProviderData( + ...paymentCapture + ), + orderPaymentMarkAsPaid: getMutationProviderData( + ...markAsPaid + ), + orderPaymentRefund: getMutationProviderData( + ...paymentRefund + ), + orderShippingMethodUpdate: getMutationProviderData( + ...updateShippingMethod + ), + orderUpdate: getMutationProviderData( + ...update + ), + orderVoid: getMutationProviderData( + ...orderVoid + ) + }) + } + + )} + + )} + + )} + + )} + + )} + + )} + + )} + + )} + + )} + + )} + + )} + + )} + + )} + + )} + + )} + + )} + +); +export default OrderOperations; diff --git a/src/orders/fixtures.ts b/src/orders/fixtures.ts new file mode 100644 index 000000000..706017967 --- /dev/null +++ b/src/orders/fixtures.ts @@ -0,0 +1,1218 @@ +import { SearchCustomers_customers_edges_node } from "../containers/SearchCustomers/types/SearchCustomers"; +import { transformOrderStatus, transformPaymentStatus } from "../misc"; +import { + FulfillmentStatus, + OrderAction, + OrderEventsEnum, + OrderStatus, + PaymentChargeStatusEnum +} from "../types/globalTypes"; +import { OrderDetails_order } from "./types/OrderDetails"; +import { OrderList_orders_edges_node } from "./types/OrderList"; + +export const clients: SearchCustomers_customers_edges_node[] = [ + { + __typename: "User" as "User", + email: "test.client1@example.com", + id: "c1" + }, + { + __typename: "User" as "User", + email: "test.client2@example.com", + id: "c2" + }, + { + __typename: "User" as "User", + email: "test.client3@example.com", + id: "c3" + }, + { + __typename: "User" as "User", + email: "test.client4@example.com", + id: "c4" + } +]; +export const orders: OrderList_orders_edges_node[] = [ + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "East Aaronville", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "BE", + country: "Belgia" + }, + countryArea: "", + firstName: "Laura", + id: "QWRkcmVzczo5", + lastName: "Stone 1 2", + phone: "", + postalCode: "88741", + streetAddress1: "3678 John Course", + streetAddress2: "" + }, + created: "2018-09-11T09:37:30.376876+00:00", + id: "T3JkZXI6MjA=", + number: "20", + paymentStatus: PaymentChargeStatusEnum.FULLY_CHARGED, + status: OrderStatus.CANCELED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 305.17, + currency: "USD" + } + }, + userEmail: "laura.stone@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "Port Danielshire", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "SE", + country: "Szwecja" + }, + countryArea: "", + firstName: "Elizabeth", + id: "QWRkcmVzczoy", + lastName: "Vaughn", + phone: "", + postalCode: "52203", + streetAddress1: "419 Ruiz Orchard Apt. 199", + streetAddress2: "" + }, + created: "2018-09-11T09:37:30.124154+00:00", + id: "T3JkZXI6MTk=", + number: "19", + paymentStatus: PaymentChargeStatusEnum.FULLY_CHARGED, + status: OrderStatus.CANCELED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 1215.89, + currency: "USD" + } + }, + userEmail: "elizabeth.vaughn@example.com" + }, + { + __typename: "Order", + billingAddress: null, + created: "2018-09-11T09:37:30.019749+00:00", + id: "T3JkZXI6MTg=", + number: "18", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.DRAFT, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 321.71, + currency: "USD" + } + }, + userEmail: "david.lawson@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "South Rodneymouth", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "GR", + country: "Grecja" + }, + countryArea: "", + firstName: "Aaron", + id: "QWRkcmVzczoyOA==", + lastName: "Randall", + phone: "", + postalCode: "30356", + streetAddress1: "326 Palmer Rapids Apt. 717", + streetAddress2: "" + }, + created: "2018-09-11T09:37:29.864391+00:00", + id: "T3JkZXI6MTc=", + number: "17", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.CANCELED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 271.95, + currency: "USD" + } + }, + userEmail: "aaron.randall@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "Jorgeview", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "UG", + country: "Uganda" + }, + countryArea: "", + firstName: "Laura", + id: "QWRkcmVzczoxNA==", + lastName: "Jensen", + phone: "", + postalCode: "77693", + streetAddress1: "01504 Olson Springs Suite 920", + streetAddress2: "" + }, + created: "2018-09-11T09:37:29.610339+00:00", + id: "T3JkZXI6MTY=", + number: "16", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.CANCELED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 335.84, + currency: "USD" + } + }, + userEmail: "laura.jensen@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "East Lauriestad", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "PW", + country: "Palau" + }, + countryArea: "", + firstName: "Jenna", + id: "QWRkcmVzczoyNw==", + lastName: "Villa", + phone: "", + postalCode: "65613", + streetAddress1: "2031 Mcdonald Mill", + streetAddress2: "" + }, + created: "2018-09-11T09:37:29.336209+00:00", + id: "T3JkZXI6MTU=", + number: "15", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.CANCELED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 1042.15, + currency: "USD" + } + }, + userEmail: "jenna.villa@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "Kaneton", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "VA", + country: "Watykan" + }, + countryArea: "", + firstName: "Wesley", + id: "QWRkcmVzczo4", + lastName: "Davis", + phone: "", + postalCode: "66203", + streetAddress1: "667 Joseph Lights", + streetAddress2: "" + }, + created: "2018-09-11T09:37:29.103651+00:00", + id: "T3JkZXI6MTQ=", + number: "14", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.CANCELED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 213.69, + currency: "USD" + } + }, + userEmail: "wesley.davis@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "New Morganshire", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "NL", + country: "Holandia" + }, + countryArea: "", + firstName: "Anthony", + id: "QWRkcmVzczo3", + lastName: "Gonzalez", + phone: "", + postalCode: "78701", + streetAddress1: "402 Mason Viaduct Suite 592", + streetAddress2: "" + }, + created: "2018-09-11T09:37:28.921956+00:00", + id: "T3JkZXI6MTM=", + number: "13", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.CANCELED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 367.03, + currency: "USD" + } + }, + userEmail: "anthony.gonzalez@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "Adamsport", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "TN", + country: "Tunezja" + }, + countryArea: "", + firstName: "Denise", + id: "QWRkcmVzczoyNg==", + lastName: "Freeman", + phone: "", + postalCode: "27744", + streetAddress1: "8376 Linda Valley Apt. 934", + streetAddress2: "" + }, + created: "2018-09-11T09:37:28.750718+00:00", + id: "T3JkZXI6MTI=", + number: "12", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.CANCELED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 298.76, + currency: "USD" + } + }, + userEmail: "denise.freeman@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "Thomasburgh", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "DJ", + country: "Dżibuti" + }, + countryArea: "", + firstName: "James", + id: "QWRkcmVzczo2", + lastName: "Ball", + phone: "", + postalCode: "70958", + streetAddress1: "60049 Fisher Grove", + streetAddress2: "" + }, + created: "2018-09-11T09:37:28.598246+00:00", + id: "T3JkZXI6MTE=", + number: "11", + paymentStatus: PaymentChargeStatusEnum.FULLY_CHARGED, + status: OrderStatus.UNFULFILLED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 663.69, + currency: "USD" + } + }, + userEmail: "james.ball@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "Lake Walter", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "MK", + country: "Macedonia" + }, + countryArea: "", + firstName: "Michael", + id: "QWRkcmVzczoz", + lastName: "Martinez", + phone: "", + postalCode: "11343", + streetAddress1: "843 Allen Ramp Suite 194", + streetAddress2: "" + }, + created: "2018-09-11T09:37:28.409836+00:00", + id: "T3JkZXI6MTA=", + number: "10", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.CANCELED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 280.41, + currency: "USD" + } + }, + userEmail: "michael.martinez@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "West Patriciastad", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "SB", + country: "Wyspy Salomona" + }, + countryArea: "", + firstName: "Melissa", + id: "QWRkcmVzczoyNQ==", + lastName: "Simon", + phone: "", + postalCode: "66272", + streetAddress1: "487 Roberto Shores", + streetAddress2: "" + }, + created: "2018-09-11T09:37:28.185874+00:00", + id: "T3JkZXI6OQ==", + number: "9", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.PARTIALLY_FULFILLED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 234.93, + currency: "USD" + } + }, + userEmail: "melissa.simon@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "Lake Kevinchester", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "CL", + country: "Chile" + }, + countryArea: "", + firstName: "Justin", + id: "QWRkcmVzczoyNA==", + lastName: "Mccoy", + phone: "", + postalCode: "03826", + streetAddress1: "74416 Jensen Gateway Suite 140", + streetAddress2: "" + }, + created: "2018-09-11T09:37:27.953588+00:00", + id: "T3JkZXI6OA==", + number: "8", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.PARTIALLY_FULFILLED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 485.19, + currency: "USD" + } + }, + userEmail: "justin.mccoy@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "New Morganshire", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "NL", + country: "Holandia" + }, + countryArea: "", + firstName: "Anthony", + id: "QWRkcmVzczo3", + lastName: "Gonzalez", + phone: "", + postalCode: "78701", + streetAddress1: "402 Mason Viaduct Suite 592", + streetAddress2: "" + }, + created: "2018-09-11T09:37:27.828033+00:00", + id: "T3JkZXI6Nw==", + number: "7", + paymentStatus: PaymentChargeStatusEnum.FULLY_CHARGED, + status: OrderStatus.PARTIALLY_FULFILLED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 223.54, + currency: "USD" + } + }, + userEmail: "anthony.gonzalez@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "Gabrielchester", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "SN", + country: "Senegal" + }, + countryArea: "", + firstName: "Bradley", + id: "QWRkcmVzczoyMw==", + lastName: "Ford", + phone: "", + postalCode: "88661", + streetAddress1: "56414 Ashley Gardens", + streetAddress2: "" + }, + created: "2018-09-11T09:37:27.636741+00:00", + id: "T3JkZXI6Ng==", + number: "6", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.FULFILLED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 237.55, + currency: "USD" + } + }, + userEmail: "bradley.ford@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "East Steven", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "CG", + country: "Kongo" + }, + countryArea: "", + firstName: "David", + id: "QWRkcmVzczoxNg==", + lastName: "Lawson", + phone: "", + postalCode: "87510", + streetAddress1: "151 Huang Pines", + streetAddress2: "" + }, + created: "2018-09-11T09:37:27.420590+00:00", + id: "T3JkZXI6NQ==", + number: "5", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.PARTIALLY_FULFILLED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 453.55, + currency: "USD" + } + }, + userEmail: "david.lawson@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "East Daniel", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "NA", + country: "Namibia" + }, + countryArea: "", + firstName: "Lauren", + id: "QWRkcmVzczoyMg==", + lastName: "Watson", + phone: "", + postalCode: "22102", + streetAddress1: "340 Amanda Tunnel Suite 869", + streetAddress2: "" + }, + created: "2018-09-11T09:37:27.230990+00:00", + id: "T3JkZXI6NA==", + number: "4", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.PARTIALLY_FULFILLED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 812.67, + currency: "USD" + } + }, + userEmail: "lauren.watson@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "Lake Margaret", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "CO", + country: "Kolumbia" + }, + countryArea: "", + firstName: "Mark", + id: "QWRkcmVzczoxNQ==", + lastName: "Lee", + phone: "", + postalCode: "18829", + streetAddress1: "34480 Daniel Centers Apt. 642", + streetAddress2: "" + }, + created: "2018-09-11T09:37:26.972507+00:00", + id: "T3JkZXI6Mw==", + number: "3", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + status: OrderStatus.PARTIALLY_FULFILLED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 481.41, + currency: "USD" + } + }, + userEmail: "mark.lee@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "Dorothyberg", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "BJ", + country: "Benin" + }, + countryArea: "", + firstName: "Kara", + id: "QWRkcmVzczoyMQ==", + lastName: "Murphy", + phone: "", + postalCode: "88138", + streetAddress1: "0674 Kent Station Suite 395", + streetAddress2: "" + }, + created: "2018-09-11T09:37:26.751359+00:00", + id: "T3JkZXI6Mg==", + number: "2", + paymentStatus: PaymentChargeStatusEnum.FULLY_CHARGED, + status: OrderStatus.PARTIALLY_FULFILLED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 569.19, + currency: "USD" + } + }, + userEmail: "kara.murphy@example.com" + }, + { + __typename: "Order", + billingAddress: { + __typename: "Address", + city: "Gregorymouth", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "CV", + country: "Republika Zielonego Przylądka" + }, + countryArea: "", + firstName: "Curtis", + id: "QWRkcmVzczox", + lastName: "Bailey", + phone: "", + postalCode: "84525", + streetAddress1: "839 Scott Lake", + streetAddress2: "" + }, + created: "2018-09-11T09:37:26.314968+00:00", + id: "T3JkZXI6MQ==", + number: "1", + paymentStatus: PaymentChargeStatusEnum.FULLY_CHARGED, + status: OrderStatus.PARTIALLY_FULFILLED, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 557, + currency: "USD" + } + }, + userEmail: "curtis.bailey@example.com" + } +]; +export const order = (placeholder: string): OrderDetails_order => ({ + __typename: "Order", + actions: [ + OrderAction.CAPTURE, + OrderAction.MARK_AS_PAID, + OrderAction.REFUND, + OrderAction.VOID + ], + availableShippingMethods: [ + { + __typename: "ShippingMethod", + id: "U2hpcHBpbmdNZXRob2Q6NQ==", + name: "FBA", + price: { + __typename: "Money", + amount: 12.41, + currency: "USD" + } + }, + { + __typename: "ShippingMethod", + id: "U2hpcHBpbmdNZXRob2Q6Nw==", + name: "Oceania Air Mail", + price: { + __typename: "Money", + amount: 9.12, + currency: "USD" + } + }, + { + __typename: "ShippingMethod", + id: "U2hpcHBpbmdNZXRob2Q6Ng==", + name: "FedEx Express", + price: { + __typename: "Money", + amount: 7.6, + currency: "USD" + } + } + ], + billingAddress: { + __typename: "Address", + city: "West Patriciastad", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "SB", + country: "Wyspy Salomona" + }, + countryArea: "", + firstName: "Melissa", + id: "QWRkcmVzczoyNQ==", + lastName: "Simon", + phone: "", + postalCode: "66272", + streetAddress1: "487 Roberto Shores", + streetAddress2: "" + }, + canFinalize: true, + created: "2018-09-11T09:37:28.185874+00:00", + customerNote: "Lorem ipsum dolor sit amet", + events: [ + { + __typename: "OrderEvent", + amount: null, + date: "2018-09-17T13:22:24.376193+00:00", + email: null, + emailType: null, + id: "T3JkZXJFdmVudDoyMQ==", + message: null, + quantity: 1, + type: OrderEventsEnum.FULFILLMENT_FULFILLED_ITEMS, + user: { + __typename: "User", + email: "admin@example.com", + id: "QWRkcmVzczoxNQ==" + } + } + ], + fulfillments: [ + { + __typename: "Fulfillment", + fulfillmentOrder: 2, + id: "RnVsZmlsbG1lbnQ6MjQ=", + lines: [ + { + __typename: "FulfillmentLine", + id: "RnVsZmlsbG1lbnRMaW5lOjM5", + orderLine: { + __typename: "OrderLine", + id: "T3JkZXJMaW5lOjIz", + isShippingRequired: false, + productName: "Williams, Garcia and Walker (XS)", + productSku: "5-1337", + quantity: 2, + quantityFulfilled: 2, + thumbnail: { + __typename: "Image" as "Image", + url: placeholder + }, + unitPrice: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 79.71, + currency: "USD" + }, + net: { + __typename: "Money", + amount: 79.71, + currency: "USD" + } + } + }, + quantity: 1 + } + ], + status: FulfillmentStatus.FULFILLED, + trackingNumber: "" + }, + { + __typename: "Fulfillment", + fulfillmentOrder: 1, + id: "RnVsZmlsbG1lbnQ6OQ==", + lines: [ + { + __typename: "FulfillmentLine", + id: "RnVsZmlsbG1lbnRMaW5lOjE1", + orderLine: { + __typename: "OrderLine", + id: "T3JkZXJMaW5lOjIz", + isShippingRequired: false, + productName: "Williams, Garcia and Walker (XS)", + productSku: "5-1337", + quantity: 2, + quantityFulfilled: 2, + thumbnail: { + __typename: "Image" as "Image", + url: placeholder + }, + unitPrice: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 79.71, + currency: "USD" + }, + net: { + __typename: "Money", + amount: 79.71, + currency: "USD" + } + } + }, + quantity: 1 + } + ], + status: FulfillmentStatus.FULFILLED, + trackingNumber: "" + } + ], + id: "T3JkZXI6OQ==", + lines: [ + { + __typename: "OrderLine", + id: "T3JkZXJMaW5lOjIy", + isShippingRequired: true, + productName: "Watkins-Gonzalez (Soft)", + productSku: "59-1337", + quantity: 3, + quantityFulfilled: 0, + thumbnail: { + __typename: "Image" as "Image", + url: placeholder + }, + unitPrice: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 18.51, + currency: "USD" + }, + net: { + __typename: "Money", + amount: 18.51, + currency: "USD" + } + } + }, + { + __typename: "OrderLine", + id: "T3JkZXJMaW5lOjIz", + isShippingRequired: true, + productName: "Williams, Garcia and Walker (XS)", + productSku: "5-1337", + quantity: 2, + quantityFulfilled: 2, + thumbnail: { + __typename: "Image" as "Image", + url: placeholder + }, + unitPrice: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 79.71, + currency: "USD" + }, + net: { + __typename: "Money", + amount: 79.71, + currency: "USD" + } + } + } + ], + number: "9", + paymentStatus: PaymentChargeStatusEnum.NOT_CHARGED, + shippingAddress: { + __typename: "Address", + city: "West Patriciastad", + cityArea: "", + companyName: "", + country: { + __typename: "CountryDisplay", + code: "SB", + country: "Wyspy Salomona" + }, + countryArea: "", + firstName: "Melissa", + id: "QWRkcmVzczoyNQ==", + lastName: "Simon", + phone: "", + postalCode: "66272", + streetAddress1: "487 Roberto Shores", + streetAddress2: "" + }, + shippingMethod: null, + shippingMethodName: "Registred priority", + shippingPrice: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 19.98, + currency: "USD" + } + }, + status: OrderStatus.PARTIALLY_FULFILLED, + subtotal: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 214.95, + currency: "USD" + } + }, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 234.93, + currency: "USD" + }, + tax: { + __typename: "Money", + amount: 0, + currency: "USD" + } + }, + totalAuthorized: { + __typename: "Money", + amount: 234.93, + currency: "USD" + }, + totalCaptured: { + __typename: "Money", + amount: 0, + currency: "USD" + }, + user: null, + userEmail: "melissa.simon@example.com" +}); +export const draftOrder = (placeholder: string): OrderDetails_order => ({ + __typename: "Order" as "Order", + actions: [OrderAction.CAPTURE], + availableShippingMethods: null, + billingAddress: null, + canFinalize: true, + created: "2018-09-20T23:23:39.811428+00:00", + customerNote: "Lorem ipsum dolor sit", + events: [], + fulfillments: [], + id: "T3JkZXI6MjQ=", + lines: [ + { + __typename: "OrderLine" as "OrderLine", + id: "T3JkZXJMaW5lOjQ1", + isShippingRequired: false, + productName: "Davis Group (Hard)", + productSku: "58-1338", + quantity: 2, + quantityFulfilled: 0, + thumbnail: { + __typename: "Image" as "Image", + url: placeholder + }, + unitPrice: { + __typename: "TaxedMoney" as "TaxedMoney", + gross: { + __typename: "Money" as "Money", + amount: 65.95, + currency: "USD" + }, + net: { + __typename: "Money" as "Money", + amount: 65.95, + currency: "USD" + } + } + }, + { + __typename: "OrderLine" as "OrderLine", + id: "T3JkZXJMaW5lOjQ2", + isShippingRequired: false, + productName: "Anderson PLC (15-1337)", + productSku: "15-1337", + quantity: 2, + quantityFulfilled: 0, + thumbnail: { + __typename: "Image" as "Image", + url: placeholder + }, + unitPrice: { + __typename: "TaxedMoney" as "TaxedMoney", + gross: { + __typename: "Money" as "Money", + amount: 68.2, + currency: "USD" + }, + net: { + __typename: "Money" as "Money", + amount: 68.2, + currency: "USD" + } + } + } + ], + number: "24", + paymentStatus: null, + shippingAddress: null, + shippingMethod: null, + shippingMethodName: null, + shippingPrice: { + __typename: "TaxedMoney" as "TaxedMoney", + gross: { + __typename: "Money" as "Money", + amount: 0, + currency: "USD" + } + }, + status: "DRAFT" as OrderStatus.DRAFT, + subtotal: { + __typename: "TaxedMoney" as "TaxedMoney", + gross: { + __typename: "Money" as "Money", + amount: 168.3, + currency: "USD" + } + }, + total: { + __typename: "TaxedMoney" as "TaxedMoney", + gross: { + __typename: "Money" as "Money", + amount: 168.3, + currency: "USD" + }, + tax: { + __typename: "Money" as "Money", + amount: 68.3, + currency: "USD" + } + }, + totalAuthorized: null, + totalCaptured: null, + user: null, + userEmail: null +}); +export const flatOrders = orders.map(order => ({ + ...order, + orderStatus: transformOrderStatus(order.status), + paymentStatus: transformPaymentStatus(order.paymentStatus) +})); +export const variants = [ + { id: "p1", name: "Product 1: variant 1", sku: "12345", stockQuantity: 3 }, + { id: "p2", name: "Product 1: variant 2", sku: "12346", stockQuantity: 1 }, + { id: "p3", name: "Product 2: variant 1", sku: "12355", stockQuantity: 10 }, + { id: "p4", name: "Product 3: variant 1", sku: "12445", stockQuantity: 12 }, + { id: "p5", name: "Product 3: variant 2", sku: "12545", stockQuantity: 7 }, + { id: "p6", name: "Product 5: variant 1", sku: "13345", stockQuantity: 3 }, + { id: "p7", name: "Product 5: variant 2", sku: "14345", stockQuantity: 11 } +]; +export const prefixes = ["01", "02", "41", "49"]; +export const countries = [ + { code: "AF", label: "Afghanistan" }, + { code: "AX", label: "Åland Islands" }, + { code: "AL", label: "Albania" }, + { code: "DZ", label: "Algeria" }, + { code: "AS", label: "American Samoa" } +]; +export const shippingMethods = [ + { id: "s1", name: "DHL", country: "whole world", price: {} }, + { id: "s2", name: "UPS", country: "Afghanistan" } +]; +export const orderLineSearch = (placeholderImage: string) => [ + { + __typename: "Product" as "Product", + id: "UHJvZHVjdDo3Mg==", + name: "Apple Juice", + thumbnail: { + __typename: "Image" as "Image", + url: placeholderImage + }, + variants: [ + { + __typename: "ProductVariant" as "ProductVariant", + id: "UHJvZHVjdFZhcmlhbnQ6MjAy", + name: "500ml", + price: { amount: 3.0, currency: "USD", __typename: "Money" as "Money" }, + sku: "93855755" + }, + { + __typename: "ProductVariant" as "ProductVariant", + id: "UHJvZHVjdFZhcmlhbnQ6MjAz", + name: "1l", + price: { amount: 5.0, currency: "USD", __typename: "Money" as "Money" }, + sku: "43226647" + }, + { + __typename: "ProductVariant" as "ProductVariant", + id: "UHJvZHVjdFZhcmlhbnQ6MjA0", + name: "2l", + price: { amount: 7.0, currency: "USD", __typename: "Money" as "Money" }, + sku: "80884671" + } + ] + }, + { + __typename: "Product" as "Product", + id: "UHJvZHVjdDo3NQ==", + name: "Pineapple Juice", + thumbnail: { + __typename: "Image" as "Image", + url: placeholderImage + }, + variants: [ + { + __typename: "ProductVariant" as "ProductVariant", + id: "UHJvZHVjdFZhcmlhbnQ6MjEx", + name: "500ml", + price: { amount: 3.0, currency: "USD", __typename: "Money" as "Money" }, + sku: "43200242" + }, + { + __typename: "ProductVariant" as "ProductVariant", + id: "UHJvZHVjdFZhcmlhbnQ6MjEy", + name: "1l", + price: { amount: 5.0, currency: "USD", __typename: "Money" as "Money" }, + sku: "79129513" + }, + { + __typename: "ProductVariant" as "ProductVariant", + id: "UHJvZHVjdFZhcmlhbnQ6MjEz", + name: "2l", + price: { amount: 7.0, currency: "USD", __typename: "Money" as "Money" }, + sku: "75799450" + } + ] + } +]; diff --git a/src/orders/index.tsx b/src/orders/index.tsx new file mode 100644 index 000000000..09490bb35 --- /dev/null +++ b/src/orders/index.tsx @@ -0,0 +1,60 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { WindowTitle } from "../components/WindowTitle"; +import i18n from "../i18n"; +import { + orderDraftListPath, + OrderDraftListUrlQueryParams, + orderListPath, + OrderListUrlQueryParams, + orderPath, + OrderUrlQueryParams +} from "./urls"; +import OrderDetailsComponent from "./views/OrderDetails"; +import OrderDraftListComponent from "./views/OrderDraftList"; +import OrderListComponent from "./views/OrderList"; + +const OrderList: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: OrderListUrlQueryParams = qs; + return ; +}; +const OrderDraftList: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: OrderDraftListUrlQueryParams = qs; + return ; +}; + +const OrderDetails: React.StatelessComponent> = ({ + location, + match +}) => { + const qs = parseQs(location.search.substr(1)); + const params: OrderUrlQueryParams = qs; + + return ( + + ); +}; + +const Component = () => ( + <> + + + + + + + +); + +export default Component; diff --git a/src/orders/mutations.ts b/src/orders/mutations.ts new file mode 100644 index 000000000..8ab8f659b --- /dev/null +++ b/src/orders/mutations.ts @@ -0,0 +1,472 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { + fragmentAddress, + fragmentOrderDetails, + fragmentOrderEvent +} from "./queries"; +import { OrderAddNote, OrderAddNoteVariables } from "./types/OrderAddNote"; +import { + OrderBulkCancel, + OrderBulkCancelVariables +} from "./types/OrderBulkCancel"; +import { OrderCancel, OrderCancelVariables } from "./types/OrderCancel"; +import { OrderCapture, OrderCaptureVariables } from "./types/OrderCapture"; +import { + OrderCreateFulfillment, + OrderCreateFulfillmentVariables +} from "./types/OrderCreateFulfillment"; +import { + OrderDraftBulkCancel, + OrderDraftBulkCancelVariables +} from "./types/OrderDraftBulkCancel"; +import { + OrderDraftCancel, + OrderDraftCancelVariables +} from "./types/OrderDraftCancel"; +import { OrderDraftCreate } from "./types/OrderDraftCreate"; +import { + OrderDraftFinalize, + OrderDraftFinalizeVariables +} from "./types/OrderDraftFinalize"; +import { + OrderDraftUpdate, + OrderDraftUpdateVariables +} from "./types/OrderDraftUpdate"; +import { + OrderFulfillmentCancel, + OrderFulfillmentCancelVariables +} from "./types/OrderFulfillmentCancel"; +import { + OrderFulfillmentUpdateTracking, + OrderFulfillmentUpdateTrackingVariables +} from "./types/OrderFulfillmentUpdateTracking"; +import { + OrderLineDelete, + OrderLineDeleteVariables +} from "./types/OrderLineDelete"; +import { OrderLinesAdd, OrderLinesAddVariables } from "./types/OrderLinesAdd"; +import { + OrderLineUpdate, + OrderLineUpdateVariables +} from "./types/OrderLineUpdate"; +import { + OrderMarkAsPaid, + OrderMarkAsPaidVariables +} from "./types/OrderMarkAsPaid"; +import { OrderRefund, OrderRefundVariables } from "./types/OrderRefund"; +import { + OrderShippingMethodUpdate, + OrderShippingMethodUpdateVariables +} from "./types/OrderShippingMethodUpdate"; +import { OrderUpdate, OrderUpdateVariables } from "./types/OrderUpdate"; +import { OrderVoid, OrderVoidVariables } from "./types/OrderVoid"; + +const orderCancelMutation = gql` + ${fragmentOrderDetails} + mutation OrderCancel($id: ID!, $restock: Boolean!) { + orderCancel(id: $id, restock: $restock) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderCancelMutation = TypedMutation< + OrderCancel, + OrderCancelVariables +>(orderCancelMutation); + +const orderBulkCancelMutation = gql` + mutation OrderBulkCancel($ids: [ID]!, $restock: Boolean!) { + orderBulkCancel(ids: $ids, restock: $restock) { + errors { + field + message + } + } + } +`; +export const TypedOrderBulkCancelMutation = TypedMutation< + OrderBulkCancel, + OrderBulkCancelVariables +>(orderBulkCancelMutation); + +const orderDraftCancelMutation = gql` + ${fragmentOrderDetails} + mutation OrderDraftCancel($id: ID!) { + draftOrderDelete(id: $id) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderDraftCancelMutation = TypedMutation< + OrderDraftCancel, + OrderDraftCancelVariables +>(orderDraftCancelMutation); + +const orderDraftBulkCancelMutation = gql` + mutation OrderDraftBulkCancel($ids: [ID]!) { + draftOrderBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedOrderDraftBulkCancelMutation = TypedMutation< + OrderDraftBulkCancel, + OrderDraftBulkCancelVariables +>(orderDraftBulkCancelMutation); + +const orderDraftFinalizeMutation = gql` + ${fragmentOrderDetails} + mutation OrderDraftFinalize($id: ID!) { + draftOrderComplete(id: $id) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderDraftFinalizeMutation = TypedMutation< + OrderDraftFinalize, + OrderDraftFinalizeVariables +>(orderDraftFinalizeMutation); + +const orderRefundMutation = gql` + ${fragmentOrderDetails} + mutation OrderRefund($id: ID!, $amount: Decimal!) { + orderRefund(id: $id, amount: $amount) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderRefundMutation = TypedMutation< + OrderRefund, + OrderRefundVariables +>(orderRefundMutation); + +const orderVoidMutation = gql` + ${fragmentOrderDetails} + mutation OrderVoid($id: ID!) { + orderVoid(id: $id) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderVoidMutation = TypedMutation< + OrderVoid, + OrderVoidVariables +>(orderVoidMutation); + +const orderMarkAsPaidMutation = gql` + ${fragmentOrderDetails} + mutation OrderMarkAsPaid($id: ID!) { + orderMarkAsPaid(id: $id) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderMarkAsPaidMutation = TypedMutation< + OrderMarkAsPaid, + OrderMarkAsPaidVariables +>(orderMarkAsPaidMutation); + +const orderCaptureMutation = gql` + ${fragmentOrderDetails} + mutation OrderCapture($id: ID!, $amount: Decimal!) { + orderCapture(id: $id, amount: $amount) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderCaptureMutation = TypedMutation< + OrderCapture, + OrderCaptureVariables +>(orderCaptureMutation); + +const orderCreateFulfillmentMutation = gql` + ${fragmentOrderDetails} + mutation OrderCreateFulfillment( + $order: ID! + $input: FulfillmentCreateInput! + ) { + orderFulfillmentCreate(order: $order, input: $input) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderCreateFulfillmentMutation = TypedMutation< + OrderCreateFulfillment, + OrderCreateFulfillmentVariables +>(orderCreateFulfillmentMutation); + +const orderFulfillmentUpdateTrackingMutation = gql` + ${fragmentOrderDetails} + mutation OrderFulfillmentUpdateTracking( + $id: ID! + $input: FulfillmentUpdateTrackingInput! + ) { + orderFulfillmentUpdateTracking(id: $id, input: $input) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderFulfillmentUpdateTrackingMutation = TypedMutation< + OrderFulfillmentUpdateTracking, + OrderFulfillmentUpdateTrackingVariables +>(orderFulfillmentUpdateTrackingMutation); + +const orderFulfillmentCancelMutation = gql` + ${fragmentOrderDetails} + mutation OrderFulfillmentCancel($id: ID!, $input: FulfillmentCancelInput!) { + orderFulfillmentCancel(id: $id, input: $input) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderFulfillmentCancelMutation = TypedMutation< + OrderFulfillmentCancel, + OrderFulfillmentCancelVariables +>(orderFulfillmentCancelMutation); + +const orderAddNoteMutation = gql` + ${fragmentOrderEvent} + mutation OrderAddNote($order: ID!, $input: OrderAddNoteInput!) { + orderAddNote(order: $order, input: $input) { + errors { + field + message + } + order { + id + events { + ...OrderEventFragment + } + } + } + } +`; +export const TypedOrderAddNoteMutation = TypedMutation< + OrderAddNote, + OrderAddNoteVariables +>(orderAddNoteMutation); + +const orderUpdateMutation = gql` + ${fragmentAddress} + mutation OrderUpdate($id: ID!, $input: OrderUpdateInput!) { + orderUpdate(id: $id, input: $input) { + errors { + field + message + } + order { + id + userEmail + billingAddress { + ...AddressFragment + } + shippingAddress { + ...AddressFragment + } + } + } + } +`; +export const TypedOrderUpdateMutation = TypedMutation< + OrderUpdate, + OrderUpdateVariables +>(orderUpdateMutation); + +const orderDraftUpdateMutation = gql` + ${fragmentOrderDetails} + mutation OrderDraftUpdate($id: ID!, $input: DraftOrderInput!) { + draftOrderUpdate(id: $id, input: $input) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderDraftUpdateMutation = TypedMutation< + OrderDraftUpdate, + OrderDraftUpdateVariables +>(orderDraftUpdateMutation); + +const orderShippingMethodUpdateMutation = gql` + mutation OrderShippingMethodUpdate( + $id: ID! + $input: OrderUpdateShippingInput! + ) { + orderUpdateShipping(order: $id, input: $input) { + errors { + field + message + } + order { + availableShippingMethods { + id + name + } + id + shippingMethod { + id + name + price { + amount + currency + } + } + shippingMethodName + shippingPrice { + gross { + amount + currency + } + } + } + } + } +`; +export const TypedOrderShippingMethodUpdateMutation = TypedMutation< + OrderShippingMethodUpdate, + OrderShippingMethodUpdateVariables +>(orderShippingMethodUpdateMutation); + +const orderDraftCreateMutation = gql` + mutation OrderDraftCreate { + draftOrderCreate(input: {}) { + errors { + field + message + } + order { + id + } + } + } +`; +export const TypedOrderDraftCreateMutation = TypedMutation< + OrderDraftCreate, + {} +>(orderDraftCreateMutation); + +const orderLineDeleteMutation = gql` + ${fragmentOrderDetails} + mutation OrderLineDelete($id: ID!) { + draftOrderLineDelete(id: $id) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderLineDeleteMutation = TypedMutation< + OrderLineDelete, + OrderLineDeleteVariables +>(orderLineDeleteMutation); + +const orderLinesAddMutation = gql` + ${fragmentOrderDetails} + mutation OrderLinesAdd($id: ID!, $input: [OrderLineCreateInput]!) { + draftOrderLinesCreate(id: $id, input: $input) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderLinesAddMutation = TypedMutation< + OrderLinesAdd, + OrderLinesAddVariables +>(orderLinesAddMutation); + +const orderLineUpdateMutation = gql` + ${fragmentOrderDetails} + mutation OrderLineUpdate($id: ID!, $input: OrderLineInput!) { + draftOrderLineUpdate(id: $id, input: $input) { + errors { + field + message + } + order { + ...OrderDetailsFragment + } + } + } +`; +export const TypedOrderLineUpdateMutation = TypedMutation< + OrderLineUpdate, + OrderLineUpdateVariables +>(orderLineUpdateMutation); diff --git a/src/orders/queries.ts b/src/orders/queries.ts new file mode 100644 index 000000000..87a006b28 --- /dev/null +++ b/src/orders/queries.ts @@ -0,0 +1,315 @@ +import gql from "graphql-tag"; + +import BaseSearch from "../containers/BaseSearch"; +import { TypedQuery } from "../queries"; +import { OrderDetails, OrderDetailsVariables } from "./types/OrderDetails"; +import { + OrderDraftList, + OrderDraftListVariables +} from "./types/OrderDraftList"; +import { OrderList, OrderListVariables } from "./types/OrderList"; +import { + SearchOrderVariant as SearchOrderVariantType, + SearchOrderVariantVariables +} from "./types/SearchOrderVariant"; + +export const fragmentOrderEvent = gql` + fragment OrderEventFragment on OrderEvent { + id + amount + date + email + emailType + message + quantity + type + user { + id + email + } + } +`; +export const fragmentAddress = gql` + fragment AddressFragment on Address { + city + cityArea + companyName + country { + __typename + code + country + } + countryArea + firstName + id + lastName + phone + postalCode + streetAddress1 + streetAddress2 + } +`; +export const fragmentOrderLine = gql` + fragment OrderLineFragment on OrderLine { + id + isShippingRequired + productName + productSku + quantity + quantityFulfilled + unitPrice { + gross { + amount + currency + } + net { + amount + currency + } + } + thumbnail { + url + } + } +`; + +export const fragmentOrderDetails = gql` + ${fragmentAddress} + ${fragmentOrderEvent} + ${fragmentOrderLine} + fragment OrderDetailsFragment on Order { + id + billingAddress { + ...AddressFragment + } + canFinalize + created + customerNote + events { + ...OrderEventFragment + } + fulfillments { + id + lines { + id + quantity + orderLine { + ...OrderLineFragment + } + } + fulfillmentOrder + status + trackingNumber + } + lines { + ...OrderLineFragment + } + number + paymentStatus + shippingAddress { + ...AddressFragment + } + shippingMethod { + id + } + shippingMethodName + shippingPrice { + gross { + amount + currency + } + } + status + subtotal { + gross { + amount + currency + } + } + total { + gross { + amount + currency + } + tax { + amount + currency + } + } + actions + totalAuthorized { + amount + currency + } + totalCaptured { + amount + currency + } + user { + id + email + } + userEmail + availableShippingMethods { + id + name + price { + amount + currency + } + } + } +`; + +export const orderListQuery = gql` + ${fragmentAddress} + query OrderList( + $first: Int + $after: String + $last: Int + $before: String + $status: OrderStatusFilter + $filter: OrderFilterInput + ) { + orders( + before: $before + after: $after + first: $first + last: $last + status: $status + filter: $filter + ) { + edges { + node { + __typename + billingAddress { + ...AddressFragment + } + created + id + number + paymentStatus + status + total { + __typename + gross { + __typename + amount + currency + } + } + userEmail + } + } + pageInfo { + hasPreviousPage + hasNextPage + startCursor + endCursor + } + } + } +`; +export const TypedOrderListQuery = TypedQuery( + orderListQuery +); + +export const orderDraftListQuery = gql` + ${fragmentAddress} + query OrderDraftList( + $first: Int + $after: String + $last: Int + $before: String + ) { + draftOrders(before: $before, after: $after, first: $first, last: $last) { + edges { + node { + __typename + billingAddress { + ...AddressFragment + } + created + id + number + paymentStatus + status + total { + __typename + gross { + __typename + amount + currency + } + } + userEmail + } + } + pageInfo { + hasPreviousPage + hasNextPage + startCursor + endCursor + } + } + } +`; +export const TypedOrderDraftListQuery = TypedQuery< + OrderDraftList, + OrderDraftListVariables +>(orderDraftListQuery); + +export const orderDetailsQuery = gql` + ${fragmentOrderDetails} + query OrderDetails($id: ID!) { + order(id: $id) { + ...OrderDetailsFragment + } + shop { + countries { + code + country + } + defaultWeightUnit + } + } +`; +export const TypedOrderDetailsQuery = TypedQuery< + OrderDetails, + OrderDetailsVariables +>(orderDetailsQuery); + +export const searchOrderVariant = gql` + query SearchOrderVariant($first: Int!, $query: String!, $after: String) { + products(query: $query, first: $first, after: $after) { + edges { + node { + id + name + thumbnail { + url + } + variants { + id + name + sku + price { + amount + currency + } + } + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } + } +`; +export const SearchOrderVariant = BaseSearch< + SearchOrderVariantType, + SearchOrderVariantVariables +>(searchOrderVariant); diff --git a/src/orders/types/AddressFragment.ts b/src/orders/types/AddressFragment.ts new file mode 100644 index 000000000..fbe0fe508 --- /dev/null +++ b/src/orders/types/AddressFragment.ts @@ -0,0 +1,29 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: AddressFragment +// ==================================================== + +export interface AddressFragment_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface AddressFragment { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: AddressFragment_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} diff --git a/src/orders/types/OrderAddNote.ts b/src/orders/types/OrderAddNote.ts new file mode 100644 index 000000000..dc42af7cb --- /dev/null +++ b/src/orders/types/OrderAddNote.ts @@ -0,0 +1,55 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderAddNoteInput, OrderEventsEmailsEnum, OrderEventsEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderAddNote +// ==================================================== + +export interface OrderAddNote_orderAddNote_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderAddNote_orderAddNote_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderAddNote_orderAddNote_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderAddNote_orderAddNote_order_events_user | null; +} + +export interface OrderAddNote_orderAddNote_order { + __typename: "Order"; + id: string; + events: (OrderAddNote_orderAddNote_order_events | null)[] | null; +} + +export interface OrderAddNote_orderAddNote { + __typename: "OrderAddNote"; + errors: OrderAddNote_orderAddNote_errors[] | null; + order: OrderAddNote_orderAddNote_order | null; +} + +export interface OrderAddNote { + orderAddNote: OrderAddNote_orderAddNote | null; +} + +export interface OrderAddNoteVariables { + order: string; + input: OrderAddNoteInput; +} diff --git a/src/orders/types/OrderBulkCancel.ts b/src/orders/types/OrderBulkCancel.ts new file mode 100644 index 000000000..ad442d58e --- /dev/null +++ b/src/orders/types/OrderBulkCancel.ts @@ -0,0 +1,27 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: OrderBulkCancel +// ==================================================== + +export interface OrderBulkCancel_orderBulkCancel_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderBulkCancel_orderBulkCancel { + __typename: "OrderBulkCancel"; + errors: OrderBulkCancel_orderBulkCancel_errors[] | null; +} + +export interface OrderBulkCancel { + orderBulkCancel: OrderBulkCancel_orderBulkCancel | null; +} + +export interface OrderBulkCancelVariables { + ids: (string | null)[]; + restock: boolean; +} diff --git a/src/orders/types/OrderCancel.ts b/src/orders/types/OrderCancel.ts new file mode 100644 index 000000000..4be781645 --- /dev/null +++ b/src/orders/types/OrderCancel.ts @@ -0,0 +1,282 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderCancel +// ==================================================== + +export interface OrderCancel_orderCancel_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderCancel_orderCancel_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderCancel_orderCancel_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderCancel_orderCancel_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderCancel_orderCancel_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderCancel_orderCancel_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderCancel_orderCancel_order_events_user | null; +} + +export interface OrderCancel_orderCancel_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderCancel_orderCancel_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderCancel_orderCancel_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderCancel_orderCancel_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderCancel_orderCancel_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderCancel_orderCancel_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderCancel_orderCancel_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderCancel_orderCancel_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderCancel_orderCancel_order_fulfillments_lines_orderLine | null; +} + +export interface OrderCancel_orderCancel_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderCancel_orderCancel_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderCancel_orderCancel_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderCancel_orderCancel_order_lines_unitPrice_gross; + net: OrderCancel_orderCancel_order_lines_unitPrice_net; +} + +export interface OrderCancel_orderCancel_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderCancel_orderCancel_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderCancel_orderCancel_order_lines_unitPrice | null; + thumbnail: OrderCancel_orderCancel_order_lines_thumbnail | null; +} + +export interface OrderCancel_orderCancel_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderCancel_orderCancel_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderCancel_orderCancel_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderCancel_orderCancel_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderCancel_orderCancel_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderCancel_orderCancel_order_shippingPrice_gross; +} + +export interface OrderCancel_orderCancel_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderCancel_orderCancel_order_subtotal_gross; +} + +export interface OrderCancel_orderCancel_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_total { + __typename: "TaxedMoney"; + gross: OrderCancel_orderCancel_order_total_gross; + tax: OrderCancel_orderCancel_order_total_tax; +} + +export interface OrderCancel_orderCancel_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderCancel_orderCancel_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCancel_orderCancel_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderCancel_orderCancel_order_availableShippingMethods_price | null; +} + +export interface OrderCancel_orderCancel_order { + __typename: "Order"; + id: string; + billingAddress: OrderCancel_orderCancel_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderCancel_orderCancel_order_events | null)[] | null; + fulfillments: (OrderCancel_orderCancel_order_fulfillments | null)[]; + lines: (OrderCancel_orderCancel_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderCancel_orderCancel_order_shippingAddress | null; + shippingMethod: OrderCancel_orderCancel_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderCancel_orderCancel_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderCancel_orderCancel_order_subtotal | null; + total: OrderCancel_orderCancel_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderCancel_orderCancel_order_totalAuthorized | null; + totalCaptured: OrderCancel_orderCancel_order_totalCaptured | null; + user: OrderCancel_orderCancel_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderCancel_orderCancel_order_availableShippingMethods | null)[] | null; +} + +export interface OrderCancel_orderCancel { + __typename: "OrderCancel"; + errors: OrderCancel_orderCancel_errors[] | null; + order: OrderCancel_orderCancel_order | null; +} + +export interface OrderCancel { + orderCancel: OrderCancel_orderCancel | null; +} + +export interface OrderCancelVariables { + id: string; + restock: boolean; +} diff --git a/src/orders/types/OrderCapture.ts b/src/orders/types/OrderCapture.ts new file mode 100644 index 000000000..2c3bf0f51 --- /dev/null +++ b/src/orders/types/OrderCapture.ts @@ -0,0 +1,282 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderCapture +// ==================================================== + +export interface OrderCapture_orderCapture_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderCapture_orderCapture_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderCapture_orderCapture_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderCapture_orderCapture_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderCapture_orderCapture_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderCapture_orderCapture_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderCapture_orderCapture_order_events_user | null; +} + +export interface OrderCapture_orderCapture_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderCapture_orderCapture_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderCapture_orderCapture_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderCapture_orderCapture_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderCapture_orderCapture_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderCapture_orderCapture_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderCapture_orderCapture_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderCapture_orderCapture_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderCapture_orderCapture_order_fulfillments_lines_orderLine | null; +} + +export interface OrderCapture_orderCapture_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderCapture_orderCapture_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderCapture_orderCapture_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderCapture_orderCapture_order_lines_unitPrice_gross; + net: OrderCapture_orderCapture_order_lines_unitPrice_net; +} + +export interface OrderCapture_orderCapture_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderCapture_orderCapture_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderCapture_orderCapture_order_lines_unitPrice | null; + thumbnail: OrderCapture_orderCapture_order_lines_thumbnail | null; +} + +export interface OrderCapture_orderCapture_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderCapture_orderCapture_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderCapture_orderCapture_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderCapture_orderCapture_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderCapture_orderCapture_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderCapture_orderCapture_order_shippingPrice_gross; +} + +export interface OrderCapture_orderCapture_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderCapture_orderCapture_order_subtotal_gross; +} + +export interface OrderCapture_orderCapture_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_total { + __typename: "TaxedMoney"; + gross: OrderCapture_orderCapture_order_total_gross; + tax: OrderCapture_orderCapture_order_total_tax; +} + +export interface OrderCapture_orderCapture_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderCapture_orderCapture_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCapture_orderCapture_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderCapture_orderCapture_order_availableShippingMethods_price | null; +} + +export interface OrderCapture_orderCapture_order { + __typename: "Order"; + id: string; + billingAddress: OrderCapture_orderCapture_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderCapture_orderCapture_order_events | null)[] | null; + fulfillments: (OrderCapture_orderCapture_order_fulfillments | null)[]; + lines: (OrderCapture_orderCapture_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderCapture_orderCapture_order_shippingAddress | null; + shippingMethod: OrderCapture_orderCapture_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderCapture_orderCapture_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderCapture_orderCapture_order_subtotal | null; + total: OrderCapture_orderCapture_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderCapture_orderCapture_order_totalAuthorized | null; + totalCaptured: OrderCapture_orderCapture_order_totalCaptured | null; + user: OrderCapture_orderCapture_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderCapture_orderCapture_order_availableShippingMethods | null)[] | null; +} + +export interface OrderCapture_orderCapture { + __typename: "OrderCapture"; + errors: OrderCapture_orderCapture_errors[] | null; + order: OrderCapture_orderCapture_order | null; +} + +export interface OrderCapture { + orderCapture: OrderCapture_orderCapture | null; +} + +export interface OrderCaptureVariables { + id: string; + amount: any; +} diff --git a/src/orders/types/OrderCreateFulfillment.ts b/src/orders/types/OrderCreateFulfillment.ts new file mode 100644 index 000000000..0cba57943 --- /dev/null +++ b/src/orders/types/OrderCreateFulfillment.ts @@ -0,0 +1,282 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { FulfillmentCreateInput, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderCreateFulfillment +// ==================================================== + +export interface OrderCreateFulfillment_orderFulfillmentCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderCreateFulfillment_orderFulfillmentCreate_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderCreateFulfillment_orderFulfillmentCreate_order_events_user | null; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines_orderLine | null; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderCreateFulfillment_orderFulfillmentCreate_order_lines_unitPrice_gross; + net: OrderCreateFulfillment_orderFulfillmentCreate_order_lines_unitPrice_net; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderCreateFulfillment_orderFulfillmentCreate_order_lines_unitPrice | null; + thumbnail: OrderCreateFulfillment_orderFulfillmentCreate_order_lines_thumbnail | null; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderCreateFulfillment_orderFulfillmentCreate_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderCreateFulfillment_orderFulfillmentCreate_order_shippingPrice_gross; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderCreateFulfillment_orderFulfillmentCreate_order_subtotal_gross; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_total { + __typename: "TaxedMoney"; + gross: OrderCreateFulfillment_orderFulfillmentCreate_order_total_gross; + tax: OrderCreateFulfillment_orderFulfillmentCreate_order_total_tax; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderCreateFulfillment_orderFulfillmentCreate_order_availableShippingMethods_price | null; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate_order { + __typename: "Order"; + id: string; + billingAddress: OrderCreateFulfillment_orderFulfillmentCreate_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderCreateFulfillment_orderFulfillmentCreate_order_events | null)[] | null; + fulfillments: (OrderCreateFulfillment_orderFulfillmentCreate_order_fulfillments | null)[]; + lines: (OrderCreateFulfillment_orderFulfillmentCreate_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderCreateFulfillment_orderFulfillmentCreate_order_shippingAddress | null; + shippingMethod: OrderCreateFulfillment_orderFulfillmentCreate_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderCreateFulfillment_orderFulfillmentCreate_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderCreateFulfillment_orderFulfillmentCreate_order_subtotal | null; + total: OrderCreateFulfillment_orderFulfillmentCreate_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderCreateFulfillment_orderFulfillmentCreate_order_totalAuthorized | null; + totalCaptured: OrderCreateFulfillment_orderFulfillmentCreate_order_totalCaptured | null; + user: OrderCreateFulfillment_orderFulfillmentCreate_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderCreateFulfillment_orderFulfillmentCreate_order_availableShippingMethods | null)[] | null; +} + +export interface OrderCreateFulfillment_orderFulfillmentCreate { + __typename: "FulfillmentCreate"; + errors: OrderCreateFulfillment_orderFulfillmentCreate_errors[] | null; + order: OrderCreateFulfillment_orderFulfillmentCreate_order | null; +} + +export interface OrderCreateFulfillment { + orderFulfillmentCreate: OrderCreateFulfillment_orderFulfillmentCreate | null; +} + +export interface OrderCreateFulfillmentVariables { + order: string; + input: FulfillmentCreateInput; +} diff --git a/src/orders/types/OrderDetails.ts b/src/orders/types/OrderDetails.ts new file mode 100644 index 000000000..b6bb55380 --- /dev/null +++ b/src/orders/types/OrderDetails.ts @@ -0,0 +1,282 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, WeightUnitsEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: OrderDetails +// ==================================================== + +export interface OrderDetails_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDetails_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderDetails_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderDetails_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderDetails_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderDetails_order_events_user | null; +} + +export interface OrderDetails_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderDetails_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderDetails_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderDetails_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderDetails_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderDetails_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderDetails_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderDetails_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderDetails_order_fulfillments_lines_orderLine | null; +} + +export interface OrderDetails_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderDetails_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderDetails_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderDetails_order_lines_unitPrice_gross; + net: OrderDetails_order_lines_unitPrice_net; +} + +export interface OrderDetails_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderDetails_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderDetails_order_lines_unitPrice | null; + thumbnail: OrderDetails_order_lines_thumbnail | null; +} + +export interface OrderDetails_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDetails_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderDetails_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderDetails_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderDetails_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderDetails_order_shippingPrice_gross; +} + +export interface OrderDetails_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderDetails_order_subtotal_gross; +} + +export interface OrderDetails_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_total { + __typename: "TaxedMoney"; + gross: OrderDetails_order_total_gross; + tax: OrderDetails_order_total_tax; +} + +export interface OrderDetails_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderDetails_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetails_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderDetails_order_availableShippingMethods_price | null; +} + +export interface OrderDetails_order { + __typename: "Order"; + id: string; + billingAddress: OrderDetails_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderDetails_order_events | null)[] | null; + fulfillments: (OrderDetails_order_fulfillments | null)[]; + lines: (OrderDetails_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderDetails_order_shippingAddress | null; + shippingMethod: OrderDetails_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderDetails_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderDetails_order_subtotal | null; + total: OrderDetails_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderDetails_order_totalAuthorized | null; + totalCaptured: OrderDetails_order_totalCaptured | null; + user: OrderDetails_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderDetails_order_availableShippingMethods | null)[] | null; +} + +export interface OrderDetails_shop_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDetails_shop { + __typename: "Shop"; + countries: (OrderDetails_shop_countries | null)[]; + defaultWeightUnit: WeightUnitsEnum | null; +} + +export interface OrderDetails { + order: OrderDetails_order | null; + shop: OrderDetails_shop | null; +} + +export interface OrderDetailsVariables { + id: string; +} diff --git a/src/orders/types/OrderDetailsFragment.ts b/src/orders/types/OrderDetailsFragment.ts new file mode 100644 index 000000000..fc2f5d3ba --- /dev/null +++ b/src/orders/types/OrderDetailsFragment.ts @@ -0,0 +1,261 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: OrderDetailsFragment +// ==================================================== + +export interface OrderDetailsFragment_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDetailsFragment_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderDetailsFragment_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderDetailsFragment_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderDetailsFragment_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderDetailsFragment_events_user | null; +} + +export interface OrderDetailsFragment_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderDetailsFragment_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderDetailsFragment_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderDetailsFragment_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderDetailsFragment_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderDetailsFragment_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderDetailsFragment_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderDetailsFragment_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderDetailsFragment_fulfillments_lines_orderLine | null; +} + +export interface OrderDetailsFragment_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderDetailsFragment_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderDetailsFragment_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderDetailsFragment_lines_unitPrice_gross; + net: OrderDetailsFragment_lines_unitPrice_net; +} + +export interface OrderDetailsFragment_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderDetailsFragment_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderDetailsFragment_lines_unitPrice | null; + thumbnail: OrderDetailsFragment_lines_thumbnail | null; +} + +export interface OrderDetailsFragment_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDetailsFragment_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderDetailsFragment_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderDetailsFragment_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderDetailsFragment_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderDetailsFragment_shippingPrice_gross; +} + +export interface OrderDetailsFragment_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_subtotal { + __typename: "TaxedMoney"; + gross: OrderDetailsFragment_subtotal_gross; +} + +export interface OrderDetailsFragment_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_total { + __typename: "TaxedMoney"; + gross: OrderDetailsFragment_total_gross; + tax: OrderDetailsFragment_total_tax; +} + +export interface OrderDetailsFragment_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderDetailsFragment_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDetailsFragment_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderDetailsFragment_availableShippingMethods_price | null; +} + +export interface OrderDetailsFragment { + __typename: "Order"; + id: string; + billingAddress: OrderDetailsFragment_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderDetailsFragment_events | null)[] | null; + fulfillments: (OrderDetailsFragment_fulfillments | null)[]; + lines: (OrderDetailsFragment_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderDetailsFragment_shippingAddress | null; + shippingMethod: OrderDetailsFragment_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderDetailsFragment_shippingPrice | null; + status: OrderStatus; + subtotal: OrderDetailsFragment_subtotal | null; + total: OrderDetailsFragment_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderDetailsFragment_totalAuthorized | null; + totalCaptured: OrderDetailsFragment_totalCaptured | null; + user: OrderDetailsFragment_user | null; + userEmail: string | null; + availableShippingMethods: (OrderDetailsFragment_availableShippingMethods | null)[] | null; +} diff --git a/src/orders/types/OrderDraftBulkCancel.ts b/src/orders/types/OrderDraftBulkCancel.ts new file mode 100644 index 000000000..e679e9055 --- /dev/null +++ b/src/orders/types/OrderDraftBulkCancel.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: OrderDraftBulkCancel +// ==================================================== + +export interface OrderDraftBulkCancel_draftOrderBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderDraftBulkCancel_draftOrderBulkDelete { + __typename: "DraftOrderBulkDelete"; + errors: OrderDraftBulkCancel_draftOrderBulkDelete_errors[] | null; +} + +export interface OrderDraftBulkCancel { + draftOrderBulkDelete: OrderDraftBulkCancel_draftOrderBulkDelete | null; +} + +export interface OrderDraftBulkCancelVariables { + ids: (string | null)[]; +} diff --git a/src/orders/types/OrderDraftCancel.ts b/src/orders/types/OrderDraftCancel.ts new file mode 100644 index 000000000..675b8bac5 --- /dev/null +++ b/src/orders/types/OrderDraftCancel.ts @@ -0,0 +1,281 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderDraftCancel +// ==================================================== + +export interface OrderDraftCancel_draftOrderDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderDraftCancel_draftOrderDelete_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderDraftCancel_draftOrderDelete_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderDraftCancel_draftOrderDelete_order_events_user | null; +} + +export interface OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderDraftCancel_draftOrderDelete_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderDraftCancel_draftOrderDelete_order_fulfillments_lines_orderLine | null; +} + +export interface OrderDraftCancel_draftOrderDelete_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderDraftCancel_draftOrderDelete_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderDraftCancel_draftOrderDelete_order_lines_unitPrice_gross; + net: OrderDraftCancel_draftOrderDelete_order_lines_unitPrice_net; +} + +export interface OrderDraftCancel_draftOrderDelete_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderDraftCancel_draftOrderDelete_order_lines_unitPrice | null; + thumbnail: OrderDraftCancel_draftOrderDelete_order_lines_thumbnail | null; +} + +export interface OrderDraftCancel_draftOrderDelete_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderDraftCancel_draftOrderDelete_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderDraftCancel_draftOrderDelete_order_shippingPrice_gross; +} + +export interface OrderDraftCancel_draftOrderDelete_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderDraftCancel_draftOrderDelete_order_subtotal_gross; +} + +export interface OrderDraftCancel_draftOrderDelete_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_total { + __typename: "TaxedMoney"; + gross: OrderDraftCancel_draftOrderDelete_order_total_gross; + tax: OrderDraftCancel_draftOrderDelete_order_total_tax; +} + +export interface OrderDraftCancel_draftOrderDelete_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftCancel_draftOrderDelete_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderDraftCancel_draftOrderDelete_order_availableShippingMethods_price | null; +} + +export interface OrderDraftCancel_draftOrderDelete_order { + __typename: "Order"; + id: string; + billingAddress: OrderDraftCancel_draftOrderDelete_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderDraftCancel_draftOrderDelete_order_events | null)[] | null; + fulfillments: (OrderDraftCancel_draftOrderDelete_order_fulfillments | null)[]; + lines: (OrderDraftCancel_draftOrderDelete_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderDraftCancel_draftOrderDelete_order_shippingAddress | null; + shippingMethod: OrderDraftCancel_draftOrderDelete_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderDraftCancel_draftOrderDelete_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderDraftCancel_draftOrderDelete_order_subtotal | null; + total: OrderDraftCancel_draftOrderDelete_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderDraftCancel_draftOrderDelete_order_totalAuthorized | null; + totalCaptured: OrderDraftCancel_draftOrderDelete_order_totalCaptured | null; + user: OrderDraftCancel_draftOrderDelete_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderDraftCancel_draftOrderDelete_order_availableShippingMethods | null)[] | null; +} + +export interface OrderDraftCancel_draftOrderDelete { + __typename: "DraftOrderDelete"; + errors: OrderDraftCancel_draftOrderDelete_errors[] | null; + order: OrderDraftCancel_draftOrderDelete_order | null; +} + +export interface OrderDraftCancel { + draftOrderDelete: OrderDraftCancel_draftOrderDelete | null; +} + +export interface OrderDraftCancelVariables { + id: string; +} diff --git a/src/orders/types/OrderDraftCreate.ts b/src/orders/types/OrderDraftCreate.ts new file mode 100644 index 000000000..a978459cc --- /dev/null +++ b/src/orders/types/OrderDraftCreate.ts @@ -0,0 +1,28 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: OrderDraftCreate +// ==================================================== + +export interface OrderDraftCreate_draftOrderCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderDraftCreate_draftOrderCreate_order { + __typename: "Order"; + id: string; +} + +export interface OrderDraftCreate_draftOrderCreate { + __typename: "DraftOrderCreate"; + errors: OrderDraftCreate_draftOrderCreate_errors[] | null; + order: OrderDraftCreate_draftOrderCreate_order | null; +} + +export interface OrderDraftCreate { + draftOrderCreate: OrderDraftCreate_draftOrderCreate | null; +} diff --git a/src/orders/types/OrderDraftFinalize.ts b/src/orders/types/OrderDraftFinalize.ts new file mode 100644 index 000000000..5076ae026 --- /dev/null +++ b/src/orders/types/OrderDraftFinalize.ts @@ -0,0 +1,281 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderDraftFinalize +// ==================================================== + +export interface OrderDraftFinalize_draftOrderComplete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderDraftFinalize_draftOrderComplete_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderDraftFinalize_draftOrderComplete_order_events_user | null; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines_orderLine | null; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderDraftFinalize_draftOrderComplete_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderDraftFinalize_draftOrderComplete_order_lines_unitPrice_gross; + net: OrderDraftFinalize_draftOrderComplete_order_lines_unitPrice_net; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderDraftFinalize_draftOrderComplete_order_lines_unitPrice | null; + thumbnail: OrderDraftFinalize_draftOrderComplete_order_lines_thumbnail | null; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderDraftFinalize_draftOrderComplete_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderDraftFinalize_draftOrderComplete_order_shippingPrice_gross; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderDraftFinalize_draftOrderComplete_order_subtotal_gross; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_total { + __typename: "TaxedMoney"; + gross: OrderDraftFinalize_draftOrderComplete_order_total_gross; + tax: OrderDraftFinalize_draftOrderComplete_order_total_tax; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftFinalize_draftOrderComplete_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderDraftFinalize_draftOrderComplete_order_availableShippingMethods_price | null; +} + +export interface OrderDraftFinalize_draftOrderComplete_order { + __typename: "Order"; + id: string; + billingAddress: OrderDraftFinalize_draftOrderComplete_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderDraftFinalize_draftOrderComplete_order_events | null)[] | null; + fulfillments: (OrderDraftFinalize_draftOrderComplete_order_fulfillments | null)[]; + lines: (OrderDraftFinalize_draftOrderComplete_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderDraftFinalize_draftOrderComplete_order_shippingAddress | null; + shippingMethod: OrderDraftFinalize_draftOrderComplete_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderDraftFinalize_draftOrderComplete_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderDraftFinalize_draftOrderComplete_order_subtotal | null; + total: OrderDraftFinalize_draftOrderComplete_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderDraftFinalize_draftOrderComplete_order_totalAuthorized | null; + totalCaptured: OrderDraftFinalize_draftOrderComplete_order_totalCaptured | null; + user: OrderDraftFinalize_draftOrderComplete_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderDraftFinalize_draftOrderComplete_order_availableShippingMethods | null)[] | null; +} + +export interface OrderDraftFinalize_draftOrderComplete { + __typename: "DraftOrderComplete"; + errors: OrderDraftFinalize_draftOrderComplete_errors[] | null; + order: OrderDraftFinalize_draftOrderComplete_order | null; +} + +export interface OrderDraftFinalize { + draftOrderComplete: OrderDraftFinalize_draftOrderComplete | null; +} + +export interface OrderDraftFinalizeVariables { + id: string; +} diff --git a/src/orders/types/OrderDraftList.ts b/src/orders/types/OrderDraftList.ts new file mode 100644 index 000000000..c3567edca --- /dev/null +++ b/src/orders/types/OrderDraftList.ts @@ -0,0 +1,84 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PaymentChargeStatusEnum, OrderStatus } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: OrderDraftList +// ==================================================== + +export interface OrderDraftList_draftOrders_edges_node_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDraftList_draftOrders_edges_node_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderDraftList_draftOrders_edges_node_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderDraftList_draftOrders_edges_node_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftList_draftOrders_edges_node_total { + __typename: "TaxedMoney"; + gross: OrderDraftList_draftOrders_edges_node_total_gross; +} + +export interface OrderDraftList_draftOrders_edges_node { + __typename: "Order"; + billingAddress: OrderDraftList_draftOrders_edges_node_billingAddress | null; + created: any; + id: string; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + status: OrderStatus; + total: OrderDraftList_draftOrders_edges_node_total | null; + userEmail: string | null; +} + +export interface OrderDraftList_draftOrders_edges { + __typename: "OrderCountableEdge"; + node: OrderDraftList_draftOrders_edges_node; +} + +export interface OrderDraftList_draftOrders_pageInfo { + __typename: "PageInfo"; + hasPreviousPage: boolean; + hasNextPage: boolean; + startCursor: string | null; + endCursor: string | null; +} + +export interface OrderDraftList_draftOrders { + __typename: "OrderCountableConnection"; + edges: OrderDraftList_draftOrders_edges[]; + pageInfo: OrderDraftList_draftOrders_pageInfo; +} + +export interface OrderDraftList { + draftOrders: OrderDraftList_draftOrders | null; +} + +export interface OrderDraftListVariables { + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/orders/types/OrderDraftUpdate.ts b/src/orders/types/OrderDraftUpdate.ts new file mode 100644 index 000000000..6d446e0fe --- /dev/null +++ b/src/orders/types/OrderDraftUpdate.ts @@ -0,0 +1,282 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { DraftOrderInput, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderDraftUpdate +// ==================================================== + +export interface OrderDraftUpdate_draftOrderUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderDraftUpdate_draftOrderUpdate_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderDraftUpdate_draftOrderUpdate_order_events_user | null; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines_orderLine | null; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderDraftUpdate_draftOrderUpdate_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderDraftUpdate_draftOrderUpdate_order_lines_unitPrice_gross; + net: OrderDraftUpdate_draftOrderUpdate_order_lines_unitPrice_net; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderDraftUpdate_draftOrderUpdate_order_lines_unitPrice | null; + thumbnail: OrderDraftUpdate_draftOrderUpdate_order_lines_thumbnail | null; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderDraftUpdate_draftOrderUpdate_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderDraftUpdate_draftOrderUpdate_order_shippingPrice_gross; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderDraftUpdate_draftOrderUpdate_order_subtotal_gross; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_total { + __typename: "TaxedMoney"; + gross: OrderDraftUpdate_draftOrderUpdate_order_total_gross; + tax: OrderDraftUpdate_draftOrderUpdate_order_total_tax; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderDraftUpdate_draftOrderUpdate_order_availableShippingMethods_price | null; +} + +export interface OrderDraftUpdate_draftOrderUpdate_order { + __typename: "Order"; + id: string; + billingAddress: OrderDraftUpdate_draftOrderUpdate_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderDraftUpdate_draftOrderUpdate_order_events | null)[] | null; + fulfillments: (OrderDraftUpdate_draftOrderUpdate_order_fulfillments | null)[]; + lines: (OrderDraftUpdate_draftOrderUpdate_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderDraftUpdate_draftOrderUpdate_order_shippingAddress | null; + shippingMethod: OrderDraftUpdate_draftOrderUpdate_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderDraftUpdate_draftOrderUpdate_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderDraftUpdate_draftOrderUpdate_order_subtotal | null; + total: OrderDraftUpdate_draftOrderUpdate_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderDraftUpdate_draftOrderUpdate_order_totalAuthorized | null; + totalCaptured: OrderDraftUpdate_draftOrderUpdate_order_totalCaptured | null; + user: OrderDraftUpdate_draftOrderUpdate_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderDraftUpdate_draftOrderUpdate_order_availableShippingMethods | null)[] | null; +} + +export interface OrderDraftUpdate_draftOrderUpdate { + __typename: "DraftOrderUpdate"; + errors: OrderDraftUpdate_draftOrderUpdate_errors[] | null; + order: OrderDraftUpdate_draftOrderUpdate_order | null; +} + +export interface OrderDraftUpdate { + draftOrderUpdate: OrderDraftUpdate_draftOrderUpdate | null; +} + +export interface OrderDraftUpdateVariables { + id: string; + input: DraftOrderInput; +} diff --git a/src/orders/types/OrderEventFragment.ts b/src/orders/types/OrderEventFragment.ts new file mode 100644 index 000000000..324d3d958 --- /dev/null +++ b/src/orders/types/OrderEventFragment.ts @@ -0,0 +1,28 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: OrderEventFragment +// ==================================================== + +export interface OrderEventFragment_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderEventFragment { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderEventFragment_user | null; +} diff --git a/src/orders/types/OrderFulfillmentCancel.ts b/src/orders/types/OrderFulfillmentCancel.ts new file mode 100644 index 000000000..217ddda7b --- /dev/null +++ b/src/orders/types/OrderFulfillmentCancel.ts @@ -0,0 +1,282 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { FulfillmentCancelInput, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderFulfillmentCancel +// ==================================================== + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderFulfillmentCancel_orderFulfillmentCancel_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderFulfillmentCancel_orderFulfillmentCancel_order_events_user | null; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines_orderLine | null; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_unitPrice_gross; + net: OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_unitPrice_net; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_unitPrice | null; + thumbnail: OrderFulfillmentCancel_orderFulfillmentCancel_order_lines_thumbnail | null; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderFulfillmentCancel_orderFulfillmentCancel_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderFulfillmentCancel_orderFulfillmentCancel_order_shippingPrice_gross; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderFulfillmentCancel_orderFulfillmentCancel_order_subtotal_gross; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_total { + __typename: "TaxedMoney"; + gross: OrderFulfillmentCancel_orderFulfillmentCancel_order_total_gross; + tax: OrderFulfillmentCancel_orderFulfillmentCancel_order_total_tax; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderFulfillmentCancel_orderFulfillmentCancel_order_availableShippingMethods_price | null; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel_order { + __typename: "Order"; + id: string; + billingAddress: OrderFulfillmentCancel_orderFulfillmentCancel_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderFulfillmentCancel_orderFulfillmentCancel_order_events | null)[] | null; + fulfillments: (OrderFulfillmentCancel_orderFulfillmentCancel_order_fulfillments | null)[]; + lines: (OrderFulfillmentCancel_orderFulfillmentCancel_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderFulfillmentCancel_orderFulfillmentCancel_order_shippingAddress | null; + shippingMethod: OrderFulfillmentCancel_orderFulfillmentCancel_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderFulfillmentCancel_orderFulfillmentCancel_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderFulfillmentCancel_orderFulfillmentCancel_order_subtotal | null; + total: OrderFulfillmentCancel_orderFulfillmentCancel_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderFulfillmentCancel_orderFulfillmentCancel_order_totalAuthorized | null; + totalCaptured: OrderFulfillmentCancel_orderFulfillmentCancel_order_totalCaptured | null; + user: OrderFulfillmentCancel_orderFulfillmentCancel_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderFulfillmentCancel_orderFulfillmentCancel_order_availableShippingMethods | null)[] | null; +} + +export interface OrderFulfillmentCancel_orderFulfillmentCancel { + __typename: "FulfillmentCancel"; + errors: OrderFulfillmentCancel_orderFulfillmentCancel_errors[] | null; + order: OrderFulfillmentCancel_orderFulfillmentCancel_order | null; +} + +export interface OrderFulfillmentCancel { + orderFulfillmentCancel: OrderFulfillmentCancel_orderFulfillmentCancel | null; +} + +export interface OrderFulfillmentCancelVariables { + id: string; + input: FulfillmentCancelInput; +} diff --git a/src/orders/types/OrderFulfillmentUpdateTracking.ts b/src/orders/types/OrderFulfillmentUpdateTracking.ts new file mode 100644 index 000000000..e1a912f15 --- /dev/null +++ b/src/orders/types/OrderFulfillmentUpdateTracking.ts @@ -0,0 +1,282 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { FulfillmentUpdateTrackingInput, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderFulfillmentUpdateTracking +// ==================================================== + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_events_user | null; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines_orderLine | null; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_unitPrice_gross; + net: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_unitPrice_net; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_unitPrice | null; + thumbnail: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines_thumbnail | null; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_shippingPrice_gross; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_subtotal_gross; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_total { + __typename: "TaxedMoney"; + gross: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_total_gross; + tax: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_total_tax; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_availableShippingMethods_price | null; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order { + __typename: "Order"; + id: string; + billingAddress: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_events | null)[] | null; + fulfillments: (OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_fulfillments | null)[]; + lines: (OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_shippingAddress | null; + shippingMethod: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_subtotal | null; + total: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_totalAuthorized | null; + totalCaptured: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_totalCaptured | null; + user: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order_availableShippingMethods | null)[] | null; +} + +export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking { + __typename: "FulfillmentUpdateTracking"; + errors: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_errors[] | null; + order: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order | null; +} + +export interface OrderFulfillmentUpdateTracking { + orderFulfillmentUpdateTracking: OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking | null; +} + +export interface OrderFulfillmentUpdateTrackingVariables { + id: string; + input: FulfillmentUpdateTrackingInput; +} diff --git a/src/orders/types/OrderLineDelete.ts b/src/orders/types/OrderLineDelete.ts new file mode 100644 index 000000000..946439ad2 --- /dev/null +++ b/src/orders/types/OrderLineDelete.ts @@ -0,0 +1,281 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderLineDelete +// ==================================================== + +export interface OrderLineDelete_draftOrderLineDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderLineDelete_draftOrderLineDelete_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderLineDelete_draftOrderLineDelete_order_events_user | null; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines_orderLine | null; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderLineDelete_draftOrderLineDelete_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderLineDelete_draftOrderLineDelete_order_lines_unitPrice_gross; + net: OrderLineDelete_draftOrderLineDelete_order_lines_unitPrice_net; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderLineDelete_draftOrderLineDelete_order_lines_unitPrice | null; + thumbnail: OrderLineDelete_draftOrderLineDelete_order_lines_thumbnail | null; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderLineDelete_draftOrderLineDelete_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderLineDelete_draftOrderLineDelete_order_shippingPrice_gross; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderLineDelete_draftOrderLineDelete_order_subtotal_gross; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_total { + __typename: "TaxedMoney"; + gross: OrderLineDelete_draftOrderLineDelete_order_total_gross; + tax: OrderLineDelete_draftOrderLineDelete_order_total_tax; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineDelete_draftOrderLineDelete_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderLineDelete_draftOrderLineDelete_order_availableShippingMethods_price | null; +} + +export interface OrderLineDelete_draftOrderLineDelete_order { + __typename: "Order"; + id: string; + billingAddress: OrderLineDelete_draftOrderLineDelete_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderLineDelete_draftOrderLineDelete_order_events | null)[] | null; + fulfillments: (OrderLineDelete_draftOrderLineDelete_order_fulfillments | null)[]; + lines: (OrderLineDelete_draftOrderLineDelete_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderLineDelete_draftOrderLineDelete_order_shippingAddress | null; + shippingMethod: OrderLineDelete_draftOrderLineDelete_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderLineDelete_draftOrderLineDelete_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderLineDelete_draftOrderLineDelete_order_subtotal | null; + total: OrderLineDelete_draftOrderLineDelete_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderLineDelete_draftOrderLineDelete_order_totalAuthorized | null; + totalCaptured: OrderLineDelete_draftOrderLineDelete_order_totalCaptured | null; + user: OrderLineDelete_draftOrderLineDelete_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderLineDelete_draftOrderLineDelete_order_availableShippingMethods | null)[] | null; +} + +export interface OrderLineDelete_draftOrderLineDelete { + __typename: "DraftOrderLineDelete"; + errors: OrderLineDelete_draftOrderLineDelete_errors[] | null; + order: OrderLineDelete_draftOrderLineDelete_order | null; +} + +export interface OrderLineDelete { + draftOrderLineDelete: OrderLineDelete_draftOrderLineDelete | null; +} + +export interface OrderLineDeleteVariables { + id: string; +} diff --git a/src/orders/types/OrderLineFragment.ts b/src/orders/types/OrderLineFragment.ts new file mode 100644 index 000000000..725832671 --- /dev/null +++ b/src/orders/types/OrderLineFragment.ts @@ -0,0 +1,42 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: OrderLineFragment +// ==================================================== + +export interface OrderLineFragment_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineFragment_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineFragment_unitPrice { + __typename: "TaxedMoney"; + gross: OrderLineFragment_unitPrice_gross; + net: OrderLineFragment_unitPrice_net; +} + +export interface OrderLineFragment_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderLineFragment { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderLineFragment_unitPrice | null; + thumbnail: OrderLineFragment_thumbnail | null; +} diff --git a/src/orders/types/OrderLineUpdate.ts b/src/orders/types/OrderLineUpdate.ts new file mode 100644 index 000000000..a511163ad --- /dev/null +++ b/src/orders/types/OrderLineUpdate.ts @@ -0,0 +1,282 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderLineInput, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderLineUpdate +// ==================================================== + +export interface OrderLineUpdate_draftOrderLineUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderLineUpdate_draftOrderLineUpdate_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderLineUpdate_draftOrderLineUpdate_order_events_user | null; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines_orderLine | null; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderLineUpdate_draftOrderLineUpdate_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderLineUpdate_draftOrderLineUpdate_order_lines_unitPrice_gross; + net: OrderLineUpdate_draftOrderLineUpdate_order_lines_unitPrice_net; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderLineUpdate_draftOrderLineUpdate_order_lines_unitPrice | null; + thumbnail: OrderLineUpdate_draftOrderLineUpdate_order_lines_thumbnail | null; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderLineUpdate_draftOrderLineUpdate_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderLineUpdate_draftOrderLineUpdate_order_shippingPrice_gross; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderLineUpdate_draftOrderLineUpdate_order_subtotal_gross; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_total { + __typename: "TaxedMoney"; + gross: OrderLineUpdate_draftOrderLineUpdate_order_total_gross; + tax: OrderLineUpdate_draftOrderLineUpdate_order_total_tax; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderLineUpdate_draftOrderLineUpdate_order_availableShippingMethods_price | null; +} + +export interface OrderLineUpdate_draftOrderLineUpdate_order { + __typename: "Order"; + id: string; + billingAddress: OrderLineUpdate_draftOrderLineUpdate_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderLineUpdate_draftOrderLineUpdate_order_events | null)[] | null; + fulfillments: (OrderLineUpdate_draftOrderLineUpdate_order_fulfillments | null)[]; + lines: (OrderLineUpdate_draftOrderLineUpdate_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderLineUpdate_draftOrderLineUpdate_order_shippingAddress | null; + shippingMethod: OrderLineUpdate_draftOrderLineUpdate_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderLineUpdate_draftOrderLineUpdate_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderLineUpdate_draftOrderLineUpdate_order_subtotal | null; + total: OrderLineUpdate_draftOrderLineUpdate_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderLineUpdate_draftOrderLineUpdate_order_totalAuthorized | null; + totalCaptured: OrderLineUpdate_draftOrderLineUpdate_order_totalCaptured | null; + user: OrderLineUpdate_draftOrderLineUpdate_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderLineUpdate_draftOrderLineUpdate_order_availableShippingMethods | null)[] | null; +} + +export interface OrderLineUpdate_draftOrderLineUpdate { + __typename: "DraftOrderLineUpdate"; + errors: OrderLineUpdate_draftOrderLineUpdate_errors[] | null; + order: OrderLineUpdate_draftOrderLineUpdate_order | null; +} + +export interface OrderLineUpdate { + draftOrderLineUpdate: OrderLineUpdate_draftOrderLineUpdate | null; +} + +export interface OrderLineUpdateVariables { + id: string; + input: OrderLineInput; +} diff --git a/src/orders/types/OrderLinesAdd.ts b/src/orders/types/OrderLinesAdd.ts new file mode 100644 index 000000000..763011990 --- /dev/null +++ b/src/orders/types/OrderLinesAdd.ts @@ -0,0 +1,282 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderLineCreateInput, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderLinesAdd +// ==================================================== + +export interface OrderLinesAdd_draftOrderLinesCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderLinesAdd_draftOrderLinesCreate_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderLinesAdd_draftOrderLinesCreate_order_events_user | null; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines_orderLine | null; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderLinesAdd_draftOrderLinesCreate_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderLinesAdd_draftOrderLinesCreate_order_lines_unitPrice_gross; + net: OrderLinesAdd_draftOrderLinesCreate_order_lines_unitPrice_net; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderLinesAdd_draftOrderLinesCreate_order_lines_unitPrice | null; + thumbnail: OrderLinesAdd_draftOrderLinesCreate_order_lines_thumbnail | null; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderLinesAdd_draftOrderLinesCreate_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderLinesAdd_draftOrderLinesCreate_order_shippingPrice_gross; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderLinesAdd_draftOrderLinesCreate_order_subtotal_gross; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_total { + __typename: "TaxedMoney"; + gross: OrderLinesAdd_draftOrderLinesCreate_order_total_gross; + tax: OrderLinesAdd_draftOrderLinesCreate_order_total_tax; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderLinesAdd_draftOrderLinesCreate_order_availableShippingMethods_price | null; +} + +export interface OrderLinesAdd_draftOrderLinesCreate_order { + __typename: "Order"; + id: string; + billingAddress: OrderLinesAdd_draftOrderLinesCreate_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderLinesAdd_draftOrderLinesCreate_order_events | null)[] | null; + fulfillments: (OrderLinesAdd_draftOrderLinesCreate_order_fulfillments | null)[]; + lines: (OrderLinesAdd_draftOrderLinesCreate_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderLinesAdd_draftOrderLinesCreate_order_shippingAddress | null; + shippingMethod: OrderLinesAdd_draftOrderLinesCreate_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderLinesAdd_draftOrderLinesCreate_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderLinesAdd_draftOrderLinesCreate_order_subtotal | null; + total: OrderLinesAdd_draftOrderLinesCreate_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderLinesAdd_draftOrderLinesCreate_order_totalAuthorized | null; + totalCaptured: OrderLinesAdd_draftOrderLinesCreate_order_totalCaptured | null; + user: OrderLinesAdd_draftOrderLinesCreate_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderLinesAdd_draftOrderLinesCreate_order_availableShippingMethods | null)[] | null; +} + +export interface OrderLinesAdd_draftOrderLinesCreate { + __typename: "DraftOrderLinesCreate"; + errors: OrderLinesAdd_draftOrderLinesCreate_errors[] | null; + order: OrderLinesAdd_draftOrderLinesCreate_order | null; +} + +export interface OrderLinesAdd { + draftOrderLinesCreate: OrderLinesAdd_draftOrderLinesCreate | null; +} + +export interface OrderLinesAddVariables { + id: string; + input: (OrderLineCreateInput | null)[]; +} diff --git a/src/orders/types/OrderList.ts b/src/orders/types/OrderList.ts new file mode 100644 index 000000000..959ca2309 --- /dev/null +++ b/src/orders/types/OrderList.ts @@ -0,0 +1,86 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderStatusFilter, OrderFilterInput, PaymentChargeStatusEnum, OrderStatus } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: OrderList +// ==================================================== + +export interface OrderList_orders_edges_node_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderList_orders_edges_node_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderList_orders_edges_node_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderList_orders_edges_node_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderList_orders_edges_node_total { + __typename: "TaxedMoney"; + gross: OrderList_orders_edges_node_total_gross; +} + +export interface OrderList_orders_edges_node { + __typename: "Order"; + billingAddress: OrderList_orders_edges_node_billingAddress | null; + created: any; + id: string; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + status: OrderStatus; + total: OrderList_orders_edges_node_total | null; + userEmail: string | null; +} + +export interface OrderList_orders_edges { + __typename: "OrderCountableEdge"; + node: OrderList_orders_edges_node; +} + +export interface OrderList_orders_pageInfo { + __typename: "PageInfo"; + hasPreviousPage: boolean; + hasNextPage: boolean; + startCursor: string | null; + endCursor: string | null; +} + +export interface OrderList_orders { + __typename: "OrderCountableConnection"; + edges: OrderList_orders_edges[]; + pageInfo: OrderList_orders_pageInfo; +} + +export interface OrderList { + orders: OrderList_orders | null; +} + +export interface OrderListVariables { + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; + status?: OrderStatusFilter | null; + filter?: OrderFilterInput | null; +} diff --git a/src/orders/types/OrderMarkAsPaid.ts b/src/orders/types/OrderMarkAsPaid.ts new file mode 100644 index 000000000..821ed8d39 --- /dev/null +++ b/src/orders/types/OrderMarkAsPaid.ts @@ -0,0 +1,281 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderMarkAsPaid +// ==================================================== + +export interface OrderMarkAsPaid_orderMarkAsPaid_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderMarkAsPaid_orderMarkAsPaid_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderMarkAsPaid_orderMarkAsPaid_order_events_user | null; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines_orderLine | null; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderMarkAsPaid_orderMarkAsPaid_order_lines_unitPrice_gross; + net: OrderMarkAsPaid_orderMarkAsPaid_order_lines_unitPrice_net; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderMarkAsPaid_orderMarkAsPaid_order_lines_unitPrice | null; + thumbnail: OrderMarkAsPaid_orderMarkAsPaid_order_lines_thumbnail | null; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderMarkAsPaid_orderMarkAsPaid_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderMarkAsPaid_orderMarkAsPaid_order_shippingPrice_gross; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderMarkAsPaid_orderMarkAsPaid_order_subtotal_gross; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_total { + __typename: "TaxedMoney"; + gross: OrderMarkAsPaid_orderMarkAsPaid_order_total_gross; + tax: OrderMarkAsPaid_orderMarkAsPaid_order_total_tax; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderMarkAsPaid_orderMarkAsPaid_order_availableShippingMethods_price | null; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid_order { + __typename: "Order"; + id: string; + billingAddress: OrderMarkAsPaid_orderMarkAsPaid_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderMarkAsPaid_orderMarkAsPaid_order_events | null)[] | null; + fulfillments: (OrderMarkAsPaid_orderMarkAsPaid_order_fulfillments | null)[]; + lines: (OrderMarkAsPaid_orderMarkAsPaid_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderMarkAsPaid_orderMarkAsPaid_order_shippingAddress | null; + shippingMethod: OrderMarkAsPaid_orderMarkAsPaid_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderMarkAsPaid_orderMarkAsPaid_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderMarkAsPaid_orderMarkAsPaid_order_subtotal | null; + total: OrderMarkAsPaid_orderMarkAsPaid_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderMarkAsPaid_orderMarkAsPaid_order_totalAuthorized | null; + totalCaptured: OrderMarkAsPaid_orderMarkAsPaid_order_totalCaptured | null; + user: OrderMarkAsPaid_orderMarkAsPaid_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderMarkAsPaid_orderMarkAsPaid_order_availableShippingMethods | null)[] | null; +} + +export interface OrderMarkAsPaid_orderMarkAsPaid { + __typename: "OrderMarkAsPaid"; + errors: OrderMarkAsPaid_orderMarkAsPaid_errors[] | null; + order: OrderMarkAsPaid_orderMarkAsPaid_order | null; +} + +export interface OrderMarkAsPaid { + orderMarkAsPaid: OrderMarkAsPaid_orderMarkAsPaid | null; +} + +export interface OrderMarkAsPaidVariables { + id: string; +} diff --git a/src/orders/types/OrderRefund.ts b/src/orders/types/OrderRefund.ts new file mode 100644 index 000000000..5fedbe1a9 --- /dev/null +++ b/src/orders/types/OrderRefund.ts @@ -0,0 +1,282 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderRefund +// ==================================================== + +export interface OrderRefund_orderRefund_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderRefund_orderRefund_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderRefund_orderRefund_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderRefund_orderRefund_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderRefund_orderRefund_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderRefund_orderRefund_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderRefund_orderRefund_order_events_user | null; +} + +export interface OrderRefund_orderRefund_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderRefund_orderRefund_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderRefund_orderRefund_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderRefund_orderRefund_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderRefund_orderRefund_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderRefund_orderRefund_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderRefund_orderRefund_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderRefund_orderRefund_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderRefund_orderRefund_order_fulfillments_lines_orderLine | null; +} + +export interface OrderRefund_orderRefund_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderRefund_orderRefund_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderRefund_orderRefund_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderRefund_orderRefund_order_lines_unitPrice_gross; + net: OrderRefund_orderRefund_order_lines_unitPrice_net; +} + +export interface OrderRefund_orderRefund_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderRefund_orderRefund_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderRefund_orderRefund_order_lines_unitPrice | null; + thumbnail: OrderRefund_orderRefund_order_lines_thumbnail | null; +} + +export interface OrderRefund_orderRefund_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderRefund_orderRefund_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderRefund_orderRefund_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderRefund_orderRefund_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderRefund_orderRefund_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderRefund_orderRefund_order_shippingPrice_gross; +} + +export interface OrderRefund_orderRefund_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderRefund_orderRefund_order_subtotal_gross; +} + +export interface OrderRefund_orderRefund_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_total { + __typename: "TaxedMoney"; + gross: OrderRefund_orderRefund_order_total_gross; + tax: OrderRefund_orderRefund_order_total_tax; +} + +export interface OrderRefund_orderRefund_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderRefund_orderRefund_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRefund_orderRefund_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderRefund_orderRefund_order_availableShippingMethods_price | null; +} + +export interface OrderRefund_orderRefund_order { + __typename: "Order"; + id: string; + billingAddress: OrderRefund_orderRefund_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderRefund_orderRefund_order_events | null)[] | null; + fulfillments: (OrderRefund_orderRefund_order_fulfillments | null)[]; + lines: (OrderRefund_orderRefund_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderRefund_orderRefund_order_shippingAddress | null; + shippingMethod: OrderRefund_orderRefund_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderRefund_orderRefund_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderRefund_orderRefund_order_subtotal | null; + total: OrderRefund_orderRefund_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderRefund_orderRefund_order_totalAuthorized | null; + totalCaptured: OrderRefund_orderRefund_order_totalCaptured | null; + user: OrderRefund_orderRefund_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderRefund_orderRefund_order_availableShippingMethods | null)[] | null; +} + +export interface OrderRefund_orderRefund { + __typename: "OrderRefund"; + errors: OrderRefund_orderRefund_errors[] | null; + order: OrderRefund_orderRefund_order | null; +} + +export interface OrderRefund { + orderRefund: OrderRefund_orderRefund | null; +} + +export interface OrderRefundVariables { + id: string; + amount: any; +} diff --git a/src/orders/types/OrderRelease.ts b/src/orders/types/OrderRelease.ts new file mode 100644 index 000000000..0fb77a66f --- /dev/null +++ b/src/orders/types/OrderRelease.ts @@ -0,0 +1,267 @@ +/* tslint:disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderRelease +// ==================================================== + +export interface OrderRelease_orderRelease_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderRelease_orderRelease_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderRelease_orderRelease_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderRelease_orderRelease_order_events_user { + __typename: "User"; + email: string; +} + +export interface OrderRelease_orderRelease_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderRelease_orderRelease_order_events_user | null; +} + +export interface OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice_gross; + net: OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice_net; +} + +export interface OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine { + __typename: "OrderLine"; + id: string; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine_unitPrice | null; + thumbnailUrl: string | null; +} + +export interface OrderRelease_orderRelease_order_fulfillments_lines_edges_node { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderRelease_orderRelease_order_fulfillments_lines_edges_node_orderLine | null; +} + +export interface OrderRelease_orderRelease_order_fulfillments_lines_edges { + __typename: "FulfillmentLineCountableEdge"; + node: OrderRelease_orderRelease_order_fulfillments_lines_edges_node; +} + +export interface OrderRelease_orderRelease_order_fulfillments_lines { + __typename: "FulfillmentLineCountableConnection"; + edges: OrderRelease_orderRelease_order_fulfillments_lines_edges[]; +} + +export interface OrderRelease_orderRelease_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: OrderRelease_orderRelease_order_fulfillments_lines | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderRelease_orderRelease_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRelease_orderRelease_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRelease_orderRelease_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderRelease_orderRelease_order_lines_unitPrice_gross; + net: OrderRelease_orderRelease_order_lines_unitPrice_net; +} + +export interface OrderRelease_orderRelease_order_lines { + __typename: "OrderLine"; + id: string; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderRelease_orderRelease_order_lines_unitPrice | null; + thumbnailUrl: string | null; +} + +export interface OrderRelease_orderRelease_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderRelease_orderRelease_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderRelease_orderRelease_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderRelease_orderRelease_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderRelease_orderRelease_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRelease_orderRelease_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderRelease_orderRelease_order_shippingPrice_gross; +} + +export interface OrderRelease_orderRelease_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRelease_orderRelease_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderRelease_orderRelease_order_subtotal_gross; +} + +export interface OrderRelease_orderRelease_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRelease_orderRelease_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRelease_orderRelease_order_total { + __typename: "TaxedMoney"; + gross: OrderRelease_orderRelease_order_total_gross; + tax: OrderRelease_orderRelease_order_total_tax; +} + +export interface OrderRelease_orderRelease_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRelease_orderRelease_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRelease_orderRelease_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderRelease_orderRelease_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderRelease_orderRelease_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderRelease_orderRelease_order_availableShippingMethods_price | null; +} + +export interface OrderRelease_orderRelease_order { + __typename: "Order"; + id: string; + billingAddress: OrderRelease_orderRelease_order_billingAddress | null; + created: any; + events: (OrderRelease_orderRelease_order_events | null)[] | null; + fulfillments: (OrderRelease_orderRelease_order_fulfillments | null)[]; + lines: (OrderRelease_orderRelease_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderRelease_orderRelease_order_shippingAddress | null; + shippingMethod: OrderRelease_orderRelease_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderRelease_orderRelease_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderRelease_orderRelease_order_subtotal | null; + total: OrderRelease_orderRelease_order_total | null; + totalAuthorized: OrderRelease_orderRelease_order_totalAuthorized | null; + totalCaptured: OrderRelease_orderRelease_order_totalCaptured | null; + user: OrderRelease_orderRelease_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderRelease_orderRelease_order_availableShippingMethods | null)[] | null; +} + +export interface OrderRelease_orderRelease { + __typename: "OrderRelease"; + order: OrderRelease_orderRelease_order | null; +} + +export interface OrderRelease { + orderRelease: OrderRelease_orderRelease | null; +} + +export interface OrderReleaseVariables { + id: string; +} diff --git a/src/orders/types/OrderShippingMethodUpdate.ts b/src/orders/types/OrderShippingMethodUpdate.ts new file mode 100644 index 000000000..abeb03535 --- /dev/null +++ b/src/orders/types/OrderShippingMethodUpdate.ts @@ -0,0 +1,69 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderUpdateShippingInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderShippingMethodUpdate +// ==================================================== + +export interface OrderShippingMethodUpdate_orderUpdateShipping_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderShippingMethodUpdate_orderUpdateShipping_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; +} + +export interface OrderShippingMethodUpdate_orderUpdateShipping_order_shippingMethod_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderShippingMethodUpdate_orderUpdateShipping_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderShippingMethodUpdate_orderUpdateShipping_order_shippingMethod_price | null; +} + +export interface OrderShippingMethodUpdate_orderUpdateShipping_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderShippingMethodUpdate_orderUpdateShipping_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderShippingMethodUpdate_orderUpdateShipping_order_shippingPrice_gross; +} + +export interface OrderShippingMethodUpdate_orderUpdateShipping_order { + __typename: "Order"; + availableShippingMethods: (OrderShippingMethodUpdate_orderUpdateShipping_order_availableShippingMethods | null)[] | null; + id: string; + shippingMethod: OrderShippingMethodUpdate_orderUpdateShipping_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderShippingMethodUpdate_orderUpdateShipping_order_shippingPrice | null; +} + +export interface OrderShippingMethodUpdate_orderUpdateShipping { + __typename: "OrderUpdateShipping"; + errors: OrderShippingMethodUpdate_orderUpdateShipping_errors[] | null; + order: OrderShippingMethodUpdate_orderUpdateShipping_order | null; +} + +export interface OrderShippingMethodUpdate { + orderUpdateShipping: OrderShippingMethodUpdate_orderUpdateShipping | null; +} + +export interface OrderShippingMethodUpdateVariables { + id: string; + input: OrderUpdateShippingInput; +} diff --git a/src/orders/types/OrderShippingMethods.ts b/src/orders/types/OrderShippingMethods.ts new file mode 100644 index 000000000..818adf916 --- /dev/null +++ b/src/orders/types/OrderShippingMethods.ts @@ -0,0 +1,31 @@ +/* tslint:disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: OrderShippingMethods +// ==================================================== + +export interface OrderShippingMethods_shippingZones_edges_node_shippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; +} + +export interface OrderShippingMethods_shippingZones_edges_node { + __typename: "ShippingZone"; + shippingMethods: (OrderShippingMethods_shippingZones_edges_node_shippingMethods | null)[] | null; +} + +export interface OrderShippingMethods_shippingZones_edges { + __typename: "ShippingZoneCountableEdge"; + node: OrderShippingMethods_shippingZones_edges_node; +} + +export interface OrderShippingMethods_shippingZones { + __typename: "ShippingZoneCountableConnection"; + edges: OrderShippingMethods_shippingZones_edges[]; +} + +export interface OrderShippingMethods { + shippingZones: OrderShippingMethods_shippingZones | null; +} diff --git a/src/orders/types/OrderUpdate.ts b/src/orders/types/OrderUpdate.ts new file mode 100644 index 000000000..66946aaab --- /dev/null +++ b/src/orders/types/OrderUpdate.ts @@ -0,0 +1,82 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderUpdateInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderUpdate +// ==================================================== + +export interface OrderUpdate_orderUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderUpdate_orderUpdate_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderUpdate_orderUpdate_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderUpdate_orderUpdate_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderUpdate_orderUpdate_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderUpdate_orderUpdate_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderUpdate_orderUpdate_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderUpdate_orderUpdate_order { + __typename: "Order"; + id: string; + userEmail: string | null; + billingAddress: OrderUpdate_orderUpdate_order_billingAddress | null; + shippingAddress: OrderUpdate_orderUpdate_order_shippingAddress | null; +} + +export interface OrderUpdate_orderUpdate { + __typename: "OrderUpdate"; + errors: OrderUpdate_orderUpdate_errors[] | null; + order: OrderUpdate_orderUpdate_order | null; +} + +export interface OrderUpdate { + orderUpdate: OrderUpdate_orderUpdate | null; +} + +export interface OrderUpdateVariables { + id: string; + input: OrderUpdateInput; +} diff --git a/src/orders/types/OrderVoid.ts b/src/orders/types/OrderVoid.ts new file mode 100644 index 000000000..1d3e76026 --- /dev/null +++ b/src/orders/types/OrderVoid.ts @@ -0,0 +1,281 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: OrderVoid +// ==================================================== + +export interface OrderVoid_orderVoid_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface OrderVoid_orderVoid_order_billingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderVoid_orderVoid_order_billingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderVoid_orderVoid_order_billingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderVoid_orderVoid_order_events_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderVoid_orderVoid_order_events { + __typename: "OrderEvent"; + id: string; + amount: number | null; + date: any | null; + email: string | null; + emailType: OrderEventsEmailsEnum | null; + message: string | null; + quantity: number | null; + type: OrderEventsEnum | null; + user: OrderVoid_orderVoid_order_events_user | null; +} + +export interface OrderVoid_orderVoid_order_fulfillments_lines_orderLine_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_fulfillments_lines_orderLine_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_fulfillments_lines_orderLine_unitPrice { + __typename: "TaxedMoney"; + gross: OrderVoid_orderVoid_order_fulfillments_lines_orderLine_unitPrice_gross; + net: OrderVoid_orderVoid_order_fulfillments_lines_orderLine_unitPrice_net; +} + +export interface OrderVoid_orderVoid_order_fulfillments_lines_orderLine_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderVoid_orderVoid_order_fulfillments_lines_orderLine { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderVoid_orderVoid_order_fulfillments_lines_orderLine_unitPrice | null; + thumbnail: OrderVoid_orderVoid_order_fulfillments_lines_orderLine_thumbnail | null; +} + +export interface OrderVoid_orderVoid_order_fulfillments_lines { + __typename: "FulfillmentLine"; + id: string; + quantity: number; + orderLine: OrderVoid_orderVoid_order_fulfillments_lines_orderLine | null; +} + +export interface OrderVoid_orderVoid_order_fulfillments { + __typename: "Fulfillment"; + id: string; + lines: (OrderVoid_orderVoid_order_fulfillments_lines | null)[] | null; + fulfillmentOrder: number; + status: FulfillmentStatus; + trackingNumber: string; +} + +export interface OrderVoid_orderVoid_order_lines_unitPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_lines_unitPrice_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_lines_unitPrice { + __typename: "TaxedMoney"; + gross: OrderVoid_orderVoid_order_lines_unitPrice_gross; + net: OrderVoid_orderVoid_order_lines_unitPrice_net; +} + +export interface OrderVoid_orderVoid_order_lines_thumbnail { + __typename: "Image"; + url: string; +} + +export interface OrderVoid_orderVoid_order_lines { + __typename: "OrderLine"; + id: string; + isShippingRequired: boolean; + productName: string; + productSku: string; + quantity: number; + quantityFulfilled: number; + unitPrice: OrderVoid_orderVoid_order_lines_unitPrice | null; + thumbnail: OrderVoid_orderVoid_order_lines_thumbnail | null; +} + +export interface OrderVoid_orderVoid_order_shippingAddress_country { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface OrderVoid_orderVoid_order_shippingAddress { + __typename: "Address"; + city: string; + cityArea: string; + companyName: string; + country: OrderVoid_orderVoid_order_shippingAddress_country; + countryArea: string; + firstName: string; + id: string; + lastName: string; + phone: string | null; + postalCode: string; + streetAddress1: string; + streetAddress2: string; +} + +export interface OrderVoid_orderVoid_order_shippingMethod { + __typename: "ShippingMethod"; + id: string; +} + +export interface OrderVoid_orderVoid_order_shippingPrice_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_shippingPrice { + __typename: "TaxedMoney"; + gross: OrderVoid_orderVoid_order_shippingPrice_gross; +} + +export interface OrderVoid_orderVoid_order_subtotal_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_subtotal { + __typename: "TaxedMoney"; + gross: OrderVoid_orderVoid_order_subtotal_gross; +} + +export interface OrderVoid_orderVoid_order_total_gross { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_total_tax { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_total { + __typename: "TaxedMoney"; + gross: OrderVoid_orderVoid_order_total_gross; + tax: OrderVoid_orderVoid_order_total_tax; +} + +export interface OrderVoid_orderVoid_order_totalAuthorized { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_totalCaptured { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_user { + __typename: "User"; + id: string; + email: string; +} + +export interface OrderVoid_orderVoid_order_availableShippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface OrderVoid_orderVoid_order_availableShippingMethods { + __typename: "ShippingMethod"; + id: string; + name: string; + price: OrderVoid_orderVoid_order_availableShippingMethods_price | null; +} + +export interface OrderVoid_orderVoid_order { + __typename: "Order"; + id: string; + billingAddress: OrderVoid_orderVoid_order_billingAddress | null; + canFinalize: boolean; + created: any; + customerNote: string; + events: (OrderVoid_orderVoid_order_events | null)[] | null; + fulfillments: (OrderVoid_orderVoid_order_fulfillments | null)[]; + lines: (OrderVoid_orderVoid_order_lines | null)[]; + number: string | null; + paymentStatus: PaymentChargeStatusEnum | null; + shippingAddress: OrderVoid_orderVoid_order_shippingAddress | null; + shippingMethod: OrderVoid_orderVoid_order_shippingMethod | null; + shippingMethodName: string | null; + shippingPrice: OrderVoid_orderVoid_order_shippingPrice | null; + status: OrderStatus; + subtotal: OrderVoid_orderVoid_order_subtotal | null; + total: OrderVoid_orderVoid_order_total | null; + actions: (OrderAction | null)[]; + totalAuthorized: OrderVoid_orderVoid_order_totalAuthorized | null; + totalCaptured: OrderVoid_orderVoid_order_totalCaptured | null; + user: OrderVoid_orderVoid_order_user | null; + userEmail: string | null; + availableShippingMethods: (OrderVoid_orderVoid_order_availableShippingMethods | null)[] | null; +} + +export interface OrderVoid_orderVoid { + __typename: "OrderVoid"; + errors: OrderVoid_orderVoid_errors[] | null; + order: OrderVoid_orderVoid_order | null; +} + +export interface OrderVoid { + orderVoid: OrderVoid_orderVoid | null; +} + +export interface OrderVoidVariables { + id: string; +} diff --git a/src/orders/types/SearchOrderVariant.ts b/src/orders/types/SearchOrderVariant.ts new file mode 100644 index 000000000..f2f0949eb --- /dev/null +++ b/src/orders/types/SearchOrderVariant.ts @@ -0,0 +1,63 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: SearchOrderVariant +// ==================================================== + +export interface SearchOrderVariant_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface SearchOrderVariant_products_edges_node_variants_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SearchOrderVariant_products_edges_node_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + price: SearchOrderVariant_products_edges_node_variants_price | null; +} + +export interface SearchOrderVariant_products_edges_node { + __typename: "Product"; + id: string; + name: string; + thumbnail: SearchOrderVariant_products_edges_node_thumbnail | null; + variants: (SearchOrderVariant_products_edges_node_variants | null)[] | null; +} + +export interface SearchOrderVariant_products_edges { + __typename: "ProductCountableEdge"; + node: SearchOrderVariant_products_edges_node; +} + +export interface SearchOrderVariant_products_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface SearchOrderVariant_products { + __typename: "ProductCountableConnection"; + edges: SearchOrderVariant_products_edges[]; + pageInfo: SearchOrderVariant_products_pageInfo; +} + +export interface SearchOrderVariant { + products: SearchOrderVariant_products | null; +} + +export interface SearchOrderVariantVariables { + first: number; + query: string; + after?: string | null; +} diff --git a/src/orders/urls.ts b/src/orders/urls.ts new file mode 100644 index 000000000..5edbbd758 --- /dev/null +++ b/src/orders/urls.ts @@ -0,0 +1,72 @@ +import { stringify as stringifyQs } from "qs"; +import * as urlJoin from "url-join"; + +import { + ActiveTab, + BulkAction, + Dialog, + Filters, + Pagination, + SingleAction +} from "../types"; + +const orderSectionUrl = "/orders"; + +export const orderListPath = orderSectionUrl; +export enum OrderListUrlFiltersEnum { + dateFrom = "dateFrom", + dateTo = "dateTo", + status = "status", + email = "email", + payment = "payment" +} +export type OrderListUrlFilters = Filters; +export type OrderListUrlDialog = "cancel" | "save-search" | "delete-search"; +export type OrderListUrlQueryParams = BulkAction & + Dialog & + OrderListUrlFilters & + Pagination & + ActiveTab; +export const orderListUrl = (params?: OrderListUrlQueryParams): string => { + const orderList = orderListPath; + if (params === undefined) { + return orderList; + } else { + return urlJoin(orderList, "?" + stringifyQs(params)); + } +}; + +export const orderDraftListPath = urlJoin(orderSectionUrl, "drafts"); +export type OrderDraftListUrlDialog = "remove"; +export type OrderDraftListUrlQueryParams = BulkAction & + Dialog & + Pagination; +export const orderDraftListUrl = ( + params?: OrderDraftListUrlQueryParams +): string => { + const orderDraftList = orderDraftListPath; + if (params === undefined) { + return orderDraftList; + } else { + return urlJoin(orderDraftList, "?" + stringifyQs(params)); + } +}; + +export const orderPath = (id: string) => urlJoin(orderSectionUrl, id); +export type OrderUrlDialog = + | "add-order-line" + | "cancel" + | "cancel-fulfillment" + | "capture" + | "edit-billing-address" + | "edit-fulfillment" + | "edit-shipping" + | "edit-shipping-address" + | "finalize" + | "fulfill" + | "mark-paid" + | "refund" + | "void"; +export type OrderUrlQueryParams = Dialog & SingleAction; +export const orderUrl = (id: string, params?: OrderUrlQueryParams) => + orderPath(encodeURIComponent(id)) + "?" + stringifyQs(params); diff --git a/src/orders/views/OrderDetails/OrderDetailsMessages.tsx b/src/orders/views/OrderDetails/OrderDetailsMessages.tsx new file mode 100644 index 000000000..e4383c107 --- /dev/null +++ b/src/orders/views/OrderDetails/OrderDetailsMessages.tsx @@ -0,0 +1,314 @@ +import * as React from "react"; + +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { OrderAddNote } from "../../types/OrderAddNote"; +import { OrderCancel } from "../../types/OrderCancel"; +import { OrderCapture } from "../../types/OrderCapture"; +import { OrderCreateFulfillment } from "../../types/OrderCreateFulfillment"; +import { OrderDraftCancel } from "../../types/OrderDraftCancel"; +import { OrderDraftFinalize } from "../../types/OrderDraftFinalize"; +import { OrderDraftUpdate } from "../../types/OrderDraftUpdate"; +import { OrderFulfillmentCancel } from "../../types/OrderFulfillmentCancel"; +import { OrderFulfillmentUpdateTracking } from "../../types/OrderFulfillmentUpdateTracking"; +import { OrderLineDelete } from "../../types/OrderLineDelete"; +import { OrderLinesAdd } from "../../types/OrderLinesAdd"; +import { OrderLineUpdate } from "../../types/OrderLineUpdate"; +import { OrderMarkAsPaid } from "../../types/OrderMarkAsPaid"; +import { OrderRefund } from "../../types/OrderRefund"; +import { OrderShippingMethodUpdate } from "../../types/OrderShippingMethodUpdate"; +import { OrderUpdate } from "../../types/OrderUpdate"; +import { OrderVoid } from "../../types/OrderVoid"; +import { orderListUrl, orderUrl } from "../../urls"; + +interface OrderDetailsMessages { + children: (props: { + handleDraftCancel: (data: OrderDraftCancel) => void; + handleDraftFinalize: (data: OrderDraftFinalize) => void; + handleDraftUpdate: (data: OrderDraftUpdate) => void; + handleNoteAdd: (data: OrderAddNote) => void; + handleOrderCancel: (data: OrderCancel) => void; + handleOrderFulfillmentCancel: (data: OrderFulfillmentCancel) => void; + handleOrderFulfillmentCreate: (data: OrderCreateFulfillment) => void; + handleOrderFulfillmentUpdate: ( + data: OrderFulfillmentUpdateTracking + ) => void; + handleOrderLinesAdd: (data: OrderLinesAdd) => void; + handleOrderLineDelete: (data: OrderLineDelete) => void; + handleOrderLineUpdate: (data: OrderLineUpdate) => void; + handleOrderMarkAsPaid: (data: OrderMarkAsPaid) => void; + handleOrderVoid: (data: OrderVoid) => void; + handlePaymentCapture: (data: OrderCapture) => void; + handlePaymentRefund: (data: OrderRefund) => void; + handleShippingMethodUpdate: (data: OrderShippingMethodUpdate) => void; + handleUpdate: (data: OrderUpdate) => void; + }) => React.ReactElement; +} + +export const OrderDetailsMessages: React.StatelessComponent< + OrderDetailsMessages +> = ({ children }) => { + const navigate = useNavigator(); + const pushMessage = useNotifier(); + + const handlePaymentCapture = (data: OrderCapture) => { + if (!maybe(() => data.orderCapture.errors.length)) { + pushMessage({ + text: i18n.t("Payment successfully captured", { + context: "notification" + }) + }); + } else { + pushMessage({ + text: i18n.t("Payment not captured: {{ errorMessage }}", { + context: "notification", + errorMessage: data.orderCapture.errors.filter( + error => error.field === "payment" + )[0].message + }) + }); + } + }; + const handlePaymentRefund = (data: OrderRefund) => { + if (!maybe(() => data.orderRefund.errors.length)) { + pushMessage({ + text: i18n.t("Payment successfully refunded", { + context: "notification" + }) + }); + } else { + pushMessage({ + text: i18n.t("Payment not refunded: {{ errorMessage }}", { + context: "notification", + errorMessage: data.orderRefund.errors.filter( + error => error.field === "payment" + )[0].message + }) + }); + } + }; + const handleOrderFulfillmentCreate = (data: OrderCreateFulfillment) => { + if (!maybe(() => data.orderFulfillmentCreate.errors.length)) { + pushMessage({ + text: i18n.t("Items successfully fulfilled", { + context: "notification" + }) + }); + navigate(orderUrl(data.orderFulfillmentCreate.order.id), true); + } else { + pushMessage({ + text: i18n.t("Could not fulfill items", { + context: "notification" + }) + }); + } + }; + const handleOrderMarkAsPaid = (data: OrderMarkAsPaid) => { + if (!maybe(() => data.orderMarkAsPaid.errors.length)) { + pushMessage({ + text: i18n.t("Order marked as paid", { + context: "notification" + }) + }); + navigate(orderUrl(data.orderMarkAsPaid.order.id), true); + } else { + pushMessage({ + text: i18n.t("Could not mark order as paid", { + context: "notification" + }) + }); + } + }; + const handleOrderCancel = (data: OrderCancel) => { + pushMessage({ + text: i18n.t("Order successfully cancelled", { + context: "notification" + }) + }); + navigate(orderUrl(data.orderCancel.order.id), true); + }; + const handleDraftCancel = () => { + pushMessage({ + text: i18n.t("Order successfully cancelled", { + context: "notification" + }) + }); + navigate(orderListUrl(), true); + }; + const handleOrderVoid = () => { + pushMessage({ + text: i18n.t("Order payment successfully voided", { + context: "notification" + }) + }); + }; + const handleNoteAdd = (data: OrderAddNote) => { + if (!maybe(() => data.orderAddNote.errors.length)) { + pushMessage({ + text: i18n.t("Note successfully added", { + context: "notification" + }) + }); + } else { + pushMessage({ + text: i18n.t("Could not add note", { + context: "notification" + }) + }); + } + }; + const handleUpdate = (data: OrderUpdate) => { + if (!maybe(() => data.orderUpdate.errors.length)) { + pushMessage({ + text: i18n.t("Order successfully updated", { + context: "notification" + }) + }); + navigate(orderUrl(data.orderUpdate.order.id), true); + } + }; + const handleDraftUpdate = (data: OrderDraftUpdate) => { + if (!maybe(() => data.draftOrderUpdate.errors.length)) { + pushMessage({ + text: i18n.t("Order successfully updated", { + context: "notification" + }) + }); + navigate(orderUrl(data.draftOrderUpdate.order.id), true); + } + }; + const handleShippingMethodUpdate = (data: OrderShippingMethodUpdate) => { + if (!maybe(() => data.orderUpdateShipping.errors.length)) { + pushMessage({ + text: i18n.t("Shipping method successfully updated", { + context: "notification" + }) + }); + } else { + pushMessage({ + text: i18n.t("Could not update shipping method", { + context: "notification" + }) + }); + } + navigate(orderUrl(data.orderUpdateShipping.order.id), true); + }; + const handleOrderLineDelete = (data: OrderLineDelete) => { + if (!maybe(() => data.draftOrderLineDelete.errors.length)) { + pushMessage({ + text: i18n.t("Order line deleted", { + context: "notification" + }) + }); + } else { + pushMessage({ + text: i18n.t("Could not delete order line", { + context: "notification" + }) + }); + } + }; + const handleOrderLinesAdd = (data: OrderLinesAdd) => { + if (!maybe(() => data.draftOrderLinesCreate.errors.length)) { + pushMessage({ + text: i18n.t("Order line added", { + context: "notification" + }) + }); + navigate(orderUrl(data.draftOrderLinesCreate.order.id), true); + } else { + pushMessage({ + text: i18n.t("Could not create order line", { + context: "notification" + }) + }); + } + }; + const handleOrderLineUpdate = (data: OrderLineUpdate) => { + if (!maybe(() => data.draftOrderLineUpdate.errors.length)) { + pushMessage({ + text: i18n.t("Order line updated", { + context: "notification" + }) + }); + } else { + pushMessage({ + text: i18n.t("Could not update order line", { + context: "notification" + }) + }); + } + }; + const handleOrderFulfillmentCancel = (data: OrderFulfillmentCancel) => { + if (!maybe(() => data.orderFulfillmentCancel.errors.length)) { + pushMessage({ + text: i18n.t("Fulfillment successfully cancelled", { + context: "notification" + }) + }); + navigate(orderUrl(data.orderFulfillmentCancel.order.id), true); + } else { + pushMessage({ + text: i18n.t("Could not cancel fulfillment", { + context: "notification" + }) + }); + } + }; + const handleOrderFulfillmentUpdate = ( + data: OrderFulfillmentUpdateTracking + ) => { + if (!maybe(() => data.orderFulfillmentUpdateTracking.errors.length)) { + pushMessage({ + text: i18n.t("Fulfillment successfully updated", { + context: "notification" + }) + }); + navigate(orderUrl(data.orderFulfillmentUpdateTracking.order.id), true); + } else { + pushMessage({ + text: i18n.t("Could not update fulfillment", { + context: "notification" + }) + }); + } + }; + const handleDraftFinalize = (data: OrderDraftFinalize) => { + if (!maybe(() => data.draftOrderComplete.errors.length)) { + pushMessage({ + text: i18n.t("Draft order successfully finalized", { + context: "notification" + }) + }); + navigate(orderUrl(data.draftOrderComplete.order.id), true); + } else { + pushMessage({ + text: i18n.t("Could not finalize draft", { + context: "notification" + }) + }); + } + }; + + return children({ + handleDraftCancel, + handleDraftFinalize, + handleDraftUpdate, + handleNoteAdd, + handleOrderCancel, + handleOrderFulfillmentCancel, + handleOrderFulfillmentCreate, + handleOrderFulfillmentUpdate, + handleOrderLineDelete, + handleOrderLineUpdate, + handleOrderLinesAdd, + handleOrderMarkAsPaid, + handleOrderVoid, + handlePaymentCapture, + handlePaymentRefund, + handleShippingMethodUpdate, + handleUpdate + }); +}; diff --git a/src/orders/views/OrderDetails/index.tsx b/src/orders/views/OrderDetails/index.tsx new file mode 100644 index 000000000..1afec5dcd --- /dev/null +++ b/src/orders/views/OrderDetails/index.tsx @@ -0,0 +1,673 @@ +import * as React from "react"; + +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import { DEFAULT_INITIAL_SEARCH_DATA } from "../../../config"; +import SearchCustomers from "../../../containers/SearchCustomers"; +import { customerUrl } from "../../../customers/urls"; +import { getMutationState, maybe, transformAddressToForm } from "../../../misc"; +import { productUrl } from "../../../products/urls"; +import { OrderStatus } from "../../../types/globalTypes"; +import OrderAddressEditDialog from "../../components/OrderAddressEditDialog"; +import OrderCancelDialog from "../../components/OrderCancelDialog"; +import OrderDetailsPage from "../../components/OrderDetailsPage"; +import OrderDraftCancelDialog from "../../components/OrderDraftCancelDialog/OrderDraftCancelDialog"; +import OrderDraftFinalizeDialog, { + OrderDraftFinalizeWarning +} from "../../components/OrderDraftFinalizeDialog"; +import OrderDraftPage from "../../components/OrderDraftPage"; +import OrderFulfillmentCancelDialog from "../../components/OrderFulfillmentCancelDialog"; +import OrderFulfillmentDialog from "../../components/OrderFulfillmentDialog"; +import OrderFulfillmentTrackingDialog from "../../components/OrderFulfillmentTrackingDialog"; +import OrderMarkAsPaidDialog from "../../components/OrderMarkAsPaidDialog/OrderMarkAsPaidDialog"; +import OrderPaymentDialog from "../../components/OrderPaymentDialog"; +import OrderPaymentVoidDialog from "../../components/OrderPaymentVoidDialog"; +import OrderProductAddDialog from "../../components/OrderProductAddDialog"; +import OrderShippingMethodEditDialog from "../../components/OrderShippingMethodEditDialog"; +import OrderOperations from "../../containers/OrderOperations"; +import { SearchOrderVariant, TypedOrderDetailsQuery } from "../../queries"; +import { OrderDetails_order } from "../../types/OrderDetails"; +import { + orderListUrl, + orderUrl, + OrderUrlDialog, + OrderUrlQueryParams +} from "../../urls"; +import { OrderDetailsMessages } from "./OrderDetailsMessages"; + +const orderDraftFinalizeWarnings = (order: OrderDetails_order) => { + const warnings = [] as OrderDraftFinalizeWarning[]; + if (!(order && order.shippingAddress)) { + warnings.push("no-shipping"); + } + if (!(order && order.billingAddress)) { + warnings.push("no-billing"); + } + if (!(order && (order.user || order.userEmail))) { + warnings.push("no-user"); + } + if ( + order && + order.lines && + order.lines.filter(line => line.isShippingRequired).length > 0 && + order.shippingMethod === null + ) { + warnings.push("no-shipping-method"); + } + if ( + order && + order.lines && + order.lines.filter(line => line.isShippingRequired).length === 0 && + order.shippingMethod !== null + ) { + warnings.push("unnecessary-shipping-method"); + } + return warnings; +}; + +interface OrderDetailsProps { + id: string; + params: OrderUrlQueryParams; +} + +export const OrderDetails: React.StatelessComponent = ({ + id, + params +}) => { + const navigate = useNavigator(); + + return ( + + {({ data, loading }) => { + const order = maybe(() => data.order); + const closeModal = () => navigate(orderUrl(id), true); + const openModal = (action: OrderUrlDialog) => + navigate( + orderUrl(id, { + action + }) + ); + return ( + + {({ search: searchUsers, result: users }) => ( + + {orderMessages => ( + + {({ + orderAddNote, + orderCancel, + orderCreateFulfillment, + orderDraftUpdate, + orderLinesAdd, + orderLineDelete, + orderLineUpdate, + orderPaymentCapture, + orderPaymentRefund, + orderVoid, + orderShippingMethodUpdate, + orderUpdate, + orderFulfillmentCancel, + orderFulfillmentUpdateTracking, + orderDraftCancel, + orderDraftFinalize, + orderPaymentMarkAsPaid + }) => { + const finalizeTransitionState = getMutationState( + orderDraftFinalize.opts.called, + orderDraftFinalize.opts.loading, + maybe( + () => + orderDraftFinalize.opts.data.draftOrderComplete + .errors + ) + ); + return ( + <> + {maybe(() => order.status !== OrderStatus.DRAFT) ? ( + <> + "Order #" + data.order.number + )} + /> + + orderAddNote.mutate({ + input: variables, + order: id + }) + } + onBack={() => navigate(orderListUrl())} + order={order} + shippingMethods={maybe( + () => data.order.availableShippingMethods, + [] + )} + onOrderCancel={() => openModal("cancel")} + onOrderFulfill={() => openModal("fulfill")} + onFulfillmentCancel={fulfillmentId => + navigate( + orderUrl(id, { + action: "cancel-fulfillment", + id: fulfillmentId + }) + ) + } + onFulfillmentTrackingNumberUpdate={fulfillmentId => + navigate( + orderUrl(id, { + action: "edit-fulfillment", + id: fulfillmentId + }) + ) + } + onPaymentCapture={() => openModal("capture")} + onPaymentVoid={() => openModal("void")} + onPaymentRefund={() => openModal("refund")} + onProductClick={id => () => + navigate(productUrl(id))} + onBillingAddressEdit={() => + openModal("edit-billing-address") + } + onShippingAddressEdit={() => + openModal("edit-shipping-address") + } + onPaymentPaid={() => openModal("mark-paid")} + onProfileView={() => + navigate(customerUrl(order.user.id)) + } + /> + + orderCancel.opts.data.orderCancel.errors + ) + )} + number={maybe(() => order.number)} + open={params.action === "cancel"} + onClose={closeModal} + onSubmit={variables => + orderCancel.mutate({ + id, + ...variables + }) + } + /> + + orderPaymentMarkAsPaid.opts.data + .orderMarkAsPaid.errors + ) + )} + onClose={closeModal} + onConfirm={() => + orderPaymentMarkAsPaid.mutate({ + id + }) + } + open={params.action === "mark-paid"} + /> + orderVoid.opts.data.orderVoid.errors + ) + )} + open={params.action === "void"} + onClose={closeModal} + onConfirm={() => orderVoid.mutate({ id })} + /> + + orderPaymentCapture.opts.data.orderCapture + .errors + ) + )} + initial={maybe(() => order.total.gross.amount)} + open={params.action === "capture"} + variant="capture" + onClose={closeModal} + onSubmit={variables => + orderPaymentCapture.mutate({ + ...variables, + id + }) + } + /> + + orderPaymentRefund.opts.data.orderRefund + .errors + ) + )} + initial={maybe(() => order.total.gross.amount)} + open={params.action === "refund"} + variant="refund" + onClose={closeModal} + onSubmit={variables => + orderPaymentRefund.mutate({ + ...variables, + id + }) + } + /> + + orderCreateFulfillment.opts.data + .orderFulfillmentCreate.errors + ) + )} + open={params.action === "fulfill"} + lines={maybe(() => order.lines, []).filter( + line => line.quantityFulfilled < line.quantity + )} + onClose={closeModal} + onSubmit={variables => + orderCreateFulfillment.mutate({ + input: { + ...variables, + lines: maybe(() => order.lines, []) + .filter( + line => + line.quantityFulfilled < + line.quantity + ) + .map((line, lineIndex) => ({ + orderLineId: line.id, + quantity: variables.lines[lineIndex] + })) + .filter(line => line.quantity > 0) + }, + order: order.id + }) + } + /> + + orderFulfillmentCancel.opts.data + .orderFulfillmentCancel.errors + ) + )} + open={params.action === "cancel-fulfillment"} + onConfirm={variables => + orderFulfillmentCancel.mutate({ + id: params.id, + input: variables + }) + } + onClose={closeModal} + /> + + orderFulfillmentUpdateTracking.opts.data + .orderFulfillmentUpdateTracking.errors + ) + )} + open={params.action === "edit-fulfillment"} + trackingNumber={maybe( + () => + data.order.fulfillments.find( + fulfillment => + fulfillment.id === params.id + ).trackingNumber + )} + onConfirm={variables => + orderFulfillmentUpdateTracking.mutate({ + id: params.id, + input: { + ...variables, + notifyCustomer: true + } + }) + } + onClose={closeModal} + /> + + ) : ( + <> + "Draft order #" + data.order.number + )} + /> + + orderAddNote.mutate({ + input: variables, + order: id + }) + } + users={maybe( + () => + users.data.customers.edges.map( + edge => edge.node + ), + [] + )} + fetchUsers={searchUsers} + usersLoading={users.loading} + onCustomerEdit={data => + orderDraftUpdate.mutate({ + id, + input: data + }) + } + onDraftFinalize={() => openModal("finalize")} + onDraftRemove={() => openModal("cancel")} + onOrderLineAdd={() => + openModal("add-order-line") + } + onBack={() => navigate(orderListUrl())} + order={order} + countries={maybe( + () => data.shop.countries, + [] + ).map(country => ({ + code: country.code, + label: country.country + }))} + onProductClick={id => () => + navigate(productUrl(encodeURIComponent(id)))} + onBillingAddressEdit={() => + openModal("edit-billing-address") + } + onShippingAddressEdit={() => + openModal("edit-shipping-address") + } + onShippingMethodEdit={() => + openModal("edit-shipping") + } + onOrderLineRemove={id => + orderLineDelete.mutate({ id }) + } + onOrderLineChange={(id, data) => + orderLineUpdate.mutate({ + id, + input: data + }) + } + saveButtonBarState="default" + onProfileView={() => + navigate(customerUrl(order.user.id)) + } + /> + + orderDraftCancel.opts.data + .draftOrderDelete.errors + ) + )} + onClose={closeModal} + onConfirm={() => + orderDraftCancel.mutate({ id }) + } + open={params.action === "cancel"} + orderNumber={maybe(() => order.number)} + /> + + orderDraftFinalize.mutate({ id }) + } + open={params.action === "finalize"} + orderNumber={maybe(() => order.number)} + warnings={orderDraftFinalizeWarnings(order)} + /> + + orderShippingMethodUpdate.opts.data + .orderUpdateShipping.errors + ) + )} + open={params.action === "edit-shipping"} + shippingMethod={maybe( + () => order.shippingMethod.id, + "..." + )} + shippingMethods={maybe( + () => order.availableShippingMethods + )} + onClose={closeModal} + onSubmit={variables => + orderShippingMethodUpdate.mutate({ + id, + input: { + shippingMethod: variables.shippingMethod + } + }) + } + /> + + {({ + search: variantSearch, + result: variantSearchOpts + }) => { + const fetchMore = () => + variantSearchOpts.loadMore( + (prev, next) => { + if ( + prev.products.pageInfo.endCursor === + next.products.pageInfo.endCursor + ) { + return prev; + } + return { + ...prev, + products: { + ...prev.products, + edges: [ + ...prev.products.edges, + ...next.products.edges + ], + pageInfo: next.products.pageInfo + } + }; + }, + { + after: + variantSearchOpts.data.products + .pageInfo.endCursor + } + ); + return ( + + orderLinesAdd.opts.data + .draftOrderLinesCreate.errors + ) + )} + loading={variantSearchOpts.loading} + open={params.action === "add-order-line"} + hasMore={maybe( + () => + variantSearchOpts.data.products + .pageInfo.hasNextPage + )} + products={maybe(() => + variantSearchOpts.data.products.edges.map( + edge => edge.node + ) + )} + onClose={closeModal} + onFetch={variantSearch} + onFetchMore={fetchMore} + onSubmit={formData => + orderLinesAdd.mutate({ + id, + input: formData.variants.map( + variant => ({ + quantity: 1, + variantId: variant.id + }) + ) + }) + } + /> + ); + }} + + + )} + orderUpdate.opts.data.orderUpdate.errors + ) + )} + address={transformAddressToForm( + maybe(() => order.shippingAddress) + )} + countries={maybe(() => data.shop.countries, []).map( + country => ({ + code: country.code, + label: country.country + }) + )} + errors={maybe( + () => orderUpdate.opts.data.orderUpdate.errors, + [] + )} + open={params.action === "edit-shipping-address"} + variant="shipping" + onClose={closeModal} + onConfirm={variables => + orderUpdate.mutate({ + id, + input: { + shippingAddress: { + ...variables, + country: variables.country.value + } + } + }) + } + /> + orderUpdate.opts.data.orderUpdate.errors + ) + )} + address={transformAddressToForm( + maybe(() => order.billingAddress) + )} + countries={maybe(() => data.shop.countries, []).map( + country => ({ + code: country.code, + label: country.country + }) + )} + errors={maybe( + () => orderUpdate.opts.data.orderUpdate.errors, + [] + )} + open={params.action === "edit-billing-address"} + variant="billing" + onClose={closeModal} + onConfirm={variables => + orderUpdate.mutate({ + id, + input: { + billingAddress: { + ...variables, + country: variables.country.value + } + } + }) + } + /> + + ); + }} + + )} + + )} + + ); + }} + + ); +}; + +export default OrderDetails; diff --git a/src/orders/views/OrderDraftList.tsx b/src/orders/views/OrderDraftList.tsx new file mode 100644 index 000000000..e73c966b8 --- /dev/null +++ b/src/orders/views/OrderDraftList.tsx @@ -0,0 +1,171 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { PAGINATE_BY } from "../../config"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import OrderDraftListPage from "../components/OrderDraftListPage"; +import { + TypedOrderDraftBulkCancelMutation, + TypedOrderDraftCreateMutation +} from "../mutations"; +import { TypedOrderDraftListQuery } from "../queries"; +import { OrderDraftBulkCancel } from "../types/OrderDraftBulkCancel"; +import { OrderDraftCreate } from "../types/OrderDraftCreate"; +import { + orderDraftListUrl, + OrderDraftListUrlQueryParams, + orderUrl +} from "../urls"; + +interface OrderDraftListProps { + params: OrderDraftListUrlQueryParams; +} + +export const OrderDraftList: React.StatelessComponent = ({ + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const closeModal = () => + navigate( + orderDraftListUrl({ + ...params, + action: undefined, + ids: undefined + }) + ); + + const handleCreateOrderCreateSuccess = (data: OrderDraftCreate) => { + notify({ + text: i18n.t("Order draft succesfully created") + }); + navigate(orderUrl(data.draftOrderCreate.order.id)); + }; + + const paginationState = createPaginationState(PAGINATE_BY, params); + + return ( + + {createOrder => ( + + {({ data, loading, refetch }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.draftOrders.pageInfo), + paginationState, + params + ); + + const handleOrderDraftBulkCancel = (data: OrderDraftBulkCancel) => { + if (data.draftOrderBulkDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed draft orders") + }); + refetch(); + reset(); + closeModal(); + } + }; + + return ( + + {(orderDraftBulkDelete, orderDraftBulkDeleteOpts) => { + const bulkRemoveTransitionState = getMutationState( + orderDraftBulkDeleteOpts.called, + orderDraftBulkDeleteOpts.loading, + maybe( + () => + orderDraftBulkDeleteOpts.data.draftOrderBulkDelete + .errors + ) + ); + const onOrderDraftBulkDelete = () => + orderDraftBulkDelete({ + variables: { + ids: params.ids + } + }); + + return ( + <> + + data.draftOrders.edges.map(edge => edge.node) + )} + pageInfo={pageInfo} + onAdd={createOrder} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRowClick={id => () => navigate(orderUrl(id))} + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + toolbar={ + + navigate( + orderDraftListUrl({ + action: "remove", + ids: listElements + }) + ) + } + > + + + } + /> + + {{ number }} order drafts?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + ); + }} + + ); + }} + + )} + + ); +}; + +export default OrderDraftList; diff --git a/src/orders/views/OrderList/OrderList.tsx b/src/orders/views/OrderList/OrderList.tsx new file mode 100644 index 000000000..f0b19205e --- /dev/null +++ b/src/orders/views/OrderList/OrderList.tsx @@ -0,0 +1,270 @@ +import Button from "@material-ui/core/Button"; +import * as React from "react"; + +import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; +import SaveFilterTabDialog, { + SaveFilterTabDialogFormData +} from "@saleor/components/SaveFilterTabDialog"; +import { PAGINATE_BY } from "@saleor/config"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useDateLocalize from "@saleor/hooks/useDateLocalize"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; +import i18n from "@saleor/i18n"; +import { getMutationState, maybe } from "@saleor/misc"; +import OrderBulkCancelDialog from "../../components/OrderBulkCancelDialog"; +import OrderListPage from "../../components/OrderListPage/OrderListPage"; +import { + TypedOrderBulkCancelMutation, + TypedOrderDraftCreateMutation +} from "../../mutations"; +import { TypedOrderListQuery } from "../../queries"; +import { OrderBulkCancel } from "../../types/OrderBulkCancel"; +import { OrderDraftCreate } from "../../types/OrderDraftCreate"; +import { + orderListUrl, + OrderListUrlDialog, + OrderListUrlFilters, + OrderListUrlQueryParams, + orderUrl +} from "../../urls"; +import { + areFiltersApplied, + createFilter, + createFilterChips, + deleteFilterTab, + getActiveFilters, + getFilterTabs, + getFilterVariables, + saveFilterTab +} from "./filters"; + +interface OrderListProps { + params: OrderListUrlQueryParams; +} + +export const OrderList: React.StatelessComponent = ({ + params +}) => { + const formatDate = useDateLocalize(); + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const shop = useShop(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const tabs = getFilterTabs(); + + const currentTab = + params.activeTab === undefined + ? areFiltersApplied(params) + ? tabs.length + 1 + : 0 + : parseInt(params.activeTab, 0); + + const closeModal = () => + navigate( + orderListUrl({ + ...params, + action: undefined, + ids: undefined + }), + true + ); + + const changeFilters = (filters: OrderListUrlFilters) => { + reset(); + navigate(orderListUrl(filters)); + }; + + const changeFilterField = (filter: OrderListUrlFilters) => { + reset(); + navigate( + orderListUrl({ + ...getActiveFilters(params), + ...filter, + activeTab: undefined + }) + ); + }; + + const openModal = (action: OrderListUrlDialog, ids?: string[]) => + navigate( + orderListUrl({ + ...params, + action, + ids + }) + ); + + const handleTabChange = (tab: number) => { + reset(); + navigate( + orderListUrl({ + activeTab: tab.toString(), + ...getFilterTabs()[tab - 1].data + }) + ); + }; + + const handleFilterTabDelete = () => { + deleteFilterTab(currentTab); + reset(); + navigate(orderListUrl()); + }; + + const handleFilterTabSave = (data: SaveFilterTabDialogFormData) => { + saveFilterTab(data.name, getActiveFilters(params)); + handleTabChange(tabs.length + 1); + }; + + const paginationState = createPaginationState(PAGINATE_BY, params); + const currencySymbol = maybe(() => shop.defaultCurrency, "USD"); + + const handleCreateOrderCreateSuccess = (data: OrderDraftCreate) => { + notify({ + text: i18n.t("Order draft succesfully created") + }); + navigate(orderUrl(data.draftOrderCreate.order.id)); + }; + + const queryVariables = React.useMemo( + () => ({ + ...paginationState, + filter: getFilterVariables(params) + }), + [params] + ); + + return ( + + {createOrder => ( + + {({ data, loading, refetch }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.orders.pageInfo), + paginationState, + params + ); + + const handleOrderBulkCancel = (data: OrderBulkCancel) => { + if (data.orderBulkCancel.errors.length === 0) { + notify({ + text: i18n.t("Orders cancelled", { + context: "notification" + }) + }); + reset(); + refetch(); + closeModal(); + } + }; + + return ( + + {(orderBulkCancel, orderBulkCancelOpts) => { + const orderBulkCancelTransitionState = getMutationState( + orderBulkCancelOpts.called, + orderBulkCancelOpts.loading, + maybe(() => orderBulkCancelOpts.data.orderBulkCancel.errors) + ); + const onOrderBulkCancel = (restock: boolean) => + orderBulkCancel({ + variables: { + ids: params.ids, + restock + } + }); + + return ( + <> + + data.orders.edges.map(edge => edge.node) + )} + pageInfo={pageInfo} + onAdd={createOrder} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRowClick={id => () => navigate(orderUrl(id))} + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + toolbar={ + + } + onSearchChange={email => changeFilterField({ email })} + onFilterAdd={filter => + changeFilterField(createFilter(filter)) + } + onFilterSave={() => openModal("save-search")} + onFilterDelete={() => openModal("delete-search")} + onTabChange={handleTabChange} + initialSearch={params.email || ""} + filterTabs={getFilterTabs()} + onAll={() => + changeFilters({ + status: undefined + }) + } + /> + params.ids.length.toString(), + "..." + )} + onClose={closeModal} + onConfirm={onOrderBulkCancel} + open={params.action === "cancel"} + /> + + tabs[currentTab - 1].name, "...")} + /> + + ); + }} + + ); + }} + + )} + + ); +}; + +export default OrderList; diff --git a/src/orders/views/OrderList/filters.ts b/src/orders/views/OrderList/filters.ts new file mode 100644 index 000000000..39bc73341 --- /dev/null +++ b/src/orders/views/OrderList/filters.ts @@ -0,0 +1,174 @@ +import { FilterContentSubmitData } from "../../../components/Filter"; +import { Filter } from "../../../components/TableFilter"; +import i18n from "../../../i18n"; +import { + OrderFilterInput, + OrderStatusFilter +} from "../../../types/globalTypes"; +import { + createFilterTabUtils, + createFilterUtils +} from "../../../utils/filters"; +import { OrderFilterKeys } from "../../components/OrderListFilter"; +import { + OrderListUrlFilters, + OrderListUrlFiltersEnum, + OrderListUrlQueryParams +} from "../../urls"; + +export const ORDER_FILTERS_KEY = "orderFilters"; + +function getStatusLabel(status: string): string { + switch (status) { + case OrderStatusFilter.FULFILLED.toString(): + return i18n.t("Fulfilled"); + + case OrderStatusFilter.PARTIALLY_FULFILLED.toString(): + return i18n.t("Partially Fulfilled"); + + case OrderStatusFilter.UNFULFILLED.toString(): + return i18n.t("Unfulfilled"); + } + + return ""; +} + +export function getFilterVariables( + params: OrderListUrlFilters +): OrderFilterInput { + return { + created: { + gte: params.dateFrom, + lte: params.dateTo + }, + customer: params.email, + status: OrderStatusFilter[params.status] + }; +} + +export function createFilter( + filter: FilterContentSubmitData +): OrderListUrlFilters { + const filterName = filter.name; + if (filterName === OrderFilterKeys.dateEqual.toString()) { + const value = filter.value as string; + return { + dateFrom: value, + dateTo: value + }; + } else if (filterName === OrderFilterKeys.dateRange.toString()) { + const { value } = filter; + return { + dateFrom: value[0], + dateTo: value[1] + }; + } else if ( + [ + OrderFilterKeys.dateLastWeek, + OrderFilterKeys.dateLastMonth, + OrderFilterKeys.dateLastYear + ] + .map(value => value.toString()) + .includes(filterName) + ) { + const { value } = filter; + return { + dateFrom: value as string, + dateTo: undefined + }; + } else if (filterName === OrderFilterKeys.fulfillment.toString()) { + const { value } = filter; + return { + status: value as string + }; + } +} + +interface OrderListChipFormatData { + formatDate: (date: string) => string; +} +export function createFilterChips( + filters: OrderListUrlFilters, + formatData: OrderListChipFormatData, + onFilterDelete: (filters: OrderListUrlFilters) => void +): Filter[] { + let filterChips: Filter[] = []; + + if (!!filters.dateFrom || !!filters.dateTo) { + if (filters.dateFrom === filters.dateTo) { + filterChips = [ + ...filterChips, + { + label: i18n.t("Date is {{ date }}", { + date: formatData.formatDate(filters.dateFrom) + }), + onClick: () => + onFilterDelete({ + ...filters, + dateFrom: undefined, + dateTo: undefined + }) + } + ]; + } else { + if (!!filters.dateFrom) { + filterChips = [ + ...filterChips, + { + label: i18n.t("Date from {{ date }}", { + date: formatData.formatDate(filters.dateFrom) + }), + onClick: () => + onFilterDelete({ + ...filters, + dateFrom: undefined + }) + } + ]; + } + + if (!!filters.dateTo) { + filterChips = [ + ...filterChips, + { + label: i18n.t("Date to {{ date }}", { + date: formatData.formatDate(filters.dateTo) + }), + onClick: () => + onFilterDelete({ + ...filters, + dateTo: undefined + }) + } + ]; + } + } + } + + if (!!filters.status) { + filterChips = [ + ...filterChips, + { + label: getStatusLabel(filters.status), + onClick: () => + onFilterDelete({ + ...filters, + status: undefined + }) + } + ]; + } + + return filterChips; +} + +export const { + deleteFilterTab, + getFilterTabs, + saveFilterTab +} = createFilterTabUtils(ORDER_FILTERS_KEY); + +export const { areFiltersApplied, getActiveFilters } = createFilterUtils< + OrderListUrlQueryParams, + OrderListUrlFilters +>(OrderListUrlFiltersEnum); diff --git a/src/orders/views/OrderList/index.ts b/src/orders/views/OrderList/index.ts new file mode 100644 index 000000000..6f012db87 --- /dev/null +++ b/src/orders/views/OrderList/index.ts @@ -0,0 +1,2 @@ +export * from "./OrderList"; +export { default } from "./OrderList"; diff --git a/src/pages/components/PageDetailsPage/PageDetailsPage.tsx b/src/pages/components/PageDetailsPage/PageDetailsPage.tsx new file mode 100644 index 000000000..18cbd54b9 --- /dev/null +++ b/src/pages/components/PageDetailsPage/PageDetailsPage.tsx @@ -0,0 +1,136 @@ +import { + ContentState, + convertFromRaw, + convertToRaw, + RawDraftContentState +} from "draft-js"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import SeoForm from "@saleor/components/SeoForm"; +import VisibilityCard from "@saleor/components/VisibilityCard"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { UserError } from "../../../types"; +import { PageDetails_page } from "../../types/PageDetails"; +import PageInfo from "../PageInfo"; +import PageSlug from "../PageSlug"; + +export interface FormData { + content: RawDraftContentState; + isPublished: boolean; + publicationDate: string; + seoDescription: string; + seoTitle: string; + slug: string; + title: string; +} + +export interface PageDetailsPageProps { + disabled: boolean; + errors: UserError[]; + page: PageDetails_page; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onRemove: () => void; + onSubmit: (data: FormData) => void; +} + +const PageDetailsPage: React.StatelessComponent = ({ + disabled, + errors, + page, + saveButtonBarState, + onBack, + onRemove, + onSubmit +}) => { + const initialForm: FormData = { + content: maybe( + () => JSON.parse(page.contentJson), + convertToRaw(ContentState.createFromText("")) + ), + isPublished: maybe(() => page.isPublished, false), + publicationDate: maybe(() => page.publicationDate, ""), + seoDescription: maybe(() => page.seoDescription || "", ""), + seoTitle: maybe(() => page.seoTitle || "", ""), + slug: maybe(() => page.slug, ""), + title: maybe(() => page.title, "") + }; + return ( +
+ {({ change, data, errors: formErrors, hasChanged, submit }) => ( + + {i18n.t("Pages")} + page.title) + } + /> + +
+ + + { + return convertFromRaw(data.content) + .getPlainText() + .slice(0, 300); + }, "")} + onChange={change} + title={data.seoTitle} + titlePlaceholder={data.title} + helperText={i18n.t( + "Add search engine title and description to make this page easier to find" + )} + /> +
+
+ + + +
+
+ +
+ )} +
+ ); +}; +PageDetailsPage.displayName = "PageDetailsPage"; +export default PageDetailsPage; diff --git a/src/pages/components/PageDetailsPage/index.ts b/src/pages/components/PageDetailsPage/index.ts new file mode 100644 index 000000000..c299df7ee --- /dev/null +++ b/src/pages/components/PageDetailsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from './PageDetailsPage'; +export * from './PageDetailsPage'; \ No newline at end of file diff --git a/src/pages/components/PageInfo/PageInfo.tsx b/src/pages/components/PageInfo/PageInfo.tsx new file mode 100644 index 000000000..3d7d5de9e --- /dev/null +++ b/src/pages/components/PageInfo/PageInfo.tsx @@ -0,0 +1,69 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import FormSpacer from "@saleor/components/FormSpacer"; +import RichTextEditor from "@saleor/components/RichTextEditor"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { FormErrors } from "../../../types"; +import { PageDetails_page } from "../../types/PageDetails"; +import { FormData } from "../PageDetailsPage"; + +export interface PageInfoProps { + data: FormData; + disabled: boolean; + errors: FormErrors<"contentJson" | "title">; + page: PageDetails_page; + onChange: (event: React.ChangeEvent) => void; +} + +const styles = createStyles({ + root: { + overflow: "visible" + } +}); + +const PageInfo = withStyles(styles, { + name: "PageInfo" +})( + ({ + classes, + data, + disabled, + errors, + page, + onChange + }: PageInfoProps & WithStyles) => ( + + + + + + JSON.parse(page.contentJson))} + label={i18n.t("Content")} + name={"content" as keyof FormData} + onChange={onChange} + /> + + + ) +); +PageInfo.displayName = "PageInfo"; +export default PageInfo; diff --git a/src/pages/components/PageInfo/index.ts b/src/pages/components/PageInfo/index.ts new file mode 100644 index 000000000..8bcf98a76 --- /dev/null +++ b/src/pages/components/PageInfo/index.ts @@ -0,0 +1,2 @@ +export { default } from './PageInfo'; +export * from './PageInfo'; \ No newline at end of file diff --git a/src/pages/components/PageList/PageList.tsx b/src/pages/components/PageList/PageList.tsx new file mode 100644 index 000000000..ad77e8d68 --- /dev/null +++ b/src/pages/components/PageList/PageList.tsx @@ -0,0 +1,151 @@ +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import * as React from "react"; + +import Checkbox from "@saleor/components/Checkbox"; +import Skeleton from "@saleor/components/Skeleton"; +import StatusLabel from "@saleor/components/StatusLabel"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { PageList_pages_edges_node } from "../../types/PageList"; + +export interface PageListProps extends ListProps, ListActions { + pages: PageList_pages_edges_node[]; +} + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colSlug: { + width: 250 + }, + colTitle: {}, + colVisibility: { + width: 200 + } + }, + colSlug: {}, + colTitle: {}, + colVisibility: {}, + link: { + cursor: "pointer" + } + }); +const PageList = withStyles(styles, { name: "PageList" })( + ({ + classes, + pages, + disabled, + onNextPage, + pageInfo, + onRowClick, + onPreviousPage, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: PageListProps & WithStyles) => ( + + + + + {i18n.t("Title", { context: "table header" })} + + + {i18n.t("Slug", { context: "table header" })} + + + {i18n.t("Visibility", { context: "table header" })} + + + + + + + + + {renderCollection( + pages, + page => { + const isSelected = page ? isChecked(page.id) : false; + + return ( + + + toggle(page.id)} + /> + + + {maybe(() => page.title, )} + + + {maybe(() => page.slug, )} + + + {maybe( + () => ( + + ), + + )} + + + ); + }, + () => ( + + {i18n.t("No pages found")} + + ) + )} + +
+
+ ) +); +PageList.displayName = "PageList"; +export default PageList; diff --git a/src/pages/components/PageList/index.ts b/src/pages/components/PageList/index.ts new file mode 100644 index 000000000..0b888e9db --- /dev/null +++ b/src/pages/components/PageList/index.ts @@ -0,0 +1,2 @@ +export { default } from './PageList'; +export * from './PageList'; \ No newline at end of file diff --git a/src/pages/components/PageListPage/PageListPage.tsx b/src/pages/components/PageListPage/PageListPage.tsx new file mode 100644 index 000000000..1e6a72bc9 --- /dev/null +++ b/src/pages/components/PageListPage/PageListPage.tsx @@ -0,0 +1,62 @@ +import Button from "@material-ui/core/Button"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { ListActions, PageListProps } from "../../../types"; +import { PageList_pages_edges_node } from "../../types/PageList"; +import PageList from "../PageList/PageList"; + +export interface PageListPageProps extends PageListProps, ListActions { + pages: PageList_pages_edges_node[]; + onBack: () => void; +} + +const PageListPage: React.StatelessComponent = ({ + disabled, + onAdd, + onBack, + onNextPage, + onPreviousPage, + onRowClick, + pageInfo, + pages, + isChecked, + selected, + toggle, + toggleAll, + toolbar +}) => ( + + {i18n.t("Configuration")} + + + + + +); +PageListPage.displayName = "PageListPage"; +export default PageListPage; diff --git a/src/pages/components/PageListPage/index.ts b/src/pages/components/PageListPage/index.ts new file mode 100644 index 000000000..c5d589974 --- /dev/null +++ b/src/pages/components/PageListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from './PageListPage'; +export * from './PageListPage'; \ No newline at end of file diff --git a/src/pages/components/PageSlug/PageSlug.tsx b/src/pages/components/PageSlug/PageSlug.tsx new file mode 100644 index 000000000..b251e4af2 --- /dev/null +++ b/src/pages/components/PageSlug/PageSlug.tsx @@ -0,0 +1,45 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; +import slugify from "slugify"; + +import CardTitle from "@saleor/components/CardTitle"; +import i18n from "../../../i18n"; +import { FormData } from "../PageDetailsPage"; + +export interface PageSlugProps { + data: FormData; + disabled: boolean; + errors: Partial>; + onChange: (event: React.ChangeEvent) => void; +} + +const PageSlug: React.StatelessComponent = ({ + data, + disabled, + errors, + onChange +}) => ( + + + + + + +); +PageSlug.displayName = "PageSlug"; +export default PageSlug; diff --git a/src/pages/components/PageSlug/index.ts b/src/pages/components/PageSlug/index.ts new file mode 100644 index 000000000..06056b307 --- /dev/null +++ b/src/pages/components/PageSlug/index.ts @@ -0,0 +1,2 @@ +export { default } from './PageSlug'; +export * from './PageSlug'; \ No newline at end of file diff --git a/src/pages/fixtures.ts b/src/pages/fixtures.ts new file mode 100644 index 000000000..86739b16c --- /dev/null +++ b/src/pages/fixtures.ts @@ -0,0 +1,45 @@ +import { content } from "../storybook/stories/components/RichTextEditor"; +import { PageDetails_page } from "./types/PageDetails"; +import { PageList_pages_edges_node } from "./types/PageList"; + +export const pageList: PageList_pages_edges_node[] = [ + { + __typename: "Page", + id: "Jzx123sEt==", + isPublished: true, + slug: "about", + title: "About" + }, + { + __typename: "Page", + id: "Jzx123sEx==", + isPublished: false, + slug: "about", + title: "About" + }, + { + __typename: "Page", + id: "Jzx123sEu==", + isPublished: true, + slug: "about", + title: "About" + }, + { + __typename: "Page", + id: "Jzx123sEm==", + isPublished: true, + slug: "about", + title: "About" + } +]; +export const page: PageDetails_page = { + __typename: "Page", + contentJson: JSON.stringify(content), + id: "Kzx152sEm==", + isPublished: false, + publicationDate: "", + seoDescription: "About", + seoTitle: "About", + slug: "about", + title: "About" +}; diff --git a/src/pages/index.tsx b/src/pages/index.tsx new file mode 100644 index 000000000..d156d0941 --- /dev/null +++ b/src/pages/index.tsx @@ -0,0 +1,51 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { WindowTitle } from "../components/WindowTitle"; +import i18n from "../i18n"; +import { + pageCreatePath, + pageListPath, + PageListUrlQueryParams, + pagePath, + PageUrlQueryParams +} from "./urls"; +import PageCreate from "./views/PageCreate"; +import PageDetailsComponent from "./views/PageDetails"; +import PageListComponent from "./views/PageList"; + +const PageList: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: PageListUrlQueryParams = qs; + return ; +}; + +const PageDetails: React.StatelessComponent> = ({ + match +}) => { + const qs = parseQs(location.search.substr(1)); + const params: PageUrlQueryParams = qs; + + return ( + + ); +}; + +const Component = () => ( + <> + + + + + + + +); + +export default Component; diff --git a/src/pages/mutations.ts b/src/pages/mutations.ts new file mode 100644 index 000000000..48432ef42 --- /dev/null +++ b/src/pages/mutations.ts @@ -0,0 +1,95 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { pageDetailsFragment } from "./queries"; +import { + PageBulkPublish, + PageBulkPublishVariables +} from "./types/PageBulkPublish"; +import { + PageBulkRemove, + PageBulkRemoveVariables +} from "./types/PageBulkRemove"; +import { PageCreate, PageCreateVariables } from "./types/PageCreate"; +import { PageRemove, PageRemoveVariables } from "./types/PageRemove"; +import { PageUpdate, PageUpdateVariables } from "./types/PageUpdate"; + +const pageCreate = gql` + ${pageDetailsFragment} + mutation PageCreate($input: PageInput!) { + pageCreate(input: $input) { + errors { + field + message + } + page { + ...PageDetailsFragment + } + } + } +`; +export const TypedPageCreate = TypedMutation( + pageCreate +); + +const pageUpdate = gql` + ${pageDetailsFragment} + mutation PageUpdate($id: ID!, $input: PageInput!) { + pageUpdate(id: $id, input: $input) { + errors { + field + message + } + page { + ...PageDetailsFragment + } + } + } +`; +export const TypedPageUpdate = TypedMutation( + pageUpdate +); + +const pageRemove = gql` + mutation PageRemove($id: ID!) { + pageDelete(id: $id) { + errors { + field + message + } + } + } +`; +export const TypedPageRemove = TypedMutation( + pageRemove +); + +const pageBulkPublish = gql` + mutation PageBulkPublish($ids: [ID]!, $isPublished: Boolean!) { + pageBulkPublish(ids: $ids, isPublished: $isPublished) { + errors { + field + message + } + } + } +`; +export const TypedPageBulkPublish = TypedMutation< + PageBulkPublish, + PageBulkPublishVariables +>(pageBulkPublish); + +const pageBulkRemove = gql` + mutation PageBulkRemove($ids: [ID]!) { + pageBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedPageBulkRemove = TypedMutation< + PageBulkRemove, + PageBulkRemoveVariables +>(pageBulkRemove); diff --git a/src/pages/queries.ts b/src/pages/queries.ts new file mode 100644 index 000000000..8990a6267 --- /dev/null +++ b/src/pages/queries.ts @@ -0,0 +1,60 @@ +import gql from "graphql-tag"; + +import { TypedQuery } from "../queries"; +import { PageDetails, PageDetailsVariables } from "./types/PageDetails"; +import { PageList, PageListVariables } from "./types/PageList"; + +export const pageFragment = gql` + fragment PageFragment on Page { + id + title + slug + isPublished + } +`; + +export const pageDetailsFragment = gql` + ${pageFragment} + fragment PageDetailsFragment on Page { + ...PageFragment + contentJson + seoTitle + seoDescription + publicationDate + } +`; + +const pageList = gql` + ${pageFragment} + query PageList($first: Int, $after: String, $last: Int, $before: String) { + pages(before: $before, after: $after, first: $first, last: $last) { + edges { + node { + ...PageFragment + } + } + pageInfo { + hasPreviousPage + hasNextPage + startCursor + endCursor + } + } + } +`; +export const TypedPageListQuery = TypedQuery( + pageList +); + +const pageDetails = gql` + ${pageDetailsFragment} + query PageDetails($id: ID!) { + page(id: $id) { + ...PageDetailsFragment + } + } +`; +export const TypedPageDetailsQuery = TypedQuery< + PageDetails, + PageDetailsVariables +>(pageDetails); diff --git a/src/pages/types/PageBulkPublish.ts b/src/pages/types/PageBulkPublish.ts new file mode 100644 index 000000000..1a84cab83 --- /dev/null +++ b/src/pages/types/PageBulkPublish.ts @@ -0,0 +1,27 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: PageBulkPublish +// ==================================================== + +export interface PageBulkPublish_pageBulkPublish_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface PageBulkPublish_pageBulkPublish { + __typename: "PageBulkPublish"; + errors: PageBulkPublish_pageBulkPublish_errors[] | null; +} + +export interface PageBulkPublish { + pageBulkPublish: PageBulkPublish_pageBulkPublish | null; +} + +export interface PageBulkPublishVariables { + ids: (string | null)[]; + isPublished: boolean; +} diff --git a/src/pages/types/PageBulkRemove.ts b/src/pages/types/PageBulkRemove.ts new file mode 100644 index 000000000..be5c1f85b --- /dev/null +++ b/src/pages/types/PageBulkRemove.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: PageBulkRemove +// ==================================================== + +export interface PageBulkRemove_pageBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface PageBulkRemove_pageBulkDelete { + __typename: "PageBulkDelete"; + errors: PageBulkRemove_pageBulkDelete_errors[] | null; +} + +export interface PageBulkRemove { + pageBulkDelete: PageBulkRemove_pageBulkDelete | null; +} + +export interface PageBulkRemoveVariables { + ids: (string | null)[]; +} diff --git a/src/pages/types/PageCreate.ts b/src/pages/types/PageCreate.ts new file mode 100644 index 000000000..b87367761 --- /dev/null +++ b/src/pages/types/PageCreate.ts @@ -0,0 +1,41 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PageInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: PageCreate +// ==================================================== + +export interface PageCreate_pageCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface PageCreate_pageCreate_page { + __typename: "Page"; + id: string; + title: string; + slug: string; + isPublished: boolean; + contentJson: any; + seoTitle: string | null; + seoDescription: string | null; + publicationDate: any | null; +} + +export interface PageCreate_pageCreate { + __typename: "PageCreate"; + errors: PageCreate_pageCreate_errors[] | null; + page: PageCreate_pageCreate_page | null; +} + +export interface PageCreate { + pageCreate: PageCreate_pageCreate | null; +} + +export interface PageCreateVariables { + input: PageInput; +} diff --git a/src/pages/types/PageDetails.ts b/src/pages/types/PageDetails.ts new file mode 100644 index 000000000..ffc94dd3a --- /dev/null +++ b/src/pages/types/PageDetails.ts @@ -0,0 +1,27 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: PageDetails +// ==================================================== + +export interface PageDetails_page { + __typename: "Page"; + id: string; + title: string; + slug: string; + isPublished: boolean; + contentJson: any; + seoTitle: string | null; + seoDescription: string | null; + publicationDate: any | null; +} + +export interface PageDetails { + page: PageDetails_page | null; +} + +export interface PageDetailsVariables { + id: string; +} diff --git a/src/pages/types/PageDetailsFragment.ts b/src/pages/types/PageDetailsFragment.ts new file mode 100644 index 000000000..1b1e48c92 --- /dev/null +++ b/src/pages/types/PageDetailsFragment.ts @@ -0,0 +1,19 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: PageDetailsFragment +// ==================================================== + +export interface PageDetailsFragment { + __typename: "Page"; + id: string; + title: string; + slug: string; + isPublished: boolean; + contentJson: any; + seoTitle: string | null; + seoDescription: string | null; + publicationDate: any | null; +} diff --git a/src/pages/types/PageFragment.ts b/src/pages/types/PageFragment.ts new file mode 100644 index 000000000..c10ca7112 --- /dev/null +++ b/src/pages/types/PageFragment.ts @@ -0,0 +1,15 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: PageFragment +// ==================================================== + +export interface PageFragment { + __typename: "Page"; + id: string; + title: string; + slug: string; + isPublished: boolean; +} diff --git a/src/pages/types/PageList.ts b/src/pages/types/PageList.ts new file mode 100644 index 000000000..df8718b7b --- /dev/null +++ b/src/pages/types/PageList.ts @@ -0,0 +1,45 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: PageList +// ==================================================== + +export interface PageList_pages_edges_node { + __typename: "Page"; + id: string; + title: string; + slug: string; + isPublished: boolean; +} + +export interface PageList_pages_edges { + __typename: "PageCountableEdge"; + node: PageList_pages_edges_node; +} + +export interface PageList_pages_pageInfo { + __typename: "PageInfo"; + hasPreviousPage: boolean; + hasNextPage: boolean; + startCursor: string | null; + endCursor: string | null; +} + +export interface PageList_pages { + __typename: "PageCountableConnection"; + edges: PageList_pages_edges[]; + pageInfo: PageList_pages_pageInfo; +} + +export interface PageList { + pages: PageList_pages | null; +} + +export interface PageListVariables { + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/pages/types/PageRemove.ts b/src/pages/types/PageRemove.ts new file mode 100644 index 000000000..d1f63ed63 --- /dev/null +++ b/src/pages/types/PageRemove.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: PageRemove +// ==================================================== + +export interface PageRemove_pageDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface PageRemove_pageDelete { + __typename: "PageDelete"; + errors: PageRemove_pageDelete_errors[] | null; +} + +export interface PageRemove { + pageDelete: PageRemove_pageDelete | null; +} + +export interface PageRemoveVariables { + id: string; +} diff --git a/src/pages/types/PageUpdate.ts b/src/pages/types/PageUpdate.ts new file mode 100644 index 000000000..853a0a34c --- /dev/null +++ b/src/pages/types/PageUpdate.ts @@ -0,0 +1,42 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PageInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: PageUpdate +// ==================================================== + +export interface PageUpdate_pageUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface PageUpdate_pageUpdate_page { + __typename: "Page"; + id: string; + title: string; + slug: string; + isPublished: boolean; + contentJson: any; + seoTitle: string | null; + seoDescription: string | null; + publicationDate: any | null; +} + +export interface PageUpdate_pageUpdate { + __typename: "PageUpdate"; + errors: PageUpdate_pageUpdate_errors[] | null; + page: PageUpdate_pageUpdate_page | null; +} + +export interface PageUpdate { + pageUpdate: PageUpdate_pageUpdate | null; +} + +export interface PageUpdateVariables { + id: string; + input: PageInput; +} diff --git a/src/pages/urls.ts b/src/pages/urls.ts new file mode 100644 index 000000000..6761dd81f --- /dev/null +++ b/src/pages/urls.ts @@ -0,0 +1,23 @@ +import { stringify as stringifyQs } from "qs"; +import * as urlJoin from "url-join"; + +import { BulkAction, Dialog, Pagination } from "../types"; + +export const pagesSection = "/pages/"; + +export const pageListPath = pagesSection; +export type PageListUrlDialog = "publish" | "unpublish" | "remove"; +export type PageListUrlQueryParams = BulkAction & + Dialog & + Pagination; +export const pageListUrl = (params?: PageListUrlQueryParams) => + pageListPath + "?" + stringifyQs(params); + +export const pagePath = (id: string) => urlJoin(pagesSection, id); +export type PageUrlDialog = "remove"; +export type PageUrlQueryParams = Dialog; +export const pageUrl = (id: string, params?: PageUrlQueryParams) => + pagePath(encodeURIComponent(id)) + "?" + stringifyQs(params); + +export const pageCreatePath = urlJoin(pagesSection, "add"); +export const pageCreateUrl = pageCreatePath; diff --git a/src/pages/views/PageCreate.tsx b/src/pages/views/PageCreate.tsx new file mode 100644 index 000000000..367d4b929 --- /dev/null +++ b/src/pages/views/PageCreate.tsx @@ -0,0 +1,84 @@ +import * as React from "react"; + +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import PageDetailsPage from "../components/PageDetailsPage"; +import { TypedPageCreate } from "../mutations"; +import { PageCreate as PageCreateData } from "../types/PageCreate"; +import { pageListUrl, pageUrl } from "../urls"; + +export interface PageCreateProps { + id: string; +} + +export const PageCreate: React.StatelessComponent = () => { + const navigate = useNavigator(); + const notify = useNotifier(); + + const handlePageCreate = (data: PageCreateData) => { + if (data.pageCreate.errors.length === 0) { + notify({ + text: i18n.t("Successfully created new page", { + context: "notification" + }) + }); + navigate(pageUrl(data.pageCreate.page.id)); + } + }; + + return ( + + {(pageCreate, pageCreateOpts) => { + const formTransitionState = getMutationState( + pageCreateOpts.called, + pageCreateOpts.loading, + maybe(() => pageCreateOpts.data.pageCreate.errors) + ); + + return ( + <> + + pageCreateOpts.data.pageCreate.errors, [])} + saveButtonBarState={formTransitionState} + page={null} + onBack={() => navigate(pageListUrl())} + onRemove={() => undefined} + onSubmit={formData => + pageCreate({ + variables: { + input: { + contentJson: JSON.stringify(formData.content), + isPublished: formData.isPublished + ? true + : formData.publicationDate === "" + ? false + : true, + publicationDate: formData.isPublished + ? null + : formData.publicationDate === "" + ? null + : formData.publicationDate, + seo: { + description: formData.seoDescription, + title: formData.seoTitle + }, + slug: formData.slug === "" ? null : formData.slug, + title: formData.title + } + } + }) + } + /> + + ); + }} + + ); +}; +PageCreate.displayName = "PageCreate"; +export default PageCreate; diff --git a/src/pages/views/PageDetails.tsx b/src/pages/views/PageDetails.tsx new file mode 100644 index 000000000..e8b64a283 --- /dev/null +++ b/src/pages/views/PageDetails.tsx @@ -0,0 +1,141 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import { PageInput } from "../../types/globalTypes"; +import PageDetailsPage, { FormData } from "../components/PageDetailsPage"; +import { TypedPageRemove, TypedPageUpdate } from "../mutations"; +import { TypedPageDetailsQuery } from "../queries"; +import { PageRemove } from "../types/PageRemove"; +import { pageListUrl, pageUrl, PageUrlQueryParams } from "../urls"; + +export interface PageDetailsProps { + id: string; + params: PageUrlQueryParams; +} + +const createPageInput = (data: FormData): PageInput => ({ + contentJson: JSON.stringify(data.content), + isPublished: data.isPublished + ? true + : data.publicationDate === "" || data.publicationDate === null + ? false + : true, + publicationDate: data.isPublished + ? null + : data.publicationDate === "" + ? null + : data.publicationDate, + seo: { + description: data.seoDescription, + title: data.seoTitle + }, + slug: data.slug === "" ? null : data.slug, + title: data.title +}); + +export const PageDetails: React.StatelessComponent = ({ + id, + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + + const handlePageRemove = (data: PageRemove) => { + if (data.pageDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed page", { + context: "notification" + }) + }); + navigate(pageListUrl()); + } + }; + return ( + + {(pageRemove, pageRemoveOpts) => ( + + {(pageUpdate, pageUpdateOpts) => ( + + {pageDetails => { + const formTransitionState = getMutationState( + pageUpdateOpts.called, + pageUpdateOpts.loading, + maybe(() => pageUpdateOpts.data.pageUpdate.errors) + ); + const removeTransitionState = getMutationState( + pageRemoveOpts.called, + pageRemoveOpts.loading, + maybe(() => pageRemoveOpts.data.pageDelete.errors) + ); + + return ( + <> + pageDetails.data.page.title)} + /> + pageUpdateOpts.data.pageUpdate.errors, + [] + )} + saveButtonBarState={formTransitionState} + page={maybe(() => pageDetails.data.page)} + onBack={() => navigate(pageListUrl())} + onRemove={() => + navigate( + pageUrl(id, { + action: "remove" + }) + ) + } + onSubmit={formData => + pageUpdate({ + variables: { + id, + input: createPageInput(formData) + } + }) + } + /> + navigate(pageUrl(id))} + onConfirm={pageRemove} + variant="delete" + > + {{ title }}?", + { + context: "page remove", + title: maybe( + () => pageDetails.data.page.title, + "..." + ) + } + ) + }} + /> + + + ); + }} + + )} + + )} + + ); +}; +PageDetails.displayName = "PageDetails"; +export default PageDetails; diff --git a/src/pages/views/PageList.tsx b/src/pages/views/PageList.tsx new file mode 100644 index 000000000..bdfea8fbb --- /dev/null +++ b/src/pages/views/PageList.tsx @@ -0,0 +1,252 @@ +import Button from "@material-ui/core/Button"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { PAGINATE_BY } from "../../config"; +import { configurationMenuUrl } from "../../configuration"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import PageListPage from "../components/PageListPage/PageListPage"; +import { TypedPageBulkPublish, TypedPageBulkRemove } from "../mutations"; +import { TypedPageListQuery } from "../queries"; +import { PageBulkPublish } from "../types/PageBulkPublish"; +import { PageBulkRemove } from "../types/PageBulkRemove"; +import { + pageCreateUrl, + pageListUrl, + PageListUrlDialog, + PageListUrlQueryParams, + pageUrl +} from "../urls"; + +interface PageListProps { + params: PageListUrlQueryParams; +} + +export const PageList: React.StatelessComponent = ({ + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const paginationState = createPaginationState(PAGINATE_BY, params); + + return ( + + {({ data, loading, refetch }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.pages.pageInfo), + paginationState, + params + ); + + const closeModal = () => + navigate( + pageListUrl({ + ...params, + action: undefined, + ids: undefined + }), + true + ); + + const openModal = (action: PageListUrlDialog, ids: string[]) => + navigate( + pageListUrl({ + ...params, + action, + ids + }) + ); + + const handlePageBulkPublish = (data: PageBulkPublish) => { + if (data.pageBulkPublish.errors.length === 0) { + closeModal(); + notify({ + text: i18n.t("Published pages") + }); + reset(); + refetch(); + } + }; + + const handlePageBulkRemove = (data: PageBulkRemove) => { + if (data.pageBulkDelete.errors.length === 0) { + closeModal(); + notify({ + text: i18n.t("Removed pages") + }); + reset(); + refetch(); + } + }; + + return ( + + {(bulkPageRemove, bulkPageRemoveOpts) => ( + + {(bulkPagePublish, bulkPagePublishOpts) => { + const deleteTransitionState = getMutationState( + bulkPageRemoveOpts.called, + bulkPageRemoveOpts.loading, + maybe(() => bulkPageRemoveOpts.data.pageBulkDelete.errors) + ); + + const publishTransitionState = getMutationState( + bulkPagePublishOpts.called, + bulkPagePublishOpts.loading, + maybe(() => bulkPagePublishOpts.data.pageBulkPublish.errors) + ); + + return ( + <> + + data.pages.edges.map(edge => edge.node) + )} + pageInfo={pageInfo} + onAdd={() => navigate(pageCreateUrl)} + onBack={() => navigate(configurationMenuUrl)} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRowClick={id => () => navigate(pageUrl(id))} + toolbar={ + <> + + + openModal("remove", listElements)} + > + + + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + /> + + bulkPagePublish({ + variables: { + ids: params.ids, + isPublished: true + } + }) + } + title={i18n.t("Publish pages")} + > + {{ number }} pages?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + bulkPagePublish({ + variables: { + ids: params.ids, + isPublished: false + } + }) + } + title={i18n.t("Unpublish pages")} + > + {{ number }} pages?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + bulkPageRemove({ + variables: { + ids: params.ids + } + }) + } + variant="delete" + title={i18n.t("Remove pages")} + > + {{ number }} pages?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + ); + }} + + )} + + ); + }} + + ); +}; + +export default PageList; diff --git a/src/productTypes/components/ProductTypeAttributeEditDialog/ProductTypeAttributeEditDialog.tsx b/src/productTypes/components/ProductTypeAttributeEditDialog/ProductTypeAttributeEditDialog.tsx new file mode 100644 index 000000000..7e431962c --- /dev/null +++ b/src/productTypes/components/ProductTypeAttributeEditDialog/ProductTypeAttributeEditDialog.tsx @@ -0,0 +1,99 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import Form from "@saleor/components/Form"; +import { FormSpacer } from "@saleor/components/FormSpacer"; +import ListField from "@saleor/components/ListField"; +import i18n from "../../../i18n"; + +export interface FormData { + name: string; + values: Array<{ + label: string; + value: string; + }>; +} + +export interface ProductTypeAttributeEditDialogProps { + disabled: boolean; + errors: Array<{ + field: string; + message: string; + }>; + name: string; + opened: boolean; + title: string; + values: Array<{ + label: string; + value: string; + }>; + onClose: () => void; + onConfirm: (data: FormData) => void; +} + +const ProductTypeAttributeEditDialog: React.StatelessComponent< + ProductTypeAttributeEditDialogProps +> = ({ disabled, errors, name, opened, title, values, onClose, onConfirm }) => { + const initialForm: FormData = { + name: name || "", + values: values || [] + }; + return ( + +
+ {({ change, data, errors: formErrors }) => ( + <> + {title} + + + + + + + + + + + )} +
+
+ ); +}; +ProductTypeAttributeEditDialog.displayName = "ProductTypeAttributeEditDialog"; +export default ProductTypeAttributeEditDialog; diff --git a/src/productTypes/components/ProductTypeAttributeEditDialog/index.ts b/src/productTypes/components/ProductTypeAttributeEditDialog/index.ts new file mode 100644 index 000000000..6344b380f --- /dev/null +++ b/src/productTypes/components/ProductTypeAttributeEditDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductTypeAttributeEditDialog"; +export * from "./ProductTypeAttributeEditDialog"; diff --git a/src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx b/src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx new file mode 100644 index 000000000..e75f41ab4 --- /dev/null +++ b/src/productTypes/components/ProductTypeAttributes/ProductTypeAttributes.tsx @@ -0,0 +1,139 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import IconButton from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { AttributeTypeEnum } from "../../../types/globalTypes"; +import { + ProductTypeDetails_productType_productAttributes, + ProductTypeDetails_productType_variantAttributes +} from "../../types/ProductTypeDetails"; + +const styles = (theme: Theme) => + createStyles({ + iconCell: { + "&:last-child": { + paddingRight: 0 + }, + width: 48 + theme.spacing.unit / 2 + }, + link: { + cursor: "pointer" + }, + textLeft: { + textAlign: "left" + } + }); + +interface ProductTypeAttributesProps extends WithStyles { + attributes: + | ProductTypeDetails_productType_productAttributes[] + | ProductTypeDetails_productType_variantAttributes[]; + type: AttributeTypeEnum; + onAttributeAdd: (type: AttributeTypeEnum) => void; + onAttributeDelete: (id: string, event: React.MouseEvent) => void; + onAttributeUpdate: (id: string) => void; +} + +const ProductTypeAttributes = withStyles(styles, { + name: "ProductTypeAttributes" +})( + ({ + attributes, + classes, + type, + onAttributeAdd, + onAttributeDelete, + onAttributeUpdate + }: ProductTypeAttributesProps) => ( + + onAttributeAdd(type)} + > + {i18n.t("Add attribute", { context: "button" })} + + } + /> + + + + {i18n.t("Attribute name")} + + {i18n.t("Values")} + + + + + + {renderCollection( + attributes, + attribute => ( + onAttributeUpdate(attribute.id) + : undefined + } + key={maybe(() => attribute.id)} + > + + {maybe(() => attribute.name) ? attribute.name : } + + + {maybe(() => attribute.values) !== undefined ? ( + attribute.values.map(value => value.name).join(", ") + ) : ( + + )} + + + onAttributeDelete(attribute.id, event)} + > + + + + + ), + () => ( + + + {i18n.t("No attributes found")} + + + ) + )} + +
+
+ ) +); +ProductTypeAttributes.displayName = "ProductTypeAttributes"; +export default ProductTypeAttributes; diff --git a/src/productTypes/components/ProductTypeAttributes/index.ts b/src/productTypes/components/ProductTypeAttributes/index.ts new file mode 100644 index 000000000..c59c84532 --- /dev/null +++ b/src/productTypes/components/ProductTypeAttributes/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductTypeAttributes"; +export * from "./ProductTypeAttributes"; diff --git a/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx b/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx new file mode 100644 index 000000000..76dfcda74 --- /dev/null +++ b/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx @@ -0,0 +1,102 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { TaxRateType, WeightUnitsEnum } from "../../../types/globalTypes"; +import ProductTypeDetails from "../ProductTypeDetails/ProductTypeDetails"; +import ProductTypeShipping from "../ProductTypeShipping/ProductTypeShipping"; +import ProductTypeTaxes from "../ProductTypeTaxes/ProductTypeTaxes"; + +export interface ProductTypeForm { + chargeTaxes: boolean; + name: string; + isShippingRequired: boolean; + taxRate: TaxRateType; + weight: number; +} + +export interface ProductTypeCreatePageProps { + errors: Array<{ + field: string; + message: string; + }>; + defaultWeightUnit: WeightUnitsEnum; + disabled: boolean; + pageTitle: string; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onSubmit: (data: ProductTypeForm) => void; +} + +const ProductTypeCreatePage: React.StatelessComponent< + ProductTypeCreatePageProps +> = ({ + defaultWeightUnit, + disabled, + errors, + pageTitle, + saveButtonBarState, + onBack, + onSubmit +}: ProductTypeCreatePageProps) => { + const formInitialData: ProductTypeForm = { + chargeTaxes: true, + isShippingRequired: false, + name: "", + taxRate: TaxRateType.STANDARD, + weight: 0 + }; + return ( +
+ {({ change, data, hasChanged, submit }) => ( + + {i18n.t("Product Types")} + + +
+ +
+
+ + + +
+
+ +
+ )} +
+ ); +}; +ProductTypeCreatePage.displayName = "ProductTypeCreatePage"; +export default ProductTypeCreatePage; diff --git a/src/productTypes/components/ProductTypeCreatePage/index.ts b/src/productTypes/components/ProductTypeCreatePage/index.ts new file mode 100644 index 000000000..2a18e4c3e --- /dev/null +++ b/src/productTypes/components/ProductTypeCreatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductTypeCreatePage"; +export * from "./ProductTypeCreatePage"; diff --git a/src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx b/src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx new file mode 100644 index 000000000..984b1f03d --- /dev/null +++ b/src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx @@ -0,0 +1,42 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import i18n from "../../../i18n"; + +const styles = createStyles({ + root: { + overflow: "visible" + } +}); + +interface ProductTypeDetailsProps extends WithStyles { + data?: { + name: string; + }; + disabled: boolean; + onChange: (event: React.ChangeEvent) => void; +} + +const ProductTypeDetails = withStyles(styles, { name: "ProductTypeDetails" })( + ({ classes, data, disabled, onChange }: ProductTypeDetailsProps) => ( + + + + + + + ) +); +ProductTypeDetails.displayName = "ProductTypeDetails"; +export default ProductTypeDetails; diff --git a/src/productTypes/components/ProductTypeDetails/index.ts b/src/productTypes/components/ProductTypeDetails/index.ts new file mode 100644 index 000000000..4677bf57a --- /dev/null +++ b/src/productTypes/components/ProductTypeDetails/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductTypeDetails"; +export * from "./ProductTypeDetails"; diff --git a/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx b/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx new file mode 100644 index 000000000..bffc67b0d --- /dev/null +++ b/src/productTypes/components/ProductTypeDetailsPage/ProductTypeDetailsPage.tsx @@ -0,0 +1,179 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { + AttributeTypeEnum, + TaxRateType, + WeightUnitsEnum +} from "../../../types/globalTypes"; +import { ProductTypeDetails_productType } from "../../types/ProductTypeDetails"; +import ProductTypeAttributes from "../ProductTypeAttributes/ProductTypeAttributes"; +import ProductTypeDetails from "../ProductTypeDetails/ProductTypeDetails"; +import ProductTypeShipping from "../ProductTypeShipping/ProductTypeShipping"; +import ProductTypeTaxes from "../ProductTypeTaxes/ProductTypeTaxes"; + +interface ChoiceType { + label: string; + value: string; +} + +export interface ProductTypeForm { + name: string; + hasVariants: boolean; + isShippingRequired: boolean; + taxRate: TaxRateType; + productAttributes: ChoiceType[]; + variantAttributes: ChoiceType[]; + weight: number; +} + +export interface ProductTypeDetailsPageProps { + errors: Array<{ + field: string; + message: string; + }>; + productType: ProductTypeDetails_productType; + defaultWeightUnit: WeightUnitsEnum; + disabled: boolean; + pageTitle: string; + saveButtonBarState: ConfirmButtonTransitionState; + onAttributeAdd: (type: AttributeTypeEnum) => void; + onAttributeDelete: (id: string, event: React.MouseEvent) => void; + onAttributeUpdate: (id: string) => void; + onBack: () => void; + onDelete: () => void; + onSubmit: (data: ProductTypeForm) => void; +} + +const ProductTypeDetailsPage: React.StatelessComponent< + ProductTypeDetailsPageProps +> = ({ + defaultWeightUnit, + disabled, + errors, + pageTitle, + productType, + saveButtonBarState, + onAttributeAdd, + onAttributeDelete, + onAttributeUpdate, + onBack, + onDelete, + onSubmit +}) => { + const formInitialData: ProductTypeForm = { + hasVariants: + maybe(() => productType.hasVariants) !== undefined + ? productType.hasVariants + : false, + isShippingRequired: + maybe(() => productType.isShippingRequired) !== undefined + ? productType.isShippingRequired + : false, + name: maybe(() => productType.name) !== undefined ? productType.name : "", + productAttributes: + maybe(() => productType.productAttributes) !== undefined + ? productType.productAttributes.map(attribute => ({ + label: attribute.name, + value: attribute.id + })) + : [], + taxRate: + maybe(() => productType.taxRate) !== undefined + ? productType.taxRate + : null, + variantAttributes: + maybe(() => productType.variantAttributes) !== undefined + ? productType.variantAttributes.map(attribute => ({ + label: attribute.name, + value: attribute.id + })) + : [], + weight: maybe(() => productType.weight.value) + }; + return ( +
+ {({ change, data, hasChanged, submit }) => ( + + {i18n.t("Product Types")} + + +
+ + + productType.productAttributes)} + type={AttributeTypeEnum.PRODUCT} + onAttributeAdd={onAttributeAdd} + onAttributeDelete={onAttributeDelete} + onAttributeUpdate={onAttributeUpdate} + /> + + + {data.hasVariants && ( + <> + + productType.variantAttributes)} + type={AttributeTypeEnum.VARIANT} + onAttributeAdd={onAttributeAdd} + onAttributeDelete={onAttributeDelete} + onAttributeUpdate={onAttributeUpdate} + /> + + )} +
+
+ + + +
+
+ +
+ )} +
+ ); +}; +ProductTypeDetailsPage.displayName = "ProductTypeDetailsPage"; +export default ProductTypeDetailsPage; diff --git a/src/productTypes/components/ProductTypeDetailsPage/index.ts b/src/productTypes/components/ProductTypeDetailsPage/index.ts new file mode 100644 index 000000000..eae6822fc --- /dev/null +++ b/src/productTypes/components/ProductTypeDetailsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductTypeDetailsPage"; +export * from "./ProductTypeDetailsPage"; diff --git a/src/productTypes/components/ProductTypeList/ProductTypeList.tsx b/src/productTypes/components/ProductTypeList/ProductTypeList.tsx new file mode 100644 index 000000000..6ad65504f --- /dev/null +++ b/src/productTypes/components/ProductTypeList/ProductTypeList.tsx @@ -0,0 +1,174 @@ +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import Checkbox from "@saleor/components/Checkbox"; +import Skeleton from "@saleor/components/Skeleton"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection, translatedTaxRates } from "../../../misc"; +import { ListActions, ListProps } from "../../../types"; +import { ProductTypeList_productTypes_edges_node } from "../../types/ProductTypeList"; + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colName: {}, + colTax: { + width: 300 + }, + colType: { + width: 300 + } + }, + colName: {}, + colTax: {}, + colType: {}, + link: { + cursor: "pointer" + } + }); + +interface ProductTypeListProps + extends ListProps, + ListActions, + WithStyles { + productTypes: ProductTypeList_productTypes_edges_node[]; +} + +const ProductTypeList = withStyles(styles, { name: "ProductTypeList" })( + ({ + classes, + disabled, + productTypes, + pageInfo, + onNextPage, + onPreviousPage, + onRowClick, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: ProductTypeListProps) => ( + + + + + {i18n.t("Type Name", { context: "table header" })} + + + {i18n.t("Type", { context: "table header" })} + + + {i18n.t("Tax", { context: "table header" })} + + + + + + + + + {renderCollection( + productTypes, + productType => { + const isSelected = productType + ? isChecked(productType.id) + : false; + return ( + + + toggle(productType.id)} + /> + + + {productType ? ( + <> + {productType.name} + + {maybe(() => productType.hasVariants) + ? i18n.t("Configurable", { + context: "product type" + }) + : i18n.t("Simple product", { + context: "product type" + })} + + + ) : ( + + )} + + + {maybe(() => productType.isShippingRequired) !== + undefined ? ( + productType.isShippingRequired ? ( + <>{i18n.t("Physical", { context: "product type" })} + ) : ( + <>{i18n.t("Digital", { context: "product type" })} + ) + ) : ( + + )} + + + {maybe(() => productType.taxRate) ? ( + translatedTaxRates()[productType.taxRate] + ) : ( + + )} + + + ); + }, + () => ( + + + {i18n.t("No product types found")} + + + ) + )} + +
+
+ ) +); +ProductTypeList.displayName = "ProductTypeList"; +export default ProductTypeList; diff --git a/src/productTypes/components/ProductTypeList/index.ts b/src/productTypes/components/ProductTypeList/index.ts new file mode 100644 index 000000000..9c1624523 --- /dev/null +++ b/src/productTypes/components/ProductTypeList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductTypeList"; +export * from "./ProductTypeList"; diff --git a/src/productTypes/components/ProductTypeListPage/ProductTypeListPage.tsx b/src/productTypes/components/ProductTypeListPage/ProductTypeListPage.tsx new file mode 100644 index 000000000..52c754557 --- /dev/null +++ b/src/productTypes/components/ProductTypeListPage/ProductTypeListPage.tsx @@ -0,0 +1,37 @@ +import Button from "@material-ui/core/Button"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { ListActions, PageListProps } from "../../../types"; +import { ProductTypeList_productTypes_edges_node } from "../../types/ProductTypeList"; +import ProductTypeList from "../ProductTypeList"; + +interface ProductTypeListPageProps extends PageListProps, ListActions { + productTypes: ProductTypeList_productTypes_edges_node[]; + onBack: () => void; +} + +const ProductTypeListPage: React.StatelessComponent< + ProductTypeListPageProps +> = ({ disabled, onAdd, onBack, ...listProps }) => ( + + {i18n.t("Configuration")} + + + + + +); +ProductTypeListPage.displayName = "ProductTypeListPage"; +export default ProductTypeListPage; diff --git a/src/productTypes/components/ProductTypeListPage/index.ts b/src/productTypes/components/ProductTypeListPage/index.ts new file mode 100644 index 000000000..55c8646cc --- /dev/null +++ b/src/productTypes/components/ProductTypeListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductTypeListPage"; +export * from "./ProductTypeListPage"; diff --git a/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.tsx b/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.tsx new file mode 100644 index 000000000..5ad7b53e8 --- /dev/null +++ b/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.tsx @@ -0,0 +1,53 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; +import i18n from "../../../i18n"; +import { WeightUnitsEnum } from "../../../types/globalTypes"; + +interface ProductTypeShippingProps { + data: { + isShippingRequired: boolean; + weight: number | null; + }; + defaultWeightUnit: WeightUnitsEnum; + disabled: boolean; + onChange: (event: React.ChangeEvent) => void; +} + +const ProductTypeShipping: React.StatelessComponent< + ProductTypeShippingProps +> = ({ data, defaultWeightUnit, disabled, onChange }) => ( + + + + + {data.isShippingRequired && ( + + )} + + +); + +ProductTypeShipping.displayName = "ProductTypeShipping"; +export default ProductTypeShipping; diff --git a/src/productTypes/components/ProductTypeShipping/index.ts b/src/productTypes/components/ProductTypeShipping/index.ts new file mode 100644 index 000000000..c0c638265 --- /dev/null +++ b/src/productTypes/components/ProductTypeShipping/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductTypeShipping"; +export * from "./ProductTypeShipping"; diff --git a/src/productTypes/components/ProductTypeTaxes/ProductTypeTaxes.tsx b/src/productTypes/components/ProductTypeTaxes/ProductTypeTaxes.tsx new file mode 100644 index 000000000..c824355b4 --- /dev/null +++ b/src/productTypes/components/ProductTypeTaxes/ProductTypeTaxes.tsx @@ -0,0 +1,44 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import SingleSelectField from "@saleor/components/SingleSelectField"; +import i18n from "../../../i18n"; +import { translatedTaxRates as taxRates } from "../../../misc"; +import { TaxRateType } from "../../../types/globalTypes"; + +interface ProductTypeTaxesProps { + data: { + taxRate: TaxRateType | null; + }; + disabled: boolean; + onChange: (event: React.ChangeEvent) => void; +} +const taxRateChoices = Object.keys(taxRates()).map(key => ({ + label: taxRates()[key], + value: key +})); +const ProductTypeTaxes: React.StatelessComponent = ({ + data, + disabled, + onChange +}) => ( + + + + + + +); +ProductTypeTaxes.displayName = "ProductTypeTaxes"; +export default ProductTypeTaxes; diff --git a/src/productTypes/components/ProductTypeTaxes/index.ts b/src/productTypes/components/ProductTypeTaxes/index.ts new file mode 100644 index 000000000..3996500a9 --- /dev/null +++ b/src/productTypes/components/ProductTypeTaxes/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductTypeTaxes"; +export * from "./ProductTypeTaxes"; diff --git a/src/productTypes/containers/ProductTypeOperations.tsx b/src/productTypes/containers/ProductTypeOperations.tsx new file mode 100644 index 000000000..f99152083 --- /dev/null +++ b/src/productTypes/containers/ProductTypeOperations.tsx @@ -0,0 +1,117 @@ +import * as React from "react"; + +import { getMutationProviderData } from "../../misc"; +import { PartialMutationProviderOutput } from "../../types"; +import { + TypedAttributeCreateMutation, + TypedAttributeDeleteMutation, + TypedAttributeUpdateMutation, + TypedProductTypeDeleteMutation, + TypedProductTypeUpdateMutation +} from "../mutations"; +import { + AttributeCreate, + AttributeCreateVariables +} from "../types/AttributeCreate"; +import { + AttributeDelete, + AttributeDeleteVariables +} from "../types/AttributeDelete"; +import { + AttributeUpdate, + AttributeUpdateVariables +} from "../types/AttributeUpdate"; +import { + ProductTypeDelete, + ProductTypeDeleteVariables +} from "../types/ProductTypeDelete"; +import { + ProductTypeUpdate, + ProductTypeUpdateVariables +} from "../types/ProductTypeUpdate"; + +interface ProductTypeOperationsProps { + children: ( + props: { + attributeCreate: PartialMutationProviderOutput< + AttributeCreate, + AttributeCreateVariables + >; + deleteAttribute: PartialMutationProviderOutput< + AttributeDelete, + AttributeDeleteVariables + >; + deleteProductType: PartialMutationProviderOutput< + ProductTypeDelete, + ProductTypeDeleteVariables + >; + updateAttribute: PartialMutationProviderOutput< + AttributeUpdate, + AttributeUpdateVariables + >; + updateProductType: PartialMutationProviderOutput< + ProductTypeUpdate, + ProductTypeUpdateVariables + >; + } + ) => React.ReactNode; + onAttributeCreate: (data: AttributeCreate) => void; + onAttributeDelete: (data: AttributeDelete) => void; + onAttributeUpdate: (data: AttributeUpdate) => void; + onProductTypeDelete: (data: ProductTypeDelete) => void; + onProductTypeUpdate: (data: ProductTypeUpdate) => void; +} + +const ProductTypeOperations: React.StatelessComponent< + ProductTypeOperationsProps +> = ({ + children, + onAttributeCreate, + onAttributeDelete, + onAttributeUpdate, + onProductTypeDelete, + onProductTypeUpdate +}) => { + return ( + + {(...deleteProductType) => ( + + {(...updateProductType) => ( + + {(...createAttribute) => ( + + {(...deleteAttribute) => ( + + {(...updateAttribute) => + children({ + attributeCreate: getMutationProviderData( + ...createAttribute + ), + deleteAttribute: getMutationProviderData( + ...deleteAttribute + ), + deleteProductType: getMutationProviderData( + ...deleteProductType + ), + updateAttribute: getMutationProviderData( + ...updateAttribute + ), + updateProductType: getMutationProviderData( + ...updateProductType + ) + }) + } + + )} + + )} + + )} + + )} + + ); +}; +export default ProductTypeOperations; diff --git a/src/productTypes/fixtures.ts b/src/productTypes/fixtures.ts new file mode 100644 index 000000000..169f08b8f --- /dev/null +++ b/src/productTypes/fixtures.ts @@ -0,0 +1,580 @@ +import { + ProductCreateData_productTypes_edges_node, + ProductCreateData_productTypes_edges_node_productAttributes +} from "../products/types/ProductCreateData"; +import { TaxRateType } from "../types/globalTypes"; +import { ProductTypeDetails_productType } from "./types/ProductTypeDetails"; +import { ProductTypeList_productTypes_edges_node } from "./types/ProductTypeList"; + +export const attributes: ProductCreateData_productTypes_edges_node_productAttributes[] = [ + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZTo5", + name: "Author", + slug: "author", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI0", + name: "John Doe", + slug: "john-doe", + sortOrder: 0, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI1", + name: "Milionare Pirate", + slug: "milionare-pirate", + sortOrder: 1, + type: "STRING", + value: "" + } + ] + } + }, + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZTo2", + name: "Box Size", + slug: "box-size", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjE1", + name: "100g", + slug: "100g", + sortOrder: 0, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjE2", + name: "250g", + slug: "250g", + sortOrder: 1, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjE3", + name: "500g", + slug: "500g", + sortOrder: 2, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjE4", + name: "1kg", + slug: "1kg", + sortOrder: 3, + type: "STRING", + value: "" + } + ] + } + }, + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZToz", + name: "Brand", + slug: "brand", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjY=", + name: "Saleor", + slug: "saleor", + sortOrder: 0, + type: "STRING", + value: "" + } + ] + } + }, + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZTo4", + name: "Candy Box Size", + slug: "candy-box-size", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjIx", + name: "100g", + slug: "100g", + sortOrder: 0, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjIy", + name: "250g", + slug: "250g", + sortOrder: 1, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjIz", + name: "500g", + slug: "500g", + sortOrder: 2, + type: "STRING", + value: "" + } + ] + } + }, + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZTo1", + name: "Coffee Genre", + slug: "coffee-genre", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjEz", + name: "Arabica", + slug: "arabica", + sortOrder: 0, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjE0", + name: "Robusta", + slug: "robusta", + sortOrder: 1, + type: "STRING", + value: "" + } + ] + } + }, + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZToy", + name: "Collar", + slug: "collar", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjM=", + name: "Round", + slug: "round", + sortOrder: 0, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjQ=", + name: "V-Neck", + slug: "v-neck", + sortOrder: 1, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjU=", + name: "Polo", + slug: "polo", + sortOrder: 2, + type: "STRING", + value: "" + } + ] + } + }, + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZTox", + name: "Color", + slug: "color", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjE=", + name: "Blue", + slug: "blue", + sortOrder: 0, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI=", + name: "White", + slug: "white", + sortOrder: 1, + type: "STRING", + value: "" + } + ] + } + }, + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZToxMg==", + name: "Cover", + slug: "cover", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjMw", + name: "Soft", + slug: "soft", + sortOrder: 0, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjMx", + name: "Hard", + slug: "hard", + sortOrder: 1, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjMy", + name: "Middle soft", + slug: "middle-soft", + sortOrder: 2, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjMz", + name: "Middle hard", + slug: "middle-hard", + sortOrder: 3, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjM0", + name: "Middle", + slug: "middle", + sortOrder: 4, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjM1", + name: "Very hard", + slug: "very-hard", + sortOrder: 5, + type: "STRING", + value: "" + } + ] + } + }, + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZTo3", + name: "Flavor", + slug: "flavor", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjE5", + name: "Sour", + slug: "sour", + sortOrder: 0, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjIw", + name: "Sweet", + slug: "sweet", + sortOrder: 1, + type: "STRING", + value: "" + } + ] + } + }, + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZToxMQ==", + name: "Language", + slug: "language", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI4", + name: "English", + slug: "english", + sortOrder: 0, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI5", + name: "Pirate", + slug: "pirate", + sortOrder: 1, + type: "STRING", + value: "" + } + ] + } + }, + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZToxMA==", + name: "Publisher", + slug: "publisher", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI2", + name: "Mirumee Press", + slug: "mirumee-press", + sortOrder: 0, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI3", + name: "Saleor Publishing", + slug: "saleor-publishing", + sortOrder: 1, + type: "STRING", + value: "" + } + ] + } + }, + { + node: { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZTo0", + name: "Size", + slug: "size", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjc=", + name: "XS", + slug: "xs", + sortOrder: 0, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjg=", + name: "S", + slug: "s", + sortOrder: 1, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjk=", + name: "M", + slug: "m", + sortOrder: 2, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjEw", + name: "L", + slug: "l", + sortOrder: 3, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjEx", + name: "XL", + slug: "xl", + sortOrder: 4, + type: "STRING", + value: "" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjEy", + name: "XXL", + slug: "xxl", + sortOrder: 5, + type: "STRING", + value: "" + } + ] + } + } +].map(edge => edge.node); + +export const productTypes: Array< + ProductCreateData_productTypes_edges_node & + ProductTypeList_productTypes_edges_node +> = [ + { + __typename: "ProductType" as "ProductType", + hasVariants: true, + id: "UHJvZHVjdFR5cGU6NA==", + isShippingRequired: true, + name: "Candy", + productAttributes: [attributes[0]], + taxRate: "FOODSTUFFS" as TaxRateType, + variantAttributes: [attributes[1], attributes[2]] + }, + { + __typename: "ProductType" as "ProductType", + hasVariants: false, + id: "UHJvZHVjdFR5cGU6NQ==", + isShippingRequired: false, + name: "E-books", + productAttributes: [attributes[5]], + taxRate: "STANDARD" as TaxRateType, + variantAttributes: [attributes[0], attributes[3]] + }, + { + __typename: "ProductType" as "ProductType", + hasVariants: false, + id: "UHJvZHVjdFR5cGU6Mg==", + isShippingRequired: true, + name: "Mugs", + productAttributes: [attributes[7]], + taxRate: "STANDARD" as TaxRateType, + variantAttributes: [attributes[2], attributes[5]] + }, + { + __typename: "ProductType" as "ProductType", + hasVariants: true, + id: "UHJvZHVjdFR5cGU6Mw==", + isShippingRequired: true, + name: "Coffee", + productAttributes: [attributes[8]], + taxRate: "STANDARD" as TaxRateType, + variantAttributes: [attributes[1], attributes[4]] + }, + { + __typename: "ProductType" as "ProductType", + hasVariants: true, + id: "UHJvZHVjdFR5cGU6MQ==", + isShippingRequired: true, + name: "T-Shirt", + productAttributes: [attributes[4]], + taxRate: "STANDARD" as TaxRateType, + variantAttributes: [attributes[1], attributes[6]] + } +].map(productType => ({ + __typename: "ProductType" as "ProductType", + ...productType +})); +export const productType: ProductTypeDetails_productType = { + __typename: "ProductType" as "ProductType", + hasVariants: false, + id: "UHJvZHVjdFR5cGU6NQ==", + isShippingRequired: false, + name: "E-books", + productAttributes: [ + { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZTo5", + name: "Author", + slug: "author", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI0", + name: "John Doe", + slug: "john-doe" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI1", + name: "Milionare Pirate", + slug: "milionare-pirate" + } + ] + }, + { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZToxMQ==", + name: "Language", + slug: "language", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI4", + name: "English", + slug: "english" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI5", + name: "Pirate", + slug: "pirate" + } + ] + }, + { + __typename: "Attribute" as "Attribute", + id: "UHJvZHVjdEF0dHJpYnV0ZToxMA==", + name: "Publisher", + slug: "publisher", + values: [ + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI2", + name: "Mirumee Press", + slug: "mirumee-press" + }, + { + __typename: "AttributeValue" as "AttributeValue", + id: "UHJvZHVjdEF0dHJpYnV0ZVZhbHVlOjI3", + name: "Saleor Publishing", + slug: "saleor-publishing" + } + ] + } + ], + taxRate: "STANDARD" as TaxRateType, + variantAttributes: [], + weight: { + __typename: "Weight", + unit: "kg", + value: 7.82 + } +}; diff --git a/src/productTypes/index.tsx b/src/productTypes/index.tsx new file mode 100644 index 000000000..c5232cfe0 --- /dev/null +++ b/src/productTypes/index.tsx @@ -0,0 +1,56 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { WindowTitle } from "../components/WindowTitle"; +import i18n from "../i18n"; +import { + productTypeAddPath, + productTypeListPath, + ProductTypeListUrlQueryParams, + productTypePath, + ProductTypeUrlQueryParams +} from "./urls"; +import ProductTypeCreate from "./views/ProductTypeCreate"; +import ProductTypeListComponent from "./views/ProductTypeList"; +import ProductTypeUpdateComponent from "./views/ProductTypeUpdate"; + +const ProductTypeList: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: ProductTypeListUrlQueryParams = qs; + return ; +}; + +interface ProductTypeUpdateRouteParams { + id: string; +} +const ProductTypeUpdate: React.StatelessComponent< + RouteComponentProps +> = ({ match }) => { + const qs = parseQs(location.search.substr(1)); + const params: ProductTypeUrlQueryParams = qs; + + return ( + + ); +}; + +export const ProductTypeRouter: React.StatelessComponent< + RouteComponentProps +> = () => ( + <> + + + + + + + +); +ProductTypeRouter.displayName = "ProductTypeRouter"; +export default ProductTypeRouter; diff --git a/src/productTypes/mutations.ts b/src/productTypes/mutations.ts new file mode 100644 index 000000000..de7cc9543 --- /dev/null +++ b/src/productTypes/mutations.ts @@ -0,0 +1,164 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { attributeFragment, productTypeDetailsFragment } from "./queries"; +import { + AttributeCreate, + AttributeCreateVariables +} from "./types/AttributeCreate"; +import { + AttributeDelete, + AttributeDeleteVariables +} from "./types/AttributeDelete"; +import { + AttributeUpdate, + AttributeUpdateVariables +} from "./types/AttributeUpdate"; +import { + ProductTypeBulkDelete, + ProductTypeBulkDeleteVariables +} from "./types/ProductTypeBulkDelete"; +import { + ProductTypeCreate, + ProductTypeCreateVariables +} from "./types/ProductTypeCreate"; +import { + ProductTypeDelete, + ProductTypeDeleteVariables +} from "./types/ProductTypeDelete"; +import { + ProductTypeUpdate, + ProductTypeUpdateVariables +} from "./types/ProductTypeUpdate"; + +export const productTypeDeleteMutation = gql` + mutation ProductTypeDelete($id: ID!) { + productTypeDelete(id: $id) { + errors { + field + message + } + productType { + id + } + } + } +`; +export const TypedProductTypeDeleteMutation = TypedMutation< + ProductTypeDelete, + ProductTypeDeleteVariables +>(productTypeDeleteMutation); + +export const productTypeBulkDeleteMutation = gql` + mutation ProductTypeBulkDelete($ids: [ID]!) { + productTypeBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedProductTypeBulkDeleteMutation = TypedMutation< + ProductTypeBulkDelete, + ProductTypeBulkDeleteVariables +>(productTypeBulkDeleteMutation); + +export const productTypeUpdateMutation = gql` + ${productTypeDetailsFragment} + mutation ProductTypeUpdate($id: ID!, $input: ProductTypeInput!) { + productTypeUpdate(id: $id, input: $input) { + errors { + field + message + } + productType { + ...ProductTypeDetailsFragment + } + } + } +`; +export const TypedProductTypeUpdateMutation = TypedMutation< + ProductTypeUpdate, + ProductTypeUpdateVariables +>(productTypeUpdateMutation); + +export const productTypeCreateMutation = gql` + ${productTypeDetailsFragment} + mutation ProductTypeCreate($input: ProductTypeInput!) { + productTypeCreate(input: $input) { + errors { + field + message + } + productType { + ...ProductTypeDetailsFragment + } + } + } +`; +export const TypedProductTypeCreateMutation = TypedMutation< + ProductTypeCreate, + ProductTypeCreateVariables +>(productTypeCreateMutation); + +export const attributeCreateMutation = gql` + ${productTypeDetailsFragment} + mutation AttributeCreate( + $id: ID! + $input: AttributeCreateInput! + $type: AttributeTypeEnum! + ) { + attributeCreate(id: $id, input: $input, type: $type) { + errors { + field + message + } + productType { + ...ProductTypeDetailsFragment + } + } + } +`; +export const TypedAttributeCreateMutation = TypedMutation< + AttributeCreate, + AttributeCreateVariables +>(attributeCreateMutation); + +export const attributeUpdateMutation = gql` + ${attributeFragment} + mutation AttributeUpdate($id: ID!, $input: AttributeUpdateInput!) { + attributeUpdate(id: $id, input: $input) { + errors { + field + message + } + attribute { + ...AttributeFragment + } + } + } +`; +export const TypedAttributeUpdateMutation = TypedMutation< + AttributeUpdate, + AttributeUpdateVariables +>(attributeUpdateMutation); + +export const attributeDeleteMutation = gql` + ${productTypeDetailsFragment} + mutation AttributeDelete($id: ID!) { + attributeDelete(id: $id) { + errors { + field + message + } + productType { + ...ProductTypeDetailsFragment + } + } + } +`; +export const TypedAttributeDeleteMutation = TypedMutation< + AttributeDelete, + AttributeDeleteVariables +>(attributeDeleteMutation); diff --git a/src/productTypes/queries.ts b/src/productTypes/queries.ts new file mode 100644 index 000000000..f3012c73a --- /dev/null +++ b/src/productTypes/queries.ts @@ -0,0 +1,108 @@ +import gql from "graphql-tag"; + +import { TypedQuery } from "../queries"; +import { ProductTypeCreateData } from "./types/ProductTypeCreateData"; +import { + ProductTypeDetails, + ProductTypeDetailsVariables +} from "./types/ProductTypeDetails"; +import { + ProductTypeList, + ProductTypeListVariables +} from "./types/ProductTypeList"; + +export const attributeFragment = gql` + fragment AttributeFragment on Attribute { + id + name + slug + values { + id + name + slug + } + } +`; +export const productTypeFragment = gql` + fragment ProductTypeFragment on ProductType { + id + name + hasVariants + isShippingRequired + taxRate + } +`; + +export const productTypeDetailsFragment = gql` + ${attributeFragment} + ${productTypeFragment} + fragment ProductTypeDetailsFragment on ProductType { + ...ProductTypeFragment + productAttributes { + ...AttributeFragment + } + variantAttributes { + ...AttributeFragment + } + weight { + unit + value + } + } +`; + +export const productTypeListQuery = gql` + ${productTypeFragment} + query ProductTypeList( + $after: String + $before: String + $first: Int + $last: Int + ) { + productTypes(after: $after, before: $before, first: $first, last: $last) { + edges { + node { + ...ProductTypeFragment + } + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + } +`; +export const TypedProductTypeListQuery = TypedQuery< + ProductTypeList, + ProductTypeListVariables +>(productTypeListQuery); + +export const productTypeDetailsQuery = gql` + ${productTypeDetailsFragment} + query ProductTypeDetails($id: ID!) { + productType(id: $id) { + ...ProductTypeDetailsFragment + } + shop { + defaultWeightUnit + } + } +`; +export const TypedProductTypeDetailsQuery = TypedQuery< + ProductTypeDetails, + ProductTypeDetailsVariables +>(productTypeDetailsQuery); + +export const productTypeCreateDataQuery = gql` + query ProductTypeCreateData { + shop { + defaultWeightUnit + } + } +`; +export const TypedProductTypeCreateDataQuery = TypedQuery< + ProductTypeCreateData, + {} +>(productTypeCreateDataQuery); diff --git a/src/productTypes/types/AttributeCreate.ts b/src/productTypes/types/AttributeCreate.ts new file mode 100644 index 000000000..63548a3bc --- /dev/null +++ b/src/productTypes/types/AttributeCreate.ts @@ -0,0 +1,79 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AttributeCreateInput, AttributeTypeEnum, TaxRateType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AttributeCreate +// ==================================================== + +export interface AttributeCreate_attributeCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface AttributeCreate_attributeCreate_productType_productAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface AttributeCreate_attributeCreate_productType_productAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (AttributeCreate_attributeCreate_productType_productAttributes_values | null)[] | null; +} + +export interface AttributeCreate_attributeCreate_productType_variantAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface AttributeCreate_attributeCreate_productType_variantAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (AttributeCreate_attributeCreate_productType_variantAttributes_values | null)[] | null; +} + +export interface AttributeCreate_attributeCreate_productType_weight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface AttributeCreate_attributeCreate_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; + isShippingRequired: boolean; + taxRate: TaxRateType | null; + productAttributes: (AttributeCreate_attributeCreate_productType_productAttributes | null)[] | null; + variantAttributes: (AttributeCreate_attributeCreate_productType_variantAttributes | null)[] | null; + weight: AttributeCreate_attributeCreate_productType_weight | null; +} + +export interface AttributeCreate_attributeCreate { + __typename: "AttributeCreate"; + errors: AttributeCreate_attributeCreate_errors[] | null; + productType: AttributeCreate_attributeCreate_productType | null; +} + +export interface AttributeCreate { + attributeCreate: AttributeCreate_attributeCreate | null; +} + +export interface AttributeCreateVariables { + id: string; + input: AttributeCreateInput; + type: AttributeTypeEnum; +} diff --git a/src/productTypes/types/AttributeDelete.ts b/src/productTypes/types/AttributeDelete.ts new file mode 100644 index 000000000..f62cd728f --- /dev/null +++ b/src/productTypes/types/AttributeDelete.ts @@ -0,0 +1,77 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { TaxRateType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AttributeDelete +// ==================================================== + +export interface AttributeDelete_attributeDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface AttributeDelete_attributeDelete_productType_productAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface AttributeDelete_attributeDelete_productType_productAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (AttributeDelete_attributeDelete_productType_productAttributes_values | null)[] | null; +} + +export interface AttributeDelete_attributeDelete_productType_variantAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface AttributeDelete_attributeDelete_productType_variantAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (AttributeDelete_attributeDelete_productType_variantAttributes_values | null)[] | null; +} + +export interface AttributeDelete_attributeDelete_productType_weight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface AttributeDelete_attributeDelete_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; + isShippingRequired: boolean; + taxRate: TaxRateType | null; + productAttributes: (AttributeDelete_attributeDelete_productType_productAttributes | null)[] | null; + variantAttributes: (AttributeDelete_attributeDelete_productType_variantAttributes | null)[] | null; + weight: AttributeDelete_attributeDelete_productType_weight | null; +} + +export interface AttributeDelete_attributeDelete { + __typename: "AttributeDelete"; + errors: AttributeDelete_attributeDelete_errors[] | null; + productType: AttributeDelete_attributeDelete_productType | null; +} + +export interface AttributeDelete { + attributeDelete: AttributeDelete_attributeDelete | null; +} + +export interface AttributeDeleteVariables { + id: string; +} diff --git a/src/productTypes/types/AttributeFragment.ts b/src/productTypes/types/AttributeFragment.ts new file mode 100644 index 000000000..35a35464f --- /dev/null +++ b/src/productTypes/types/AttributeFragment.ts @@ -0,0 +1,22 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: AttributeFragment +// ==================================================== + +export interface AttributeFragment_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface AttributeFragment { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (AttributeFragment_values | null)[] | null; +} diff --git a/src/productTypes/types/AttributeUpdate.ts b/src/productTypes/types/AttributeUpdate.ts new file mode 100644 index 000000000..08245fd55 --- /dev/null +++ b/src/productTypes/types/AttributeUpdate.ts @@ -0,0 +1,45 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AttributeUpdateInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AttributeUpdate +// ==================================================== + +export interface AttributeUpdate_attributeUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface AttributeUpdate_attributeUpdate_attribute_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface AttributeUpdate_attributeUpdate_attribute { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (AttributeUpdate_attributeUpdate_attribute_values | null)[] | null; +} + +export interface AttributeUpdate_attributeUpdate { + __typename: "AttributeUpdate"; + errors: AttributeUpdate_attributeUpdate_errors[] | null; + attribute: AttributeUpdate_attributeUpdate_attribute | null; +} + +export interface AttributeUpdate { + attributeUpdate: AttributeUpdate_attributeUpdate | null; +} + +export interface AttributeUpdateVariables { + id: string; + input: AttributeUpdateInput; +} diff --git a/src/productTypes/types/ProductTypeBulkDelete.ts b/src/productTypes/types/ProductTypeBulkDelete.ts new file mode 100644 index 000000000..5924436f6 --- /dev/null +++ b/src/productTypes/types/ProductTypeBulkDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: ProductTypeBulkDelete +// ==================================================== + +export interface ProductTypeBulkDelete_productTypeBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ProductTypeBulkDelete_productTypeBulkDelete { + __typename: "ProductTypeBulkDelete"; + errors: ProductTypeBulkDelete_productTypeBulkDelete_errors[] | null; +} + +export interface ProductTypeBulkDelete { + productTypeBulkDelete: ProductTypeBulkDelete_productTypeBulkDelete | null; +} + +export interface ProductTypeBulkDeleteVariables { + ids: (string | null)[]; +} diff --git a/src/productTypes/types/ProductTypeCreate.ts b/src/productTypes/types/ProductTypeCreate.ts new file mode 100644 index 000000000..a146ea60f --- /dev/null +++ b/src/productTypes/types/ProductTypeCreate.ts @@ -0,0 +1,77 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ProductTypeInput, TaxRateType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: ProductTypeCreate +// ==================================================== + +export interface ProductTypeCreate_productTypeCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ProductTypeCreate_productTypeCreate_productType_productAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductTypeCreate_productTypeCreate_productType_productAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (ProductTypeCreate_productTypeCreate_productType_productAttributes_values | null)[] | null; +} + +export interface ProductTypeCreate_productTypeCreate_productType_variantAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductTypeCreate_productTypeCreate_productType_variantAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (ProductTypeCreate_productTypeCreate_productType_variantAttributes_values | null)[] | null; +} + +export interface ProductTypeCreate_productTypeCreate_productType_weight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface ProductTypeCreate_productTypeCreate_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; + isShippingRequired: boolean; + taxRate: TaxRateType | null; + productAttributes: (ProductTypeCreate_productTypeCreate_productType_productAttributes | null)[] | null; + variantAttributes: (ProductTypeCreate_productTypeCreate_productType_variantAttributes | null)[] | null; + weight: ProductTypeCreate_productTypeCreate_productType_weight | null; +} + +export interface ProductTypeCreate_productTypeCreate { + __typename: "ProductTypeCreate"; + errors: ProductTypeCreate_productTypeCreate_errors[] | null; + productType: ProductTypeCreate_productTypeCreate_productType | null; +} + +export interface ProductTypeCreate { + productTypeCreate: ProductTypeCreate_productTypeCreate | null; +} + +export interface ProductTypeCreateVariables { + input: ProductTypeInput; +} diff --git a/src/productTypes/types/ProductTypeCreateData.ts b/src/productTypes/types/ProductTypeCreateData.ts new file mode 100644 index 000000000..483dedd6a --- /dev/null +++ b/src/productTypes/types/ProductTypeCreateData.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { WeightUnitsEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: ProductTypeCreateData +// ==================================================== + +export interface ProductTypeCreateData_shop { + __typename: "Shop"; + defaultWeightUnit: WeightUnitsEnum | null; +} + +export interface ProductTypeCreateData { + shop: ProductTypeCreateData_shop | null; +} diff --git a/src/productTypes/types/ProductTypeDelete.ts b/src/productTypes/types/ProductTypeDelete.ts new file mode 100644 index 000000000..a4b523b6a --- /dev/null +++ b/src/productTypes/types/ProductTypeDelete.ts @@ -0,0 +1,32 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: ProductTypeDelete +// ==================================================== + +export interface ProductTypeDelete_productTypeDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ProductTypeDelete_productTypeDelete_productType { + __typename: "ProductType"; + id: string; +} + +export interface ProductTypeDelete_productTypeDelete { + __typename: "ProductTypeDelete"; + errors: ProductTypeDelete_productTypeDelete_errors[] | null; + productType: ProductTypeDelete_productTypeDelete_productType | null; +} + +export interface ProductTypeDelete { + productTypeDelete: ProductTypeDelete_productTypeDelete | null; +} + +export interface ProductTypeDeleteVariables { + id: string; +} diff --git a/src/productTypes/types/ProductTypeDetails.ts b/src/productTypes/types/ProductTypeDetails.ts new file mode 100644 index 000000000..38cbc73a6 --- /dev/null +++ b/src/productTypes/types/ProductTypeDetails.ts @@ -0,0 +1,71 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { TaxRateType, WeightUnitsEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: ProductTypeDetails +// ==================================================== + +export interface ProductTypeDetails_productType_productAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductTypeDetails_productType_productAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (ProductTypeDetails_productType_productAttributes_values | null)[] | null; +} + +export interface ProductTypeDetails_productType_variantAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductTypeDetails_productType_variantAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (ProductTypeDetails_productType_variantAttributes_values | null)[] | null; +} + +export interface ProductTypeDetails_productType_weight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface ProductTypeDetails_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; + isShippingRequired: boolean; + taxRate: TaxRateType | null; + productAttributes: (ProductTypeDetails_productType_productAttributes | null)[] | null; + variantAttributes: (ProductTypeDetails_productType_variantAttributes | null)[] | null; + weight: ProductTypeDetails_productType_weight | null; +} + +export interface ProductTypeDetails_shop { + __typename: "Shop"; + defaultWeightUnit: WeightUnitsEnum | null; +} + +export interface ProductTypeDetails { + productType: ProductTypeDetails_productType | null; + shop: ProductTypeDetails_shop | null; +} + +export interface ProductTypeDetailsVariables { + id: string; +} diff --git a/src/productTypes/types/ProductTypeDetailsFragment.ts b/src/productTypes/types/ProductTypeDetailsFragment.ts new file mode 100644 index 000000000..85b673786 --- /dev/null +++ b/src/productTypes/types/ProductTypeDetailsFragment.ts @@ -0,0 +1,57 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { TaxRateType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: ProductTypeDetailsFragment +// ==================================================== + +export interface ProductTypeDetailsFragment_productAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductTypeDetailsFragment_productAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (ProductTypeDetailsFragment_productAttributes_values | null)[] | null; +} + +export interface ProductTypeDetailsFragment_variantAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductTypeDetailsFragment_variantAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (ProductTypeDetailsFragment_variantAttributes_values | null)[] | null; +} + +export interface ProductTypeDetailsFragment_weight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface ProductTypeDetailsFragment { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; + isShippingRequired: boolean; + taxRate: TaxRateType | null; + productAttributes: (ProductTypeDetailsFragment_productAttributes | null)[] | null; + variantAttributes: (ProductTypeDetailsFragment_variantAttributes | null)[] | null; + weight: ProductTypeDetailsFragment_weight | null; +} diff --git a/src/productTypes/types/ProductTypeFragment.ts b/src/productTypes/types/ProductTypeFragment.ts new file mode 100644 index 000000000..f1443f1ff --- /dev/null +++ b/src/productTypes/types/ProductTypeFragment.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { TaxRateType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: ProductTypeFragment +// ==================================================== + +export interface ProductTypeFragment { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; + isShippingRequired: boolean; + taxRate: TaxRateType | null; +} diff --git a/src/productTypes/types/ProductTypeList.ts b/src/productTypes/types/ProductTypeList.ts new file mode 100644 index 000000000..89d1f26d0 --- /dev/null +++ b/src/productTypes/types/ProductTypeList.ts @@ -0,0 +1,48 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { TaxRateType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: ProductTypeList +// ==================================================== + +export interface ProductTypeList_productTypes_edges_node { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; + isShippingRequired: boolean; + taxRate: TaxRateType | null; +} + +export interface ProductTypeList_productTypes_edges { + __typename: "ProductTypeCountableEdge"; + node: ProductTypeList_productTypes_edges_node; +} + +export interface ProductTypeList_productTypes_pageInfo { + __typename: "PageInfo"; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; + endCursor: string | null; +} + +export interface ProductTypeList_productTypes { + __typename: "ProductTypeCountableConnection"; + edges: ProductTypeList_productTypes_edges[]; + pageInfo: ProductTypeList_productTypes_pageInfo; +} + +export interface ProductTypeList { + productTypes: ProductTypeList_productTypes | null; +} + +export interface ProductTypeListVariables { + after?: string | null; + before?: string | null; + first?: number | null; + last?: number | null; +} diff --git a/src/productTypes/types/ProductTypeUpdate.ts b/src/productTypes/types/ProductTypeUpdate.ts new file mode 100644 index 000000000..6c7f4ce11 --- /dev/null +++ b/src/productTypes/types/ProductTypeUpdate.ts @@ -0,0 +1,78 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ProductTypeInput, TaxRateType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: ProductTypeUpdate +// ==================================================== + +export interface ProductTypeUpdate_productTypeUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ProductTypeUpdate_productTypeUpdate_productType_productAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductTypeUpdate_productTypeUpdate_productType_productAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (ProductTypeUpdate_productTypeUpdate_productType_productAttributes_values | null)[] | null; +} + +export interface ProductTypeUpdate_productTypeUpdate_productType_variantAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductTypeUpdate_productTypeUpdate_productType_variantAttributes { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (ProductTypeUpdate_productTypeUpdate_productType_variantAttributes_values | null)[] | null; +} + +export interface ProductTypeUpdate_productTypeUpdate_productType_weight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface ProductTypeUpdate_productTypeUpdate_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; + isShippingRequired: boolean; + taxRate: TaxRateType | null; + productAttributes: (ProductTypeUpdate_productTypeUpdate_productType_productAttributes | null)[] | null; + variantAttributes: (ProductTypeUpdate_productTypeUpdate_productType_variantAttributes | null)[] | null; + weight: ProductTypeUpdate_productTypeUpdate_productType_weight | null; +} + +export interface ProductTypeUpdate_productTypeUpdate { + __typename: "ProductTypeUpdate"; + errors: ProductTypeUpdate_productTypeUpdate_errors[] | null; + productType: ProductTypeUpdate_productTypeUpdate_productType | null; +} + +export interface ProductTypeUpdate { + productTypeUpdate: ProductTypeUpdate_productTypeUpdate | null; +} + +export interface ProductTypeUpdateVariables { + id: string; + input: ProductTypeInput; +} diff --git a/src/productTypes/urls.ts b/src/productTypes/urls.ts new file mode 100644 index 000000000..509f22d47 --- /dev/null +++ b/src/productTypes/urls.ts @@ -0,0 +1,32 @@ +import { stringify as stringifyQs } from "qs"; +import * as urlJoin from "url-join"; + +import { BulkAction, Dialog, Pagination, SingleAction } from "../types"; +import { AttributeTypeEnum } from "../types/globalTypes"; + +const productTypeSection = "/product-types/"; + +export const productTypeListPath = productTypeSection; +export type ProductTypeListUrlDialog = "remove"; +export type ProductTypeListUrlQueryParams = BulkAction & + Dialog & + Pagination; +export const productTypeListUrl = (params?: ProductTypeListUrlQueryParams) => + productTypeListPath + "?" + stringifyQs(params); + +export const productTypeAddPath = urlJoin(productTypeSection, "add"); +export const productTypeAddUrl = productTypeAddPath; + +export const productTypePath = (id: string) => urlJoin(productTypeSection, id); +export type ProductTypeUrlDialog = + | "add-attribute" + | "edit-attribute" + | "remove"; +export type ProductTypeUrlQueryParams = Dialog & + SingleAction & { + type?: AttributeTypeEnum; + }; +export const productTypeUrl = ( + id: string, + params?: ProductTypeUrlQueryParams +) => productTypePath(encodeURIComponent(id)) + "?" + stringifyQs(params); diff --git a/src/productTypes/views/ProductTypeCreate.tsx b/src/productTypes/views/ProductTypeCreate.tsx new file mode 100644 index 000000000..1b21b96f2 --- /dev/null +++ b/src/productTypes/views/ProductTypeCreate.tsx @@ -0,0 +1,74 @@ +import * as React from "react"; + +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../i18n"; +import { maybe } from "../../misc"; +import ProductTypeCreatePage, { + ProductTypeForm +} from "../components/ProductTypeCreatePage"; +import { TypedProductTypeCreateMutation } from "../mutations"; +import { TypedProductTypeCreateDataQuery } from "../queries"; +import { ProductTypeCreate as ProductTypeCreateMutation } from "../types/ProductTypeCreate"; +import { productTypeListUrl, productTypeUrl } from "../urls"; + +export const ProductTypeCreate: React.StatelessComponent = () => { + const navigate = useNavigator(); + const notify = useNotifier(); + + const handleCreateSuccess = (updateData: ProductTypeCreateMutation) => { + if (updateData.productTypeCreate.errors.length === 0) { + notify({ + text: i18n.t("Successfully created product type") + }); + navigate(productTypeUrl(updateData.productTypeCreate.productType.id)); + } + }; + return ( + + {( + createProductType, + { loading: loadingCreate, data: createProductTypeData } + ) => { + const handleCreate = (formData: ProductTypeForm) => + createProductType({ + variables: { + input: { + hasVariants: false, + isShippingRequired: formData.isShippingRequired, + name: formData.name, + taxRate: formData.chargeTaxes ? formData.taxRate : null, + weight: formData.weight + } + } + }); + return ( + + {({ data, loading }) => ( + <> + + data.shop.defaultWeightUnit)} + disabled={loadingCreate || loading} + errors={ + createProductTypeData + ? createProductTypeData.productTypeCreate.errors + : undefined + } + pageTitle={i18n.t("Create Product Type", { + context: "page title" + })} + saveButtonBarState={loadingCreate ? "loading" : "default"} + onBack={() => navigate(productTypeListUrl())} + onSubmit={handleCreate} + /> + + )} + + ); + }} + + ); +}; +export default ProductTypeCreate; diff --git a/src/productTypes/views/ProductTypeList.tsx b/src/productTypes/views/ProductTypeList.tsx new file mode 100644 index 000000000..40d66ef2f --- /dev/null +++ b/src/productTypes/views/ProductTypeList.tsx @@ -0,0 +1,156 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { PAGINATE_BY } from "../../config"; +import { configurationMenuUrl } from "../../configuration"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import ProductTypeListPage from "../components/ProductTypeListPage"; +import { TypedProductTypeBulkDeleteMutation } from "../mutations"; +import { TypedProductTypeListQuery } from "../queries"; +import { ProductTypeBulkDelete } from "../types/ProductTypeBulkDelete"; +import { + productTypeAddUrl, + productTypeListUrl, + ProductTypeListUrlQueryParams, + productTypeUrl +} from "../urls"; + +interface ProductTypeListProps { + params: ProductTypeListUrlQueryParams; +} + +export const ProductTypeList: React.StatelessComponent< + ProductTypeListProps +> = ({ params }) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const closeModal = () => navigate(productTypeListUrl(), true); + + const paginationState = createPaginationState(PAGINATE_BY, params); + return ( + + {({ data, loading, refetch }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.productTypes.pageInfo), + paginationState, + params + ); + + const handleProductTypeBulkDelete = (data: ProductTypeBulkDelete) => { + if (data.productTypeBulkDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed product types") + }); + reset(); + refetch(); + navigate( + productTypeListUrl({ + ...params, + action: undefined, + ids: undefined + }) + ); + } + }; + + return ( + + {(productTypeBulkDelete, productTypeBulkDeleteOpts) => { + const bulkRemoveTransitionState = getMutationState( + productTypeBulkDeleteOpts.called, + productTypeBulkDeleteOpts.loading, + maybe( + () => + productTypeBulkDeleteOpts.data.productTypeBulkDelete.errors + ) + ); + + const onProductTypeBulkDelete = () => + productTypeBulkDelete({ + variables: { + ids: params.ids + } + }); + return ( + <> + + data.productTypes.edges.map(edge => edge.node) + )} + pageInfo={pageInfo} + onAdd={() => navigate(productTypeAddUrl)} + onBack={() => navigate(configurationMenuUrl)} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRowClick={id => () => navigate(productTypeUrl(id))} + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + toolbar={ + + navigate( + productTypeListUrl({ + action: "remove", + ids: listElements + }) + ) + } + > + + + } + /> + + {{ number }} product types?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + ); + }} + + ); + }} + + ); +}; +ProductTypeList.displayName = "ProductTypeList"; +export default ProductTypeList; diff --git a/src/productTypes/views/ProductTypeUpdate/errors.tsx b/src/productTypes/views/ProductTypeUpdate/errors.tsx new file mode 100644 index 000000000..851bf6c30 --- /dev/null +++ b/src/productTypes/views/ProductTypeUpdate/errors.tsx @@ -0,0 +1,46 @@ +import * as React from "react"; + +import { UserError } from "../../../types"; + +interface ProductTypeUpdateErrorsState { + addAttributeErrors: UserError[]; + editAttributeErrors: UserError[]; + formErrors: UserError[]; +} +interface ProductTypeUpdateErrorsProps { + children: ( + props: { + errors: ProductTypeUpdateErrorsState; + set: { + addAttributeErrors: (errors: UserError[]) => void; + editAttributeErrors: (errors: UserError[]) => void; + formErrors: (errors: UserError[]) => void; + }; + } + ) => React.ReactNode; +} + +export class ProductTypeUpdateErrors extends React.Component< + ProductTypeUpdateErrorsProps, + ProductTypeUpdateErrorsState +> { + state: ProductTypeUpdateErrorsState = { + addAttributeErrors: [], + editAttributeErrors: [], + formErrors: [] + }; + + render() { + return this.props.children({ + errors: this.state, + set: { + addAttributeErrors: (addAttributeErrors: UserError[]) => + this.setState({ addAttributeErrors }), + editAttributeErrors: (editAttributeErrors: UserError[]) => + this.setState({ editAttributeErrors }), + formErrors: (formErrors: UserError[]) => this.setState({ formErrors }) + } + }); + } +} +export default ProductTypeUpdateErrors; diff --git a/src/productTypes/views/ProductTypeUpdate/index.tsx b/src/productTypes/views/ProductTypeUpdate/index.tsx new file mode 100644 index 000000000..d7099f31b --- /dev/null +++ b/src/productTypes/views/ProductTypeUpdate/index.tsx @@ -0,0 +1,350 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../../i18n"; +import { getMutationState, maybe } from "../../../misc"; +import { AttributeTypeEnum } from "../../../types/globalTypes"; +import ProductTypeAttributeEditDialog, { + FormData as AttributeForm +} from "../../components/ProductTypeAttributeEditDialog"; +import ProductTypeDetailsPage, { + ProductTypeForm +} from "../../components/ProductTypeDetailsPage"; +import ProductTypeOperations from "../../containers/ProductTypeOperations"; +import { TypedProductTypeDetailsQuery } from "../../queries"; +import { AttributeCreate } from "../../types/AttributeCreate"; +import { AttributeDelete } from "../../types/AttributeDelete"; +import { AttributeUpdate } from "../../types/AttributeUpdate"; +import { ProductTypeDelete } from "../../types/ProductTypeDelete"; +import { ProductTypeUpdate as ProductTypeUpdateMutation } from "../../types/ProductTypeUpdate"; +import { + productTypeListUrl, + productTypeUrl, + ProductTypeUrlQueryParams +} from "../../urls"; +import { ProductTypeUpdateErrors } from "./errors"; + +interface ProductTypeUpdateProps { + id: string; + params: ProductTypeUrlQueryParams; +} + +export const ProductTypeUpdate: React.StatelessComponent< + ProductTypeUpdateProps +> = ({ id, params }) => { + const navigate = useNavigator(); + const notify = useNotifier(); + + return ( + + {({ errors, set: setErrors }) => ( + + {({ data, loading: dataLoading }) => { + const closeModal = () => { + navigate(productTypeUrl(id), true); + setErrors.addAttributeErrors([]); + setErrors.editAttributeErrors([]); + }; + const handleAttributeCreateSuccess = (data: AttributeCreate) => { + if (data.attributeCreate.errors.length === 0) { + notify({ + text: i18n.t("Attribute created", { + context: "notification" + }) + }); + closeModal(); + } else if ( + data.attributeCreate.errors !== null && + data.attributeCreate.errors.length > 0 + ) { + setErrors.addAttributeErrors(data.attributeCreate.errors); + } + }; + const handleAttributeDeleteSuccess = (data: AttributeDelete) => { + if (!data.attributeDelete.errors) { + notify({ + text: i18n.t("Attribute deleted", { + context: "notification" + }) + }); + } + }; + const handleAttributeUpdateSuccess = (data: AttributeUpdate) => { + if (data.attributeUpdate.errors.length === 0) { + notify({ + text: i18n.t("Attribute updated", { + context: "notification" + }) + }); + closeModal(); + } else if ( + data.attributeUpdate.errors !== null && + data.attributeUpdate.errors.length > 0 + ) { + setErrors.editAttributeErrors(data.attributeUpdate.errors); + } + }; + const handleProductTypeDeleteSuccess = ( + deleteData: ProductTypeDelete + ) => { + if (deleteData.productTypeDelete.errors.length === 0) { + notify({ + text: i18n.t("Product type deleted", { + context: "notification" + }) + }); + navigate(productTypeListUrl(), true); + } + }; + const handleProductTypeUpdateSuccess = ( + updateData: ProductTypeUpdateMutation + ) => { + if ( + !updateData.productTypeUpdate.errors || + updateData.productTypeUpdate.errors.length === 0 + ) { + notify({ + text: i18n.t("Product type updated", { + context: "notification" + }) + }); + } else if ( + updateData.productTypeUpdate.errors !== null && + updateData.productTypeUpdate.errors.length > 0 + ) { + setErrors.formErrors(updateData.productTypeUpdate.errors); + } + }; + + return ( + + {({ + attributeCreate, + deleteAttribute, + deleteProductType, + updateAttribute, + updateProductType + }) => { + const handleProductTypeDelete = () => + deleteProductType.mutate({ id }); + const handleProductTypeUpdate = ( + formData: ProductTypeForm + ) => { + updateProductType.mutate({ + id, + input: { + hasVariants: formData.hasVariants, + isShippingRequired: formData.isShippingRequired, + name: formData.name, + productAttributes: formData.productAttributes.map( + choice => choice.value + ), + taxRate: formData.taxRate, + variantAttributes: formData.variantAttributes.map( + choice => choice.value + ), + weight: formData.weight + } + }); + }; + const handleAttributeCreate = ( + data: AttributeForm, + type: AttributeTypeEnum + ) => + attributeCreate.mutate({ + id, + input: { + name: data.name, + values: data.values.map(value => ({ + name: value.label + })) + }, + type + }); + const handleAttributeDelete = ( + id: string, + event: React.MouseEvent + ) => { + event.stopPropagation(); + deleteAttribute.mutate({ id }); + }; + const handleAttributeUpdate = ( + id: string, + formData: AttributeForm + ) => { + const attribute = data.productType.variantAttributes + .concat(data.productType.productAttributes) + .filter(attribute => attribute.id === id)[0]; + updateAttribute.mutate({ + id, + input: { + addValues: formData.values + .filter( + value => + !attribute.values + .map(value => value.id) + .includes(value.value) + ) + .map(value => ({ + name: value.label + })), + name: formData.name, + removeValues: attribute.values + .filter( + value => + !formData.values + .map(value => value.value) + .includes(value.id) + ) + .map(value => value.id) + } + }); + }; + const loading = updateProductType.opts.loading || dataLoading; + const deleteTransactionState = getMutationState( + deleteProductType.opts.called, + deleteProductType.opts.loading, + maybe( + () => deleteProductType.opts.data.productTypeDelete.errors + ) + ); + + const attribute = maybe(() => + data.productType.productAttributes + .concat(data.productType.variantAttributes) + .find(attribute => attribute.id === params.id) + ); + + return ( + <> + data.productType.name)} /> + data.shop.defaultWeightUnit + )} + disabled={loading} + errors={errors.formErrors} + pageTitle={maybe(() => data.productType.name)} + productType={maybe(() => data.productType)} + saveButtonBarState={loading ? "loading" : "default"} + onAttributeAdd={type => + navigate( + productTypeUrl(id, { + action: "add-attribute", + type + }) + ) + } + onAttributeDelete={handleAttributeDelete} + onAttributeUpdate={attributeId => + navigate( + productTypeUrl(id, { + action: "edit-attribute", + id: attributeId + }) + ) + } + onBack={() => navigate(productTypeListUrl())} + onDelete={() => + navigate( + productTypeUrl(id, { + action: "remove" + }) + ) + } + onSubmit={handleProductTypeUpdate} + /> + {!dataLoading && ( + <> + {Object.keys(AttributeTypeEnum).map(key => ( + + handleAttributeCreate( + data, + AttributeTypeEnum[key] + ) + } + opened={ + params.action === "add-attribute" && + params.type === AttributeTypeEnum[key] + } + title={i18n.t("Add Attribute", { + context: "modal title" + })} + key={key} + /> + ))} + attribute.name)} + values={maybe(() => + attribute.values.map(value => ({ + label: value.name, + value: value.id + })) + )} + onClose={closeModal} + onConfirm={data => + handleAttributeUpdate(params.id, data) + } + opened={params.action === "edit-attribute"} + title={i18n.t("Edit Attribute", { + context: "modal title" + })} + /> + navigate(productTypeUrl(id))} + onConfirm={handleProductTypeDelete} + title={i18n.t("Remove product type")} + variant="delete" + > + {{ name }}?", + { + name: maybe( + () => data.productType.name, + "..." + ) + } + ) + }} + /> + + + )} + + ); + }} + + ); + }} + + )} + + ); +}; +export default ProductTypeUpdate; diff --git a/src/productTypes/views/ProductTypeUpdate/urls.ts b/src/productTypes/views/ProductTypeUpdate/urls.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/products/components/ProductCategoryAndCollectionsForm/ProductCategoryAndCollectionsForm.tsx b/src/products/components/ProductCategoryAndCollectionsForm/ProductCategoryAndCollectionsForm.tsx new file mode 100644 index 000000000..ae890a1a2 --- /dev/null +++ b/src/products/components/ProductCategoryAndCollectionsForm/ProductCategoryAndCollectionsForm.tsx @@ -0,0 +1,59 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import * as React from "react"; + +import FormSpacer from "@saleor/components/FormSpacer"; +import MultiSelectField from "@saleor/components/MultiSelectField"; +import PageHeader from "@saleor/components/PageHeader"; +import SingleSelectField from "@saleor/components/SingleSelectField"; +import i18n from "../../../i18n"; + +interface ProductCategoryAndCollectionsFormProps { + categories?: Array<{ value: string; label: string }>; + collections?: Array<{ value: string; label: string }>; + errors: { [key: string]: string }; + productCollections?: string[]; + category?: string; + loading?: boolean; + onChange: (event: React.ChangeEvent) => void; +} + +const ProductCategoryAndCollectionsForm = ({ + categories, + collections, + errors, + productCollections, + category, + loading, + onChange +}: ProductCategoryAndCollectionsFormProps) => ( + + + + + + + + +); +ProductCategoryAndCollectionsForm.displayName = + "ProductCategoryAndCollectionsForm"; +export default ProductCategoryAndCollectionsForm; diff --git a/src/products/components/ProductCategoryAndCollectionsForm/index.ts b/src/products/components/ProductCategoryAndCollectionsForm/index.ts new file mode 100644 index 000000000..a706be21c --- /dev/null +++ b/src/products/components/ProductCategoryAndCollectionsForm/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductCategoryAndCollectionsForm"; +export * from "./ProductCategoryAndCollectionsForm"; diff --git a/src/products/components/ProductCreatePage/ProductCreatePage.tsx b/src/products/components/ProductCreatePage/ProductCreatePage.tsx new file mode 100644 index 000000000..ce65f194e --- /dev/null +++ b/src/products/components/ProductCreatePage/ProductCreatePage.tsx @@ -0,0 +1,229 @@ +import { RawDraftContentState } from "draft-js"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import SeoForm from "@saleor/components/SeoForm"; +import VisibilityCard from "@saleor/components/VisibilityCard"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { UserError } from "../../../types"; +import { ProductCreateData_productTypes_edges_node_productAttributes } from "../../types/ProductCreateData"; +import ProductDetailsForm from "../ProductDetailsForm"; +import ProductOrganization from "../ProductOrganization"; +import ProductPricing from "../ProductPricing"; +import ProductStock from "../ProductStock"; + +interface ChoiceType { + label: string; + value: string; +} +export interface FormData { + attributes: Array<{ + slug: string; + value: string; + }>; + basePrice: number; + publicationDate: string; + category: ChoiceType; + chargeTaxes: boolean; + collections: ChoiceType[]; + description: RawDraftContentState; + isPublished: boolean; + name: string; + productType: { + label: string; + value: { + hasVariants: boolean; + id: string; + name: string; + productAttributes: ProductCreateData_productTypes_edges_node_productAttributes[]; + }; + }; + seoDescription: string; + seoTitle: string; + sku: string; + stockQuantity: number; +} + +interface ProductCreatePageProps { + errors: UserError[]; + collections?: Array<{ + id: string; + name: string; + }>; + currency: string; + categories?: Array<{ + id: string; + name: string; + }>; + disabled: boolean; + productTypes?: Array<{ + id: string; + name: string; + hasVariants: boolean; + productAttributes: ProductCreateData_productTypes_edges_node_productAttributes[]; + }>; + header: string; + saveButtonBarState: ConfirmButtonTransitionState; + fetchCategories: (data: string) => void; + fetchCollections: (data: string) => void; + onAttributesEdit: () => void; + onBack?(); + onSubmit?(data: FormData); +} + +export const ProductCreatePage: React.StatelessComponent< + ProductCreatePageProps +> = ({ + currency, + disabled, + categories, + collections, + errors: userErrors, + fetchCategories, + fetchCollections, + header, + productTypes, + saveButtonBarState, + onBack, + onSubmit +}: ProductCreatePageProps) => { + const initialData: FormData = { + attributes: [], + basePrice: 0, + category: { + label: "", + value: "" + }, + chargeTaxes: false, + collections: [], + description: {} as any, + isPublished: false, + name: "", + productType: { + label: "", + value: { + hasVariants: false, + id: "", + name: "", + productAttributes: [] as ProductCreateData_productTypes_edges_node_productAttributes[] + } + }, + publicationDate: "", + seoDescription: "", + seoTitle: "", + sku: null, + stockQuantity: null + }; + + return ( +
+ {({ change, data, errors, hasChanged, submit }) => { + const hasVariants = + data.productType && data.productType.value.hasVariants; + return ( + + {i18n.t("Products")} + + +
+ + + + + {!hasVariants && ( + <> + + + + )} + +
+
+ + categories.map(category => ({ + label: category.name, + value: category.id + })), + [] + )} + errors={errors} + fetchCategories={fetchCategories} + fetchCollections={fetchCollections} + collections={maybe( + () => + collections.map(collection => ({ + label: collection.name, + value: collection.id + })), + [] + )} + productTypes={productTypes} + data={data} + disabled={disabled} + onChange={change} + /> + + +
+
+ +
+ ); + }} +
+ ); +}; +ProductCreatePage.displayName = "ProductCreatePage"; +export default ProductCreatePage; diff --git a/src/products/components/ProductCreatePage/index.ts b/src/products/components/ProductCreatePage/index.ts new file mode 100644 index 000000000..7174a4e9d --- /dev/null +++ b/src/products/components/ProductCreatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductCreatePage"; +export * from "./ProductCreatePage"; diff --git a/src/products/components/ProductDetailsForm/ProductDetailsForm.tsx b/src/products/components/ProductDetailsForm/ProductDetailsForm.tsx new file mode 100644 index 000000000..2c3c47074 --- /dev/null +++ b/src/products/components/ProductDetailsForm/ProductDetailsForm.tsx @@ -0,0 +1,80 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import FormSpacer from "@saleor/components/FormSpacer"; +import RichTextEditor from "@saleor/components/RichTextEditor"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { ProductDetails_product } from "../../types/ProductDetails"; +import { FormData as CreateFormData } from "../ProductCreatePage"; +import { FormData as UpdateFormData } from "../ProductUpdatePage"; + +const styles = (theme: Theme) => + createStyles({ + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridTemplateColumns: `3fr 1fr` + } + }); + +interface ProductDetailsFormProps extends WithStyles { + data: CreateFormData & UpdateFormData; + disabled?: boolean; + errors: { [key: string]: string }; + product?: ProductDetails_product; + onChange(event: any); +} + +export const ProductDetailsForm = withStyles(styles, { + name: "ProductDetailsForm" +})( + ({ + classes, + data, + disabled, + errors, + product, + onChange + }: ProductDetailsFormProps) => ( + + + +
+ +
+ + JSON.parse(product.descriptionJson), null)} + label={i18n.t("Description")} + name="description" + onChange={onChange} + /> +
+
+ ) +); +ProductDetailsForm.displayName = "ProductDetailsForm"; +export default ProductDetailsForm; diff --git a/src/products/components/ProductDetailsForm/index.ts b/src/products/components/ProductDetailsForm/index.ts new file mode 100644 index 000000000..a8c915932 --- /dev/null +++ b/src/products/components/ProductDetailsForm/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductDetailsForm"; +export * from "./ProductDetailsForm"; diff --git a/src/products/components/ProductImageNavigation/ProductImageNavigation.tsx b/src/products/components/ProductImageNavigation/ProductImageNavigation.tsx new file mode 100644 index 000000000..ca3112569 --- /dev/null +++ b/src/products/components/ProductImageNavigation/ProductImageNavigation.tsx @@ -0,0 +1,94 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as classNames from "classnames"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + card: { + marginBottom: 2 * theme.spacing.unit + }, + highlightedImageContainer: { + borderColor: theme.palette.primary.main + }, + image: { + height: "100%", + objectFit: "contain", + userSelect: "none", + width: "100%" + }, + imageContainer: { + background: "#ffffff", + border: "2px solid #eaeaea", + borderRadius: theme.spacing.unit, + cursor: "pointer", + height: 48, + overflow: "hidden", + padding: theme.spacing.unit / 2, + position: "relative" + }, + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridRowGap: theme.spacing.unit + "px", + gridTemplateColumns: "repeat(4, 1fr)" + }, + toolbar: { marginTop: -theme.spacing.unit / 2 } + }); + +interface ProductImageNavigationProps extends WithStyles { + disabled: boolean; + images?: Array<{ + id: string; + url: string; + }>; + highlighted?: string; + onRowClick: (id: string) => () => void; +} + +const ProductImageNavigation = withStyles(styles, { + name: "ProductImageNavigation" +})( + ({ + classes, + highlighted, + images, + onRowClick + }: ProductImageNavigationProps) => ( + + + + {images === undefined ? ( + + ) : ( +
+ {images.map(image => ( +
+ +
+ ))} +
+ )} +
+
+ ) +); +ProductImageNavigation.displayName = "ProductImageNavigation"; +export default ProductImageNavigation; diff --git a/src/products/components/ProductImageNavigation/index.ts b/src/products/components/ProductImageNavigation/index.ts new file mode 100644 index 000000000..d4d8bf59e --- /dev/null +++ b/src/products/components/ProductImageNavigation/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductImageNavigation"; +export * from "./ProductImageNavigation"; diff --git a/src/products/components/ProductImagePage/ProductImagePage.tsx b/src/products/components/ProductImagePage/ProductImagePage.tsx new file mode 100644 index 000000000..4363e2546 --- /dev/null +++ b/src/products/components/ProductImagePage/ProductImagePage.tsx @@ -0,0 +1,136 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardTitle from "@saleor/components/CardTitle"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import ProductImageNavigation from "../ProductImageNavigation"; + +const styles = (theme: Theme) => + createStyles({ + image: { + height: "100%", + objectFit: "contain", + width: "100%" + }, + imageContainer: { + background: "#ffffff", + border: "1px solid #eaeaea", + borderRadius: theme.spacing.unit, + margin: `0 auto ${theme.spacing.unit * 2}px`, + maxWidth: 552, + padding: theme.spacing.unit * 2 + } + }); + +interface ProductImagePageProps extends WithStyles { + image?: { + id: string; + alt: string; + url: string; + }; + images?: Array<{ + id: string; + url: string; + }>; + disabled: boolean; + product: string; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onDelete: () => void; + onRowClick: (id: string) => () => void; + onSubmit: (data: { description: string }) => void; +} + +const ProductImagePage = withStyles(styles, { name: "ProductImagePage" })( + ({ + classes, + disabled, + image, + images, + product, + saveButtonBarState, + onBack, + onDelete, + onRowClick, + onSubmit + }: ProductImagePageProps) => ( +
+ {({ change, data, hasChanged, submit }) => { + return ( + + {product} + + +
+ + + + + + + +
+
+ + + + {!!image ? ( +
+ +
+ ) : ( + + )} +
+
+
+
+ +
+ ); + }} +
+ ) +); +ProductImagePage.displayName = "ProductImagePage"; +export default ProductImagePage; diff --git a/src/products/components/ProductImagePage/index.ts b/src/products/components/ProductImagePage/index.ts new file mode 100644 index 000000000..75e8f7bda --- /dev/null +++ b/src/products/components/ProductImagePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductImagePage"; +export * from "./ProductImagePage"; diff --git a/src/products/components/ProductImages/ProductImages.tsx b/src/products/components/ProductImages/ProductImages.tsx new file mode 100644 index 000000000..1cef09dcd --- /dev/null +++ b/src/products/components/ProductImages/ProductImages.tsx @@ -0,0 +1,242 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import classNames from "classnames"; + +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import CardTitle from "@saleor/components/CardTitle"; +import ImageTile from "@saleor/components/ImageTile"; +import ImageUpload from "@saleor/components/ImageUpload"; +import * as React from "react"; +import { SortableContainer, SortableElement } from "react-sortable-hoc"; +import i18n from "../../../i18n"; +import { ProductDetails_product_images } from "../../types/ProductDetails"; + +const styles = (theme: Theme) => + createStyles({ + card: { + marginTop: theme.spacing.unit * 2, + [theme.breakpoints.down("sm")]: { + marginTop: 0 + } + }, + fileField: { + display: "none" + }, + icon: { + color: "rgba(255, 255, 255, 0.54)" + }, + image: { + height: "100%", + objectFit: "contain", + userSelect: "none", + width: "100%" + }, + imageContainer: { + "&:hover, &.dragged": { + "& $imageOverlay": { + display: "block" + } + }, + background: "#ffffff", + border: "1px solid #eaeaea", + borderRadius: theme.spacing.unit, + height: 140, + margin: "auto", + overflow: "hidden", + padding: theme.spacing.unit * 2, + position: "relative", + width: 140 + }, + imageGridContainer: { + position: "relative" + }, + imageOverlay: { + background: "rgba(0, 0, 0, 0.6)", + cursor: "move", + display: "none", + height: 140, + left: 0, + padding: theme.spacing.unit * 2, + position: "absolute", + top: 0, + width: 140 + }, + imageOverlayToolbar: { + alignContent: "flex-end", + display: "flex", + position: "relative", + right: -theme.spacing.unit * 3, + top: -theme.spacing.unit * 2 + }, + imageUpload: { + height: "100%", + left: 0, + position: "absolute", + top: 0, + width: "100%" + }, + imageUploadActive: { + zIndex: 1 + }, + imageUploadIcon: { + display: "none" + }, + imageUploadIconActive: { + display: "block" + }, + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridRowGap: theme.spacing.unit * 2 + "px", + gridTemplateColumns: "repeat(4, 1fr)", + [theme.breakpoints.down("sm")]: { + gridTemplateColumns: "repeat(3, 1fr)" + }, + [theme.breakpoints.down("xs")]: { + gridTemplateColumns: "repeat(2, 1fr)" + } + }, + rootDragActive: { + opacity: 0.2 + } + }); + +interface ProductImagesProps extends WithStyles { + placeholderImage?: string; + images: ProductDetails_product_images[]; + loading?: boolean; + onImageDelete: (id: string) => () => void; + onImageEdit: (id: string) => () => void; + onImageUpload(file: File); + onImageReorder?(event: { oldIndex: number; newIndex: number }); +} + +interface ImageListContainerProps extends WithStyles { + items: any; + onImageDelete: (id: string) => () => void; + onImageEdit: (id: string) => () => void; +} + +const SortableImage = SortableElement( + ({ image, onImageEdit, onImageDelete }) => ( + onImageEdit(image.id) : undefined} + onImageDelete={onImageDelete} + /> + ) +); + +const ImageListContainer = SortableContainer( + withStyles(styles, { name: "ImageListContainer" })( + ({ + classes, + items, + onImageDelete, + onImageEdit, + ...props + }: ImageListContainerProps) => { + return ( +
+ {items.map((image, index) => ( + + ))} +
+ ); + } + ) +); + +const ProductImages = withStyles(styles, { name: "ProductImages" })( + ({ + classes, + images, + placeholderImage, + loading, + onImageEdit, + onImageDelete, + onImageReorder, + onImageUpload + }: ProductImagesProps) => ( + + + + onImageUpload(event.target.files[0])} + type="file" + ref={ref => (this.upload = ref)} + /> + + } + /> +
+ {images === undefined ? ( + +
+
+ +
+
+
+ ) : images.length > 0 ? ( + <> + + {({ isDragActive }) => ( + + + + )} + + + ) : ( + + )} +
+
+ ) +); +ProductImages.displayName = "ProductImages"; +export default ProductImages; diff --git a/src/products/components/ProductImages/index.ts b/src/products/components/ProductImages/index.ts new file mode 100644 index 000000000..0ec8845a8 --- /dev/null +++ b/src/products/components/ProductImages/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductImages"; +export * from "./ProductImages"; diff --git a/src/products/components/ProductListCard/ProductListCard.tsx b/src/products/components/ProductListCard/ProductListCard.tsx new file mode 100644 index 000000000..c14617933 --- /dev/null +++ b/src/products/components/ProductListCard/ProductListCard.tsx @@ -0,0 +1,68 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import ProductList from "@saleor/components/ProductList"; +import { CategoryDetails_category_products_edges_node } from "../../../categories/types/CategoryDetails"; +import i18n from "../../../i18n"; +import { FilterPageProps, ListActions, PageListProps } from "../../../types"; +import { ProductListUrlFilters } from "../../urls"; +import ProductListFilter from "../ProductListFilter"; + +export interface ProductListCardProps + extends PageListProps, + ListActions, + FilterPageProps { + currencySymbol: string; + products: CategoryDetails_category_products_edges_node[]; +} + +export const ProductListCard: React.StatelessComponent< + ProductListCardProps +> = ({ + currencySymbol, + currentTab, + filtersList, + filterTabs, + initialSearch, + onAdd, + onAll, + onSearchChange, + onFilterAdd, + onFilterSave, + onTabChange, + onFilterDelete, + ...listProps +}) => ( + + + + + + + + + +); +ProductListCard.displayName = "ProductListCard"; +export default ProductListCard; diff --git a/src/products/components/ProductListCard/index.ts b/src/products/components/ProductListCard/index.ts new file mode 100644 index 000000000..995a575ae --- /dev/null +++ b/src/products/components/ProductListCard/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductListCard"; +export * from "./ProductListCard"; diff --git a/src/products/components/ProductListFilter/ProductListFilter.tsx b/src/products/components/ProductListFilter/ProductListFilter.tsx new file mode 100644 index 000000000..a9db1f5cf --- /dev/null +++ b/src/products/components/ProductListFilter/ProductListFilter.tsx @@ -0,0 +1,95 @@ +import * as React from "react"; + +import { FieldType, IFilter } from "@saleor/components/Filter"; +import FilterBar from "@saleor/components/FilterBar"; +import i18n from "@saleor/i18n"; +import { FilterProps } from "@saleor/types"; +import { StockAvailability } from "@saleor/types/globalTypes"; +import { ProductListUrlFilters } from "../../urls"; + +type ProductListFilterProps = FilterProps; + +export enum ProductFilterKeys { + published, + price, + priceEqual, + priceRange, + stock, + query +} +const filterMenu: IFilter = [ + { + children: [], + data: { + additionalText: i18n.t("is set as"), + fieldLabel: i18n.t("Status"), + options: [ + { + label: i18n.t("Visible"), + value: true + }, + { + label: i18n.t("Hidden"), + value: false + } + ], + type: FieldType.select + }, + label: i18n.t("Visibility"), + value: ProductFilterKeys.published.toString() + }, + { + children: [], + data: { + fieldLabel: i18n.t("Stock quantity"), + options: [ + { + label: i18n.t("Available"), + value: StockAvailability.IN_STOCK + }, + { + label: i18n.t("Out Of Stock"), + value: StockAvailability.OUT_OF_STOCK + } + ], + type: FieldType.select + }, + label: i18n.t("Stock"), + value: ProductFilterKeys.stock.toString() + }, + { + children: [ + { + children: [], + data: { + additionalText: i18n.t("equals"), + fieldLabel: null, + type: FieldType.price + }, + label: i18n.t("Specific Price"), + value: ProductFilterKeys.priceEqual.toString() + }, + { + children: [], + data: { + fieldLabel: i18n.t("Range"), + type: FieldType.rangePrice + }, + label: i18n.t("Range"), + value: ProductFilterKeys.priceRange.toString() + } + ], + data: { + fieldLabel: i18n.t("Price"), + type: FieldType.range + }, + label: i18n.t("Price"), + value: ProductFilterKeys.price.toString() + } +]; + +const ProductListFilter: React.FC = props => ( + +); +ProductListFilter.displayName = "ProductListFilter"; +export default ProductListFilter; diff --git a/src/products/components/ProductListFilter/index.ts b/src/products/components/ProductListFilter/index.ts new file mode 100644 index 000000000..c251bdbef --- /dev/null +++ b/src/products/components/ProductListFilter/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductListFilter"; +export * from "./ProductListFilter"; diff --git a/src/products/components/ProductOrganization/ProductOrganization.tsx b/src/products/components/ProductOrganization/ProductOrganization.tsx new file mode 100644 index 000000000..1081878db --- /dev/null +++ b/src/products/components/ProductOrganization/ProductOrganization.tsx @@ -0,0 +1,319 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardSpacer from "@saleor/components/CardSpacer"; +import CardTitle from "@saleor/components/CardTitle"; +import Chip from "@saleor/components/Chip"; +import { FormSpacer } from "@saleor/components/FormSpacer"; +import MultiAutocompleteSelectField from "@saleor/components/MultiAutocompleteSelectField"; +import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { ProductCreateData_productTypes_edges_node_productAttributes } from "../../types/ProductCreateData"; + +interface ChoiceType { + label: string; + value: string; +} +interface ProductType { + hasVariants: boolean; + id: string; + name: string; + productAttributes: ProductCreateData_productTypes_edges_node_productAttributes[]; +} + +const styles = (theme: Theme) => + createStyles({ + card: { + overflow: "visible" + }, + cardSubtitle: { + fontSize: "1rem", + marginBottom: theme.spacing.unit / 2 + }, + hr: { + backgroundColor: theme.overrides.MuiCard.root.borderColor, + border: "none", + height: 1, + margin: `0 -${theme.spacing.unit * 3}px ${theme.spacing.unit * 3}px` + }, + label: { + marginBottom: theme.spacing.unit / 2 + } + }); + +interface ProductOrganizationProps extends WithStyles { + canChangeType: boolean; + categories?: Array<{ value: string; label: string }>; + collections?: Array<{ value: string; label: string }>; + data: { + attributes: Array<{ + slug: string; + value: string; + }>; + category: ChoiceType; + collections: ChoiceType[]; + productType: { + label: string; + value: { + hasVariants: boolean; + id: string; + name: string; + productAttributes: ProductCreateData_productTypes_edges_node_productAttributes[]; + }; + }; + }; + disabled: boolean; + errors: { [key: string]: string }; + product?: { + productType?: { + hasVariants?: boolean; + name?: string; + }; + }; + productTypes?: ProductType[]; + fetchCategories: (query: string) => void; + fetchCollections: (query: string) => void; + onChange: (event: React.ChangeEvent, cb?: () => void) => void; +} + +const ProductOrganization = withStyles(styles, { name: "ProductOrganization" })( + ({ + canChangeType, + categories, + classes, + collections, + data, + disabled, + errors, + fetchCategories, + fetchCollections, + product, + productTypes, + onChange + }: ProductOrganizationProps) => { + const unrolledAttributes = maybe( + () => data.productType.value.productAttributes, + [] + ); + const getAttributeName = (slug: string) => { + const match = unrolledAttributes.find(a => a.slug === slug); + if (!match) { + return ""; + } + return match.name; + }; + const getAttributeValue = (slug: string) => { + if (unrolledAttributes.length > 0) { + const value = data.attributes.find(a => a.slug === slug); + const attributeMatch = unrolledAttributes.find(a => a.slug === slug); + if (!attributeMatch) { + return { + label: "", + value: "" + }; + } + const attributeValueMatch = attributeMatch.values.find( + v => v.slug === value.value + ); + const label = !!attributeValueMatch + ? attributeValueMatch.name + : value.value; + return { + label, + value + }; + } + return { + label: "", + value: "" + }; + }; + const getAttributeValues = (slug: string) => { + const match = unrolledAttributes.find(a => a.slug === slug); + if (match) { + return match.values; + } + + return []; + }; + const handleProductTypeSelect = ( + event: React.ChangeEvent<{ + name: string; + value: { + label: string; + value: ProductType; + }; + }> + ) => { + onChange(event, () => + onChange({ + ...event, + target: { + ...event.target, + name: "attributes", + value: event.target.value.value.productAttributes.map( + attribute => ({ + slug: attribute.slug, + value: "" + }) + ) + } + }) + ); + }; + const handleAttributeValueSelect = ( + event: React.ChangeEvent<{ + name: string; + value: { + label: string; + value: string; + }; + }> + ) => { + onChange({ + ...event, + target: { + ...event.target, + name: "attributes", + value: data.attributes.map(a => + a.slug === event.target.name + ? { slug: a.slug, value: event.target.value.value } + : a + ) + } + }); + }; + return ( + + + + {canChangeType ? ( + ({ label: pt.name, value: pt })) + : [] + } + value={data.productType} + onChange={handleProductTypeSelect} + /> + ) : ( + <> + + {i18n.t("Product Type")} + + + {maybe(() => product.productType.name, "...")} + + + + {i18n.t("Product Type")} + + + {maybe( + () => + product.productType.hasVariants + ? i18n.t("Configurable") + : i18n.t("Simple"), + "..." + )} + + + )} + {!(data && data.attributes && data.attributes.length === 0) ? ( + <> + + + {i18n.t("Attributes")} + +
+ + ) : ( + + )} + {data.attributes ? ( + data.attributes.map((item, index) => { + return ( + + ({ + label: v.name, + value: v.slug + }))} + custom + /> + + + ); + }) + ) : ( + + )} +
+ + +
+ + {({ deleteItem, items }) => ( + <> + +
+ {items.map(item => ( + deleteItem(item)} + /> + ))} +
+ + )} +
+
+
+ ); + } +); +ProductOrganization.displayName = "ProductOrganization"; +export default ProductOrganization; diff --git a/src/products/components/ProductOrganization/index.ts b/src/products/components/ProductOrganization/index.ts new file mode 100644 index 000000000..5ef78dde8 --- /dev/null +++ b/src/products/components/ProductOrganization/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductOrganization"; +export * from "./ProductOrganization"; diff --git a/src/products/components/ProductPricing/ProductPricing.tsx b/src/products/components/ProductPricing/ProductPricing.tsx new file mode 100644 index 000000000..41cb7b50a --- /dev/null +++ b/src/products/components/ProductPricing/ProductPricing.tsx @@ -0,0 +1,63 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; +import PriceField from "@saleor/components/PriceField"; +import i18n from "../../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridTemplateColumns: "1fr 1fr" + } + }); + +interface ProductPricingProps extends WithStyles { + currency?: string; + data: { + chargeTaxes: boolean; + basePrice: number; + }; + disabled: boolean; + onChange: (event: React.ChangeEvent) => void; +} + +const ProductPricing = withStyles(styles, { name: "ProductPricing" })( + ({ classes, currency, data, disabled, onChange }: ProductPricingProps) => ( + + + + + +
+ +
+
+
+ ) +); +ProductPricing.displayName = "ProductPricing"; +export default ProductPricing; diff --git a/src/products/components/ProductPricing/index.ts b/src/products/components/ProductPricing/index.ts new file mode 100644 index 000000000..4a41ac8e5 --- /dev/null +++ b/src/products/components/ProductPricing/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductPricing"; +export * from "./ProductPricing"; diff --git a/src/products/components/ProductStock/ProductStock.tsx b/src/products/components/ProductStock/ProductStock.tsx new file mode 100644 index 000000000..f861b817c --- /dev/null +++ b/src/products/components/ProductStock/ProductStock.tsx @@ -0,0 +1,73 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { ProductDetails_product } from "../../types/ProductDetails"; + +const styles = (theme: Theme) => + createStyles({ + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridTemplateColumns: "1fr 1fr" + } + }); + +interface ProductStockProps extends WithStyles { + data: { + sku: string; + stockQuantity: number; + }; + disabled: boolean; + errors: { [key: string]: string }; + product: ProductDetails_product; + onChange: (event: React.ChangeEvent) => void; +} + +const ProductStock = withStyles(styles, { name: "ProductStock" })( + ({ classes, data, disabled, product, onChange, errors }: ProductStockProps) => ( + + + +
+ + product.variants[0].quantityAllocated) + }) + : undefined + } + /> +
+
+
+ ) +); +ProductStock.displayName = "ProductStock"; +export default ProductStock; diff --git a/src/products/components/ProductStock/index.ts b/src/products/components/ProductStock/index.ts new file mode 100644 index 000000000..f98d67440 --- /dev/null +++ b/src/products/components/ProductStock/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductStock"; +export * from "./ProductStock"; diff --git a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx new file mode 100644 index 000000000..6f1d6f0aa --- /dev/null +++ b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx @@ -0,0 +1,314 @@ +import { convertFromRaw, RawDraftContentState } from "draft-js"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import SeoForm from "@saleor/components/SeoForm"; +import VisibilityCard from "@saleor/components/VisibilityCard"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { ListActions, UserError } from "../../../types"; +import { + ProductDetails_product, + ProductDetails_product_attributes_attribute, + ProductDetails_product_images, + ProductDetails_product_variants +} from "../../types/ProductDetails"; +import ProductDetailsForm from "../ProductDetailsForm"; +import ProductImages from "../ProductImages"; +import ProductOrganization from "../ProductOrganization"; +import ProductPricing from "../ProductPricing"; +import ProductStock from "../ProductStock"; +import ProductVariants from "../ProductVariants"; + +interface ProductUpdateProps extends ListActions { + errors: UserError[]; + placeholderImage: string; + collections?: Array<{ + id: string; + name: string; + }>; + categories?: Array<{ + id: string; + name: string; + }>; + disabled?: boolean; + productCollections?: Array<{ + id: string; + name: string; + }>; + variants: ProductDetails_product_variants[]; + images?: ProductDetails_product_images[]; + product?: ProductDetails_product; + header: string; + saveButtonBarState: ConfirmButtonTransitionState; + fetchCategories: (query: string) => void; + fetchCollections: (query: string) => void; + onVariantShow: (id: string) => () => void; + onImageDelete: (id: string) => () => void; + onAttributesEdit: () => void; + onBack?(); + onDelete(); + onImageEdit?(id: string); + onImageReorder?(event: { oldIndex: number; newIndex: number }); + onImageUpload(file: File); + onProductShow?(); + onSeoClick?(); + onSubmit?(data: any); + onVariantAdd?(); +} + +interface ChoiceType { + label: string; + value: string; +} +export interface FormData { + attributes: Array<{ + slug: string; + value: string; + }>; + basePrice: number; + category: ChoiceType | null; + chargeTaxes: boolean; + collections: ChoiceType[]; + description: RawDraftContentState; + isPublished: boolean; + name: string; + productType: { + label: string; + value: { + hasVariants: boolean; + id: string; + name: string; + productAttributes: Array< + Exclude + >; + }; + } | null; + publicationDate: string; + seoDescription: string; + seoTitle: string; + sku: string; + stockQuantity: number; +} + +export const ProductUpdate: React.StatelessComponent = ({ + disabled, + categories: categoryChoiceList, + collections: collectionChoiceList, + errors: userErrors, + fetchCategories, + fetchCollections, + images, + header, + placeholderImage, + product, + productCollections, + saveButtonBarState, + variants, + onAttributesEdit, + onBack, + onDelete, + onImageDelete, + onImageEdit, + onImageReorder, + onImageUpload, + onSeoClick, + onSubmit, + onVariantAdd, + onVariantShow, + isChecked, + selected, + toggle, + toggleAll, + toolbar +}) => { + const initialData: FormData = { + attributes: maybe( + () => + product.attributes.map(a => ({ + slug: a.attribute.slug, + value: a.value ? a.value.slug : null + })), + [] + ), + basePrice: maybe(() => product.basePrice.amount), + category: maybe(() => ({ + label: product.category.name, + value: product.category.id + })), + chargeTaxes: maybe(() => product.chargeTaxes, false), + collections: productCollections + ? productCollections.map(collection => ({ + label: collection.name, + value: collection.id + })) + : [], + description: maybe(() => JSON.parse(product.descriptionJson)), + isPublished: maybe(() => product.isPublished, false), + name: maybe(() => product.name), + productType: maybe(() => ({ + label: product.productType.name, + value: { + hasVariants: product.productType.hasVariants, + id: product.productType.id, + name: product.productType.name, + productAttributes: product.attributes.map(a => a.attribute) + } + })), + publicationDate: maybe(() => product.publicationDate), + seoDescription: maybe(() => product.seoDescription) || "", + seoTitle: maybe(() => product.seoTitle) || "", + sku: maybe(() => + product.productType.hasVariants + ? undefined + : variants && variants[0] + ? variants[0].sku + : undefined + ), + stockQuantity: maybe(() => + product.productType.hasVariants + ? undefined + : variants && variants[0] + ? variants[0].quantity + : undefined + ) + }; + const categories = + categoryChoiceList !== undefined + ? categoryChoiceList.map(category => ({ + label: category.name, + value: category.id + })) + : []; + const collections = + collectionChoiceList !== undefined + ? collectionChoiceList.map(collection => ({ + label: collection.name, + value: collection.id + })) + : []; + const currency = + product && product.basePrice ? product.basePrice.currency : undefined; + const hasVariants = + product && product.productType && product.productType.hasVariants; + + return ( +
+ {({ change, data, errors, hasChanged, submit }) => ( + <> + + {i18n.t("Products")} + + +
+ + + + + + + {hasVariants ? ( + + ) : ( + + )} + + + convertFromRaw(data.description) + .getPlainText() + .slice(0, 300) + )} + loading={disabled} + onClick={onSeoClick} + onChange={change} + /> +
+
+ + + +
+
+ +
+ + )} +
+ ); +}; +ProductUpdate.displayName = "ProductUpdate"; +export default ProductUpdate; diff --git a/src/products/components/ProductUpdatePage/index.ts b/src/products/components/ProductUpdatePage/index.ts new file mode 100644 index 000000000..0eb59fe6a --- /dev/null +++ b/src/products/components/ProductUpdatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductUpdatePage"; +export * from "./ProductUpdatePage"; diff --git a/src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx b/src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx new file mode 100644 index 000000000..06a49a06c --- /dev/null +++ b/src/products/components/ProductVariantAttributes/ProductVariantAttributes.tsx @@ -0,0 +1,139 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { ProductVariant_attributes_attribute } from "../../types/ProductVariant"; + +const styles = (theme: Theme) => + createStyles({ + card: { + overflow: "visible" + }, + grid: { + display: "grid", + gridColumnGap: `${theme.spacing.unit * 2}px`, + gridRowGap: `${theme.spacing.unit * 3}px`, + gridTemplateColumns: "1fr 1fr" + } + }); + +interface ProductVariantAttributesProps extends WithStyles { + attributes?: ProductVariant_attributes_attribute[]; + data: { + attributes?: Array<{ + slug: string; + value: string; + }>; + }; + disabled: boolean; + onChange: ( + event: React.ChangeEvent<{ + name: string; + value: Array<{ + slug: string; + value: string; + }>; + }> + ) => void; +} + +const ProductVariantAttributes = withStyles(styles, { + name: "ProductVariantAttributes" +})( + ({ + attributes, + classes, + data, + disabled, + onChange + }: ProductVariantAttributesProps) => { + return ( + + + + {attributes === undefined ? ( + + ) : ( + attributes.map((item, index) => { + const getAttributeValue = (slug: string) => { + const valueMatches = attributes.filter(a => a.slug === slug); + if (valueMatches.length > 0) { + const value = data.attributes.filter(a => a.slug === slug)[0] + .value; + const labelMatches = valueMatches[0].values.filter( + v => v.slug === value + ); + const label = + labelMatches.length > 0 ? labelMatches[0].name : value; + return { + label, + value + }; + } + return { + label: "", + value: "" + }; + }; + const getAttributeValues = (slug: string) => { + const matches = attributes.filter(a => a.slug === slug); + return matches.length > 0 + ? matches[0].values.map(v => ({ + label: v.name, + value: v.slug + })) + : []; + }; + const handleAttributeValueSelect = ( + event: React.ChangeEvent<{ + name: string; + value: { + label: string; + value: string; + }; + }> + ) => + onChange({ + ...(event as any), + target: { + ...event.target, + name: "attributes", + value: data.attributes.map(a => + a.slug === event.target.name + ? { slug: a.slug, value: event.target.value.value } + : a + ) + } + }); + + return ( + + ); + }) + )} + + + ); + } +); +ProductVariantAttributes.displayName = "ProductVariantAttributes"; +export default ProductVariantAttributes; diff --git a/src/products/components/ProductVariantAttributes/index.ts b/src/products/components/ProductVariantAttributes/index.ts new file mode 100644 index 000000000..e8ffccfe7 --- /dev/null +++ b/src/products/components/ProductVariantAttributes/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductVariantAttributes"; +export * from "./ProductVariantAttributes"; diff --git a/src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx b/src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx new file mode 100644 index 000000000..b865a7b3d --- /dev/null +++ b/src/products/components/ProductVariantCreatePage/ProductVariantCreatePage.tsx @@ -0,0 +1,130 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { UserError } from "../../../types"; +import { ProductVariantCreateData_product } from "../../types/ProductVariantCreateData"; +import ProductVariantAttributes from "../ProductVariantAttributes"; +import ProductVariantNavigation from "../ProductVariantNavigation"; +import ProductVariantPrice from "../ProductVariantPrice"; +import ProductVariantStock from "../ProductVariantStock"; + +interface FormData { + attributes?: Array<{ + slug: string; + value: string; + }>; + costPrice?: string; + images?: string[]; + priceOverride?: string; + quantity?: number; + sku?: string; +} + +interface ProductVariantCreatePageProps { + currencySymbol: string; + errors: UserError[]; + header: string; + loading: boolean; + product: ProductVariantCreateData_product; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onSubmit: (data: FormData) => void; + onVariantClick: (variantId: string) => void; +} + +const ProductVariantCreatePage: React.StatelessComponent< + ProductVariantCreatePageProps +> = ({ + currencySymbol, + errors: formErrors, + loading, + header, + product, + saveButtonBarState, + onBack, + onSubmit, + onVariantClick +}) => { + const initialForm = { + attributes: maybe(() => + product.productType.variantAttributes.map(attribute => ({ + slug: attribute.slug, + value: "" + })) + ), + costPrice: "", + images: maybe(() => product.images.map(image => image.id)), + priceOverride: "", + quantity: 0, + sku: "" + }; + return ( +
+ {({ change, data, errors, hasChanged, submit }) => ( + + {maybe(() => product.name)} + + +
+ product.thumbnail.url)} + variants={maybe(() => product.variants)} + onRowClick={(variantId: string) => { + if (product && product.variants) { + return onVariantClick(variantId); + } + }} + /> +
+
+ product.productType.variantAttributes)} + data={data} + disabled={loading} + onChange={change} + /> + + + + +
+
+ +
+ )} +
+ ); +}; +ProductVariantCreatePage.displayName = "ProductVariantCreatePage"; +export default ProductVariantCreatePage; diff --git a/src/products/components/ProductVariantCreatePage/index.ts b/src/products/components/ProductVariantCreatePage/index.ts new file mode 100644 index 000000000..91493fd60 --- /dev/null +++ b/src/products/components/ProductVariantCreatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductVariantCreatePage"; +export * from "./ProductVariantCreatePage"; diff --git a/src/products/components/ProductVariantDeleteDialog/ProductVariantDeleteDialog.tsx b/src/products/components/ProductVariantDeleteDialog/ProductVariantDeleteDialog.tsx new file mode 100644 index 000000000..73569e58e --- /dev/null +++ b/src/products/components/ProductVariantDeleteDialog/ProductVariantDeleteDialog.tsx @@ -0,0 +1,82 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import i18n from "../../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + deleteButton: { + "&:hover": { + backgroundColor: theme.palette.error.main + }, + backgroundColor: theme.palette.error.main, + color: theme.palette.error.contrastText + } + }); + +export interface ProductVariantDeleteDialogProps + extends WithStyles { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + name: string; + onClose?(); + onConfirm?(); +} + +const ProductVariantDeleteDialog = withStyles(styles, { + name: "ProductVariantDeleteDialog" +})( + ({ + classes, + confirmButtonState, + name, + open, + onConfirm, + onClose + }: ProductVariantDeleteDialogProps) => ( + + + {i18n.t("Delete variant", { context: "title" })} + + + {{name}}?", + { name } + ) + }} + /> + + + + + {i18n.t("Delete variant", { context: "button" })} + + + + ) +); +ProductVariantDeleteDialog.displayName = "ProductVariantDeleteDialog"; +export default ProductVariantDeleteDialog; diff --git a/src/products/components/ProductVariantDeleteDialog/index.ts b/src/products/components/ProductVariantDeleteDialog/index.ts new file mode 100644 index 000000000..2310ca8b9 --- /dev/null +++ b/src/products/components/ProductVariantDeleteDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductVariantDeleteDialog"; +export * from "./ProductVariantDeleteDialog"; diff --git a/src/products/components/ProductVariantImageSelectDialog/ProductVariantImageSelectDialog.tsx b/src/products/components/ProductVariantImageSelectDialog/ProductVariantImageSelectDialog.tsx new file mode 100644 index 000000000..19c5bde55 --- /dev/null +++ b/src/products/components/ProductVariantImageSelectDialog/ProductVariantImageSelectDialog.tsx @@ -0,0 +1,107 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as classNames from "classnames"; +import * as React from "react"; + +import i18n from "../../../i18n"; +import { ProductImage } from "../../types/ProductImage"; + +const styles = (theme: Theme) => + createStyles({ + image: { + height: "100%", + objectFit: "contain", + userSelect: "none", + width: "100%" + }, + imageContainer: { + background: "#ffffff", + border: "1px solid #eaeaea", + borderRadius: theme.spacing.unit, + cursor: "pointer", + height: theme.spacing.unit * 21.5, + overflow: "hidden", + padding: theme.spacing.unit * 2, + position: "relative", + transitionDuration: theme.transitions.duration.standard + "ms" + }, + root: { + display: "grid", + gridColumnGap: `${theme.spacing.unit * 2}px`, + gridRowGap: `${theme.spacing.unit * 2}px`, + gridTemplateColumns: "repeat(3, 1fr)", + maxWidth: "100%", + width: theme.breakpoints.values.lg, + [theme.breakpoints.down("sm")]: { + gridTemplateColumns: "repeat(2, 1fr)" + } + }, + selectedImageContainer: { + borderColor: theme.palette.primary.main + } + }); + +interface ProductVariantImageSelectDialogProps + extends WithStyles { + images?: ProductImage[]; + selectedImages?: string[]; + open: boolean; + onClose(); + onImageSelect(id: string); +} + +const ProductVariantImageSelectDialog = withStyles(styles, { + name: "ProductVariantImageSelectDialog" +})( + ({ + classes, + images, + open, + selectedImages, + onClose, + onImageSelect + }: ProductVariantImageSelectDialogProps) => ( + + + {i18n.t("Image selection", { context: "title" })} + + +
+ {images + .sort((prev, next) => (prev.sortOrder > next.sortOrder ? 1 : -1)) + .map(tile => ( +
+ +
+ ))} +
+
+ + + +
+ ) +); +ProductVariantImageSelectDialog.displayName = "ProductVariantImageSelectDialog"; +export default ProductVariantImageSelectDialog; diff --git a/src/products/components/ProductVariantImageSelectDialog/index.ts b/src/products/components/ProductVariantImageSelectDialog/index.ts new file mode 100644 index 000000000..91232d9cb --- /dev/null +++ b/src/products/components/ProductVariantImageSelectDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductVariantImageSelectDialog"; +export * from "./ProductVariantImageSelectDialog"; diff --git a/src/products/components/ProductVariantImages/ProductVariantImages.tsx b/src/products/components/ProductVariantImages/ProductVariantImages.tsx new file mode 100644 index 000000000..b111281cb --- /dev/null +++ b/src/products/components/ProductVariantImages/ProductVariantImages.tsx @@ -0,0 +1,94 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { ProductImage } from "../../types/ProductImage"; + +const styles = (theme: Theme) => + createStyles({ + gridElement: { + "& img": { + width: "100%" + } + }, + helpText: { + gridColumnEnd: "span 4" + }, + image: { + height: "100%", + objectFit: "contain", + width: "100%" + }, + imageContainer: { + background: "#ffffff", + border: "1px solid #eaeaea", + borderRadius: theme.spacing.unit, + height: theme.spacing.unit * 17.5, + marginBottom: theme.spacing.unit * 2, + padding: theme.spacing.unit * 2 + }, + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridTemplateColumns: "repeat(4, 1fr)" + } + }); + +interface ProductVariantImagesProps extends WithStyles { + images?: ProductImage[]; + placeholderImage?: string; + disabled: boolean; + onImageAdd(); +} + +export const ProductVariantImages = withStyles(styles, { + name: "ProductVariantImages" +})(({ classes, disabled, images, onImageAdd }: ProductVariantImagesProps) => ( + + + {i18n.t("Choose photos")} + + } + /> + +
+ {images === undefined || images === null ? ( + + ) : images.length > 0 ? ( + images + .sort((prev, next) => (prev.sortOrder > next.sortOrder ? 1 : -1)) + .map(tile => ( +
+ +
+ )) + ) : ( + + {i18n.t("Select a specific variant image from product images")} + + )} +
+
+
+)); +ProductVariantImages.displayName = "ProductVariantImages"; +export default ProductVariantImages; diff --git a/src/products/components/ProductVariantImages/index.ts b/src/products/components/ProductVariantImages/index.ts new file mode 100644 index 000000000..cd0ac0f9f --- /dev/null +++ b/src/products/components/ProductVariantImages/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductVariantImages"; +export * from "./ProductVariantImages"; diff --git a/src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx b/src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx new file mode 100644 index 000000000..34efe0235 --- /dev/null +++ b/src/products/components/ProductVariantNavigation/ProductVariantNavigation.tsx @@ -0,0 +1,122 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import * as classNames from "classnames"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; +import TableCellAvatar from "@saleor/components/TableCellAvatar"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ProductVariantCreateData_product_variants } from "../../types/ProductVariantCreateData"; +import { ProductVariantDetails_productVariant } from "../../types/ProductVariantDetails"; + +const styles = (theme: Theme) => + createStyles({ + link: { + cursor: "pointer" + }, + tabActive: { + "&:before": { + background: theme.palette.primary.main, + content: '""', + height: "100%", + left: 0, + position: "absolute", + top: 0, + width: 2 + }, + position: "relative" + }, + textLeft: { + textAlign: [["left"], "!important"] as any + } + }); + +interface ProductVariantNavigationProps extends WithStyles { + current?: string; + fallbackThumbnail: string; + variants: + | ProductVariantDetails_productVariant[] + | ProductVariantCreateData_product_variants[]; + onAdd?: () => void; + onRowClick: (variantId: string) => void; +} + +const ProductVariantNavigation = withStyles(styles, { + name: "ProductVariantNavigation" +})( + ({ + classes, + current, + fallbackThumbnail, + variants, + onAdd, + onRowClick + }: ProductVariantNavigationProps) => ( + + + + + {renderCollection( + variants, + variant => ( + onRowClick(variant.id) : undefined} + > + variant.images[0].url, + fallbackThumbnail + )} + /> + + {variant ? variant.name || variant.sku : } + + + ), + () => ( + + {i18n.t("This product has no variants")} + + ) + )} + {onAdd ? ( + + + + + + ) : ( + + + + {i18n.t("New Variant")} + + + )} + +
+
+ ) +); +ProductVariantNavigation.displayName = "ProductVariantNavigation"; +export default ProductVariantNavigation; diff --git a/src/products/components/ProductVariantNavigation/index.ts b/src/products/components/ProductVariantNavigation/index.ts new file mode 100644 index 000000000..00e2930d8 --- /dev/null +++ b/src/products/components/ProductVariantNavigation/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductVariantNavigation"; +export * from "./ProductVariantNavigation"; diff --git a/src/products/components/ProductVariantPage/ProductVariantPage.tsx b/src/products/components/ProductVariantPage/ProductVariantPage.tsx new file mode 100644 index 000000000..90caa1290 --- /dev/null +++ b/src/products/components/ProductVariantPage/ProductVariantPage.tsx @@ -0,0 +1,183 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import { maybe } from "../../../misc"; +import { UserError } from "../../../types"; +import { ProductVariant } from "../../types/ProductVariant"; +import ProductVariantAttributes from "../ProductVariantAttributes"; +import ProductVariantImages from "../ProductVariantImages"; +import ProductVariantImageSelectDialog from "../ProductVariantImageSelectDialog"; +import ProductVariantNavigation from "../ProductVariantNavigation"; +import ProductVariantPrice from "../ProductVariantPrice"; +import ProductVariantStock from "../ProductVariantStock"; + +interface ProductVariantPageProps { + variant?: ProductVariant; + errors: UserError[]; + saveButtonBarState: ConfirmButtonTransitionState; + loading?: boolean; + placeholderImage?: string; + header: string; + onAdd(); + onBack(); + onDelete(); + onSubmit(data: any); + onImageSelect(id: string); + onVariantClick(variantId: string); +} + +const ProductVariantPage: React.StatelessComponent = ({ + errors: formErrors, + loading, + header, + placeholderImage, + saveButtonBarState, + variant, + onAdd, + onBack, + onDelete, + onImageSelect, + onSubmit, + onVariantClick +}) => { + const [isModalOpened, setModalStatus] = React.useState(false); + const toggleModal = () => setModalStatus(!isModalOpened); + + const variantImages = variant ? variant.images.map(image => image.id) : []; + const productImages = variant + ? variant.product.images.sort((prev, next) => + prev.sortOrder > next.sortOrder ? 1 : -1 + ) + : undefined; + const images = productImages + ? productImages + .filter(image => variantImages.indexOf(image.id) !== -1) + .sort((prev, next) => (prev.sortOrder > next.sortOrder ? 1 : -1)) + : undefined; + return ( + <> + + + {maybe(() => variant.product.name)} + + +
({ + slug: a.attribute.slug, + value: a.value.slug + })) + : [], + costPrice: + variant && variant.costPrice + ? variant.costPrice.amount.toString() + : null, + priceOverride: + variant && variant.priceOverride + ? variant.priceOverride.amount.toString() + : null, + quantity: variant && variant.quantity ? variant.quantity : "", + sku: variant && variant.sku + }} + errors={formErrors} + onSubmit={onSubmit} + confirmLeave + > + {({ change, data, errors, hasChanged, submit }) => ( + <> + +
+ variant.product.thumbnail.url + )} + variants={maybe(() => variant.product.variants)} + onAdd={onAdd} + onRowClick={(variantId: string) => { + if (variant) { + return onVariantClick(variantId); + } + }} + /> +
+
+ a.attribute) + : undefined + } + data={data} + disabled={loading} + onChange={change} + /> + + + + + + +
+
+ + + )} + +
+ {variant && ( + variant.images.map(image => image.id))} + /> + )} + + ); +}; +ProductVariantPage.displayName = "ProductVariantPage"; +export default ProductVariantPage; diff --git a/src/products/components/ProductVariantPage/index.ts b/src/products/components/ProductVariantPage/index.ts new file mode 100644 index 000000000..3e9311e1d --- /dev/null +++ b/src/products/components/ProductVariantPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductVariantPage"; +export * from "./ProductVariantPage"; diff --git a/src/products/components/ProductVariantPrice/ProductVariantPrice.tsx b/src/products/components/ProductVariantPrice/ProductVariantPrice.tsx new file mode 100644 index 000000000..7166242bf --- /dev/null +++ b/src/products/components/ProductVariantPrice/ProductVariantPrice.tsx @@ -0,0 +1,81 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import PriceField from "@saleor/components/PriceField"; +import i18n from "../../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + grid: { + display: "grid", + gridColumnGap: `${theme.spacing.unit * 2}px`, + gridTemplateColumns: "1fr 1fr" + } + }); + +interface ProductVariantPriceProps extends WithStyles { + currencySymbol?: string; + priceOverride?: string; + costPrice?: string; + errors: { [key: string]: string }; + loading?: boolean; + onChange(event: any); +} + +const ProductVariantPrice = withStyles(styles, { name: "ProductVariantPrice" })( + ({ + classes, + currencySymbol, + costPrice, + errors, + priceOverride, + loading, + onChange + }: ProductVariantPriceProps) => ( + + + +
+
+ +
+
+ +
+
+
+
+ ) +); +ProductVariantPrice.displayName = "ProductVariantPrice"; +export default ProductVariantPrice; diff --git a/src/products/components/ProductVariantPrice/index.ts b/src/products/components/ProductVariantPrice/index.ts new file mode 100644 index 000000000..104957ff1 --- /dev/null +++ b/src/products/components/ProductVariantPrice/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductVariantPrice"; +export * from "./ProductVariantPrice"; diff --git a/src/products/components/ProductVariantStock/ProductVariantStock.tsx b/src/products/components/ProductVariantStock/ProductVariantStock.tsx new file mode 100644 index 000000000..9e07de8b6 --- /dev/null +++ b/src/products/components/ProductVariantStock/ProductVariantStock.tsx @@ -0,0 +1,89 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import i18n from "../../../i18n"; + +const styles = (theme: Theme) => + createStyles({ + grid: { + display: "grid", + gridColumnGap: `${theme.spacing.unit * 2}px`, + gridTemplateColumns: "1fr 1fr" + } + }); + +interface ProductVariantStockProps extends WithStyles { + errors: { + quantity?: string; + sku?: string; + }; + sku: string; + quantity: number; + stockAllocated?: number; + loading?: boolean; + onChange(event: any); +} + +const ProductVariantStock = withStyles(styles, { name: "ProductVariantStock" })( + ({ + classes, + errors, + sku, + quantity, + stockAllocated, + loading, + onChange + }: ProductVariantStockProps) => ( + + + +
+
+ +
+
+ +
+
+
+
+ ) +); +ProductVariantStock.displayName = "ProductVariantStock"; +export default ProductVariantStock; diff --git a/src/products/components/ProductVariantStock/index.ts b/src/products/components/ProductVariantStock/index.ts new file mode 100644 index 000000000..0cb07fabd --- /dev/null +++ b/src/products/components/ProductVariantStock/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductVariantStock"; +export * from "./ProductVariantStock"; diff --git a/src/products/components/ProductVariants/ProductVariants.tsx b/src/products/components/ProductVariants/ProductVariants.tsx new file mode 100644 index 000000000..389834ac2 --- /dev/null +++ b/src/products/components/ProductVariants/ProductVariants.tsx @@ -0,0 +1,203 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Hidden from "@material-ui/core/Hidden"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Checkbox from "@saleor/components/Checkbox"; +import Money from "@saleor/components/Money"; +import Skeleton from "@saleor/components/Skeleton"; +import StatusLabel from "@saleor/components/StatusLabel"; +import TableHead from "@saleor/components/TableHead"; +import i18n from "../../../i18n"; +import { renderCollection } from "../../../misc"; +import { ListActions } from "../../../types"; +import { ProductDetails_product_variants } from "../../types/ProductDetails"; +import { ProductVariant_costPrice } from "../../types/ProductVariant"; + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colName: {}, + colPrice: { + width: 200 + }, + colSku: { + width: 250 + }, + colStatus: { + width: 200 + } + }, + colName: {}, + colPrice: { + textAlign: "right" + }, + colSku: {}, + colStatus: {}, + denseTable: { + "& td, & th": { + paddingRight: theme.spacing.unit * 3 + } + }, + link: { + cursor: "pointer" + }, + textLeft: { + textAlign: "left" as "left" + }, + textRight: { + textAlign: "right" as "right" + } + }); + +interface ProductVariantsProps extends ListActions, WithStyles { + disabled: boolean; + variants: ProductDetails_product_variants[]; + fallbackPrice?: ProductVariant_costPrice; + onAttributesEdit: () => void; + onRowClick: (id: string) => () => void; + onVariantAdd?(); +} + +export const ProductVariants = withStyles(styles, { name: "ProductVariants" })( + ({ + classes, + disabled, + variants, + fallbackPrice, + onAttributesEdit, + onRowClick, + onVariantAdd, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: ProductVariantsProps) => ( + + + + + + } + /> + + + {i18n.t( + "Use variants for products that come in a variety of versions for example different sizes or colors" + )} + + + + + {i18n.t("Name")} + + {i18n.t("Status")} + + {i18n.t("SKU")} + + + {i18n.t("Price")} + + + + + {renderCollection( + variants, + variant => { + const isSelected = variant ? isChecked(variant.id) : false; + + return ( + + + toggle(variant.id)} + /> + + + {variant ? variant.name || variant.sku : } + + + {variant ? ( + 0 ? "success" : "error"} + label={ + variant.stockQuantity > 0 + ? i18n.t("Available") + : i18n.t("Unavailable") + } + /> + ) : ( + + )} + + + {variant ? variant.sku : } + + + + {variant ? ( + variant.priceOverride ? ( + + ) : fallbackPrice ? ( + + ) : ( + + ) + ) : ( + + )} + + + + ); + }, + () => ( + + + {i18n.t("This product has no variants")} + + + ) + )} + +
+
+ ) +); +ProductVariants.displayName = "ProductVariants"; +export default ProductVariants; diff --git a/src/products/components/ProductVariants/index.ts b/src/products/components/ProductVariants/index.ts new file mode 100644 index 000000000..f62aea928 --- /dev/null +++ b/src/products/components/ProductVariants/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductVariants"; +export * from "./ProductVariants"; diff --git a/src/products/containers/ProductImagesReorder.tsx b/src/products/containers/ProductImagesReorder.tsx new file mode 100644 index 000000000..3a9cd2d7b --- /dev/null +++ b/src/products/containers/ProductImagesReorder.tsx @@ -0,0 +1,57 @@ +import * as React from "react"; + +import { TypedMutationInnerProps } from "../../mutations"; +import { TypedProductImagesReorder } from "../mutations"; +import { + ProductImageReorder, + ProductImageReorderVariables +} from "../types/ProductImageReorder"; + +interface ProductImagesReorderProviderProps + extends TypedMutationInnerProps< + ProductImageReorder, + ProductImageReorderVariables + > { + productId: string; + productImages: Array<{ + id: string; + url: string; + }>; +} + +const ProductImagesReorderProvider: React.StatelessComponent< + ProductImagesReorderProviderProps +> = ({ children, productId, productImages, ...mutationProps }) => ( + + {(mutate, mutationResult) => + children(opts => { + const productImagesMap = productImages.reduce((prev, curr) => { + prev[curr.id] = curr; + return prev; + }, {}); + const newProductImages = opts.variables.imagesIds.map((id, index) => ({ + __typename: "ProductImage", + ...productImagesMap[id], + sortOrder: index + })); + const optimisticResponse: typeof mutationResult["data"] = { + productImageReorder: { + __typename: "ProductImageReorder", + errors: null, + product: { + __typename: "Product", + id: productId, + images: newProductImages + } + } + }; + return mutate({ + ...opts, + optimisticResponse + }); + }, mutationResult) + } + +); + +export default ProductImagesReorderProvider; diff --git a/src/products/containers/ProductUpdateOperations.tsx b/src/products/containers/ProductUpdateOperations.tsx new file mode 100644 index 000000000..e00558c41 --- /dev/null +++ b/src/products/containers/ProductUpdateOperations.tsx @@ -0,0 +1,155 @@ +import * as React from "react"; + +import { getMutationProviderData, maybe } from "../../misc"; +import { PartialMutationProviderOutput } from "../../types"; +import { + TypedProductDeleteMutation, + TypedProductImageCreateMutation, + TypedProductImageDeleteMutation, + TypedProductUpdateMutation, + TypedProductVariantBulkDeleteMutation, + TypedSimpleProductUpdateMutation +} from "../mutations"; +import { ProductDelete, ProductDeleteVariables } from "../types/ProductDelete"; +import { ProductDetails_product } from "../types/ProductDetails"; +import { + ProductImageCreate, + ProductImageCreateVariables +} from "../types/ProductImageCreate"; +import { + ProductImageDelete, + ProductImageDeleteVariables +} from "../types/ProductImageDelete"; +import { + ProductImageReorder, + ProductImageReorderVariables +} from "../types/ProductImageReorder"; +import { ProductUpdate, ProductUpdateVariables } from "../types/ProductUpdate"; +import { + ProductVariantBulkDelete, + ProductVariantBulkDeleteVariables +} from "../types/ProductVariantBulkDelete"; +import { + SimpleProductUpdate, + SimpleProductUpdateVariables +} from "../types/SimpleProductUpdate"; +import ProductImagesReorderProvider from "./ProductImagesReorder"; + +interface ProductUpdateOperationsProps { + product: ProductDetails_product; + children: (props: { + bulkProductVariantDelete: PartialMutationProviderOutput< + ProductVariantBulkDelete, + ProductVariantBulkDeleteVariables + >; + createProductImage: PartialMutationProviderOutput< + ProductImageCreate, + ProductImageCreateVariables + >; + deleteProduct: PartialMutationProviderOutput< + ProductDelete, + ProductDeleteVariables + >; + deleteProductImage: PartialMutationProviderOutput< + ProductImageDelete, + ProductImageDeleteVariables + >; + reorderProductImages: PartialMutationProviderOutput< + ProductImageReorder, + ProductImageReorderVariables + >; + updateProduct: PartialMutationProviderOutput< + ProductUpdate, + ProductUpdateVariables + >; + updateSimpleProduct: PartialMutationProviderOutput< + SimpleProductUpdate, + SimpleProductUpdateVariables + >; + }) => React.ReactNode; + onBulkProductVariantDelete?: (data: ProductVariantBulkDelete) => void; + onDelete?: (data: ProductDelete) => void; + onImageCreate?: (data: ProductImageCreate) => void; + onImageDelete?: (data: ProductImageDelete) => void; + onImageReorder?: (data: ProductImageReorder) => void; + onUpdate?: (data: ProductUpdate) => void; +} + +const ProductUpdateOperations: React.StatelessComponent< + ProductUpdateOperationsProps +> = ({ + product, + children, + onBulkProductVariantDelete, + onDelete, + onImageDelete, + onImageCreate, + onImageReorder, + onUpdate +}) => { + const productId = product ? product.id : ""; + return ( + + {(...updateProduct) => ( + product.images, [])} + onCompleted={onImageReorder} + > + {(...reorderProductImages) => ( + + {(...createProductImage) => ( + + {(...deleteProduct) => ( + + {(...deleteProductImage) => ( + + {(...updateSimpleProduct) => ( + + {(...bulkProductVariantDelete) => + children({ + bulkProductVariantDelete: getMutationProviderData( + ...bulkProductVariantDelete + ), + createProductImage: getMutationProviderData( + ...createProductImage + ), + deleteProduct: getMutationProviderData( + ...deleteProduct + ), + deleteProductImage: getMutationProviderData( + ...deleteProductImage + ), + reorderProductImages: getMutationProviderData( + ...reorderProductImages + ), + updateProduct: getMutationProviderData( + ...updateProduct + ), + updateSimpleProduct: getMutationProviderData( + ...updateSimpleProduct + ) + }) + } + + )} + + )} + + )} + + )} + + )} + + )} + + ); +}; +export default ProductUpdateOperations; diff --git a/src/products/containers/ProductVariantOperations.tsx b/src/products/containers/ProductVariantOperations.tsx new file mode 100644 index 000000000..a636ac989 --- /dev/null +++ b/src/products/containers/ProductVariantOperations.tsx @@ -0,0 +1,77 @@ +import * as React from "react"; + +import { getMutationProviderData } from "../../misc"; +import { PartialMutationProviderOutput } from "../../types"; +import { + TypedVariantDeleteMutation, + TypedVariantImageAssignMutation, + TypedVariantImageUnassignMutation, + TypedVariantUpdateMutation +} from "../mutations"; +import { VariantDelete, VariantDeleteVariables } from "../types/VariantDelete"; +import { + VariantImageAssign, + VariantImageAssignVariables +} from "../types/VariantImageAssign"; +import { + VariantImageUnassign, + VariantImageUnassignVariables +} from "../types/VariantImageUnassign"; +import { VariantUpdate, VariantUpdateVariables } from "../types/VariantUpdate"; + +interface VariantDeleteOperationsProps { + children: ( + props: { + deleteVariant: PartialMutationProviderOutput< + VariantDelete, + VariantDeleteVariables + >; + updateVariant: PartialMutationProviderOutput< + VariantUpdate, + VariantUpdateVariables + >; + assignImage: PartialMutationProviderOutput< + VariantImageAssign, + VariantImageAssignVariables + >; + unassignImage: PartialMutationProviderOutput< + VariantImageUnassign, + VariantImageUnassignVariables + >; + } + ) => React.ReactNode; + onDelete?: (data: VariantDelete) => void; + onImageAssign?: (data: VariantImageAssign) => void; + onImageUnassign?: (data: VariantImageUnassign) => void; + onUpdate?: (data: VariantUpdate) => void; +} + +const VariantUpdateOperations: React.StatelessComponent< + VariantDeleteOperationsProps +> = ({ children, onDelete, onUpdate, onImageAssign, onImageUnassign }) => { + return ( + + {(...assignImage) => ( + + {(...unassignImage) => ( + + {(...updateVariant) => ( + + {(...deleteVariant) => + children({ + assignImage: getMutationProviderData(...assignImage), + deleteVariant: getMutationProviderData(...deleteVariant), + unassignImage: getMutationProviderData(...unassignImage), + updateVariant: getMutationProviderData(...updateVariant) + }) + } + + )} + + )} + + )} + + ); +}; +export default VariantUpdateOperations; diff --git a/src/products/fixtures.ts b/src/products/fixtures.ts new file mode 100644 index 000000000..2fc48bc95 --- /dev/null +++ b/src/products/fixtures.ts @@ -0,0 +1,2424 @@ +import { content } from "../storybook/stories/components/RichTextEditor"; +import { ProductDetails_product } from "./types/ProductDetails"; +import { ProductVariant } from "./types/ProductVariant"; +import { ProductVariantCreateData_product } from "./types/ProductVariantCreateData"; + +export const product: ( + placeholderImage: string +) => ProductDetails_product & + ProductVariantCreateData_product = placeholderImage => ({ + __typename: "Product", + attributes: [ + { + __typename: "SelectedAttribute", + attribute: { + __typename: "Attribute", + id: "pta18161", + name: "Borders", + slug: "Borders", + sortNumber: 0, + values: [ + { + __typename: "AttributeValue", + id: "ptav47282", + name: "portals", + slug: "portals", + sortNumber: 0 + }, + { + __typename: "AttributeValue", + id: "ptav17253", + name: "Baht", + slug: "Baht", + sortNumber: 1 + } + ] + }, + value: { + __typename: "AttributeValue", + id: "ptav47282", + name: "portals", + slug: "portals", + sortNumber: 0 + } + }, + { + __typename: "SelectedAttribute", + attribute: { + __typename: "Attribute", + id: "pta22785", + name: "Legacy", + slug: "Legacy", + sortNumber: 1, + values: [ + { + __typename: "AttributeValue", + id: "ptav31282", + name: "payment", + slug: "payment", + sortNumber: 0 + }, + { + __typename: "AttributeValue", + id: "ptav14907", + name: "Auto Loan Account", + slug: "Auto-Loan-Account", + sortNumber: 1 + }, + { + __typename: "AttributeValue", + id: "ptav27366", + name: "Garden", + slug: "Garden", + sortNumber: 2 + }, + { + __typename: "AttributeValue", + id: "ptav11873", + name: "override", + slug: "override", + sortNumber: 3 + } + ] + }, + value: { + __typename: "AttributeValue", + id: "ptav14907", + name: "Auto Loan Account", + slug: "Auto-Loan-Account", + sortNumber: 1 + } + } + ], + basePrice: { + __typename: "Money", + amount: 339.39, + currency: "NZD", + localized: "339.39 NZD" + }, + category: { __typename: "Category", id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + chargeTaxes: true, + collections: [ + { + __typename: "Collection", + id: "Q29sbGVjdGlvbjoy", + name: "Winter sale" + } + ], + descriptionJson: JSON.stringify(content), + id: "p10171", + images: [ + { + __typename: "ProductImage", + alt: "Id sit dolores adipisci", + id: "UHJvZHVjdEltYWdlOjE=", + sortOrder: 0, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Id sit dolores adipisci", + id: "UHJvZHVjdEltYWdlOaE=", + sortOrder: 2, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Id sit dolores adipisci", + id: "UPJvZHVjdEltYWdlOjV=", + sortOrder: 1, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Id sit dolores adipisci", + id: "UHJvZHVjdEltYHdlOjX=", + sortOrder: 3, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Id sit dolores adipisci", + id: "UHJvZHVjdIlnYWdlOjX=", + sortOrder: 4, + url: placeholderImage + } + ], + isAvailable: false, + isFeatured: false, + isPublished: true, + margin: { __typename: "Margin", start: 2, stop: 7 }, + name: "Ergonomic Plastic Bacon", + pricing: { + __typename: "ProductPricingInfo", + priceRange: { + __typename: "TaxedMoneyRange", + start: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 12.3, + currency: "USD" + }, + net: { + __typename: "Money", + amount: 10, + currency: "USD" + } + }, + stop: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + amount: 24.6, + currency: "USD" + }, + net: { + __typename: "Money", + amount: 20, + currency: "USD" + } + } + } + }, + productType: { + __typename: "ProductType", + hasVariants: true, + id: "pt76406", + name: "Versatile", + seoDescription: "Omnis rerum ea. Fugit dignissimos modi est rerum", + seoTitle: "Ergonomic Plastic Bacon", + variantAttributes: [ + { + __typename: "Attribute", + id: "pta18161", + name: "Color", + slug: "color", + sortOrder: 0, + values: [ + { + __typename: "AttributeValue", + id: "ptvav47282", + name: "Black", + slug: "black", + sortOrder: 0 + }, + { + __typename: "AttributeValue", + id: "ptvav17253", + name: "White", + slug: "white", + sortOrder: 1 + } + ] + } + ] + }, + publicationDate: "2018-08-25T18:45:54.125Z", + purchaseCost: { + __typename: "MoneyRange", + start: { + __typename: "Money", + amount: 339.39, + currency: "NZD", + localized: "339.39 NZD" + }, + stop: { + __typename: "Money", + amount: 678.78, + currency: "NZD", + localized: "678.78 NZD" + } + }, + seoDescription: "Seo description", + seoTitle: "Seo title", + sku: "59661-34207", + thumbnail: { __typename: "Image", url: placeholderImage }, + url: "/example-url", + variants: [ + { + __typename: "ProductVariant", + id: "pv75934", + images: [ + { + __typename: "ProductImage", + id: "pi92837", + url: placeholderImage + }, + { + __typename: "ProductImage", + id: "pi92838", + url: placeholderImage + } + ], + margin: 2, + name: "Cordoba Oro", + priceOverride: { + __typename: "Money", + amount: 678.78, + currency: "USD" + }, + quantity: 12, + quantityAllocated: 1, + sku: "87192-94370", + stockQuantity: 48 + }, + { + __typename: "ProductVariant", + id: "pv68615", + images: [ + { + __typename: "ProductImage", + id: "pi81234", + url: placeholderImage + }, + { + __typename: "ProductImage", + id: "pi1236912", + url: placeholderImage + } + ], + margin: 7, + name: "silver", + priceOverride: null, + quantity: 12, + quantityAllocated: 1, + sku: "69055-15190", + stockQuantity: 14 + } + ] +}); +export const products = (placeholderImage: string) => [ + { + attributes: [ + { + attribute: { + id: "pta37372", + name: "expedite", + slug: "expedite", + sortOrder: 0, + values: [ + { id: "ptav84718", name: "violet", slug: "violet", sortOrder: 0 }, + { id: "ptav4189", name: "virtual", slug: "virtual", sortOrder: 1 }, + { + id: "ptav39406", + name: "supply-chains", + slug: "supply-chains", + sortOrder: 2 + }, + { + id: "ptav57910", + name: "Implementation", + slug: "Implementation", + sortOrder: 3 + } + ] + }, + value: { + id: "ptav4189", + name: "virtual", + slug: "virtual", + sortOrder: 1 + } + }, + { + attribute: { + id: "pta3183", + name: "system", + slug: "system", + sortOrder: 1, + values: [ + { + id: "ptav83133", + name: "turn-key", + slug: "turn-key", + sortOrder: 0 + }, + { id: "ptav60236", name: "red", slug: "red", sortOrder: 1 }, + { id: "ptav99015", name: "Fort", slug: "Fort", sortOrder: 2 }, + { id: "ptav98580", name: "Borders", slug: "Borders", sortOrder: 3 }, + { id: "ptav34875", name: "Guam", slug: "Guam", sortOrder: 4 } + ] + }, + value: { + id: "ptav98580", + name: "Borders", + slug: "Borders", + sortOrder: 3 + } + }, + { + attribute: { + id: "pta47147", + name: "interactive", + slug: "interactive", + sortOrder: 2, + values: [ + { + id: "ptav67400", + name: "fault-tolerant", + slug: "fault-tolerant", + sortOrder: 0 + } + ] + }, + value: { + id: "ptav67400", + name: "fault-tolerant", + slug: "fault-tolerant", + sortOrder: 0 + } + }, + { + attribute: { + id: "pta34499", + name: "deposit", + slug: "deposit", + sortOrder: 3, + values: [ + { id: "ptav11679", name: "silver", slug: "silver", sortOrder: 0 }, + { + id: "ptav12539", + name: "Iranian Rial", + slug: "Iranian-Rial", + sortOrder: 1 + }, + { + id: "ptav93140", + name: "Gorgeous Cotton Tuna", + slug: "Gorgeous-Cotton-Tuna", + sortOrder: 2 + }, + { id: "ptav7930", name: "hybrid", slug: "hybrid", sortOrder: 3 }, + { + id: "ptav75590", + name: "navigating", + slug: "navigating", + sortOrder: 4 + } + ] + }, + value: { + id: "ptav75590", + name: "navigating", + slug: "navigating", + sortOrder: 4 + } + } + ], + basePrice: { amount: 274.99389477595827, currency: "XAG" }, + category: { id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + collections: { + edges: [{ node: { id: "Q29sbGVjdGlvbjoy", name: "Winter sale" } }] + }, + description: + "Autem odit tempora nesciunt quaerat enim reprehenderit eius. Excepturi nemo quos veritatis laboriosam aperiam atque natus soluta. Quos enim illo eum explicabo sapiente voluptates. Ad et fugiat alias. Perspiciatis quod tenetur ex aspernatur nesciunt ab veritatis perspiciatis. A numquam odio aperiam nobis consequatur voluptatum id. Culpa excepturi et voluptate dolore sint esse voluptate optio ut. Sit quis consequatur quo quia praesentium accusamus quia reiciendis repellendus.", + id: "p25557", + images: { + edges: [ + { + node: { + id: "UHJvZHVjdEltYWdlOjE=", + image: placeholderImage, + sortOrder: 0, + url: placeholderImage + } + } + ] + }, + isAvailable: true, + isFeatured: false, + isPublished: false, + margin: { start: 6, stop: 18 }, + name: "Gorgeous Frozen Chips", + productType: { + hasVariants: true, + id: "pt41284", + name: "Awesome Wooden Pizza" + }, + publicationDate: null, + purchaseCost: { + start: { amount: 274.99389477595827, currency: "XAG" }, + stop: { amount: 274.99389477595827, currency: "XAG" } + }, + seoDescription: + "Autem odit tempora nesciunt quaerat enim reprehenderit eius. Excepturi nemo quos veritatis laboriosam aperiam atque natus soluta", + seoTitle: "Generic Rubber Pants", + sku: "57599-97473", + thumbnail: { __typename: "Image", url: placeholderImage }, + variants: { + edges: [ + { + node: { + id: "pv44405", + margin: 18, + name: "Minnesota", + priceOverride: null, + quantity: 42, + sku: "26012-49906" + } + }, + { + node: { + id: "pv27827", + margin: 6, + name: "Specialist", + priceOverride: null, + quantity: 45, + sku: "12278-95926" + } + } + ] + } + }, + { + attributes: [ + { + attribute: { + id: "pta1529", + name: "Granite", + slug: "Granite", + sortOrder: 0, + values: [ + { + id: "ptav30634", + name: "multi-byte", + slug: "multi-byte", + sortOrder: 0 + }, + { id: "ptav77390", name: "Soft", slug: "Soft", sortOrder: 1 }, + { + id: "ptav42995", + name: "navigating", + slug: "navigating", + sortOrder: 2 + } + ] + }, + value: { + id: "ptav30634", + name: "multi-byte", + slug: "multi-byte", + sortOrder: 0 + } + }, + { + attribute: { + id: "pta44120", + name: "wireless", + slug: "wireless", + sortOrder: 1, + values: [ + { + id: "ptav89151", + name: "Tasty Wooden Shirt", + slug: "Tasty-Wooden-Shirt", + sortOrder: 0 + }, + { id: "ptav69476", name: "monitor", slug: "monitor", sortOrder: 1 }, + { + id: "ptav71380", + name: "Operative", + slug: "Operative", + sortOrder: 2 + }, + { + id: "ptav73557", + name: "vertical", + slug: "vertical", + sortOrder: 3 + }, + { id: "ptav61047", name: "Managed", slug: "Managed", sortOrder: 4 } + ] + }, + value: { + id: "ptav73557", + name: "vertical", + slug: "vertical", + sortOrder: 3 + } + }, + { + attribute: { + id: "pta83114", + name: "6th generation", + slug: "6th-generation", + sortOrder: 2, + values: [ + { + id: "ptav42344", + name: "Division", + slug: "Division", + sortOrder: 0 + }, + { + id: "ptav76960", + name: "sky blue", + slug: "sky-blue", + sortOrder: 1 + } + ] + }, + value: { + id: "ptav76960", + name: "sky blue", + slug: "sky-blue", + sortOrder: 1 + } + } + ], + basePrice: { amount: 432.2991706153576, currency: "ZWL" }, + category: { id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + collections: { + edges: [{ node: { id: "Q29sbGVjdGlvbjoy", name: "Winter sale" } }] + }, + description: + "Cumque sed vero velit. Quas autem ipsam aperiam assumenda autem. Voluptatum et similique consequatur. Ipsum praesentium omnis eveniet veritatis possimus perspiciatis. Quae sint perferendis quia ut reiciendis magnam qui dolorum impedit. Ut placeat quod doloribus est hic error doloremque amet sint. Ut esse ex explicabo culpa ab eaque adipisci ut. Esse rerum et asperiores libero.", + id: "p59567", + images: { + edges: [ + { + node: { + id: "UHJvZHVjdEltYWdlOjE=", + image: placeholderImage, + sortOrder: 0, + url: placeholderImage + } + } + ] + }, + isAvailable: true, + isFeatured: false, + isPublished: true, + margin: { start: 4, stop: 19 }, + name: "Handcrafted Wooden Towels", + productType: { hasVariants: false, id: "pt29020", name: "Future" }, + publicationDate: null, + purchaseCost: { + start: { amount: 432.2991706153576, currency: "ZWL" }, + stop: { amount: 8213.684241691793, currency: "ZWL" } + }, + seoDescription: "enim est recusandae soluta aperiam", + seoTitle: "Handcrafted Wooden Towels", + sku: "6526-89350", + thumbnail: { __typename: "Image", url: placeholderImage }, + variants: { + edges: [ + { + node: { + id: "pv21736", + margin: 19, + name: "Plain", + priceOverride: 8213.684241691793, + quantity: 19, + sku: "28237-88009" + } + }, + { + node: { + id: "pv51132", + margin: 4, + name: "secured line", + priceOverride: null, + quantity: 38, + sku: "94362-46644" + } + }, + { + node: { + id: "pv43456", + margin: 18, + name: "compressing", + priceOverride: 7781.385071076436, + quantity: 47, + sku: "29140-85285" + } + }, + { + node: { + id: "pv274", + margin: 6, + name: "Sports", + priceOverride: null, + quantity: 0, + sku: "61813-6435" + } + }, + { + node: { + id: "pv7724", + margin: 16, + name: "copy", + priceOverride: 6916.786729845721, + quantity: 42, + sku: "68556-81832" + } + } + ] + } + }, + { + attributes: [ + { + attribute: { + id: "pta40940", + name: "monitor", + slug: "monitor", + sortOrder: 0, + values: [ + { + id: "ptav64256", + name: "alliance", + slug: "alliance", + sortOrder: 0 + }, + { + id: "ptav9644", + name: "content-based", + slug: "content-based", + sortOrder: 1 + }, + { + id: "ptav27621", + name: "East Caribbean Dollar", + slug: "East-Caribbean-Dollar", + sortOrder: 2 + }, + { + id: "ptav21347", + name: "Licensed", + slug: "Licensed", + sortOrder: 3 + }, + { + id: "ptav94604", + name: "client-server", + slug: "client-server", + sortOrder: 4 + } + ] + }, + value: { + id: "ptav21347", + name: "Licensed", + slug: "Licensed", + sortOrder: 3 + } + }, + { + attribute: { + id: "pta33894", + name: "Assurance", + slug: "Assurance", + sortOrder: 1, + values: [ + { id: "ptav28890", name: "exploit", slug: "exploit", sortOrder: 0 }, + { + id: "ptav4427", + name: "Team-oriented", + slug: "Team-oriented", + sortOrder: 1 + }, + { + id: "ptav16612", + name: "Money Market Account", + slug: "Money-Market-Account", + sortOrder: 2 + }, + { id: "ptav61387", name: "monitor", slug: "monitor", sortOrder: 3 }, + { + id: "ptav51902", + name: "synthesize", + slug: "synthesize", + sortOrder: 4 + } + ] + }, + value: { + id: "ptav16612", + name: "Money Market Account", + slug: "Money-Market-Account", + sortOrder: 2 + } + }, + { + attribute: { + id: "pta35528", + name: "Function-based", + slug: "Function-based", + sortOrder: 2, + values: [ + { + id: "ptav77876", + name: "generating", + slug: "generating", + sortOrder: 0 + } + ] + }, + value: { + id: "ptav77876", + name: "generating", + slug: "generating", + sortOrder: 0 + } + } + ], + basePrice: { amount: 688.3543328975433, currency: "XDR" }, + category: { id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + collections: { + edges: [{ node: { id: "Q29sbGVjdGlvbjoy", name: "Winter sale" } }] + }, + description: + "Ut iusto iusto minus odio. Id sunt dolores esse. Asperiores minima nihil et vel id hic possimus temporibus. Ut dolor soluta et eum. Qui ut quaerat deserunt voluptas corporis consequatur saepe. Quo possimus qui laborum. Nesciunt quos dolore dolor consectetur dolor. Qui autem voluptatem.", + id: "p92172", + images: { + edges: [ + { + node: { + id: "UHJvZHVjdEltYWdlOjE=", + image: placeholderImage, + sortOrder: 0, + url: placeholderImage + } + } + ] + }, + isAvailable: false, + isFeatured: false, + isPublished: true, + margin: { start: 3, stop: 18 }, + name: "Handcrafted Metal Cheese", + productType: { hasVariants: true, id: "pt23508", name: "SMS" }, + publicationDate: null, + purchaseCost: { + start: { amount: 688.3543328975433, currency: "XDR" }, + stop: { amount: 3441.7716644877164, currency: "XDR" } + }, + seoDescription: "quas minima error repudiandae corrupti", + seoTitle: "Handcrafted Metal Cheese", + sku: "9937-5954", + thumbnail: { __typename: "Image", url: placeholderImage }, + variants: { + edges: [ + { + node: { + id: "pv34161", + margin: 3, + name: "Iraq", + priceOverride: 2065.0629986926297, + quantity: 21, + sku: "92335-9731" + } + }, + { + node: { + id: "pv43741", + margin: 5, + name: "invoice", + priceOverride: 3441.7716644877164, + quantity: 47, + sku: "91798-87295" + } + }, + { + node: { + id: "pv52463", + margin: 18, + name: "fuchsia", + priceOverride: null, + quantity: 40, + sku: "71687-8488" + } + }, + { + node: { + id: "pv93602", + margin: 5, + name: "lime", + priceOverride: 3441.7716644877164, + quantity: 8, + sku: "95750-91626" + } + } + ] + } + }, + { + attributes: [ + { + attribute: { + id: "pta58079", + name: "Cotton", + slug: "Cotton", + sortOrder: 0, + values: [ + { id: "ptav12741", name: "Table", slug: "Table", sortOrder: 0 }, + { id: "ptav24310", name: "Salad", slug: "Salad", sortOrder: 1 }, + { id: "ptav98446", name: "Hawaii", slug: "Hawaii", sortOrder: 2 }, + { + id: "ptav18267", + name: "Assurance", + slug: "Assurance", + sortOrder: 3 + }, + { id: "ptav57428", name: "Liberia", slug: "Liberia", sortOrder: 4 } + ] + }, + value: { + id: "ptav57428", + name: "Liberia", + slug: "Liberia", + sortOrder: 4 + } + }, + { + attribute: { + id: "pta51731", + name: "Assistant", + slug: "Assistant", + sortOrder: 1, + values: [ + { id: "ptav85577", name: "black", slug: "black", sortOrder: 0 } + ] + }, + value: { id: "ptav85577", name: "black", slug: "black", sortOrder: 0 } + }, + { + attribute: { + id: "pta53013", + name: "target", + slug: "target", + sortOrder: 2, + values: [ + { id: "ptav1569", name: "Tuna", slug: "Tuna", sortOrder: 0 }, + { + id: "ptav99901", + name: "quantify", + slug: "quantify", + sortOrder: 1 + }, + { + id: "ptav77006", + name: "Saudi Riyal", + slug: "Saudi-Riyal", + sortOrder: 2 + }, + { + id: "ptav74813", + name: "New Hampshire", + slug: "New-Hampshire", + sortOrder: 3 + } + ] + }, + value: { + id: "ptav99901", + name: "quantify", + slug: "quantify", + sortOrder: 1 + } + }, + { + attribute: { + id: "pta98307", + name: "Brand", + slug: "Brand", + sortOrder: 3, + values: [ + { + id: "ptav93905", + name: "Clothing", + slug: "Clothing", + sortOrder: 0 + } + ] + }, + value: { + id: "ptav93905", + name: "Clothing", + slug: "Clothing", + sortOrder: 0 + } + }, + { + attribute: { + id: "pta52191", + name: "invoice", + slug: "invoice", + sortOrder: 4, + values: [ + { + id: "ptav74932", + name: "Implementation", + slug: "Implementation", + sortOrder: 0 + }, + { + id: "ptav68802", + name: "Berkshire", + slug: "Berkshire", + sortOrder: 1 + }, + { + id: "ptav89987", + name: "Generic Rubber Gloves", + slug: "Generic-Rubber-Gloves", + sortOrder: 2 + }, + { id: "ptav60428", name: "HDD", slug: "HDD", sortOrder: 3 } + ] + }, + value: { id: "ptav60428", name: "HDD", slug: "HDD", sortOrder: 3 } + } + ], + basePrice: { amount: 540.3817687240911, currency: "SLL" }, + category: { id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + collections: { + edges: [{ node: { id: "Q29sbGVjdGlvbjoy", name: "Winter sale" } }] + }, + description: + "Veniam quasi temporibus ab similique. Praesentium vero repudiandae. Tempora facilis perspiciatis minus et. Ea soluta reiciendis ipsum facilis architecto alias voluptatem molestiae. Enim nam velit accusantium. Aut vitae voluptas sint rerum laborum. Voluptatem quod provident possimus voluptatem illum. Dignissimos saepe et.", + id: "p89786", + images: { + edges: [ + { + node: { + id: "UHJvZHVjdEltYWdlOjE=", + image: placeholderImage, + sortOrder: 0, + url: placeholderImage + } + } + ] + }, + isAvailable: false, + isFeatured: true, + isPublished: true, + margin: { start: 4, stop: 19 }, + name: "Refined Rubber Keyboard", + productType: { hasVariants: false, id: "pt20625", name: "Virtual" }, + publicationDate: null, + purchaseCost: { + start: { amount: 540.3817687240911, currency: "SLL" }, + stop: { amount: 4863.43591851682, currency: "SLL" } + }, + seoDescription: + "Veniam quasi temporibus ab similique. Praesentium vero repudiandae", + seoTitle: "Awesome Granite Car", + sku: "96777-48145", + thumbnail: { __typename: "Image", url: placeholderImage }, + variants: { + edges: [ + { + node: { + id: "pv92097", + margin: 6, + name: "productize", + priceOverride: null, + quantity: 48, + sku: "6312-11173" + } + }, + { + node: { + id: "pv56701", + margin: 19, + name: "bifurcated", + priceOverride: null, + quantity: 30, + sku: "93662-14792" + } + }, + { + node: { + id: "pv98872", + margin: 9, + name: "multimedia", + priceOverride: 4863.43591851682, + quantity: 21, + sku: "89986-48759" + } + }, + { + node: { + id: "pv92133", + margin: 8, + name: "paradigm", + priceOverride: 4323.054149792729, + quantity: 5, + sku: "15410-64401" + } + }, + { + node: { + id: "pv24205", + margin: 12, + name: "Squares", + priceOverride: null, + quantity: 5, + sku: "51743-88427" + } + }, + { + node: { + id: "pv33740", + margin: 6, + name: "invoice", + priceOverride: null, + quantity: 42, + sku: "35615-85883" + } + }, + { + node: { + id: "pv4519", + margin: 4, + name: "Arizona", + priceOverride: null, + quantity: 1, + sku: "56452-53097" + } + } + ] + } + }, + { + attributes: [ + { + attribute: { + id: "pta96115", + name: "Officer", + slug: "Officer", + sortOrder: 0, + values: [ + { id: "ptav14754", name: "Rubber", slug: "Rubber", sortOrder: 0 } + ] + }, + value: { id: "ptav14754", name: "Rubber", slug: "Rubber", sortOrder: 0 } + }, + { + attribute: { + id: "pta74440", + name: "driver", + slug: "driver", + sortOrder: 1, + values: [ + { id: "ptav84649", name: "FTP", slug: "FTP", sortOrder: 0 }, + { id: "ptav82177", name: "parse", slug: "parse", sortOrder: 1 }, + { + id: "ptav4221", + name: "Executive", + slug: "Executive", + sortOrder: 2 + }, + { id: "ptav44337", name: "Gateway", slug: "Gateway", sortOrder: 3 } + ] + }, + value: { id: "ptav84649", name: "FTP", slug: "FTP", sortOrder: 0 } + }, + { + attribute: { + id: "pta95292", + name: "SDD", + slug: "SDD", + sortOrder: 2, + values: [ + { + id: "ptav61506", + name: "forecast", + slug: "forecast", + sortOrder: 0 + }, + { + id: "ptav33698", + name: "Virginia", + slug: "Virginia", + sortOrder: 1 + } + ] + }, + value: { + id: "ptav33698", + name: "Virginia", + slug: "Virginia", + sortOrder: 1 + } + }, + { + attribute: { + id: "pta28064", + name: "firewall", + slug: "firewall", + sortOrder: 3, + values: [ + { + id: "ptav56676", + name: "initiative", + slug: "initiative", + sortOrder: 0 + }, + { id: "ptav77667", name: "Web", slug: "Web", sortOrder: 1 } + ] + }, + value: { id: "ptav77667", name: "Web", slug: "Web", sortOrder: 1 } + }, + { + attribute: { + id: "pta90527", + name: "Jamaica", + slug: "Jamaica", + sortOrder: 4, + values: [ + { id: "ptav52878", name: "Burgs", slug: "Burgs", sortOrder: 0 }, + { + id: "ptav772", + name: "workforce", + slug: "workforce", + sortOrder: 1 + }, + { id: "ptav82565", name: "Human", slug: "Human", sortOrder: 2 }, + { + id: "ptav46804", + name: "cross-platform", + slug: "cross-platform", + sortOrder: 3 + } + ] + }, + value: { id: "ptav52878", name: "Burgs", slug: "Burgs", sortOrder: 0 } + } + ], + basePrice: { amount: 4.359138839276078, currency: "AMD" }, + category: { id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + collections: { + edges: [{ node: { id: "Q29sbGVjdGlvbjoy", name: "Winter sale" } }] + }, + description: + "Minima quaerat error incidunt qui quis vitae maxime. Est ab et. Optio animi corporis tempore possimus facere. Qui voluptatem fuga at reprehenderit id molestias voluptate. Et consectetur odit at. Nemo sed nulla nemo non et dicta tenetur. Omnis in fugiat. Ex ea commodi minus sed sint.", + id: "p67851", + images: { + edges: [ + { + node: { + id: "UHJvZHVjdEltYWdlOjE=", + image: placeholderImage, + sortOrder: 0, + url: placeholderImage + } + } + ] + }, + isAvailable: true, + isFeatured: false, + isPublished: false, + margin: { start: 6, stop: 17 }, + name: "Gorgeous Metal Gloves", + productType: { hasVariants: true, id: "pt91547", name: "Vermont" }, + publicationDate: null, + purchaseCost: { + start: { amount: 4.359138839276078, currency: "AMD" }, + stop: { amount: 74.10536026769333, currency: "AMD" } + }, + seoDescription: + "Minima quaerat error incidunt qui quis vitae maxime. Est ab et", + seoTitle: "Gorgeous Metal Gloves", + sku: "60799-40023", + thumbnail: { __typename: "Image", url: placeholderImage }, + variants: { + edges: [ + { + node: { + id: "pv10610", + margin: 17, + name: "Data", + priceOverride: 74.10536026769333, + quantity: 15, + sku: "70713-29057" + } + }, + { + node: { + id: "pv35325", + margin: 11, + name: "CSS", + priceOverride: null, + quantity: 16, + sku: "85366-83000" + } + }, + { + node: { + id: "pv56132", + margin: 10, + name: "compressing", + priceOverride: null, + quantity: 16, + sku: "94401-90694" + } + }, + { + node: { + id: "pv7891", + margin: 12, + name: "hacking", + priceOverride: null, + quantity: 23, + sku: "75089-16931" + } + }, + { + node: { + id: "pv90884", + margin: 15, + name: "Assimilated", + priceOverride: null, + quantity: 18, + sku: "44872-68830" + } + }, + { + node: { + id: "pv19605", + margin: 15, + name: "Arkansas", + priceOverride: null, + quantity: 32, + sku: "69686-14483" + } + }, + { + node: { + id: "pv45238", + margin: 6, + name: "deliverables", + priceOverride: null, + quantity: 23, + sku: "81817-51892" + } + }, + { + node: { + id: "pv67414", + margin: 8, + name: "Cambridgeshire", + priceOverride: null, + quantity: 25, + sku: "23890-14998" + } + } + ] + } + }, + { + attributes: [ + { + attribute: { + id: "pta77866", + name: "well-modulated", + slug: "well-modulated", + sortOrder: 0, + values: [ + { id: "ptav48728", name: "Group", slug: "Group", sortOrder: 0 }, + { id: "ptav45439", name: "Rubber", slug: "Rubber", sortOrder: 1 }, + { + id: "ptav80318", + name: "Handmade Steel Chips", + slug: "Handmade-Steel-Chips", + sortOrder: 2 + }, + { id: "ptav55820", name: "yellow", slug: "yellow", sortOrder: 3 }, + { id: "ptav46550", name: "bypass", slug: "bypass", sortOrder: 4 } + ] + }, + value: { id: "ptav45439", name: "Rubber", slug: "Rubber", sortOrder: 1 } + }, + { + attribute: { + id: "pta46984", + name: "magenta", + slug: "magenta", + sortOrder: 1, + values: [ + { + id: "ptav95090", + name: "Credit Card Account", + slug: "Credit-Card-Account", + sortOrder: 0 + } + ] + }, + value: { + id: "ptav95090", + name: "Credit Card Account", + slug: "Credit-Card-Account", + sortOrder: 0 + } + }, + { + attribute: { + id: "pta58329", + name: "District", + slug: "District", + sortOrder: 2, + values: [ + { + id: "ptav38516", + name: "Home Loan Account", + slug: "Home-Loan-Account", + sortOrder: 0 + }, + { id: "ptav42626", name: "panel", slug: "panel", sortOrder: 1 } + ] + }, + value: { + id: "ptav38516", + name: "Home Loan Account", + slug: "Home-Loan-Account", + sortOrder: 0 + } + }, + { + attribute: { + id: "pta24725", + name: "payment", + slug: "payment", + sortOrder: 3, + values: [ + { + id: "ptav37397", + name: "firmware", + slug: "firmware", + sortOrder: 0 + }, + { id: "ptav29524", name: "Music", slug: "Music", sortOrder: 1 }, + { + id: "ptav66933", + name: "Team-oriented", + slug: "Team-oriented", + sortOrder: 2 + }, + { + id: "ptav94930", + name: "Singapore Dollar", + slug: "Singapore-Dollar", + sortOrder: 3 + } + ] + }, + value: { + id: "ptav94930", + name: "Singapore Dollar", + slug: "Singapore-Dollar", + sortOrder: 3 + } + }, + { + attribute: { + id: "pta20828", + name: "functionalities", + slug: "functionalities", + sortOrder: 4, + values: [ + { + id: "ptav75959", + name: "Buckinghamshire", + slug: "Buckinghamshire", + sortOrder: 0 + }, + { id: "ptav76195", name: "Idaho", slug: "Idaho", sortOrder: 1 }, + { id: "ptav91880", name: "systems", slug: "systems", sortOrder: 2 }, + { id: "ptav2568", name: "SMS", slug: "SMS", sortOrder: 3 }, + { + id: "ptav29590", + name: "convergence", + slug: "convergence", + sortOrder: 4 + } + ] + }, + value: { + id: "ptav29590", + name: "convergence", + slug: "convergence", + sortOrder: 4 + } + } + ], + basePrice: { amount: 538.0974149450597, currency: "GMD" }, + category: { id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + collections: { + edges: [{ node: { id: "Q29sbGVjdGlvbjoy", name: "Winter sale" } }] + }, + description: + "Esse quia voluptates veniam eveniet. Velit laborum possimus eveniet consequuntur magnam eveniet provident et voluptatem. Exercitationem magni quas aliquid unde voluptatibus hic ut et quam. Quia a cumque iusto delectus aut et inventore vero. Qui mollitia qui. Dolores quos quas est quidem aut ab aut vel et. Repellendus suscipit ut iure quis cupiditate. Sapiente ut rerum impedit mollitia quam quos provident.", + id: "p54272", + images: { + edges: [ + { + node: { + id: "UHJvZHVjdEltYWdlOjE=", + image: placeholderImage, + sortOrder: 0, + url: placeholderImage + } + } + ] + }, + isAvailable: false, + isFeatured: false, + isPublished: false, + margin: { start: 1, stop: 15 }, + name: "Small Cotton Shirt", + productType: { hasVariants: false, id: "pt69941", name: "Gorgeous" }, + publicationDate: null, + purchaseCost: { + start: { amount: 538.0974149450597, currency: "GMD" }, + stop: { amount: 6457.168979340716, currency: "GMD" } + }, + seoDescription: + "Esse quia voluptates veniam eveniet. Velit laborum possimus eveniet consequuntur magnam eveniet provident et voluptatem", + seoTitle: "Unbranded Rubber Ball", + sku: "2840-48373", + thumbnail: { __typename: "Image", url: placeholderImage }, + variants: { + edges: [ + { + node: { + id: "pv95364", + margin: 9, + name: "Security", + priceOverride: null, + quantity: 48, + sku: "22565-57147" + } + }, + { + node: { + id: "pv15691", + margin: 1, + name: "auxiliary", + priceOverride: 538.0974149450597, + quantity: 49, + sku: "53060-31227" + } + }, + { + node: { + id: "pv4077", + margin: 15, + name: "Representative", + priceOverride: null, + quantity: 21, + sku: "23136-18988" + } + }, + { + node: { + id: "pv44826", + margin: 12, + name: "Licensed Cotton Chair", + priceOverride: 6457.168979340716, + quantity: 2, + sku: "2124-66425" + } + }, + { + node: { + id: "pv46723", + margin: 13, + name: "evolve", + priceOverride: null, + quantity: 30, + sku: "73188-73743" + } + }, + { + node: { + id: "pv34683", + margin: 12, + name: "Generic", + priceOverride: null, + quantity: 45, + sku: "98860-41086" + } + }, + { + node: { + id: "pv83082", + margin: 15, + name: "copying", + priceOverride: null, + quantity: 39, + sku: "1132-39166" + } + }, + { + node: { + id: "pv4635", + margin: 2, + name: "Ville", + priceOverride: null, + quantity: 18, + sku: "38968-44206" + } + } + ] + } + }, + { + attributes: [ + { + attribute: { + id: "pta66889", + name: "Compatible", + slug: "Compatible", + sortOrder: 0, + values: [ + { + id: "ptav34671", + name: "Minnesota", + slug: "Minnesota", + sortOrder: 0 + }, + { + id: "ptav83835", + name: "networks", + slug: "networks", + sortOrder: 1 + }, + { + id: "ptav25230", + name: "Generic Frozen Bike", + slug: "Generic-Frozen-Bike", + sortOrder: 2 + }, + { + id: "ptav76000", + name: "withdrawal", + slug: "withdrawal", + sortOrder: 3 + } + ] + }, + value: { + id: "ptav83835", + name: "networks", + slug: "networks", + sortOrder: 1 + } + }, + { + attribute: { + id: "pta85893", + name: "program", + slug: "program", + sortOrder: 1, + values: [ + { id: "ptav70505", name: "Avon", slug: "Avon", sortOrder: 0 }, + { id: "ptav49968", name: "Analyst", slug: "Analyst", sortOrder: 1 }, + { + id: "ptav43009", + name: "Computer", + slug: "Computer", + sortOrder: 2 + }, + { + id: "ptav29188", + name: "composite", + slug: "composite", + sortOrder: 3 + }, + { + id: "ptav95526", + name: "Norwegian Krone", + slug: "Norwegian-Krone", + sortOrder: 4 + } + ] + }, + value: { id: "ptav70505", name: "Avon", slug: "Avon", sortOrder: 0 } + } + ], + basePrice: { amount: 56.90596710694962, currency: "CVE" }, + category: { id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + collections: { + edges: [{ node: { id: "Q29sbGVjdGlvbjoy", name: "Winter sale" } }] + }, + description: + "Sed tempore autem voluptas voluptas aut sit et. Molestiae rem quo cupiditate consectetur. Dolorum quidem exercitationem sed placeat explicabo adipisci culpa. Sunt et soluta dolor sit nihil incidunt est. Nisi expedita ipsam ducimus quibusdam sed aspernatur. Atque voluptas perferendis ut soluta. Voluptatem aliquid ex quis alias molestiae in voluptatum. Aut ut sapiente tenetur asperiores et voluptatem assumenda.", + id: "p63346", + images: { + edges: [ + { + node: { + id: "UHJvZHVjdEltYWdlOjE=", + image: placeholderImage, + sortOrder: 0, + url: placeholderImage + } + } + ] + }, + isAvailable: false, + isFeatured: false, + isPublished: false, + margin: { start: 0, stop: 4 }, + name: "Fantastic Cotton Tuna", + productType: { hasVariants: true, id: "pt41677", name: "TCP" }, + publicationDate: null, + purchaseCost: { + start: { amount: 56.90596710694962, currency: "CVE" }, + stop: { amount: 227.62386842779847, currency: "CVE" } + }, + seoDescription: + "Sed tempore autem voluptas voluptas aut sit et. Molestiae rem quo cupiditate consectetur", + seoTitle: "Fantastic Cotton Tuna", + sku: "63913-27946", + thumbnail: { __typename: "Image", url: placeholderImage }, + variants: { + edges: [ + { + node: { + id: "pv79408", + margin: 4, + name: "Multi-tiered", + priceOverride: 227.62386842779847, + quantity: 9, + sku: "28000-61818" + } + }, + { + node: { + id: "pv64466", + margin: 4, + name: "Solutions", + priceOverride: null, + quantity: 22, + sku: "57287-58162" + } + }, + { + node: { + id: "pv33325", + margin: 0, + name: "zero administration", + priceOverride: 0, + quantity: 31, + sku: "45268-79894" + } + }, + { + node: { + id: "pv1168", + margin: 2, + name: "world-class", + priceOverride: null, + quantity: 24, + sku: "43680-57669" + } + } + ] + } + }, + { + attributes: [ + { + attribute: { + id: "pta3756", + name: "directional", + slug: "directional", + sortOrder: 0, + values: [ + { id: "ptav98940", name: "silver", slug: "silver", sortOrder: 0 }, + { + id: "ptav67536", + name: "navigate", + slug: "navigate", + sortOrder: 1 + }, + { + id: "ptav58905", + name: "structure", + slug: "structure", + sortOrder: 2 + }, + { id: "ptav25008", name: "mobile", slug: "mobile", sortOrder: 3 } + ] + }, + value: { id: "ptav98940", name: "silver", slug: "silver", sortOrder: 0 } + } + ], + basePrice: { amount: 981.0598640464501, currency: "XAG" }, + category: { id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + collections: { + edges: [{ node: { id: "Q29sbGVjdGlvbjoy", name: "Winter sale" } }] + }, + description: + "Voluptatem veniam aut rerum. Illum veniam asperiores ut et iusto enim vel sapiente quia. Numquam non et aliquid dolores qui quis non assumenda at. Aut magni iusto qui nihil neque suscipit dolore incidunt. Debitis id sunt. Eius eum et quia nobis molestias placeat reprehenderit. Qui consequatur deserunt dolor quos quasi numquam quibusdam non. Nihil numquam vel eveniet.", + id: "p67185", + images: { + edges: [ + { + node: { + id: "UHJvZHVjdEltYWdlOjE=", + image: placeholderImage, + sortOrder: 0, + url: placeholderImage + } + } + ] + }, + isAvailable: false, + isFeatured: false, + isPublished: true, + margin: { start: 0, stop: 18 }, + name: "Tasty Steel Pants", + productType: { hasVariants: true, id: "pt93233", name: "Buckinghamshire" }, + publicationDate: null, + purchaseCost: { + start: { amount: 981.0598640464501, currency: "XAG" }, + stop: { amount: 16678.017688789652, currency: "XAG" } + }, + seoDescription: + "Voluptatem veniam aut rerum. Illum veniam asperiores ut et iusto enim vel sapiente quia", + seoTitle: "Tasty Steel Pants", + sku: "4110-47925", + thumbnail: { __typename: "Image", url: placeholderImage }, + variants: { + edges: [ + { + node: { + id: "pv34567", + margin: 0, + name: "value-added", + priceOverride: 0, + quantity: 38, + sku: "53179-25529" + } + }, + { + node: { + id: "pv47783", + margin: 17, + name: "Internal", + priceOverride: 16678.017688789652, + quantity: 4, + sku: "8483-38189" + } + }, + { + node: { + id: "pv63369", + margin: 0, + name: "connecting", + priceOverride: 0, + quantity: 41, + sku: "44970-77755" + } + }, + { + node: { + id: "pv62179", + margin: 18, + name: "Oklahoma", + priceOverride: null, + quantity: 42, + sku: "66847-73235" + } + }, + { + node: { + id: "pv4122", + margin: 11, + name: "open-source", + priceOverride: 10791.658504510951, + quantity: 19, + sku: "62633-56792" + } + }, + { + node: { + id: "pv50156", + margin: 7, + name: "Wisconsin", + priceOverride: 6867.4190483251505, + quantity: 32, + sku: "49819-59437" + } + }, + { + node: { + id: "pv7095", + margin: 10, + name: "Somali Shilling", + priceOverride: null, + quantity: 22, + sku: "37034-79128" + } + } + ] + } + }, + { + attributes: [ + { + attribute: { + id: "pta93061", + name: "Cotton", + slug: "Cotton", + sortOrder: 0, + values: [ + { id: "ptav30744", name: "USB", slug: "USB", sortOrder: 0 }, + { + id: "ptav64622", + name: "Developer", + slug: "Developer", + sortOrder: 1 + }, + { id: "ptav26323", name: "Squares", slug: "Squares", sortOrder: 2 }, + { id: "ptav91686", name: "Group", slug: "Group", sortOrder: 3 }, + { + id: "ptav95456", + name: "out-of-the-box", + slug: "out-of-the-box", + sortOrder: 4 + } + ] + }, + value: { + id: "ptav64622", + name: "Developer", + slug: "Developer", + sortOrder: 1 + } + }, + { + attribute: { + id: "pta58822", + name: "Shore", + slug: "Shore", + sortOrder: 1, + values: [ + { id: "ptav38761", name: "RSS", slug: "RSS", sortOrder: 0 }, + { id: "ptav9858", name: "Metal", slug: "Metal", sortOrder: 1 }, + { id: "ptav84091", name: "JBOD", slug: "JBOD", sortOrder: 2 } + ] + }, + value: { id: "ptav84091", name: "JBOD", slug: "JBOD", sortOrder: 2 } + }, + { + attribute: { + id: "pta33738", + name: "Communications", + slug: "Communications", + sortOrder: 2, + values: [ + { id: "ptav75637", name: "uniform", slug: "uniform", sortOrder: 0 }, + { + id: "ptav65428", + name: "Administrator", + slug: "Administrator", + sortOrder: 1 + } + ] + }, + value: { + id: "ptav75637", + name: "uniform", + slug: "uniform", + sortOrder: 0 + } + }, + { + attribute: { + id: "pta46618", + name: "Credit Card Account", + slug: "Credit-Card-Account", + sortOrder: 3, + values: [ + { + id: "ptav2397", + name: "Intranet", + slug: "Intranet", + sortOrder: 0 + }, + { id: "ptav77181", name: "orchid", slug: "orchid", sortOrder: 1 }, + { + id: "ptav29222", + name: "Sleek Concrete Keyboard", + slug: "Sleek-Concrete-Keyboard", + sortOrder: 2 + }, + { id: "ptav10489", name: "24/365", slug: "24365", sortOrder: 3 } + ] + }, + value: { id: "ptav77181", name: "orchid", slug: "orchid", sortOrder: 1 } + } + ], + basePrice: { amount: 449.93166054829857, currency: "WST" }, + category: { id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + collections: { + edges: [{ node: { id: "Q29sbGVjdGlvbjoy", name: "Winter sale" } }] + }, + description: + "Sapiente qui error. Placeat hic nulla repudiandae delectus et. Est aut veniam vitae dolor et aut ut. Eligendi sit maxime dolorem fuga porro quo. Culpa aut possimus voluptatibus. Illum tenetur reprehenderit. Nihil dolor repudiandae natus et consectetur error. Aut qui sint in reprehenderit voluptate et sed ratione.", + id: "p8161", + images: { + edges: [ + { + node: { + id: "UHJvZHVjdEltYWdlOjE=", + image: placeholderImage, + sortOrder: 0, + url: placeholderImage + } + } + ] + }, + isAvailable: true, + isFeatured: false, + isPublished: true, + margin: { start: 0, stop: 11 }, + name: "Ergonomic Cotton Shoes", + productType: { hasVariants: true, id: "pt53386", name: "Jewelery" }, + publicationDate: null, + purchaseCost: { + start: { amount: 449.93166054829857, currency: "WST" }, + stop: { amount: 4949.248266031284, currency: "WST" } + }, + seoDescription: + "Sapiente qui error. Placeat hic nulla repudiandae delectus et", + seoTitle: "Ergonomic Cotton Shoes", + sku: "9207-4523", + thumbnail: { __typename: "Image", url: placeholderImage }, + variants: { + edges: [ + { + node: { + id: "pv45430", + margin: 2, + name: "maximize", + priceOverride: null, + quantity: 7, + sku: "43154-53177" + } + }, + { + node: { + id: "pv65956", + margin: 0, + name: "Engineer", + priceOverride: null, + quantity: 11, + sku: "67562-61106" + } + }, + { + node: { + id: "pv64710", + margin: 11, + name: "navigate", + priceOverride: null, + quantity: 41, + sku: "27307-67723" + } + }, + { + node: { + id: "pv2452", + margin: 11, + name: "Bedfordshire", + priceOverride: 4949.248266031284, + quantity: 37, + sku: "65824-26057" + } + }, + { + node: { + id: "pv69865", + margin: 10, + name: "Money Market Account", + priceOverride: 4499.316605482985, + quantity: 40, + sku: "94712-89379" + } + }, + { + node: { + id: "pv98755", + margin: 4, + name: "Home", + priceOverride: null, + quantity: 14, + sku: "89314-44273" + } + } + ] + } + }, + { + attributes: [ + { + attribute: { + id: "pta1842", + name: "Small", + slug: "Small", + sortOrder: 0, + values: [ + { + id: "ptav67439", + name: "Function-based", + slug: "Function-based", + sortOrder: 0 + }, + { + id: "ptav66687", + name: "Savings Account", + slug: "Savings-Account", + sortOrder: 1 + } + ] + }, + value: { + id: "ptav66687", + name: "Savings Account", + slug: "Savings-Account", + sortOrder: 1 + } + } + ], + basePrice: { amount: 590.5928694420302, currency: "MGA" }, + category: { id: "Q2F0ZWdvcnk6MQ==", name: "Apparel" }, + collections: { + edges: [{ node: { id: "Q29sbGVjdGlvbjoy", name: "Winter sale" } }] + }, + description: + "Id ut molestiae. Rerum ut aliquid quas consectetur minima eos. Eum assumenda voluptas dolores perferendis. Accusantium unde sit velit aliquam sed rerum voluptas corrupti. Deleniti dolorem ullam qui dolorem voluptatum suscipit qui nihil voluptatibus. Ipsum iusto et sed tempora est voluptas quis voluptatum aliquid. Ab et ipsum facilis qui asperiores numquam. Sunt suscipit provident quam vero accusantium facilis.", + id: "p34578", + images: { + edges: [ + { + node: { + id: "UHJvZHVjdEltYWdlOjE=", + image: placeholderImage, + sortOrder: 0, + url: placeholderImage + } + } + ] + }, + isAvailable: false, + isFeatured: false, + isPublished: true, + margin: { start: 4, stop: 17 }, + name: "Unbranded Steel Tuna", + productType: { hasVariants: true, id: "pt48315", name: "Agent" }, + publicationDate: null, + purchaseCost: { + start: { amount: 590.5928694420302, currency: "MGA" }, + stop: { amount: 590.5928694420302, currency: "MGA" } + }, + seoDescription: "adipisci laboriosam autem vel soluta", + seoTitle: "Unbranded Steel Tuna", + sku: "84653-71539", + thumbnail: { __typename: "Image", url: placeholderImage }, + variants: { + edges: [ + { + node: { + id: "pv60683", + margin: 17, + name: "solid state", + priceOverride: null, + quantity: 27, + sku: "95378-52353" + } + }, + { + node: { + id: "pv52655", + margin: 4, + name: "Officer", + priceOverride: null, + quantity: 26, + sku: "75748-57597" + } + }, + { + node: { + id: "pv6216", + margin: 6, + name: "Trace", + priceOverride: null, + quantity: 12, + sku: "84820-87762" + } + }, + { + node: { + id: "pv89371", + margin: 4, + name: "deposit", + priceOverride: null, + quantity: 14, + sku: "72976-95755" + } + }, + { + node: { + id: "pv38613", + margin: 9, + name: "primary", + priceOverride: null, + quantity: 8, + sku: "85693-86731" + } + } + ] + } + } +]; +export const variant = (placeholderImage: string): ProductVariant => ({ + __typename: "ProductVariant", + attributes: [ + { + __typename: "SelectedAttribute", + attribute: { + __typename: "Attribute", + id: "pta18161", + name: "Borders", + slug: "Borders", + values: [ + { + __typename: "AttributeValue", + id: "ptav47282", + name: "portals", + slug: "portals" + }, + { + __typename: "AttributeValue", + id: "ptav17253", + name: "Baht", + slug: "Baht" + } + ] + }, + value: { + __typename: "AttributeValue", + id: "ptav47282", + name: "portals", + slug: "portals" + } + }, + { + __typename: "SelectedAttribute", + attribute: { + __typename: "Attribute", + id: "pta22785", + name: "Legacy", + slug: "Legacy", + values: [ + { + __typename: "AttributeValue", + id: "ptav31282", + name: "payment", + slug: "payment" + }, + { + __typename: "AttributeValue", + id: "ptav14907", + name: "Auto Loan Account", + slug: "Auto-Loan-Account" + }, + { + __typename: "AttributeValue", + id: "ptav27366", + name: "Garden", + slug: "Garden" + }, + { + __typename: "AttributeValue", + id: "ptav11873", + name: "override", + slug: "override" + } + ] + }, + value: { + __typename: "AttributeValue", + id: "ptav14907", + name: "Auto Loan Account", + slug: "Auto-Loan-Account" + } + } + ], + costPrice: { + __typename: "Money", + amount: 12, + currency: "USD" + }, + id: "var1", + images: [ + { + __typename: "ProductImage", + id: "img1", + url: placeholderImage + }, + { + __typename: "ProductImage", + id: "img2", + url: placeholderImage + }, + { + __typename: "ProductImage", + id: "img7", + url: placeholderImage + }, + { + __typename: "ProductImage", + id: "img8", + url: placeholderImage + } + ], + name: "Extended Hard", + priceOverride: { + __typename: "Money", + amount: 100, + currency: "USD" + }, + product: { + __typename: "Product", + id: "prod1", + images: [ + { + __typename: "ProductImage", + alt: "Front", + id: "img1", + sortOrder: 1, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Back", + id: "img2", + sortOrder: 4, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Right side", + id: "img3", + sortOrder: 2, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Left side", + id: "img4", + sortOrder: 3, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Paper", + id: "img5", + sortOrder: 0, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Hard cover", + id: "img6", + sortOrder: 1, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Extended version", + id: "img7", + sortOrder: 0, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Cut version", + id: "img8", + sortOrder: 2, + url: placeholderImage + }, + { + __typename: "ProductImage", + alt: "Soft cover", + id: "img9", + sortOrder: 2, + url: placeholderImage + } + ], + name: "Our Awesome Book", + thumbnail: { __typename: "Image", url: placeholderImage }, + variants: [ + { + __typename: "ProductVariant", + id: "var1", + images: [ + { + __typename: "ProductImage", + id: "23123", + url: placeholderImage + } + ], + name: "Extended Hard", + sku: "13-1337" + }, + { + __typename: "ProductVariant", + id: "var2", + images: [ + { + __typename: "ProductImage", + id: "23123", + url: placeholderImage + } + ], + name: "Extended Soft", + sku: "13-1338" + }, + { + __typename: "ProductVariant", + id: "var3", + images: [ + { + __typename: "ProductImage", + id: "23123", + url: placeholderImage + } + ], + name: "Normal Hard", + sku: "13-1339" + }, + { + __typename: "ProductVariant", + id: "var4", + images: [ + { + __typename: "ProductImage", + id: "23123", + url: placeholderImage + } + ], + name: "Normal Soft", + sku: "13-1340" + } + ] + }, + quantity: 19, + quantityAllocated: 12, + sku: "1230959124123" +}); +export const variantImages = (placeholderImage: string) => + variant(placeholderImage).images; +export const variantProductImages = (placeholderImage: string) => + variant(placeholderImage).product.images; +export const variantSiblings = (placeholderImage: string) => + variant(placeholderImage).product.variants; diff --git a/src/products/index.tsx b/src/products/index.tsx new file mode 100644 index 000000000..d5023e58f --- /dev/null +++ b/src/products/index.tsx @@ -0,0 +1,113 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { WindowTitle } from "../components/WindowTitle"; +import i18n from "../i18n"; +import { + productAddPath, + productImagePath, + ProductImageUrlQueryParams, + productListPath, + ProductListUrlQueryParams, + productPath, + ProductUrlQueryParams, + productVariantAddPath, + productVariantEditPath, + ProductVariantEditUrlQueryParams +} from "./urls"; +import ProductCreate from "./views/ProductCreate"; +import ProductImageComponent from "./views/ProductImage"; +import ProductListComponent from "./views/ProductList"; +import ProductUpdateComponent from "./views/ProductUpdate"; +import ProductVariantComponent from "./views/ProductVariant"; +import ProductVariantCreateComponent from "./views/ProductVariantCreate"; + +const ProductList: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: ProductListUrlQueryParams = qs; + return ; +}; + +const ProductUpdate: React.StatelessComponent> = ({ + match +}) => { + const qs = parseQs(location.search.substr(1)); + const params: ProductUrlQueryParams = qs; + + return ( + + ); +}; + +const ProductVariant: React.StatelessComponent> = ({ + match +}) => { + const qs = parseQs(location.search.substr(1)); + const params: ProductVariantEditUrlQueryParams = qs; + + return ( + + ); +}; + +const ProductImage: React.StatelessComponent> = ({ + location, + match +}) => { + const qs = parseQs(location.search.substr(1)); + const params: ProductImageUrlQueryParams = qs; + + return ( + + ); +}; + +const ProductVariantCreate: React.StatelessComponent< + RouteComponentProps +> = ({ match }) => { + return ( + + ); +}; + +const Component = () => ( + <> + + + + + + + + + + +); + +export default Component; diff --git a/src/products/mutations.ts b/src/products/mutations.ts new file mode 100644 index 000000000..b8845d331 --- /dev/null +++ b/src/products/mutations.ts @@ -0,0 +1,468 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { ProductCreate, ProductCreateVariables } from "./types/ProductCreate"; +import { ProductDelete, ProductDeleteVariables } from "./types/ProductDelete"; +import { + ProductImageCreate, + ProductImageCreateVariables +} from "./types/ProductImageCreate"; +import { + ProductImageDelete, + ProductImageDeleteVariables +} from "./types/ProductImageDelete"; +import { + ProductImageReorder, + ProductImageReorderVariables +} from "./types/ProductImageReorder"; +import { + ProductImageUpdate, + ProductImageUpdateVariables +} from "./types/ProductImageUpdate"; +import { ProductUpdate, ProductUpdateVariables } from "./types/ProductUpdate"; +import { + SimpleProductUpdate, + SimpleProductUpdateVariables +} from "./types/SimpleProductUpdate"; +import { VariantCreate, VariantCreateVariables } from "./types/VariantCreate"; +import { VariantDelete, VariantDeleteVariables } from "./types/VariantDelete"; +import { + VariantImageAssign, + VariantImageAssignVariables +} from "./types/VariantImageAssign"; +import { + VariantImageUnassign, + VariantImageUnassignVariables +} from "./types/VariantImageUnassign"; +import { VariantUpdate, VariantUpdateVariables } from "./types/VariantUpdate"; + +import { fragmentVariant, productFragmentDetails } from "./queries"; +import { + productBulkDelete, + productBulkDeleteVariables +} from "./types/productBulkDelete"; +import { + productBulkPublish, + productBulkPublishVariables +} from "./types/productBulkPublish"; +import { + ProductVariantBulkDelete, + ProductVariantBulkDeleteVariables +} from "./types/ProductVariantBulkDelete"; + +export const productImageCreateMutation = gql` + ${productFragmentDetails} + mutation ProductImageCreate($product: ID!, $image: Upload!, $alt: String) { + productImageCreate(input: { alt: $alt, image: $image, product: $product }) { + errors { + field + message + } + product { + ...Product + } + } + } +`; +export const TypedProductImageCreateMutation = TypedMutation< + ProductImageCreate, + ProductImageCreateVariables +>(productImageCreateMutation); + +export const productDeleteMutation = gql` + mutation ProductDelete($id: ID!) { + productDelete(id: $id) { + errors { + field + message + } + product { + id + } + } + } +`; +export const TypedProductDeleteMutation = TypedMutation< + ProductDelete, + ProductDeleteVariables +>(productDeleteMutation); + +export const productImagesReorder = gql` + mutation ProductImageReorder($productId: ID!, $imagesIds: [ID]!) { + productImageReorder(productId: $productId, imagesIds: $imagesIds) { + errors { + field + message + } + product { + id + images { + id + alt + sortOrder + url + } + } + } + } +`; +export const TypedProductImagesReorder = TypedMutation< + ProductImageReorder, + ProductImageReorderVariables +>(productImagesReorder); + +export const productUpdateMutation = gql` + ${productFragmentDetails} + mutation ProductUpdate( + $id: ID! + $attributes: [AttributeValueInput] + $publicationDate: Date + $category: ID + $chargeTaxes: Boolean! + $collections: [ID] + $descriptionJson: JSONString + $isPublished: Boolean! + $name: String + $basePrice: Decimal + ) { + productUpdate( + id: $id + input: { + attributes: $attributes + publicationDate: $publicationDate + category: $category + chargeTaxes: $chargeTaxes + collections: $collections + descriptionJson: $descriptionJson + isPublished: $isPublished + name: $name + basePrice: $basePrice + } + ) { + errors { + field + message + } + product { + ...Product + } + } + } +`; +export const TypedProductUpdateMutation = TypedMutation< + ProductUpdate, + ProductUpdateVariables +>(productUpdateMutation); + +export const simpleProductUpdateMutation = gql` + ${productFragmentDetails} + ${fragmentVariant} + mutation SimpleProductUpdate( + $id: ID! + $attributes: [AttributeValueInput] + $publicationDate: Date + $category: ID + $chargeTaxes: Boolean! + $collections: [ID] + $descriptionJson: JSONString + $isPublished: Boolean! + $name: String + $basePrice: Decimal + $productVariantId: ID! + $productVariantInput: ProductVariantInput! + ) { + productUpdate( + id: $id + input: { + attributes: $attributes + publicationDate: $publicationDate + category: $category + chargeTaxes: $chargeTaxes + collections: $collections + descriptionJson: $descriptionJson + isPublished: $isPublished + name: $name + basePrice: $basePrice + } + ) { + errors { + field + message + } + product { + ...Product + } + } + productVariantUpdate(id: $productVariantId, input: $productVariantInput) { + errors { + field + message + } + productVariant { + ...ProductVariant + } + } + } +`; +export const TypedSimpleProductUpdateMutation = TypedMutation< + SimpleProductUpdate, + SimpleProductUpdateVariables +>(simpleProductUpdateMutation); + +export const productCreateMutation = gql` + ${productFragmentDetails} + mutation ProductCreate( + $attributes: [AttributeValueInput] + $publicationDate: Date + $category: ID! + $chargeTaxes: Boolean! + $collections: [ID] + $descriptionJson: JSONString + $isPublished: Boolean! + $name: String! + $basePrice: Decimal + $productType: ID! + $sku: String + $stockQuantity: Int + ) { + productCreate( + input: { + attributes: $attributes + publicationDate: $publicationDate + category: $category + chargeTaxes: $chargeTaxes + collections: $collections + descriptionJson: $descriptionJson + isPublished: $isPublished + name: $name + basePrice: $basePrice + productType: $productType + sku: $sku + quantity: $stockQuantity + } + ) { + errors { + field + message + } + product { + ...Product + } + } + } +`; +export const TypedProductCreateMutation = TypedMutation< + ProductCreate, + ProductCreateVariables +>(productCreateMutation); + +export const variantDeleteMutation = gql` + mutation VariantDelete($id: ID!) { + productVariantDelete(id: $id) { + errors { + field + message + } + productVariant { + id + } + } + } +`; +export const TypedVariantDeleteMutation = TypedMutation< + VariantDelete, + VariantDeleteVariables +>(variantDeleteMutation); + +export const variantUpdateMutation = gql` + ${fragmentVariant} + mutation VariantUpdate( + $id: ID! + $attributes: [AttributeValueInput] + $costPrice: Decimal + $priceOverride: Decimal + $sku: String + $quantity: Int + $trackInventory: Boolean! + ) { + productVariantUpdate( + id: $id + input: { + attributes: $attributes + costPrice: $costPrice + priceOverride: $priceOverride + sku: $sku + quantity: $quantity + trackInventory: $trackInventory + } + ) { + errors { + field + message + } + productVariant { + ...ProductVariant + } + } + } +`; +export const TypedVariantUpdateMutation = TypedMutation< + VariantUpdate, + VariantUpdateVariables +>(variantUpdateMutation); + +export const variantCreateMutation = gql` + ${fragmentVariant} + mutation VariantCreate( + $attributes: [AttributeValueInput]! + $costPrice: Decimal + $priceOverride: Decimal + $product: ID! + $sku: String + $quantity: Int + $trackInventory: Boolean! + ) { + productVariantCreate( + input: { + attributes: $attributes + costPrice: $costPrice + priceOverride: $priceOverride + product: $product + sku: $sku + quantity: $quantity + trackInventory: $trackInventory + } + ) { + errors { + field + message + } + productVariant { + ...ProductVariant + } + } + } +`; +export const TypedVariantCreateMutation = TypedMutation< + VariantCreate, + VariantCreateVariables +>(variantCreateMutation); + +export const productImageDeleteMutation = gql` + mutation ProductImageDelete($id: ID!) { + productImageDelete(id: $id) { + product { + id + images { + id + } + } + } + } +`; +export const TypedProductImageDeleteMutation = TypedMutation< + ProductImageDelete, + ProductImageDeleteVariables +>(productImageDeleteMutation); + +export const productImageUpdateMutation = gql` + ${productFragmentDetails} + mutation ProductImageUpdate($id: ID!, $alt: String!) { + productImageUpdate(id: $id, input: { alt: $alt }) { + errors { + field + message + } + product { + ...Product + } + } + } +`; +export const TypedProductImageUpdateMutation = TypedMutation< + ProductImageUpdate, + ProductImageUpdateVariables +>(productImageUpdateMutation); + +export const variantImageAssignMutation = gql` + ${fragmentVariant} + mutation VariantImageAssign($variantId: ID!, $imageId: ID!) { + variantImageAssign(variantId: $variantId, imageId: $imageId) { + errors { + field + message + } + productVariant { + ...ProductVariant + } + } + } +`; +export const TypedVariantImageAssignMutation = TypedMutation< + VariantImageAssign, + VariantImageAssignVariables +>(variantImageAssignMutation); + +export const variantImageUnassignMutation = gql` + ${fragmentVariant} + mutation VariantImageUnassign($variantId: ID!, $imageId: ID!) { + variantImageUnassign(variantId: $variantId, imageId: $imageId) { + errors { + field + message + } + productVariant { + ...ProductVariant + } + } + } +`; +export const TypedVariantImageUnassignMutation = TypedMutation< + VariantImageUnassign, + VariantImageUnassignVariables +>(variantImageUnassignMutation); + +export const productBulkDeleteMutation = gql` + mutation productBulkDelete($ids: [ID!]!) { + productBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedProductBulkDeleteMutation = TypedMutation< + productBulkDelete, + productBulkDeleteVariables +>(productBulkDeleteMutation); + +export const productBulkPublishMutation = gql` + mutation productBulkPublish($ids: [ID!]!, $isPublished: Boolean!) { + productBulkPublish(ids: $ids, isPublished: $isPublished) { + errors { + field + message + } + } + } +`; +export const TypedProductBulkPublishMutation = TypedMutation< + productBulkPublish, + productBulkPublishVariables +>(productBulkPublishMutation); + +export const ProductVariantBulkDeleteMutation = gql` + mutation ProductVariantBulkDelete($ids: [ID!]!) { + productVariantBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedProductVariantBulkDeleteMutation = TypedMutation< + ProductVariantBulkDelete, + ProductVariantBulkDeleteVariables +>(ProductVariantBulkDeleteMutation); diff --git a/src/products/queries.ts b/src/products/queries.ts new file mode 100644 index 000000000..84c3c345d --- /dev/null +++ b/src/products/queries.ts @@ -0,0 +1,358 @@ +import gql from "graphql-tag"; + +import { TypedQuery } from "../queries"; +import { ProductCreateData } from "./types/ProductCreateData"; +import { + ProductDetails, + ProductDetailsVariables +} from "./types/ProductDetails"; +import { + ProductImageById, + ProductImageByIdVariables +} from "./types/ProductImageById"; +import { ProductList, ProductListVariables } from "./types/ProductList"; +import { + ProductVariantCreateData, + ProductVariantCreateDataVariables +} from "./types/ProductVariantCreateData"; +import { + ProductVariantDetails, + ProductVariantDetailsVariables +} from "./types/ProductVariantDetails"; + +export const fragmentMoney = gql` + fragment Money on Money { + amount + currency + } +`; + +export const fragmentProductImage = gql` + fragment ProductImageFragment on ProductImage { + id + alt + sortOrder + url + } +`; + +export const productFragment = gql` + ${fragmentMoney} + fragment ProductFragment on Product { + id + name + thumbnail { + url + } + isAvailable + basePrice { + ...Money + } + productType { + id + name + } + } +`; +export const productFragmentDetails = gql` + ${fragmentProductImage} + ${fragmentMoney} + fragment Product on Product { + id + name + descriptionJson + seoTitle + seoDescription + category { + id + name + } + collections { + id + name + } + basePrice { + ...Money + } + margin { + start + stop + } + purchaseCost { + start { + ...Money + } + stop { + ...Money + } + } + isAvailable + isPublished + chargeTaxes + publicationDate + attributes { + attribute { + id + slug + name + values { + name + slug + } + } + value { + id + name + slug + } + } + pricing { + priceRange { + start { + net { + ...Money + } + } + stop { + net { + ...Money + } + } + } + } + images { + ...ProductImageFragment + } + variants { + id + sku + name + priceOverride { + ...Money + } + margin + quantity + quantityAllocated + stockQuantity + } + productType { + id + name + hasVariants + } + url + } +`; + +export const fragmentVariant = gql` + ${fragmentMoney} + ${fragmentProductImage} + fragment ProductVariant on ProductVariant { + id + attributes { + attribute { + id + name + slug + values { + id + name + slug + } + } + value { + id + name + slug + } + } + costPrice { + ...Money + } + images { + id + url + } + name + priceOverride { + ...Money + } + product { + id + images { + ...ProductImageFragment + } + name + thumbnail { + url + } + variants { + id + name + sku + images { + id + url + } + } + } + sku + quantity + quantityAllocated + } +`; + +const productListQuery = gql` + ${productFragment} + query ProductList( + $first: Int + $after: String + $last: Int + $before: String + $filter: ProductFilterInput + ) { + products( + before: $before + after: $after + first: $first + last: $last + filter: $filter + ) { + edges { + node { + ...ProductFragment + } + } + pageInfo { + hasPreviousPage + hasNextPage + startCursor + endCursor + } + } + } +`; +export const TypedProductListQuery = TypedQuery< + ProductList, + ProductListVariables +>(productListQuery); + +const productDetailsQuery = gql` + ${productFragmentDetails} + query ProductDetails($id: ID!) { + product(id: $id) { + ...Product + } + } +`; +export const TypedProductDetailsQuery = TypedQuery< + ProductDetails, + ProductDetailsVariables +>(productDetailsQuery); + +const productVariantQuery = gql` + ${fragmentVariant} + query ProductVariantDetails($id: ID!) { + productVariant(id: $id) { + ...ProductVariant + } + } +`; +export const TypedProductVariantQuery = TypedQuery< + ProductVariantDetails, + ProductVariantDetailsVariables +>(productVariantQuery); + +const productCreateQuery = gql` + query ProductCreateData { + productTypes(first: 20) { + edges { + node { + id + name + hasVariants + productAttributes { + id + slug + name + values { + id + sortOrder + name + slug + } + } + } + } + } + } +`; +export const TypedProductCreateQuery = TypedQuery( + productCreateQuery +); + +const productVariantCreateQuery = gql` + query ProductVariantCreateData($id: ID!) { + product(id: $id) { + id + images { + id + sortOrder + url + } + name + productType { + id + variantAttributes { + id + slug + name + values { + id + sortOrder + name + slug + } + } + } + thumbnail { + url + } + variants { + id + name + sku + images { + id + url + } + } + } + } +`; +export const TypedProductVariantCreateQuery = TypedQuery< + ProductVariantCreateData, + ProductVariantCreateDataVariables +>(productVariantCreateQuery); + +const productImageQuery = gql` + query ProductImageById($productId: ID!, $imageId: ID!) { + product(id: $productId) { + id + name + mainImage: imageById(id: $imageId) { + id + alt + url + } + images { + id + url(size: 48) + } + } + } +`; +export const TypedProductImageQuery = TypedQuery< + ProductImageById, + ProductImageByIdVariables +>(productImageQuery); diff --git a/src/products/types/Money.ts b/src/products/types/Money.ts new file mode 100644 index 000000000..f48f8fa9d --- /dev/null +++ b/src/products/types/Money.ts @@ -0,0 +1,13 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: Money +// ==================================================== + +export interface Money { + __typename: "Money"; + amount: number; + currency: string; +} diff --git a/src/products/types/Product.ts b/src/products/types/Product.ts new file mode 100644 index 000000000..2396b200b --- /dev/null +++ b/src/products/types/Product.ts @@ -0,0 +1,166 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: Product +// ==================================================== + +export interface Product_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface Product_collections { + __typename: "Collection"; + id: string; + name: string; +} + +export interface Product_basePrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface Product_margin { + __typename: "Margin"; + start: number | null; + stop: number | null; +} + +export interface Product_purchaseCost_start { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface Product_purchaseCost_stop { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface Product_purchaseCost { + __typename: "MoneyRange"; + start: Product_purchaseCost_start | null; + stop: Product_purchaseCost_stop | null; +} + +export interface Product_attributes_attribute_values { + __typename: "AttributeValue"; + name: string | null; + slug: string | null; +} + +export interface Product_attributes_attribute { + __typename: "Attribute"; + id: string; + slug: string | null; + name: string | null; + values: (Product_attributes_attribute_values | null)[] | null; +} + +export interface Product_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface Product_attributes { + __typename: "SelectedAttribute"; + attribute: Product_attributes_attribute; + value: Product_attributes_value; +} + +export interface Product_pricing_priceRange_start_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface Product_pricing_priceRange_start { + __typename: "TaxedMoney"; + net: Product_pricing_priceRange_start_net; +} + +export interface Product_pricing_priceRange_stop_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface Product_pricing_priceRange_stop { + __typename: "TaxedMoney"; + net: Product_pricing_priceRange_stop_net; +} + +export interface Product_pricing_priceRange { + __typename: "TaxedMoneyRange"; + start: Product_pricing_priceRange_start | null; + stop: Product_pricing_priceRange_stop | null; +} + +export interface Product_pricing { + __typename: "ProductPricingInfo"; + priceRange: Product_pricing_priceRange | null; +} + +export interface Product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface Product_variants_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface Product_variants { + __typename: "ProductVariant"; + id: string; + sku: string; + name: string; + priceOverride: Product_variants_priceOverride | null; + margin: number | null; + quantity: number; + quantityAllocated: number; + stockQuantity: number; +} + +export interface Product_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; +} + +export interface Product { + __typename: "Product"; + id: string; + name: string; + descriptionJson: any; + seoTitle: string | null; + seoDescription: string | null; + category: Product_category; + collections: (Product_collections | null)[] | null; + basePrice: Product_basePrice | null; + margin: Product_margin | null; + purchaseCost: Product_purchaseCost | null; + isAvailable: boolean | null; + isPublished: boolean; + chargeTaxes: boolean; + publicationDate: any | null; + attributes: Product_attributes[]; + pricing: Product_pricing | null; + images: (Product_images | null)[] | null; + variants: (Product_variants | null)[] | null; + productType: Product_productType; + url: string; +} diff --git a/src/products/types/ProductCreate.ts b/src/products/types/ProductCreate.ts new file mode 100644 index 000000000..2ea047957 --- /dev/null +++ b/src/products/types/ProductCreate.ts @@ -0,0 +1,199 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AttributeValueInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: ProductCreate +// ==================================================== + +export interface ProductCreate_productCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ProductCreate_productCreate_product_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface ProductCreate_productCreate_product_collections { + __typename: "Collection"; + id: string; + name: string; +} + +export interface ProductCreate_productCreate_product_basePrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductCreate_productCreate_product_margin { + __typename: "Margin"; + start: number | null; + stop: number | null; +} + +export interface ProductCreate_productCreate_product_purchaseCost_start { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductCreate_productCreate_product_purchaseCost_stop { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductCreate_productCreate_product_purchaseCost { + __typename: "MoneyRange"; + start: ProductCreate_productCreate_product_purchaseCost_start | null; + stop: ProductCreate_productCreate_product_purchaseCost_stop | null; +} + +export interface ProductCreate_productCreate_product_attributes_attribute_values { + __typename: "AttributeValue"; + name: string | null; + slug: string | null; +} + +export interface ProductCreate_productCreate_product_attributes_attribute { + __typename: "Attribute"; + id: string; + slug: string | null; + name: string | null; + values: (ProductCreate_productCreate_product_attributes_attribute_values | null)[] | null; +} + +export interface ProductCreate_productCreate_product_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductCreate_productCreate_product_attributes { + __typename: "SelectedAttribute"; + attribute: ProductCreate_productCreate_product_attributes_attribute; + value: ProductCreate_productCreate_product_attributes_value; +} + +export interface ProductCreate_productCreate_product_pricing_priceRange_start_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductCreate_productCreate_product_pricing_priceRange_start { + __typename: "TaxedMoney"; + net: ProductCreate_productCreate_product_pricing_priceRange_start_net; +} + +export interface ProductCreate_productCreate_product_pricing_priceRange_stop_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductCreate_productCreate_product_pricing_priceRange_stop { + __typename: "TaxedMoney"; + net: ProductCreate_productCreate_product_pricing_priceRange_stop_net; +} + +export interface ProductCreate_productCreate_product_pricing_priceRange { + __typename: "TaxedMoneyRange"; + start: ProductCreate_productCreate_product_pricing_priceRange_start | null; + stop: ProductCreate_productCreate_product_pricing_priceRange_stop | null; +} + +export interface ProductCreate_productCreate_product_pricing { + __typename: "ProductPricingInfo"; + priceRange: ProductCreate_productCreate_product_pricing_priceRange | null; +} + +export interface ProductCreate_productCreate_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface ProductCreate_productCreate_product_variants_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductCreate_productCreate_product_variants { + __typename: "ProductVariant"; + id: string; + sku: string; + name: string; + priceOverride: ProductCreate_productCreate_product_variants_priceOverride | null; + margin: number | null; + quantity: number; + quantityAllocated: number; + stockQuantity: number; +} + +export interface ProductCreate_productCreate_product_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; +} + +export interface ProductCreate_productCreate_product { + __typename: "Product"; + id: string; + name: string; + descriptionJson: any; + seoTitle: string | null; + seoDescription: string | null; + category: ProductCreate_productCreate_product_category; + collections: (ProductCreate_productCreate_product_collections | null)[] | null; + basePrice: ProductCreate_productCreate_product_basePrice | null; + margin: ProductCreate_productCreate_product_margin | null; + purchaseCost: ProductCreate_productCreate_product_purchaseCost | null; + isAvailable: boolean | null; + isPublished: boolean; + chargeTaxes: boolean; + publicationDate: any | null; + attributes: ProductCreate_productCreate_product_attributes[]; + pricing: ProductCreate_productCreate_product_pricing | null; + images: (ProductCreate_productCreate_product_images | null)[] | null; + variants: (ProductCreate_productCreate_product_variants | null)[] | null; + productType: ProductCreate_productCreate_product_productType; + url: string; +} + +export interface ProductCreate_productCreate { + __typename: "ProductCreate"; + errors: ProductCreate_productCreate_errors[] | null; + product: ProductCreate_productCreate_product | null; +} + +export interface ProductCreate { + productCreate: ProductCreate_productCreate | null; +} + +export interface ProductCreateVariables { + attributes?: (AttributeValueInput | null)[] | null; + publicationDate?: any | null; + category: string; + chargeTaxes: boolean; + collections?: (string | null)[] | null; + descriptionJson?: any | null; + isPublished: boolean; + name: string; + basePrice?: any | null; + productType: string; + sku?: string | null; + stockQuantity?: number | null; +} diff --git a/src/products/types/ProductCreateData.ts b/src/products/types/ProductCreateData.ts new file mode 100644 index 000000000..a19865341 --- /dev/null +++ b/src/products/types/ProductCreateData.ts @@ -0,0 +1,45 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: ProductCreateData +// ==================================================== + +export interface ProductCreateData_productTypes_edges_node_productAttributes_values { + __typename: "AttributeValue"; + id: string; + sortOrder: number | null; + name: string | null; + slug: string | null; +} + +export interface ProductCreateData_productTypes_edges_node_productAttributes { + __typename: "Attribute"; + id: string; + slug: string | null; + name: string | null; + values: (ProductCreateData_productTypes_edges_node_productAttributes_values | null)[] | null; +} + +export interface ProductCreateData_productTypes_edges_node { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; + productAttributes: (ProductCreateData_productTypes_edges_node_productAttributes | null)[] | null; +} + +export interface ProductCreateData_productTypes_edges { + __typename: "ProductTypeCountableEdge"; + node: ProductCreateData_productTypes_edges_node; +} + +export interface ProductCreateData_productTypes { + __typename: "ProductTypeCountableConnection"; + edges: ProductCreateData_productTypes_edges[]; +} + +export interface ProductCreateData { + productTypes: ProductCreateData_productTypes | null; +} diff --git a/src/products/types/ProductDelete.ts b/src/products/types/ProductDelete.ts new file mode 100644 index 000000000..d5efb26f1 --- /dev/null +++ b/src/products/types/ProductDelete.ts @@ -0,0 +1,32 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: ProductDelete +// ==================================================== + +export interface ProductDelete_productDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ProductDelete_productDelete_product { + __typename: "Product"; + id: string; +} + +export interface ProductDelete_productDelete { + __typename: "ProductDelete"; + errors: ProductDelete_productDelete_errors[] | null; + product: ProductDelete_productDelete_product | null; +} + +export interface ProductDelete { + productDelete: ProductDelete_productDelete | null; +} + +export interface ProductDeleteVariables { + id: string; +} diff --git a/src/products/types/ProductDetails.ts b/src/products/types/ProductDetails.ts new file mode 100644 index 000000000..4e0326d16 --- /dev/null +++ b/src/products/types/ProductDetails.ts @@ -0,0 +1,174 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: ProductDetails +// ==================================================== + +export interface ProductDetails_product_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface ProductDetails_product_collections { + __typename: "Collection"; + id: string; + name: string; +} + +export interface ProductDetails_product_basePrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductDetails_product_margin { + __typename: "Margin"; + start: number | null; + stop: number | null; +} + +export interface ProductDetails_product_purchaseCost_start { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductDetails_product_purchaseCost_stop { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductDetails_product_purchaseCost { + __typename: "MoneyRange"; + start: ProductDetails_product_purchaseCost_start | null; + stop: ProductDetails_product_purchaseCost_stop | null; +} + +export interface ProductDetails_product_attributes_attribute_values { + __typename: "AttributeValue"; + name: string | null; + slug: string | null; +} + +export interface ProductDetails_product_attributes_attribute { + __typename: "Attribute"; + id: string; + slug: string | null; + name: string | null; + values: (ProductDetails_product_attributes_attribute_values | null)[] | null; +} + +export interface ProductDetails_product_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductDetails_product_attributes { + __typename: "SelectedAttribute"; + attribute: ProductDetails_product_attributes_attribute; + value: ProductDetails_product_attributes_value; +} + +export interface ProductDetails_product_pricing_priceRange_start_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductDetails_product_pricing_priceRange_start { + __typename: "TaxedMoney"; + net: ProductDetails_product_pricing_priceRange_start_net; +} + +export interface ProductDetails_product_pricing_priceRange_stop_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductDetails_product_pricing_priceRange_stop { + __typename: "TaxedMoney"; + net: ProductDetails_product_pricing_priceRange_stop_net; +} + +export interface ProductDetails_product_pricing_priceRange { + __typename: "TaxedMoneyRange"; + start: ProductDetails_product_pricing_priceRange_start | null; + stop: ProductDetails_product_pricing_priceRange_stop | null; +} + +export interface ProductDetails_product_pricing { + __typename: "ProductPricingInfo"; + priceRange: ProductDetails_product_pricing_priceRange | null; +} + +export interface ProductDetails_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface ProductDetails_product_variants_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductDetails_product_variants { + __typename: "ProductVariant"; + id: string; + sku: string; + name: string; + priceOverride: ProductDetails_product_variants_priceOverride | null; + margin: number | null; + quantity: number; + quantityAllocated: number; + stockQuantity: number; +} + +export interface ProductDetails_product_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; +} + +export interface ProductDetails_product { + __typename: "Product"; + id: string; + name: string; + descriptionJson: any; + seoTitle: string | null; + seoDescription: string | null; + category: ProductDetails_product_category; + collections: (ProductDetails_product_collections | null)[] | null; + basePrice: ProductDetails_product_basePrice | null; + margin: ProductDetails_product_margin | null; + purchaseCost: ProductDetails_product_purchaseCost | null; + isAvailable: boolean | null; + isPublished: boolean; + chargeTaxes: boolean; + publicationDate: any | null; + attributes: ProductDetails_product_attributes[]; + pricing: ProductDetails_product_pricing | null; + images: (ProductDetails_product_images | null)[] | null; + variants: (ProductDetails_product_variants | null)[] | null; + productType: ProductDetails_product_productType; + url: string; +} + +export interface ProductDetails { + product: ProductDetails_product | null; +} + +export interface ProductDetailsVariables { + id: string; +} diff --git a/src/products/types/ProductFragment.ts b/src/products/types/ProductFragment.ts new file mode 100644 index 000000000..7187a9791 --- /dev/null +++ b/src/products/types/ProductFragment.ts @@ -0,0 +1,34 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: ProductFragment +// ==================================================== + +export interface ProductFragment_thumbnail { + __typename: "Image"; + url: string; +} + +export interface ProductFragment_basePrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductFragment_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface ProductFragment { + __typename: "Product"; + id: string; + name: string; + thumbnail: ProductFragment_thumbnail | null; + isAvailable: boolean | null; + basePrice: ProductFragment_basePrice | null; + productType: ProductFragment_productType; +} diff --git a/src/products/types/ProductImage.ts b/src/products/types/ProductImage.ts new file mode 100644 index 000000000..8a5b981af --- /dev/null +++ b/src/products/types/ProductImage.ts @@ -0,0 +1,14 @@ +/* tslint:disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: ProductImage +// ==================================================== + +export interface ProductImage { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number; + url: string; +} diff --git a/src/products/types/ProductImageById.ts b/src/products/types/ProductImageById.ts new file mode 100644 index 000000000..d5fc6ef97 --- /dev/null +++ b/src/products/types/ProductImageById.ts @@ -0,0 +1,37 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: ProductImageById +// ==================================================== + +export interface ProductImageById_product_mainImage { + __typename: "ProductImage"; + id: string; + alt: string; + url: string; +} + +export interface ProductImageById_product_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface ProductImageById_product { + __typename: "Product"; + id: string; + name: string; + mainImage: ProductImageById_product_mainImage | null; + images: (ProductImageById_product_images | null)[] | null; +} + +export interface ProductImageById { + product: ProductImageById_product | null; +} + +export interface ProductImageByIdVariables { + productId: string; + imageId: string; +} diff --git a/src/products/types/ProductImageCreate.ts b/src/products/types/ProductImageCreate.ts new file mode 100644 index 000000000..1e4baa729 --- /dev/null +++ b/src/products/types/ProductImageCreate.ts @@ -0,0 +1,188 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: ProductImageCreate +// ==================================================== + +export interface ProductImageCreate_productImageCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ProductImageCreate_productImageCreate_product_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface ProductImageCreate_productImageCreate_product_collections { + __typename: "Collection"; + id: string; + name: string; +} + +export interface ProductImageCreate_productImageCreate_product_basePrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageCreate_productImageCreate_product_margin { + __typename: "Margin"; + start: number | null; + stop: number | null; +} + +export interface ProductImageCreate_productImageCreate_product_purchaseCost_start { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageCreate_productImageCreate_product_purchaseCost_stop { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageCreate_productImageCreate_product_purchaseCost { + __typename: "MoneyRange"; + start: ProductImageCreate_productImageCreate_product_purchaseCost_start | null; + stop: ProductImageCreate_productImageCreate_product_purchaseCost_stop | null; +} + +export interface ProductImageCreate_productImageCreate_product_attributes_attribute_values { + __typename: "AttributeValue"; + name: string | null; + slug: string | null; +} + +export interface ProductImageCreate_productImageCreate_product_attributes_attribute { + __typename: "Attribute"; + id: string; + slug: string | null; + name: string | null; + values: (ProductImageCreate_productImageCreate_product_attributes_attribute_values | null)[] | null; +} + +export interface ProductImageCreate_productImageCreate_product_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductImageCreate_productImageCreate_product_attributes { + __typename: "SelectedAttribute"; + attribute: ProductImageCreate_productImageCreate_product_attributes_attribute; + value: ProductImageCreate_productImageCreate_product_attributes_value; +} + +export interface ProductImageCreate_productImageCreate_product_pricing_priceRange_start_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageCreate_productImageCreate_product_pricing_priceRange_start { + __typename: "TaxedMoney"; + net: ProductImageCreate_productImageCreate_product_pricing_priceRange_start_net; +} + +export interface ProductImageCreate_productImageCreate_product_pricing_priceRange_stop_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageCreate_productImageCreate_product_pricing_priceRange_stop { + __typename: "TaxedMoney"; + net: ProductImageCreate_productImageCreate_product_pricing_priceRange_stop_net; +} + +export interface ProductImageCreate_productImageCreate_product_pricing_priceRange { + __typename: "TaxedMoneyRange"; + start: ProductImageCreate_productImageCreate_product_pricing_priceRange_start | null; + stop: ProductImageCreate_productImageCreate_product_pricing_priceRange_stop | null; +} + +export interface ProductImageCreate_productImageCreate_product_pricing { + __typename: "ProductPricingInfo"; + priceRange: ProductImageCreate_productImageCreate_product_pricing_priceRange | null; +} + +export interface ProductImageCreate_productImageCreate_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface ProductImageCreate_productImageCreate_product_variants_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageCreate_productImageCreate_product_variants { + __typename: "ProductVariant"; + id: string; + sku: string; + name: string; + priceOverride: ProductImageCreate_productImageCreate_product_variants_priceOverride | null; + margin: number | null; + quantity: number; + quantityAllocated: number; + stockQuantity: number; +} + +export interface ProductImageCreate_productImageCreate_product_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; +} + +export interface ProductImageCreate_productImageCreate_product { + __typename: "Product"; + id: string; + name: string; + descriptionJson: any; + seoTitle: string | null; + seoDescription: string | null; + category: ProductImageCreate_productImageCreate_product_category; + collections: (ProductImageCreate_productImageCreate_product_collections | null)[] | null; + basePrice: ProductImageCreate_productImageCreate_product_basePrice | null; + margin: ProductImageCreate_productImageCreate_product_margin | null; + purchaseCost: ProductImageCreate_productImageCreate_product_purchaseCost | null; + isAvailable: boolean | null; + isPublished: boolean; + chargeTaxes: boolean; + publicationDate: any | null; + attributes: ProductImageCreate_productImageCreate_product_attributes[]; + pricing: ProductImageCreate_productImageCreate_product_pricing | null; + images: (ProductImageCreate_productImageCreate_product_images | null)[] | null; + variants: (ProductImageCreate_productImageCreate_product_variants | null)[] | null; + productType: ProductImageCreate_productImageCreate_product_productType; + url: string; +} + +export interface ProductImageCreate_productImageCreate { + __typename: "ProductImageCreate"; + errors: ProductImageCreate_productImageCreate_errors[] | null; + product: ProductImageCreate_productImageCreate_product | null; +} + +export interface ProductImageCreate { + productImageCreate: ProductImageCreate_productImageCreate | null; +} + +export interface ProductImageCreateVariables { + product: string; + image: any; + alt?: string | null; +} diff --git a/src/products/types/ProductImageDelete.ts b/src/products/types/ProductImageDelete.ts new file mode 100644 index 000000000..4d55c57a8 --- /dev/null +++ b/src/products/types/ProductImageDelete.ts @@ -0,0 +1,31 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: ProductImageDelete +// ==================================================== + +export interface ProductImageDelete_productImageDelete_product_images { + __typename: "ProductImage"; + id: string; +} + +export interface ProductImageDelete_productImageDelete_product { + __typename: "Product"; + id: string; + images: (ProductImageDelete_productImageDelete_product_images | null)[] | null; +} + +export interface ProductImageDelete_productImageDelete { + __typename: "ProductImageDelete"; + product: ProductImageDelete_productImageDelete_product | null; +} + +export interface ProductImageDelete { + productImageDelete: ProductImageDelete_productImageDelete | null; +} + +export interface ProductImageDeleteVariables { + id: string; +} diff --git a/src/products/types/ProductImageFragment.ts b/src/products/types/ProductImageFragment.ts new file mode 100644 index 000000000..de4e5b5ca --- /dev/null +++ b/src/products/types/ProductImageFragment.ts @@ -0,0 +1,15 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: ProductImageFragment +// ==================================================== + +export interface ProductImageFragment { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} diff --git a/src/products/types/ProductImageReorder.ts b/src/products/types/ProductImageReorder.ts new file mode 100644 index 000000000..4e5960389 --- /dev/null +++ b/src/products/types/ProductImageReorder.ts @@ -0,0 +1,42 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: ProductImageReorder +// ==================================================== + +export interface ProductImageReorder_productImageReorder_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ProductImageReorder_productImageReorder_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface ProductImageReorder_productImageReorder_product { + __typename: "Product"; + id: string; + images: (ProductImageReorder_productImageReorder_product_images | null)[] | null; +} + +export interface ProductImageReorder_productImageReorder { + __typename: "ProductImageReorder"; + errors: ProductImageReorder_productImageReorder_errors[] | null; + product: ProductImageReorder_productImageReorder_product | null; +} + +export interface ProductImageReorder { + productImageReorder: ProductImageReorder_productImageReorder | null; +} + +export interface ProductImageReorderVariables { + productId: string; + imagesIds: (string | null)[]; +} diff --git a/src/products/types/ProductImageUpdate.ts b/src/products/types/ProductImageUpdate.ts new file mode 100644 index 000000000..bd2a9d178 --- /dev/null +++ b/src/products/types/ProductImageUpdate.ts @@ -0,0 +1,187 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: ProductImageUpdate +// ==================================================== + +export interface ProductImageUpdate_productImageUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ProductImageUpdate_productImageUpdate_product_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_collections { + __typename: "Collection"; + id: string; + name: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_basePrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_margin { + __typename: "Margin"; + start: number | null; + stop: number | null; +} + +export interface ProductImageUpdate_productImageUpdate_product_purchaseCost_start { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_purchaseCost_stop { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_purchaseCost { + __typename: "MoneyRange"; + start: ProductImageUpdate_productImageUpdate_product_purchaseCost_start | null; + stop: ProductImageUpdate_productImageUpdate_product_purchaseCost_stop | null; +} + +export interface ProductImageUpdate_productImageUpdate_product_attributes_attribute_values { + __typename: "AttributeValue"; + name: string | null; + slug: string | null; +} + +export interface ProductImageUpdate_productImageUpdate_product_attributes_attribute { + __typename: "Attribute"; + id: string; + slug: string | null; + name: string | null; + values: (ProductImageUpdate_productImageUpdate_product_attributes_attribute_values | null)[] | null; +} + +export interface ProductImageUpdate_productImageUpdate_product_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductImageUpdate_productImageUpdate_product_attributes { + __typename: "SelectedAttribute"; + attribute: ProductImageUpdate_productImageUpdate_product_attributes_attribute; + value: ProductImageUpdate_productImageUpdate_product_attributes_value; +} + +export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRange_start_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRange_start { + __typename: "TaxedMoney"; + net: ProductImageUpdate_productImageUpdate_product_pricing_priceRange_start_net; +} + +export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRange_stop_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRange_stop { + __typename: "TaxedMoney"; + net: ProductImageUpdate_productImageUpdate_product_pricing_priceRange_stop_net; +} + +export interface ProductImageUpdate_productImageUpdate_product_pricing_priceRange { + __typename: "TaxedMoneyRange"; + start: ProductImageUpdate_productImageUpdate_product_pricing_priceRange_start | null; + stop: ProductImageUpdate_productImageUpdate_product_pricing_priceRange_stop | null; +} + +export interface ProductImageUpdate_productImageUpdate_product_pricing { + __typename: "ProductPricingInfo"; + priceRange: ProductImageUpdate_productImageUpdate_product_pricing_priceRange | null; +} + +export interface ProductImageUpdate_productImageUpdate_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_variants_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductImageUpdate_productImageUpdate_product_variants { + __typename: "ProductVariant"; + id: string; + sku: string; + name: string; + priceOverride: ProductImageUpdate_productImageUpdate_product_variants_priceOverride | null; + margin: number | null; + quantity: number; + quantityAllocated: number; + stockQuantity: number; +} + +export interface ProductImageUpdate_productImageUpdate_product_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; +} + +export interface ProductImageUpdate_productImageUpdate_product { + __typename: "Product"; + id: string; + name: string; + descriptionJson: any; + seoTitle: string | null; + seoDescription: string | null; + category: ProductImageUpdate_productImageUpdate_product_category; + collections: (ProductImageUpdate_productImageUpdate_product_collections | null)[] | null; + basePrice: ProductImageUpdate_productImageUpdate_product_basePrice | null; + margin: ProductImageUpdate_productImageUpdate_product_margin | null; + purchaseCost: ProductImageUpdate_productImageUpdate_product_purchaseCost | null; + isAvailable: boolean | null; + isPublished: boolean; + chargeTaxes: boolean; + publicationDate: any | null; + attributes: ProductImageUpdate_productImageUpdate_product_attributes[]; + pricing: ProductImageUpdate_productImageUpdate_product_pricing | null; + images: (ProductImageUpdate_productImageUpdate_product_images | null)[] | null; + variants: (ProductImageUpdate_productImageUpdate_product_variants | null)[] | null; + productType: ProductImageUpdate_productImageUpdate_product_productType; + url: string; +} + +export interface ProductImageUpdate_productImageUpdate { + __typename: "ProductImageUpdate"; + errors: ProductImageUpdate_productImageUpdate_errors[] | null; + product: ProductImageUpdate_productImageUpdate_product | null; +} + +export interface ProductImageUpdate { + productImageUpdate: ProductImageUpdate_productImageUpdate | null; +} + +export interface ProductImageUpdateVariables { + id: string; + alt: string; +} diff --git a/src/products/types/ProductList.ts b/src/products/types/ProductList.ts new file mode 100644 index 000000000..075889875 --- /dev/null +++ b/src/products/types/ProductList.ts @@ -0,0 +1,67 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ProductFilterInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: ProductList +// ==================================================== + +export interface ProductList_products_edges_node_thumbnail { + __typename: "Image"; + url: string; +} + +export interface ProductList_products_edges_node_basePrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductList_products_edges_node_productType { + __typename: "ProductType"; + id: string; + name: string; +} + +export interface ProductList_products_edges_node { + __typename: "Product"; + id: string; + name: string; + thumbnail: ProductList_products_edges_node_thumbnail | null; + isAvailable: boolean | null; + basePrice: ProductList_products_edges_node_basePrice | null; + productType: ProductList_products_edges_node_productType; +} + +export interface ProductList_products_edges { + __typename: "ProductCountableEdge"; + node: ProductList_products_edges_node; +} + +export interface ProductList_products_pageInfo { + __typename: "PageInfo"; + hasPreviousPage: boolean; + hasNextPage: boolean; + startCursor: string | null; + endCursor: string | null; +} + +export interface ProductList_products { + __typename: "ProductCountableConnection"; + edges: ProductList_products_edges[]; + pageInfo: ProductList_products_pageInfo; +} + +export interface ProductList { + products: ProductList_products | null; +} + +export interface ProductListVariables { + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; + filter?: ProductFilterInput | null; +} diff --git a/src/products/types/ProductUpdate.ts b/src/products/types/ProductUpdate.ts new file mode 100644 index 000000000..0b8795836 --- /dev/null +++ b/src/products/types/ProductUpdate.ts @@ -0,0 +1,197 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AttributeValueInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: ProductUpdate +// ==================================================== + +export interface ProductUpdate_productUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ProductUpdate_productUpdate_product_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface ProductUpdate_productUpdate_product_collections { + __typename: "Collection"; + id: string; + name: string; +} + +export interface ProductUpdate_productUpdate_product_basePrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductUpdate_productUpdate_product_margin { + __typename: "Margin"; + start: number | null; + stop: number | null; +} + +export interface ProductUpdate_productUpdate_product_purchaseCost_start { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductUpdate_productUpdate_product_purchaseCost_stop { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductUpdate_productUpdate_product_purchaseCost { + __typename: "MoneyRange"; + start: ProductUpdate_productUpdate_product_purchaseCost_start | null; + stop: ProductUpdate_productUpdate_product_purchaseCost_stop | null; +} + +export interface ProductUpdate_productUpdate_product_attributes_attribute_values { + __typename: "AttributeValue"; + name: string | null; + slug: string | null; +} + +export interface ProductUpdate_productUpdate_product_attributes_attribute { + __typename: "Attribute"; + id: string; + slug: string | null; + name: string | null; + values: (ProductUpdate_productUpdate_product_attributes_attribute_values | null)[] | null; +} + +export interface ProductUpdate_productUpdate_product_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductUpdate_productUpdate_product_attributes { + __typename: "SelectedAttribute"; + attribute: ProductUpdate_productUpdate_product_attributes_attribute; + value: ProductUpdate_productUpdate_product_attributes_value; +} + +export interface ProductUpdate_productUpdate_product_pricing_priceRange_start_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductUpdate_productUpdate_product_pricing_priceRange_start { + __typename: "TaxedMoney"; + net: ProductUpdate_productUpdate_product_pricing_priceRange_start_net; +} + +export interface ProductUpdate_productUpdate_product_pricing_priceRange_stop_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductUpdate_productUpdate_product_pricing_priceRange_stop { + __typename: "TaxedMoney"; + net: ProductUpdate_productUpdate_product_pricing_priceRange_stop_net; +} + +export interface ProductUpdate_productUpdate_product_pricing_priceRange { + __typename: "TaxedMoneyRange"; + start: ProductUpdate_productUpdate_product_pricing_priceRange_start | null; + stop: ProductUpdate_productUpdate_product_pricing_priceRange_stop | null; +} + +export interface ProductUpdate_productUpdate_product_pricing { + __typename: "ProductPricingInfo"; + priceRange: ProductUpdate_productUpdate_product_pricing_priceRange | null; +} + +export interface ProductUpdate_productUpdate_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface ProductUpdate_productUpdate_product_variants_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductUpdate_productUpdate_product_variants { + __typename: "ProductVariant"; + id: string; + sku: string; + name: string; + priceOverride: ProductUpdate_productUpdate_product_variants_priceOverride | null; + margin: number | null; + quantity: number; + quantityAllocated: number; + stockQuantity: number; +} + +export interface ProductUpdate_productUpdate_product_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; +} + +export interface ProductUpdate_productUpdate_product { + __typename: "Product"; + id: string; + name: string; + descriptionJson: any; + seoTitle: string | null; + seoDescription: string | null; + category: ProductUpdate_productUpdate_product_category; + collections: (ProductUpdate_productUpdate_product_collections | null)[] | null; + basePrice: ProductUpdate_productUpdate_product_basePrice | null; + margin: ProductUpdate_productUpdate_product_margin | null; + purchaseCost: ProductUpdate_productUpdate_product_purchaseCost | null; + isAvailable: boolean | null; + isPublished: boolean; + chargeTaxes: boolean; + publicationDate: any | null; + attributes: ProductUpdate_productUpdate_product_attributes[]; + pricing: ProductUpdate_productUpdate_product_pricing | null; + images: (ProductUpdate_productUpdate_product_images | null)[] | null; + variants: (ProductUpdate_productUpdate_product_variants | null)[] | null; + productType: ProductUpdate_productUpdate_product_productType; + url: string; +} + +export interface ProductUpdate_productUpdate { + __typename: "ProductUpdate"; + errors: ProductUpdate_productUpdate_errors[] | null; + product: ProductUpdate_productUpdate_product | null; +} + +export interface ProductUpdate { + productUpdate: ProductUpdate_productUpdate | null; +} + +export interface ProductUpdateVariables { + id: string; + attributes?: (AttributeValueInput | null)[] | null; + publicationDate?: any | null; + category?: string | null; + chargeTaxes: boolean; + collections?: (string | null)[] | null; + descriptionJson?: any | null; + isPublished: boolean; + name?: string | null; + basePrice?: any | null; +} diff --git a/src/products/types/ProductVariant.ts b/src/products/types/ProductVariant.ts new file mode 100644 index 000000000..86239a599 --- /dev/null +++ b/src/products/types/ProductVariant.ts @@ -0,0 +1,103 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: ProductVariant +// ==================================================== + +export interface ProductVariant_attributes_attribute_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductVariant_attributes_attribute { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (ProductVariant_attributes_attribute_values | null)[] | null; +} + +export interface ProductVariant_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductVariant_attributes { + __typename: "SelectedAttribute"; + attribute: ProductVariant_attributes_attribute; + value: ProductVariant_attributes_value; +} + +export interface ProductVariant_costPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductVariant_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface ProductVariant_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductVariant_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface ProductVariant_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface ProductVariant_product_variants_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface ProductVariant_product_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + images: (ProductVariant_product_variants_images | null)[] | null; +} + +export interface ProductVariant_product { + __typename: "Product"; + id: string; + images: (ProductVariant_product_images | null)[] | null; + name: string; + thumbnail: ProductVariant_product_thumbnail | null; + variants: (ProductVariant_product_variants | null)[] | null; +} + +export interface ProductVariant { + __typename: "ProductVariant"; + id: string; + attributes: ProductVariant_attributes[]; + costPrice: ProductVariant_costPrice | null; + images: (ProductVariant_images | null)[] | null; + name: string; + priceOverride: ProductVariant_priceOverride | null; + product: ProductVariant_product; + sku: string; + quantity: number; + quantityAllocated: number; +} diff --git a/src/products/types/ProductVariantBulkDelete.ts b/src/products/types/ProductVariantBulkDelete.ts new file mode 100644 index 000000000..d77fb6ca3 --- /dev/null +++ b/src/products/types/ProductVariantBulkDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: ProductVariantBulkDelete +// ==================================================== + +export interface ProductVariantBulkDelete_productVariantBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ProductVariantBulkDelete_productVariantBulkDelete { + __typename: "ProductVariantBulkDelete"; + errors: ProductVariantBulkDelete_productVariantBulkDelete_errors[] | null; +} + +export interface ProductVariantBulkDelete { + productVariantBulkDelete: ProductVariantBulkDelete_productVariantBulkDelete | null; +} + +export interface ProductVariantBulkDeleteVariables { + ids: string[]; +} diff --git a/src/products/types/ProductVariantCreateData.ts b/src/products/types/ProductVariantCreateData.ts new file mode 100644 index 000000000..956873a6a --- /dev/null +++ b/src/products/types/ProductVariantCreateData.ts @@ -0,0 +1,73 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: ProductVariantCreateData +// ==================================================== + +export interface ProductVariantCreateData_product_images { + __typename: "ProductImage"; + id: string; + sortOrder: number | null; + url: string; +} + +export interface ProductVariantCreateData_product_productType_variantAttributes_values { + __typename: "AttributeValue"; + id: string; + sortOrder: number | null; + name: string | null; + slug: string | null; +} + +export interface ProductVariantCreateData_product_productType_variantAttributes { + __typename: "Attribute"; + id: string; + slug: string | null; + name: string | null; + values: (ProductVariantCreateData_product_productType_variantAttributes_values | null)[] | null; +} + +export interface ProductVariantCreateData_product_productType { + __typename: "ProductType"; + id: string; + variantAttributes: (ProductVariantCreateData_product_productType_variantAttributes | null)[] | null; +} + +export interface ProductVariantCreateData_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface ProductVariantCreateData_product_variants_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface ProductVariantCreateData_product_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + images: (ProductVariantCreateData_product_variants_images | null)[] | null; +} + +export interface ProductVariantCreateData_product { + __typename: "Product"; + id: string; + images: (ProductVariantCreateData_product_images | null)[] | null; + name: string; + productType: ProductVariantCreateData_product_productType; + thumbnail: ProductVariantCreateData_product_thumbnail | null; + variants: (ProductVariantCreateData_product_variants | null)[] | null; +} + +export interface ProductVariantCreateData { + product: ProductVariantCreateData_product | null; +} + +export interface ProductVariantCreateDataVariables { + id: string; +} diff --git a/src/products/types/ProductVariantDetails.ts b/src/products/types/ProductVariantDetails.ts new file mode 100644 index 000000000..d7337cbac --- /dev/null +++ b/src/products/types/ProductVariantDetails.ts @@ -0,0 +1,111 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: ProductVariantDetails +// ==================================================== + +export interface ProductVariantDetails_productVariant_attributes_attribute_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductVariantDetails_productVariant_attributes_attribute { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (ProductVariantDetails_productVariant_attributes_attribute_values | null)[] | null; +} + +export interface ProductVariantDetails_productVariant_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface ProductVariantDetails_productVariant_attributes { + __typename: "SelectedAttribute"; + attribute: ProductVariantDetails_productVariant_attributes_attribute; + value: ProductVariantDetails_productVariant_attributes_value; +} + +export interface ProductVariantDetails_productVariant_costPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductVariantDetails_productVariant_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface ProductVariantDetails_productVariant_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ProductVariantDetails_productVariant_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface ProductVariantDetails_productVariant_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface ProductVariantDetails_productVariant_product_variants_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface ProductVariantDetails_productVariant_product_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + images: (ProductVariantDetails_productVariant_product_variants_images | null)[] | null; +} + +export interface ProductVariantDetails_productVariant_product { + __typename: "Product"; + id: string; + images: (ProductVariantDetails_productVariant_product_images | null)[] | null; + name: string; + thumbnail: ProductVariantDetails_productVariant_product_thumbnail | null; + variants: (ProductVariantDetails_productVariant_product_variants | null)[] | null; +} + +export interface ProductVariantDetails_productVariant { + __typename: "ProductVariant"; + id: string; + attributes: ProductVariantDetails_productVariant_attributes[]; + costPrice: ProductVariantDetails_productVariant_costPrice | null; + images: (ProductVariantDetails_productVariant_images | null)[] | null; + name: string; + priceOverride: ProductVariantDetails_productVariant_priceOverride | null; + product: ProductVariantDetails_productVariant_product; + sku: string; + quantity: number; + quantityAllocated: number; +} + +export interface ProductVariantDetails { + productVariant: ProductVariantDetails_productVariant | null; +} + +export interface ProductVariantDetailsVariables { + id: string; +} diff --git a/src/products/types/SimpleProductUpdate.ts b/src/products/types/SimpleProductUpdate.ts new file mode 100644 index 000000000..66563c9aa --- /dev/null +++ b/src/products/types/SimpleProductUpdate.ts @@ -0,0 +1,308 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AttributeValueInput, ProductVariantInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: SimpleProductUpdate +// ==================================================== + +export interface SimpleProductUpdate_productUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface SimpleProductUpdate_productUpdate_product_category { + __typename: "Category"; + id: string; + name: string; +} + +export interface SimpleProductUpdate_productUpdate_product_collections { + __typename: "Collection"; + id: string; + name: string; +} + +export interface SimpleProductUpdate_productUpdate_product_basePrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productUpdate_product_margin { + __typename: "Margin"; + start: number | null; + stop: number | null; +} + +export interface SimpleProductUpdate_productUpdate_product_purchaseCost_start { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productUpdate_product_purchaseCost_stop { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productUpdate_product_purchaseCost { + __typename: "MoneyRange"; + start: SimpleProductUpdate_productUpdate_product_purchaseCost_start | null; + stop: SimpleProductUpdate_productUpdate_product_purchaseCost_stop | null; +} + +export interface SimpleProductUpdate_productUpdate_product_attributes_attribute_values { + __typename: "AttributeValue"; + name: string | null; + slug: string | null; +} + +export interface SimpleProductUpdate_productUpdate_product_attributes_attribute { + __typename: "Attribute"; + id: string; + slug: string | null; + name: string | null; + values: (SimpleProductUpdate_productUpdate_product_attributes_attribute_values | null)[] | null; +} + +export interface SimpleProductUpdate_productUpdate_product_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface SimpleProductUpdate_productUpdate_product_attributes { + __typename: "SelectedAttribute"; + attribute: SimpleProductUpdate_productUpdate_product_attributes_attribute; + value: SimpleProductUpdate_productUpdate_product_attributes_value; +} + +export interface SimpleProductUpdate_productUpdate_product_pricing_priceRange_start_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productUpdate_product_pricing_priceRange_start { + __typename: "TaxedMoney"; + net: SimpleProductUpdate_productUpdate_product_pricing_priceRange_start_net; +} + +export interface SimpleProductUpdate_productUpdate_product_pricing_priceRange_stop_net { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productUpdate_product_pricing_priceRange_stop { + __typename: "TaxedMoney"; + net: SimpleProductUpdate_productUpdate_product_pricing_priceRange_stop_net; +} + +export interface SimpleProductUpdate_productUpdate_product_pricing_priceRange { + __typename: "TaxedMoneyRange"; + start: SimpleProductUpdate_productUpdate_product_pricing_priceRange_start | null; + stop: SimpleProductUpdate_productUpdate_product_pricing_priceRange_stop | null; +} + +export interface SimpleProductUpdate_productUpdate_product_pricing { + __typename: "ProductPricingInfo"; + priceRange: SimpleProductUpdate_productUpdate_product_pricing_priceRange | null; +} + +export interface SimpleProductUpdate_productUpdate_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface SimpleProductUpdate_productUpdate_product_variants_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productUpdate_product_variants { + __typename: "ProductVariant"; + id: string; + sku: string; + name: string; + priceOverride: SimpleProductUpdate_productUpdate_product_variants_priceOverride | null; + margin: number | null; + quantity: number; + quantityAllocated: number; + stockQuantity: number; +} + +export interface SimpleProductUpdate_productUpdate_product_productType { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; +} + +export interface SimpleProductUpdate_productUpdate_product { + __typename: "Product"; + id: string; + name: string; + descriptionJson: any; + seoTitle: string | null; + seoDescription: string | null; + category: SimpleProductUpdate_productUpdate_product_category; + collections: (SimpleProductUpdate_productUpdate_product_collections | null)[] | null; + basePrice: SimpleProductUpdate_productUpdate_product_basePrice | null; + margin: SimpleProductUpdate_productUpdate_product_margin | null; + purchaseCost: SimpleProductUpdate_productUpdate_product_purchaseCost | null; + isAvailable: boolean | null; + isPublished: boolean; + chargeTaxes: boolean; + publicationDate: any | null; + attributes: SimpleProductUpdate_productUpdate_product_attributes[]; + pricing: SimpleProductUpdate_productUpdate_product_pricing | null; + images: (SimpleProductUpdate_productUpdate_product_images | null)[] | null; + variants: (SimpleProductUpdate_productUpdate_product_variants | null)[] | null; + productType: SimpleProductUpdate_productUpdate_product_productType; + url: string; +} + +export interface SimpleProductUpdate_productUpdate { + __typename: "ProductUpdate"; + errors: SimpleProductUpdate_productUpdate_errors[] | null; + product: SimpleProductUpdate_productUpdate_product | null; +} + +export interface SimpleProductUpdate_productVariantUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_attributes_attribute_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_attributes_attribute { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (SimpleProductUpdate_productVariantUpdate_productVariant_attributes_attribute_values | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_attributes { + __typename: "SelectedAttribute"; + attribute: SimpleProductUpdate_productVariantUpdate_productVariant_attributes_attribute; + value: SimpleProductUpdate_productVariantUpdate_productVariant_attributes_value; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_costPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_product_variants_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_product_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + images: (SimpleProductUpdate_productVariantUpdate_productVariant_product_variants_images | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant_product { + __typename: "Product"; + id: string; + images: (SimpleProductUpdate_productVariantUpdate_productVariant_product_images | null)[] | null; + name: string; + thumbnail: SimpleProductUpdate_productVariantUpdate_productVariant_product_thumbnail | null; + variants: (SimpleProductUpdate_productVariantUpdate_productVariant_product_variants | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantUpdate_productVariant { + __typename: "ProductVariant"; + id: string; + attributes: SimpleProductUpdate_productVariantUpdate_productVariant_attributes[]; + costPrice: SimpleProductUpdate_productVariantUpdate_productVariant_costPrice | null; + images: (SimpleProductUpdate_productVariantUpdate_productVariant_images | null)[] | null; + name: string; + priceOverride: SimpleProductUpdate_productVariantUpdate_productVariant_priceOverride | null; + product: SimpleProductUpdate_productVariantUpdate_productVariant_product; + sku: string; + quantity: number; + quantityAllocated: number; +} + +export interface SimpleProductUpdate_productVariantUpdate { + __typename: "ProductVariantUpdate"; + errors: SimpleProductUpdate_productVariantUpdate_errors[] | null; + productVariant: SimpleProductUpdate_productVariantUpdate_productVariant | null; +} + +export interface SimpleProductUpdate { + productUpdate: SimpleProductUpdate_productUpdate | null; + productVariantUpdate: SimpleProductUpdate_productVariantUpdate | null; +} + +export interface SimpleProductUpdateVariables { + id: string; + attributes?: (AttributeValueInput | null)[] | null; + publicationDate?: any | null; + category?: string | null; + chargeTaxes: boolean; + collections?: (string | null)[] | null; + descriptionJson?: any | null; + isPublished: boolean; + name?: string | null; + basePrice?: any | null; + productVariantId: string; + productVariantInput: ProductVariantInput; +} diff --git a/src/products/types/VariantCreate.ts b/src/products/types/VariantCreate.ts new file mode 100644 index 000000000..3c8d9f64c --- /dev/null +++ b/src/products/types/VariantCreate.ts @@ -0,0 +1,131 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AttributeValueInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: VariantCreate +// ==================================================== + +export interface VariantCreate_productVariantCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface VariantCreate_productVariantCreate_productVariant_attributes_attribute_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface VariantCreate_productVariantCreate_productVariant_attributes_attribute { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (VariantCreate_productVariantCreate_productVariant_attributes_attribute_values | null)[] | null; +} + +export interface VariantCreate_productVariantCreate_productVariant_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface VariantCreate_productVariantCreate_productVariant_attributes { + __typename: "SelectedAttribute"; + attribute: VariantCreate_productVariantCreate_productVariant_attributes_attribute; + value: VariantCreate_productVariantCreate_productVariant_attributes_value; +} + +export interface VariantCreate_productVariantCreate_productVariant_costPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface VariantCreate_productVariantCreate_productVariant_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface VariantCreate_productVariantCreate_productVariant_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface VariantCreate_productVariantCreate_productVariant_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface VariantCreate_productVariantCreate_productVariant_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface VariantCreate_productVariantCreate_productVariant_product_variants_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface VariantCreate_productVariantCreate_productVariant_product_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + images: (VariantCreate_productVariantCreate_productVariant_product_variants_images | null)[] | null; +} + +export interface VariantCreate_productVariantCreate_productVariant_product { + __typename: "Product"; + id: string; + images: (VariantCreate_productVariantCreate_productVariant_product_images | null)[] | null; + name: string; + thumbnail: VariantCreate_productVariantCreate_productVariant_product_thumbnail | null; + variants: (VariantCreate_productVariantCreate_productVariant_product_variants | null)[] | null; +} + +export interface VariantCreate_productVariantCreate_productVariant { + __typename: "ProductVariant"; + id: string; + attributes: VariantCreate_productVariantCreate_productVariant_attributes[]; + costPrice: VariantCreate_productVariantCreate_productVariant_costPrice | null; + images: (VariantCreate_productVariantCreate_productVariant_images | null)[] | null; + name: string; + priceOverride: VariantCreate_productVariantCreate_productVariant_priceOverride | null; + product: VariantCreate_productVariantCreate_productVariant_product; + sku: string; + quantity: number; + quantityAllocated: number; +} + +export interface VariantCreate_productVariantCreate { + __typename: "ProductVariantCreate"; + errors: VariantCreate_productVariantCreate_errors[] | null; + productVariant: VariantCreate_productVariantCreate_productVariant | null; +} + +export interface VariantCreate { + productVariantCreate: VariantCreate_productVariantCreate | null; +} + +export interface VariantCreateVariables { + attributes: (AttributeValueInput | null)[]; + costPrice?: any | null; + priceOverride?: any | null; + product: string; + sku?: string | null; + quantity?: number | null; + trackInventory: boolean; +} diff --git a/src/products/types/VariantDelete.ts b/src/products/types/VariantDelete.ts new file mode 100644 index 000000000..7aceceb21 --- /dev/null +++ b/src/products/types/VariantDelete.ts @@ -0,0 +1,32 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: VariantDelete +// ==================================================== + +export interface VariantDelete_productVariantDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface VariantDelete_productVariantDelete_productVariant { + __typename: "ProductVariant"; + id: string; +} + +export interface VariantDelete_productVariantDelete { + __typename: "ProductVariantDelete"; + errors: VariantDelete_productVariantDelete_errors[] | null; + productVariant: VariantDelete_productVariantDelete_productVariant | null; +} + +export interface VariantDelete { + productVariantDelete: VariantDelete_productVariantDelete | null; +} + +export interface VariantDeleteVariables { + id: string; +} diff --git a/src/products/types/VariantImageAssign.ts b/src/products/types/VariantImageAssign.ts new file mode 100644 index 000000000..dfc6bf05c --- /dev/null +++ b/src/products/types/VariantImageAssign.ts @@ -0,0 +1,124 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: VariantImageAssign +// ==================================================== + +export interface VariantImageAssign_variantImageAssign_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_attributes_attribute_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_attributes_attribute { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (VariantImageAssign_variantImageAssign_productVariant_attributes_attribute_values | null)[] | null; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_attributes { + __typename: "SelectedAttribute"; + attribute: VariantImageAssign_variantImageAssign_productVariant_attributes_attribute; + value: VariantImageAssign_variantImageAssign_productVariant_attributes_value; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_costPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_product_variants_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_product_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + images: (VariantImageAssign_variantImageAssign_productVariant_product_variants_images | null)[] | null; +} + +export interface VariantImageAssign_variantImageAssign_productVariant_product { + __typename: "Product"; + id: string; + images: (VariantImageAssign_variantImageAssign_productVariant_product_images | null)[] | null; + name: string; + thumbnail: VariantImageAssign_variantImageAssign_productVariant_product_thumbnail | null; + variants: (VariantImageAssign_variantImageAssign_productVariant_product_variants | null)[] | null; +} + +export interface VariantImageAssign_variantImageAssign_productVariant { + __typename: "ProductVariant"; + id: string; + attributes: VariantImageAssign_variantImageAssign_productVariant_attributes[]; + costPrice: VariantImageAssign_variantImageAssign_productVariant_costPrice | null; + images: (VariantImageAssign_variantImageAssign_productVariant_images | null)[] | null; + name: string; + priceOverride: VariantImageAssign_variantImageAssign_productVariant_priceOverride | null; + product: VariantImageAssign_variantImageAssign_productVariant_product; + sku: string; + quantity: number; + quantityAllocated: number; +} + +export interface VariantImageAssign_variantImageAssign { + __typename: "VariantImageAssign"; + errors: VariantImageAssign_variantImageAssign_errors[] | null; + productVariant: VariantImageAssign_variantImageAssign_productVariant | null; +} + +export interface VariantImageAssign { + variantImageAssign: VariantImageAssign_variantImageAssign | null; +} + +export interface VariantImageAssignVariables { + variantId: string; + imageId: string; +} diff --git a/src/products/types/VariantImageUnassign.ts b/src/products/types/VariantImageUnassign.ts new file mode 100644 index 000000000..420d03223 --- /dev/null +++ b/src/products/types/VariantImageUnassign.ts @@ -0,0 +1,124 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: VariantImageUnassign +// ==================================================== + +export interface VariantImageUnassign_variantImageUnassign_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_attributes_attribute_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_attributes_attribute { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (VariantImageUnassign_variantImageUnassign_productVariant_attributes_attribute_values | null)[] | null; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_attributes { + __typename: "SelectedAttribute"; + attribute: VariantImageUnassign_variantImageUnassign_productVariant_attributes_attribute; + value: VariantImageUnassign_variantImageUnassign_productVariant_attributes_value; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_costPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_product_variants_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_product_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + images: (VariantImageUnassign_variantImageUnassign_productVariant_product_variants_images | null)[] | null; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant_product { + __typename: "Product"; + id: string; + images: (VariantImageUnassign_variantImageUnassign_productVariant_product_images | null)[] | null; + name: string; + thumbnail: VariantImageUnassign_variantImageUnassign_productVariant_product_thumbnail | null; + variants: (VariantImageUnassign_variantImageUnassign_productVariant_product_variants | null)[] | null; +} + +export interface VariantImageUnassign_variantImageUnassign_productVariant { + __typename: "ProductVariant"; + id: string; + attributes: VariantImageUnassign_variantImageUnassign_productVariant_attributes[]; + costPrice: VariantImageUnassign_variantImageUnassign_productVariant_costPrice | null; + images: (VariantImageUnassign_variantImageUnassign_productVariant_images | null)[] | null; + name: string; + priceOverride: VariantImageUnassign_variantImageUnassign_productVariant_priceOverride | null; + product: VariantImageUnassign_variantImageUnassign_productVariant_product; + sku: string; + quantity: number; + quantityAllocated: number; +} + +export interface VariantImageUnassign_variantImageUnassign { + __typename: "VariantImageUnassign"; + errors: VariantImageUnassign_variantImageUnassign_errors[] | null; + productVariant: VariantImageUnassign_variantImageUnassign_productVariant | null; +} + +export interface VariantImageUnassign { + variantImageUnassign: VariantImageUnassign_variantImageUnassign | null; +} + +export interface VariantImageUnassignVariables { + variantId: string; + imageId: string; +} diff --git a/src/products/types/VariantUpdate.ts b/src/products/types/VariantUpdate.ts new file mode 100644 index 000000000..e979e4edf --- /dev/null +++ b/src/products/types/VariantUpdate.ts @@ -0,0 +1,131 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AttributeValueInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: VariantUpdate +// ==================================================== + +export interface VariantUpdate_productVariantUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_attributes_attribute_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_attributes_attribute { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + values: (VariantUpdate_productVariantUpdate_productVariant_attributes_attribute_values | null)[] | null; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_attributes_value { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_attributes { + __typename: "SelectedAttribute"; + attribute: VariantUpdate_productVariantUpdate_productVariant_attributes_attribute; + value: VariantUpdate_productVariantUpdate_productVariant_attributes_value; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_costPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_product_variants_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_product_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + images: (VariantUpdate_productVariantUpdate_productVariant_product_variants_images | null)[] | null; +} + +export interface VariantUpdate_productVariantUpdate_productVariant_product { + __typename: "Product"; + id: string; + images: (VariantUpdate_productVariantUpdate_productVariant_product_images | null)[] | null; + name: string; + thumbnail: VariantUpdate_productVariantUpdate_productVariant_product_thumbnail | null; + variants: (VariantUpdate_productVariantUpdate_productVariant_product_variants | null)[] | null; +} + +export interface VariantUpdate_productVariantUpdate_productVariant { + __typename: "ProductVariant"; + id: string; + attributes: VariantUpdate_productVariantUpdate_productVariant_attributes[]; + costPrice: VariantUpdate_productVariantUpdate_productVariant_costPrice | null; + images: (VariantUpdate_productVariantUpdate_productVariant_images | null)[] | null; + name: string; + priceOverride: VariantUpdate_productVariantUpdate_productVariant_priceOverride | null; + product: VariantUpdate_productVariantUpdate_productVariant_product; + sku: string; + quantity: number; + quantityAllocated: number; +} + +export interface VariantUpdate_productVariantUpdate { + __typename: "ProductVariantUpdate"; + errors: VariantUpdate_productVariantUpdate_errors[] | null; + productVariant: VariantUpdate_productVariantUpdate_productVariant | null; +} + +export interface VariantUpdate { + productVariantUpdate: VariantUpdate_productVariantUpdate | null; +} + +export interface VariantUpdateVariables { + id: string; + attributes?: (AttributeValueInput | null)[] | null; + costPrice?: any | null; + priceOverride?: any | null; + sku?: string | null; + quantity?: number | null; + trackInventory: boolean; +} diff --git a/src/products/types/productBulkDelete.ts b/src/products/types/productBulkDelete.ts new file mode 100644 index 000000000..51f2e1870 --- /dev/null +++ b/src/products/types/productBulkDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: productBulkDelete +// ==================================================== + +export interface productBulkDelete_productBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface productBulkDelete_productBulkDelete { + __typename: "ProductBulkDelete"; + errors: productBulkDelete_productBulkDelete_errors[] | null; +} + +export interface productBulkDelete { + productBulkDelete: productBulkDelete_productBulkDelete | null; +} + +export interface productBulkDeleteVariables { + ids: string[]; +} diff --git a/src/products/types/productBulkPublish.ts b/src/products/types/productBulkPublish.ts new file mode 100644 index 000000000..2fc358588 --- /dev/null +++ b/src/products/types/productBulkPublish.ts @@ -0,0 +1,27 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: productBulkPublish +// ==================================================== + +export interface productBulkPublish_productBulkPublish_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface productBulkPublish_productBulkPublish { + __typename: "ProductBulkPublish"; + errors: productBulkPublish_productBulkPublish_errors[] | null; +} + +export interface productBulkPublish { + productBulkPublish: productBulkPublish_productBulkPublish | null; +} + +export interface productBulkPublishVariables { + ids: string[]; + isPublished: boolean; +} diff --git a/src/products/urls.ts b/src/products/urls.ts new file mode 100644 index 000000000..7f9fa09ce --- /dev/null +++ b/src/products/urls.ts @@ -0,0 +1,73 @@ +import { stringify as stringifyQs } from "qs"; +import * as urlJoin from "url-join"; + +import { ActiveTab, BulkAction, Dialog, Filters, Pagination } from "../types"; + +const productSection = "/products/"; + +export const productAddPath = urlJoin(productSection, "add"); +export const productAddUrl = productAddPath; + +export const productListPath = productSection; +export type ProductListUrlDialog = + | "publish" + | "unpublish" + | "delete" + | "save-search" + | "delete-search"; +export enum ProductListUrlFiltersEnum { + isPublished = "isPublished", + priceFrom = "priceFrom", + priceTo = "priceTo", + status = "status", + query = "query" +} +export type ProductListUrlFilters = Filters; +export type ProductListUrlQueryParams = BulkAction & + Dialog & + ProductListUrlFilters & + Pagination & + ActiveTab; +export const productListUrl = (params?: ProductListUrlQueryParams): string => + productListPath + "?" + stringifyQs(params); + +export const productPath = (id: string) => urlJoin(productSection + id); +export type ProductUrlDialog = "remove"; +export type ProductUrlQueryParams = BulkAction & + Dialog<"remove" | "remove-variants">; +export const productUrl = (id: string, params?: ProductUrlQueryParams) => + productPath(encodeURIComponent(id)) + "?" + stringifyQs(params); + +export const productVariantEditPath = (productId: string, variantId: string) => + urlJoin(productSection, productId, "variant", variantId); +export type ProductVariantEditUrlDialog = "remove"; +export type ProductVariantEditUrlQueryParams = Dialog<"remove">; +export const productVariantEditUrl = ( + productId: string, + variantId: string, + params?: ProductVariantEditUrlQueryParams +) => + productVariantEditPath( + encodeURIComponent(productId), + encodeURIComponent(variantId) + ) + + "?" + + stringifyQs(params); + +export const productVariantAddPath = (productId: string) => + urlJoin(productSection, productId, "variant/add"); +export const productVariantAddUrl = (productId: string) => + productVariantAddPath(encodeURIComponent(productId)); + +export const productImagePath = (productId: string, imageId: string) => + urlJoin(productSection, productId, "image", imageId); +export type ProductImageUrlDialog = "remove"; +export type ProductImageUrlQueryParams = Dialog<"remove">; +export const productImageUrl = ( + productId: string, + imageId: string, + params?: ProductImageUrlQueryParams +) => + productImagePath(encodeURIComponent(productId), encodeURIComponent(imageId)) + + "?" + + stringifyQs(params); diff --git a/src/products/views/ProductCreate.tsx b/src/products/views/ProductCreate.tsx new file mode 100644 index 000000000..7a996113a --- /dev/null +++ b/src/products/views/ProductCreate.tsx @@ -0,0 +1,136 @@ +import * as React from "react"; + +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import { DEFAULT_INITIAL_SEARCH_DATA } from "../../config"; +import SearchCategories from "../../containers/SearchCategories"; +import SearchCollections from "../../containers/SearchCollections"; +import i18n from "../../i18n"; +import { decimal, getMutationState, maybe } from "../../misc"; +import ProductCreatePage, { FormData } from "../components/ProductCreatePage"; +import { TypedProductCreateMutation } from "../mutations"; +import { TypedProductCreateQuery } from "../queries"; +import { ProductCreate } from "../types/ProductCreate"; +import { productListUrl, productUrl } from "../urls"; + +interface ProductUpdateProps { + id: string; +} + +export const ProductUpdate: React.StatelessComponent< + ProductUpdateProps +> = () => { + const navigate = useNavigator(); + const notify = useNotifier(); + const shop = useShop(); + + const handleAttributesEdit = undefined; + const handleBack = () => navigate(productListUrl()); + + return ( + + {({ search: searchCategory, result: searchCategoryOpts }) => ( + + {({ search: searchCollection, result: searchCollectionOpts }) => ( + + {({ data, loading }) => { + const handleSuccess = (data: ProductCreate) => { + if (data.productCreate.errors.length === 0) { + notify({ + text: i18n.t("Product created") + }); + navigate(productUrl(data.productCreate.product.id)); + } + }; + + return ( + + {( + productCreate, + { + called: productCreateCalled, + data: productCreateData, + loading: productCreateDataLoading + } + ) => { + const handleSubmit = (formData: FormData) => { + productCreate({ + variables: { + attributes: formData.attributes, + basePrice: decimal(formData.basePrice), + category: formData.category.value, + chargeTaxes: formData.chargeTaxes, + collections: formData.collections.map( + collection => collection.value + ), + descriptionJson: JSON.stringify( + formData.description + ), + isPublished: formData.isPublished, + name: formData.name, + productType: formData.productType.value.id, + publicationDate: + formData.publicationDate !== "" + ? formData.publicationDate + : null, + sku: formData.sku, + stockQuantity: + formData.stockQuantity !== null + ? formData.stockQuantity + : 0 + } + }); + }; + + const disabled = loading || productCreateDataLoading; + + const formTransitionState = getMutationState( + productCreateCalled, + productCreateDataLoading, + maybe(() => productCreateData.productCreate.errors) + ); + return ( + <> + + shop.defaultCurrency)} + categories={maybe( + () => searchCategoryOpts.data.categories.edges, + [] + ).map(edge => edge.node)} + collections={maybe( + () => searchCollectionOpts.data.collections.edges, + [] + ).map(edge => edge.node)} + disabled={disabled} + errors={maybe( + () => productCreateData.productCreate.errors, + [] + )} + fetchCategories={searchCategory} + fetchCollections={searchCollection} + header={i18n.t("New Product")} + productTypes={maybe(() => + data.productTypes.edges.map(edge => edge.node) + )} + onAttributesEdit={handleAttributesEdit} + onBack={handleBack} + onSubmit={handleSubmit} + saveButtonBarState={formTransitionState} + /> + + ); + }} + + ); + }} + + )} + + )} + + ); +}; +export default ProductUpdate; diff --git a/src/products/views/ProductImage.tsx b/src/products/views/ProductImage.tsx new file mode 100644 index 000000000..e2c6601bc --- /dev/null +++ b/src/products/views/ProductImage.tsx @@ -0,0 +1,132 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import ProductImagePage from "../components/ProductImagePage"; +import { + TypedProductImageDeleteMutation, + TypedProductImageUpdateMutation +} from "../mutations"; +import { TypedProductImageQuery } from "../queries"; +import { ProductImageUpdate } from "../types/ProductImageUpdate"; +import { + productImageUrl, + ProductImageUrlQueryParams, + productUrl +} from "../urls"; + +interface ProductImageProps { + imageId: string; + productId: string; + params: ProductImageUrlQueryParams; +} + +export const ProductImage: React.StatelessComponent = ({ + imageId, + productId, + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + + const handleBack = () => navigate(productUrl(productId)); + const handleUpdateSuccess = (data: ProductImageUpdate) => { + if (data.productImageUpdate.errors.length === 0) { + notify({ text: "Saved changes" }); + } + }; + return ( + + {({ data, loading }) => { + return ( + + {(updateImage, updateResult) => ( + + {(deleteImage, deleteResult) => { + const handleDelete = () => + deleteImage({ variables: { id: imageId } }); + const handleImageClick = (id: string) => () => + navigate(productImageUrl(productId, id)); + const handleUpdate = (formData: { description: string }) => { + updateImage({ + variables: { + alt: formData.description, + id: imageId + } + }); + }; + const image = data && data.product && data.product.mainImage; + + const formTransitionState = getMutationState( + updateResult.called, + updateResult.loading, + maybe(() => updateResult.data.productImageUpdate.errors) + ); + const deleteTransitionState = getMutationState( + deleteResult.called, + deleteResult.loading, + [] + ); + return ( + <> + data.product.name)} + image={image || null} + images={maybe(() => data.product.images)} + onBack={handleBack} + onDelete={() => + navigate( + productImageUrl(productId, imageId, { + action: "remove" + }) + ) + } + onRowClick={handleImageClick} + onSubmit={handleUpdate} + saveButtonBarState={formTransitionState} + /> + + navigate(productImageUrl(productId, imageId), true) + } + onConfirm={handleDelete} + open={params.action === "remove"} + title={i18n.t("Remove image", { + context: "modal title" + })} + variant="delete" + confirmButtonState={deleteTransitionState} + > + + {i18n.t( + "Are you sure you want to remove this image?", + { + context: "modal content" + } + )} + + + + ); + }} + + )} + + ); + }} + + ); +}; +export default ProductImage; diff --git a/src/products/views/ProductList/ProductList.tsx b/src/products/views/ProductList/ProductList.tsx new file mode 100644 index 000000000..ad411bf24 --- /dev/null +++ b/src/products/views/ProductList/ProductList.tsx @@ -0,0 +1,363 @@ +import Button from "@material-ui/core/Button"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; +import SaveFilterTabDialog, { + SaveFilterTabDialogFormData +} from "@saleor/components/SaveFilterTabDialog"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useLocale from "@saleor/hooks/useLocale"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; +import { PAGINATE_BY } from "../../../config"; +import i18n from "../../../i18n"; +import { getMutationState, maybe } from "../../../misc"; +import ProductListCard from "../../components/ProductListCard"; +import { + TypedProductBulkDeleteMutation, + TypedProductBulkPublishMutation +} from "../../mutations"; +import { TypedProductListQuery } from "../../queries"; +import { productBulkDelete } from "../../types/productBulkDelete"; +import { productBulkPublish } from "../../types/productBulkPublish"; +import { + productAddUrl, + productListUrl, + ProductListUrlDialog, + ProductListUrlFilters, + ProductListUrlQueryParams, + productUrl +} from "../../urls"; +import { + areFiltersApplied, + createFilter, + createFilterChips, + deleteFilterTab, + getActiveFilters, + getFilterTabs, + getFilterVariables, + saveFilterTab +} from "./filters"; + +interface ProductListProps { + params: ProductListUrlQueryParams; +} + +export const ProductList: React.StatelessComponent = ({ + params +}) => { + const locale = useLocale(); + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const shop = useShop(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const tabs = getFilterTabs(); + + const currentTab = + params.activeTab === undefined + ? areFiltersApplied(params) + ? tabs.length + 1 + : 0 + : parseInt(params.activeTab, 0); + + const closeModal = () => + navigate( + productListUrl({ + ...params, + action: undefined, + ids: undefined + }), + true + ); + + const changeFilters = (filters: ProductListUrlFilters) => { + reset(); + navigate(productListUrl(filters)); + }; + + const changeFilterField = (filter: ProductListUrlFilters) => { + reset(); + navigate( + productListUrl({ + ...getActiveFilters(params), + ...filter, + activeTab: undefined + }) + ); + }; + + const openModal = (action: ProductListUrlDialog, ids?: string[]) => + navigate( + productListUrl({ + ...params, + action, + ids + }) + ); + + const handleTabChange = (tab: number) => { + reset(); + navigate( + productListUrl({ + activeTab: tab.toString(), + ...getFilterTabs()[tab - 1].data + }) + ); + }; + + const handleFilterTabDelete = () => { + deleteFilterTab(currentTab); + reset(); + navigate(productListUrl()); + }; + + const handleFilterTabSave = (data: SaveFilterTabDialogFormData) => { + saveFilterTab(data.name, getActiveFilters(params)); + handleTabChange(tabs.length + 1); + }; + + const paginationState = createPaginationState(PAGINATE_BY, params); + const currencySymbol = maybe(() => shop.defaultCurrency, "USD"); + const queryVariables = React.useMemo( + () => ({ + ...paginationState, + filter: getFilterVariables(params) + }), + [params] + ); + + return ( + + {({ data, loading, refetch }) => { + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.products.pageInfo), + paginationState, + params + ); + + const handleBulkDelete = (data: productBulkDelete) => { + if (data.productBulkDelete.errors.length === 0) { + closeModal(); + notify({ + text: i18n.t("Products removed") + }); + reset(); + refetch(); + } + }; + + const handleBulkPublish = (data: productBulkPublish) => { + if (data.productBulkPublish.errors.length === 0) { + closeModal(); + notify({ + text: i18n.t("Changed publication status") + }); + reset(); + refetch(); + } + }; + + return ( + + {(productBulkDelete, productBulkDeleteOpts) => ( + + {(productBulkPublish, productBulkPublishOpts) => { + const bulkDeleteMutationState = getMutationState( + productBulkDeleteOpts.called, + productBulkDeleteOpts.loading, + maybe( + () => productBulkDeleteOpts.data.productBulkDelete.errors + ) + ); + + const bulkPublishMutationState = getMutationState( + productBulkPublishOpts.called, + productBulkPublishOpts.loading, + maybe( + () => + productBulkPublishOpts.data.productBulkPublish.errors + ) + ); + + return ( + <> + navigate(productAddUrl)} + disabled={loading} + products={maybe(() => + data.products.edges.map(edge => edge.node) + )} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + pageInfo={pageInfo} + onRowClick={id => () => navigate(productUrl(id))} + onAll={() => + changeFilters({ + status: undefined + }) + } + toolbar={ + <> + + + openModal("delete", listElements)} + > + + + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + onSearchChange={query => changeFilterField({ query })} + onFilterAdd={filter => + changeFilterField(createFilter(filter)) + } + onFilterSave={() => openModal("save-search")} + onFilterDelete={() => openModal("delete-search")} + onTabChange={handleTabChange} + initialSearch={params.query || ""} + filterTabs={getFilterTabs()} + /> + + productBulkDelete({ variables: { ids: params.ids } }) + } + title={i18n.t("Remove products")} + variant="delete" + > + {{ number }} products?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + productBulkPublish({ + variables: { + ids: params.ids, + isPublished: true + } + }) + } + title={i18n.t("Publish products")} + > + {{ number }} products?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + productBulkPublish({ + variables: { + ids: params.ids, + isPublished: false + } + }) + } + title={i18n.t("Unpublish products")} + > + {{ number }} products?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + tabs[currentTab - 1].name, "...")} + /> + + ); + }} + + )} + + ); + }} + + ); +}; +export default ProductList; diff --git a/src/products/views/ProductList/filters.ts b/src/products/views/ProductList/filters.ts new file mode 100644 index 000000000..79f6ab112 --- /dev/null +++ b/src/products/views/ProductList/filters.ts @@ -0,0 +1,190 @@ +import { FilterContentSubmitData } from "../../../components/Filter"; +import { Filter } from "../../../components/TableFilter"; +import i18n from "../../../i18n"; +import { + ProductFilterInput, + StockAvailability +} from "../../../types/globalTypes"; +import { + createFilterTabUtils, + createFilterUtils +} from "../../../utils/filters"; +import { ProductFilterKeys } from "../../components/ProductListFilter"; +import { + ProductListUrlFilters, + ProductListUrlFiltersEnum, + ProductListUrlQueryParams +} from "../../urls"; + +export const PRODUCT_FILTERS_KEY = "productFilters"; + +export function getFilterVariables( + params: ProductListUrlFilters +): ProductFilterInput { + return { + isPublished: + params.isPublished !== undefined ? params.isPublished === "true" : null, + price: { + gte: parseFloat(params.priceFrom), + lte: parseFloat(params.priceTo) + }, + search: params.query, + stockAvailability: StockAvailability[params.status] + }; +} + +export function createFilter( + filter: FilterContentSubmitData +): ProductListUrlFilters { + const filterName = filter.name; + if (filterName === ProductFilterKeys.priceEqual.toString()) { + const value = filter.value as string; + return { + priceFrom: value, + priceTo: value + }; + } else if (filterName === ProductFilterKeys.priceRange.toString()) { + const { value } = filter; + return { + priceFrom: value[0], + priceTo: value[1] + }; + } else if (filterName === ProductFilterKeys.published.toString()) { + return { + isPublished: filter.value as string + }; + } else if (filterName === ProductFilterKeys.stock.toString()) { + const value = filter.value as string; + return { + status: StockAvailability[value] + }; + } +} + +interface ProductListChipFormatData { + currencySymbol: string; + locale: string; +} +export function createFilterChips( + filters: ProductListUrlFilters, + formatData: ProductListChipFormatData, + onFilterDelete: (filters: ProductListUrlFilters) => void +): Filter[] { + let filterChips: Filter[] = []; + + if (!!filters.priceFrom || !!filters.priceTo) { + if (filters.priceFrom === filters.priceTo) { + filterChips = [ + ...filterChips, + { + label: i18n.t("Price is {{ price }}", { + price: parseFloat(filters.priceFrom).toLocaleString( + formatData.locale, + { + currency: formatData.currencySymbol, + style: "currency" + } + ) + }), + onClick: () => + onFilterDelete({ + ...filters, + priceFrom: undefined, + priceTo: undefined + }) + } + ]; + } else { + if (!!filters.priceFrom) { + filterChips = [ + ...filterChips, + { + label: i18n.t("Price from {{ price }}", { + price: parseFloat(filters.priceFrom).toLocaleString( + formatData.locale, + { + currency: formatData.currencySymbol, + style: "currency" + } + ) + }), + onClick: () => + onFilterDelete({ + ...filters, + priceFrom: undefined + }) + } + ]; + } + + if (!!filters.priceTo) { + filterChips = [ + ...filterChips, + { + label: i18n.t("Price to {{ price }}", { + price: parseFloat(filters.priceTo).toLocaleString( + formatData.locale, + { + currency: formatData.currencySymbol, + style: "currency" + } + ) + }), + onClick: () => + onFilterDelete({ + ...filters, + priceTo: undefined + }) + } + ]; + } + } + } + + if (!!filters.status) { + filterChips = [ + ...filterChips, + { + label: + filters.status === StockAvailability.IN_STOCK.toString() + ? i18n.t("Available") + : i18n.t("Out Of Stock"), + onClick: () => + onFilterDelete({ + ...filters, + status: undefined + }) + } + ]; + } + + if (!!filters.isPublished) { + filterChips = [ + ...filterChips, + { + label: + filters.isPublished === StockAvailability.IN_STOCK.toString() + ? i18n.t("Published") + : i18n.t("Hidden"), + onClick: () => + onFilterDelete({ + ...filters, + isPublished: undefined + }) + } + ]; + } + + return filterChips; +} + +export const { + deleteFilterTab, + getFilterTabs, + saveFilterTab +} = createFilterTabUtils(PRODUCT_FILTERS_KEY); + +export const { areFiltersApplied, getActiveFilters } = createFilterUtils< + ProductListUrlQueryParams, + ProductListUrlFilters +>(ProductListUrlFiltersEnum); diff --git a/src/products/views/ProductList/index.ts b/src/products/views/ProductList/index.ts new file mode 100644 index 000000000..3308d7c0f --- /dev/null +++ b/src/products/views/ProductList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductList"; +export * from "./ProductList"; diff --git a/src/products/views/ProductUpdate.tsx b/src/products/views/ProductUpdate.tsx new file mode 100644 index 000000000..c97645a79 --- /dev/null +++ b/src/products/views/ProductUpdate.tsx @@ -0,0 +1,366 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; +import { arrayMove } from "react-sortable-hoc"; + +import * as placeholderImg from "@assets/images/placeholder255x255.png"; +import ActionDialog from "@saleor/components/ActionDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import { DEFAULT_INITIAL_SEARCH_DATA } from "../../config"; +import SearchCategories from "../../containers/SearchCategories"; +import SearchCollections from "../../containers/SearchCollections"; +import i18n from "../../i18n"; +import { decimal, getMutationState, maybe } from "../../misc"; +import { productTypeUrl } from "../../productTypes/urls"; +import ProductUpdatePage, { FormData } from "../components/ProductUpdatePage"; +import ProductUpdateOperations from "../containers/ProductUpdateOperations"; +import { TypedProductDetailsQuery } from "../queries"; +import { + ProductImageCreate, + ProductImageCreateVariables +} from "../types/ProductImageCreate"; +import { ProductVariantBulkDelete } from "../types/ProductVariantBulkDelete"; +import { + productImageUrl, + productListUrl, + productUrl, + ProductUrlQueryParams, + productVariantAddUrl, + productVariantEditUrl +} from "../urls"; + +interface ProductUpdateProps { + id: string; + params: ProductUrlQueryParams; +} + +export const ProductUpdate: React.StatelessComponent = ({ + id, + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + return ( + + {({ search: searchCategories, result: searchCategoriesOpts }) => ( + + {({ search: searchCollections, result: searchCollectionsOpts }) => ( + + {({ data, loading, refetch }) => { + const handleDelete = () => { + notify({ text: i18n.t("Product removed") }); + navigate(productListUrl()); + }; + const handleUpdate = () => + notify({ text: i18n.t("Saved changes") }); + const handleImageCreate = (data: ProductImageCreate) => { + const imageError = data.productImageCreate.errors.find( + error => + error.field === + ("image" as keyof ProductImageCreateVariables) + ); + if (imageError) { + notify({ + text: imageError.message + }); + } + }; + const handleImageDeleteSuccess = () => + notify({ + text: i18n.t("Image successfully deleted") + }); + const handleVariantAdd = () => + navigate(productVariantAddUrl(id)); + + const handleBulkProductVariantDelete = ( + data: ProductVariantBulkDelete + ) => { + if (data.productVariantBulkDelete.errors.length === 0) { + navigate(productUrl(id), true); + reset(); + refetch(); + } + }; + + const product = data ? data.product : undefined; + return ( + + {({ + bulkProductVariantDelete, + createProductImage, + deleteProduct, + deleteProductImage, + reorderProductImages, + updateProduct, + updateSimpleProduct + }) => { + const handleImageDelete = (id: string) => () => + deleteProductImage.mutate({ id }); + const handleImageEdit = (imageId: string) => () => + navigate(productImageUrl(id, imageId)); + const handleSubmit = (data: FormData) => { + if (product) { + if (product.productType.hasVariants) { + updateProduct.mutate({ + attributes: data.attributes, + basePrice: decimal(data.basePrice), + category: data.category.value, + chargeTaxes: data.chargeTaxes, + collections: data.collections.map( + collection => collection.value + ), + descriptionJson: JSON.stringify(data.description), + id: product.id, + isPublished: data.isPublished, + name: data.name, + publicationDate: + data.publicationDate !== "" + ? data.publicationDate + : null + }); + } else { + updateSimpleProduct.mutate({ + attributes: data.attributes, + basePrice: decimal(data.basePrice), + category: data.category.value, + chargeTaxes: data.chargeTaxes, + collections: data.collections.map( + collection => collection.value + ), + descriptionJson: JSON.stringify(data.description), + id: product.id, + isPublished: data.isPublished, + name: data.name, + productVariantId: product.variants[0].id, + productVariantInput: { + quantity: data.stockQuantity, + sku: data.sku + }, + publicationDate: + data.publicationDate !== "" + ? data.publicationDate + : null + }); + } + } + }; + + const disableFormSave = + createProductImage.opts.loading || + deleteProduct.opts.loading || + reorderProductImages.opts.loading || + updateProduct.opts.loading || + loading; + const formTransitionState = getMutationState( + updateProduct.opts.called || + updateSimpleProduct.opts.called, + updateProduct.opts.loading || + updateSimpleProduct.opts.loading, + maybe( + () => updateProduct.opts.data.productUpdate.errors + ), + maybe( + () => + updateSimpleProduct.opts.data.productUpdate.errors + ), + maybe( + () => + updateSimpleProduct.opts.data.productVariantUpdate + .errors + ) + ); + const deleteTransitionState = getMutationState( + deleteProduct.opts.called, + deleteProduct.opts.loading, + maybe( + () => deleteProduct.opts.data.productDelete.errors + ) + ); + + const bulkProductVariantDeleteTransitionState = getMutationState( + bulkProductVariantDelete.opts.called, + bulkProductVariantDelete.opts.loading, + maybe( + () => + bulkProductVariantDelete.opts.data + .productVariantBulkDelete.errors + ) + ); + + return ( + <> + data.product.name)} /> + searchCategoriesOpts.data.categories.edges, + [] + ).map(edge => edge.node)} + collections={maybe( + () => + searchCollectionsOpts.data.collections.edges, + [] + ).map(edge => edge.node)} + disabled={disableFormSave} + errors={maybe( + () => + updateProduct.opts.data.productUpdate.errors, + [] + )} + fetchCategories={searchCategories} + fetchCollections={searchCollections} + saveButtonBarState={formTransitionState} + images={maybe(() => data.product.images)} + header={maybe(() => product.name)} + placeholderImage={placeholderImg} + product={product} + productCollections={maybe( + () => product.collections + )} + variants={maybe(() => product.variants)} + onAttributesEdit={() => + navigate( + productTypeUrl(data.product.productType.id) + ) + } + onBack={() => { + navigate(productListUrl()); + }} + onDelete={() => + navigate( + productUrl(id, { + action: "remove" + }) + ) + } + onProductShow={() => { + if (product) { + window.open(product.url); + } + }} + onImageReorder={({ newIndex, oldIndex }) => { + if (product) { + let ids = product.images.map(image => image.id); + ids = arrayMove(ids, oldIndex, newIndex); + reorderProductImages.mutate({ + imagesIds: ids, + productId: product.id + }); + } + }} + onSubmit={handleSubmit} + onVariantAdd={handleVariantAdd} + onVariantShow={variantId => () => + navigate( + productVariantEditUrl(product.id, variantId) + )} + onImageUpload={file => { + if (product) { + createProductImage.mutate({ + alt: "", + image: file, + product: product.id + }); + } + }} + onImageEdit={handleImageEdit} + onImageDelete={handleImageDelete} + toolbar={ + + navigate( + productUrl(id, { + action: "remove-variants", + ids: listElements + }) + ) + } + > + + + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + /> + navigate(productUrl(id), true)} + confirmButtonState={deleteTransitionState} + onConfirm={() => deleteProduct.mutate({ id })} + variant="delete" + title={i18n.t("Remove product")} + > + {{ name }}?", + { + name: product ? product.name : undefined + } + ) + }} + /> + + navigate(productUrl(id), true)} + confirmButtonState={ + bulkProductVariantDeleteTransitionState + } + onConfirm={() => + bulkProductVariantDelete.mutate({ + ids: params.ids + }) + } + variant="delete" + title={i18n.t("Remove product variants")} + > + {{ number }} variants?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + ); + }} + + ); + }} + + )} + + )} + + ); +}; +export default ProductUpdate; diff --git a/src/products/views/ProductVariant.tsx b/src/products/views/ProductVariant.tsx new file mode 100644 index 000000000..be42c88f7 --- /dev/null +++ b/src/products/views/ProductVariant.tsx @@ -0,0 +1,169 @@ +import * as React from "react"; + +import * as placeholderImg from "@assets/images/placeholder255x255.png"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../i18n"; +import { decimal, getMutationState, maybe } from "../../misc"; +import ProductVariantDeleteDialog from "../components/ProductVariantDeleteDialog"; +import ProductVariantPage from "../components/ProductVariantPage"; +import ProductVariantOperations from "../containers/ProductVariantOperations"; +import { TypedProductVariantQuery } from "../queries"; +import { VariantUpdate } from "../types/VariantUpdate"; +import { + productUrl, + productVariantAddUrl, + productVariantEditUrl, + ProductVariantEditUrlQueryParams +} from "../urls"; + +interface ProductUpdateProps { + variantId: string; + productId: string; + params: ProductVariantEditUrlQueryParams; +} + +interface FormData { + id: string; + attributes?: Array<{ + slug: string; + value: string; + }>; + costPrice?: string; + priceOverride?: string; + quantity: number; + sku: string; +} + +export const ProductVariant: React.StatelessComponent = ({ + variantId, + productId, + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + + return ( + + {({ data, loading }) => { + const variant = data ? data.productVariant : undefined; + const handleBack = () => navigate(productUrl(productId)); + const handleDelete = () => { + notify({ text: i18n.t("Variant removed") }); + navigate(productUrl(productId)); + }; + const handleUpdate = (data: VariantUpdate) => { + if (!maybe(() => data.productVariantUpdate.errors.length)) { + notify({ text: i18n.t("Changes saved") }); + } + }; + + return ( + + {({ assignImage, deleteVariant, updateVariant, unassignImage }) => { + const disableFormSave = + loading || + deleteVariant.opts.loading || + updateVariant.opts.loading || + assignImage.opts.loading || + unassignImage.opts.loading; + const formTransitionState = getMutationState( + updateVariant.opts.called, + updateVariant.opts.loading, + maybe(() => updateVariant.opts.data.productVariantUpdate.errors) + ); + const removeTransitionState = getMutationState( + deleteVariant.opts.called, + deleteVariant.opts.loading, + maybe(() => deleteVariant.opts.data.productVariantDelete.errors) + ); + const handleImageSelect = (id: string) => () => { + if (variant) { + if ( + variant.images && + variant.images.map(image => image.id).indexOf(id) !== -1 + ) { + unassignImage.mutate({ + imageId: id, + variantId: variant.id + }); + } else { + assignImage.mutate({ + imageId: id, + variantId: variant.id + }); + } + } + }; + + return ( + <> + data.productVariant.name)} /> + updateVariant.opts.data.productVariantUpdate.errors, + [] + )} + saveButtonBarState={formTransitionState} + loading={disableFormSave} + placeholderImage={placeholderImg} + variant={variant} + header={variant ? variant.name || variant.sku : undefined} + onAdd={() => navigate(productVariantAddUrl(productId))} + onBack={handleBack} + onDelete={() => + navigate( + productVariantEditUrl(productId, variantId, { + action: "remove" + }) + ) + } + onImageSelect={handleImageSelect} + onSubmit={(data: FormData) => { + if (variant) { + updateVariant.mutate({ + attributes: data.attributes ? data.attributes : null, + costPrice: decimal(data.costPrice), + id: variantId, + priceOverride: decimal(data.priceOverride), + quantity: data.quantity || null, + sku: data.sku, + trackInventory: true // FIXME: missing in UI + }); + } + }} + onVariantClick={variantId => { + navigate(productVariantEditUrl(productId, variantId)); + }} + /> + + navigate(productVariantEditUrl(productId, variantId)) + } + onConfirm={() => + deleteVariant.mutate({ + id: variantId + }) + } + open={params.action === "remove"} + name={maybe(() => data.productVariant.name)} + /> + + ); + }} + + ); + }} + + ); +}; +export default ProductVariant; diff --git a/src/products/views/ProductVariantCreate.tsx b/src/products/views/ProductVariantCreate.tsx new file mode 100644 index 000000000..f2dfa4f09 --- /dev/null +++ b/src/products/views/ProductVariantCreate.tsx @@ -0,0 +1,111 @@ +import * as React from "react"; + +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import i18n from "../../i18n"; +import { decimal, getMutationState, maybe } from "../../misc"; +import ProductVariantCreatePage from "../components/ProductVariantCreatePage"; +import { TypedVariantCreateMutation } from "../mutations"; +import { TypedProductVariantCreateQuery } from "../queries"; +import { VariantCreate } from "../types/VariantCreate"; +import { productUrl, productVariantEditUrl } from "../urls"; + +interface ProductUpdateProps { + productId: string; +} + +interface FormData { + attributes?: Array<{ + slug: string; + value: string; + }>; + costPrice?: string; + priceOverride?: string; + quantity: number; + sku: string; +} + +export const ProductVariant: React.StatelessComponent = ({ + productId +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const shop = useShop(); + + return ( + + {({ data, loading: productLoading }) => { + const handleCreateSuccess = (data: VariantCreate) => { + if (data.productVariantCreate.errors.length === 0) { + notify({ text: i18n.t("Product created") }); + navigate( + productVariantEditUrl( + productId, + data.productVariantCreate.productVariant.id + ) + ); + } + }; + + return ( + + {(variantCreate, variantCreateResult) => { + const handleBack = () => navigate(productUrl(productId)); + const handleSubmit = (formData: FormData) => + variantCreate({ + variables: { + attributes: formData.attributes, + costPrice: decimal(formData.costPrice), + priceOverride: decimal(formData.priceOverride), + product: productId, + quantity: formData.quantity || null, + sku: formData.sku, + trackInventory: true + } + }); + const handleVariantClick = (id: string) => + navigate(productVariantEditUrl(productId, id)); + + const disableForm = productLoading || variantCreateResult.loading; + + const formTransitionstate = getMutationState( + variantCreateResult.called, + variantCreateResult.loading, + maybe( + () => variantCreateResult.data.productVariantCreate.errors + ) + ); + return ( + <> + + shop.defaultCurrency)} + errors={maybe( + () => + variantCreateResult.data.productVariantCreate.errors, + [] + )} + header={i18n.t("Add Variant")} + loading={disableForm} + product={maybe(() => data.product)} + onBack={handleBack} + onSubmit={handleSubmit} + onVariantClick={handleVariantClick} + saveButtonBarState={formTransitionstate} + /> + + ); + }} + + ); + }} + + ); +}; +export default ProductVariant; diff --git a/src/queries.tsx b/src/queries.tsx new file mode 100644 index 000000000..2364ee6b7 --- /dev/null +++ b/src/queries.tsx @@ -0,0 +1,169 @@ +import { DocumentNode } from "graphql"; +import gql from "graphql-tag"; +import * as React from "react"; +import { Query, QueryResult } from "react-apollo"; + +import { ApolloQueryResult } from "apollo-client"; +import AppProgress from "./components/AppProgress"; +import ErrorPage from "./components/ErrorPage/ErrorPage"; +import useNavigator from "./hooks/useNavigator"; +import useNotifier from "./hooks/useNotifier"; +import i18n from "./i18n"; +import { RequireAtLeastOne } from "./misc"; + +export interface LoadMore { + loadMore: ( + mergeFunc: (prev: TData, next: TData) => TData, + extraVariables: RequireAtLeastOne + ) => Promise>; +} + +export type TypedQueryResult = QueryResult< + TData, + TVariables +> & + LoadMore; + +export interface TypedQueryInnerProps { + children: (result: TypedQueryResult) => React.ReactNode; + displayLoader?: boolean; + skip?: boolean; + variables?: TVariables; + require?: Array; +} + +interface QueryProgressProps { + loading: boolean; + onLoading: () => void; + onCompleted: () => void; +} + +class QueryProgress extends React.Component { + componentDidMount() { + const { loading, onLoading } = this.props; + if (loading) { + onLoading(); + } + } + + componentDidUpdate(prevProps) { + const { loading, onLoading, onCompleted } = this.props; + if (prevProps.loading !== loading) { + if (loading) { + onLoading(); + } else { + onCompleted(); + } + } + } + + render() { + return this.props.children; + } +} + +export function TypedQuery( + query: DocumentNode +): React.FC> { + class StrictTypedQuery extends Query {} + return props => { + const navigate = useNavigator(); + const pushMessage = useNotifier(); + + return ( + + {({ setProgressState }) => { + // Obviously, this is workaround to the problem described here: + // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/32588 + const { + children, + displayLoader, + skip, + variables, + require + } = props as JSX.LibraryManagedAttributes< + typeof StrictTypedQuery, + typeof props + >; + return ( + + {queryData => { + if (queryData.error) { + const msg = i18n.t("Something went wrong: {{ message }}", { + message: queryData.error.message + }); + pushMessage({ text: msg }); + } + + const loadMore = ( + mergeFunc: ( + previousResults: TData, + fetchMoreResult: TData + ) => TData, + extraVariables: RequireAtLeastOne + ) => + queryData.fetchMore({ + query, + updateQuery: (previousResults, { fetchMoreResult }) => { + if (!fetchMoreResult) { + return previousResults; + } + return mergeFunc(previousResults, fetchMoreResult); + }, + variables: { ...variables, ...extraVariables } + }); + + let childrenOrNotFound = children({ + ...queryData, + loadMore + }); + if ( + !queryData.loading && + require && + queryData.data && + !require.reduce( + (acc, key) => acc && queryData.data[key] !== null, + true + ) + ) { + childrenOrNotFound = ( + navigate("/")} /> + ); + } + + if (displayLoader) { + return ( + setProgressState(false)} + onLoading={() => setProgressState(true)} + > + {childrenOrNotFound} + + ); + } + + return childrenOrNotFound; + }} + + ); + }} + + ); + }; +} + +export const pageInfoFragment = gql` + fragment PageInfoFragment on PageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } +`; diff --git a/src/shipping/components/ShippingWeightUnitForm/ShippingWeightUnitForm.tsx b/src/shipping/components/ShippingWeightUnitForm/ShippingWeightUnitForm.tsx new file mode 100644 index 000000000..b1f72dc6b --- /dev/null +++ b/src/shipping/components/ShippingWeightUnitForm/ShippingWeightUnitForm.tsx @@ -0,0 +1,74 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardActions from "@material-ui/core/CardActions"; +import CardContent from "@material-ui/core/CardContent"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Form from "@saleor/components/Form"; +import Hr from "@saleor/components/Hr"; +import SingleSelectField from "@saleor/components/SingleSelectField"; +import i18n from "../../../i18n"; +import { WeightUnitsEnum } from "../../../types/globalTypes"; + +export interface FormData { + unit: WeightUnitsEnum; +} + +export interface ShippingWeightUnitFormProps { + defaultWeightUnit: WeightUnitsEnum; + disabled: boolean; + onSubmit: (unit: WeightUnitsEnum) => void; +} + +const ShippingWeightUnitForm: React.StatelessComponent< + ShippingWeightUnitFormProps +> = ({ defaultWeightUnit, disabled, onSubmit }) => { + const initialForm: FormData = { + unit: defaultWeightUnit + }; + return ( +
onSubmit(formData.unit)}> + {({ change, data, submit }) => ( + + + + ({ + label: WeightUnitsEnum[unit], + value: WeightUnitsEnum[unit] + }))} + label={i18n.t("Shipping Weight Unit", { + context: "input label" + })} + hint={i18n.t( + "This unit will be used as default shipping weight", + { + context: "input help text" + } + )} + name={"unit" as keyof FormData} + value={data.unit} + onChange={change} + /> + +
+ + + +
+ )} +
+ ); +}; +ShippingWeightUnitForm.displayName = "ShippingWeightUnitForm"; +export default ShippingWeightUnitForm; diff --git a/src/shipping/components/ShippingWeightUnitForm/index.ts b/src/shipping/components/ShippingWeightUnitForm/index.ts new file mode 100644 index 000000000..8c4dc991f --- /dev/null +++ b/src/shipping/components/ShippingWeightUnitForm/index.ts @@ -0,0 +1,2 @@ +export { default } from './ShippingWeightUnitForm'; +export * from './ShippingWeightUnitForm'; \ No newline at end of file diff --git a/src/shipping/components/ShippingZoneCountriesAssignDialog/ShippingZoneCountriesAssignDialog.tsx b/src/shipping/components/ShippingZoneCountriesAssignDialog/ShippingZoneCountriesAssignDialog.tsx new file mode 100644 index 000000000..2f7ce5238 --- /dev/null +++ b/src/shipping/components/ShippingZoneCountriesAssignDialog/ShippingZoneCountriesAssignDialog.tsx @@ -0,0 +1,233 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import { filter } from "fuzzaldrin"; +import * as React from "react"; + +import Checkbox from "@saleor/components/Checkbox"; +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import FormSpacer from "@saleor/components/FormSpacer"; +import Hr from "@saleor/components/Hr"; +// tslint:disable no-submodule-imports +import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo"; +import i18n from "../../../i18n"; + +interface FormData { + countries: string[]; + query: string; + restOfTheWorld: boolean; +} + +export interface ShippingZoneCountriesAssignDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + countries: ShopInfo_shop_countries[]; + initial: string[]; + isDefault: boolean; + open: boolean; + onClose: () => void; + onConfirm: (data: FormData) => void; +} + +const styles = (theme: Theme) => + createStyles({ + checkboxCell: { + paddingLeft: 0 + }, + container: { + maxHeight: 400 + }, + heading: { + marginBottom: theme.spacing.unit * 2, + marginTop: theme.spacing.unit * 2 + }, + table: { + border: "1px solid " + theme.palette.grey[200] + }, + wideCell: { + width: "100%" + } + }); +const ShippingZoneCountriesAssignDialog = withStyles(styles, { + name: "ShippingZoneCountriesAssignDialog" +})( + ({ + classes, + confirmButtonState, + isDefault, + onClose, + countries, + open, + initial, + onConfirm + }: ShippingZoneCountriesAssignDialogProps & WithStyles) => { + const initialForm: FormData = { + countries: initial, + query: "", + restOfTheWorld: isDefault + }; + return ( + +
+ {({ data, change }) => { + const countrySelectionMap = countries.reduce((acc, country) => { + acc[country.code] = !!data.countries.find( + selectedCountries => selectedCountries === country.code + ); + return acc; + }, {}); + + return ( + <> + {i18n.t("Assign Countries")} + + + {i18n.t( + "Choose countries you want to add to shipping zone from list below" + )} + + + change(event, () => fetch(data.query))} + label={i18n.t("Search Countries", { + context: "country search input label" + })} + placeholder={i18n.t("Search by country name", { + context: "country search input placeholder" + })} + fullWidth + /> + +
+ + + + {i18n.t("Quick Pick")} + + + + + + {i18n.t("Rest of the World")} + + {i18n.t( + "If selected, this will add all of the countries not selected to other shipping zones" + )} + + + + + change({ + target: { + name: "restOfTheWorld" as keyof FormData, + value: !data.restOfTheWorld + } + } as any) + } + /> + + + +
+
+ + + + {i18n.t("Countries A to Z", { + context: "country selection" + })} + + + + {filter(countries, data.query, { + key: "country" + }).map(country => { + const isChecked = countrySelectionMap[country.code]; + + return ( + + + {country.country} + + + + isChecked + ? change({ + target: { + name: "countries" as keyof FormData, + value: data.countries.filter( + selectedCountries => + selectedCountries !== country.code + ) + } + } as any) + : change({ + target: { + name: "countries" as keyof FormData, + value: [ + ...data.countries, + country.code + ] + } + } as any) + } + /> + + + ); + })} + +
+
+ + + + {i18n.t("Assign countries", { context: "button" })} + + + + ); + }} +
+
+ ); + } +); +ShippingZoneCountriesAssignDialog.displayName = + "ShippingZoneCountriesAssignDialog"; +export default ShippingZoneCountriesAssignDialog; diff --git a/src/shipping/components/ShippingZoneCountriesAssignDialog/index.ts b/src/shipping/components/ShippingZoneCountriesAssignDialog/index.ts new file mode 100644 index 000000000..882ec3f99 --- /dev/null +++ b/src/shipping/components/ShippingZoneCountriesAssignDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from './ShippingZoneCountriesAssignDialog'; +export * from './ShippingZoneCountriesAssignDialog'; \ No newline at end of file diff --git a/src/shipping/components/ShippingZoneCreatePage/ShippingZoneCreatePage.tsx b/src/shipping/components/ShippingZoneCreatePage/ShippingZoneCreatePage.tsx new file mode 100644 index 000000000..ee805fb05 --- /dev/null +++ b/src/shipping/components/ShippingZoneCreatePage/ShippingZoneCreatePage.tsx @@ -0,0 +1,130 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import CountryList from "@saleor/components/CountryList"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { CountryFragment } from "../../../taxes/types/CountryFragment"; +import { UserError } from "../../../types"; +import ShippingZoneCountriesAssignDialog from "../ShippingZoneCountriesAssignDialog"; +import ShippingZoneInfo from "../ShippingZoneInfo"; + +export interface FormData { + countries: string[]; + default: boolean; + name: string; +} + +export interface ShippingZoneCreatePageProps { + countries: CountryFragment[]; + disabled: boolean; + errors: UserError[]; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onSubmit: (data: FormData) => void; +} + +const ShippingZoneCreatePage: React.StatelessComponent< + ShippingZoneCreatePageProps +> = ({ countries, disabled, errors, onBack, onSubmit, saveButtonBarState }) => { + const [isModalOpened, setModalStatus] = React.useState(false); + const toggleModal = () => setModalStatus(!isModalOpened); + + const initialForm: FormData = { + countries: [], + default: false, + name: "" + }; + + return ( +
+ {({ change, data, errors: formErrors, hasChanged, submit }) => ( + <> + + {i18n.t("Shipping")} + + +
+ + + + countries.find(country => country.code === selectedCountry) + )} + disabled={disabled} + emptyText={ + data.default + ? i18n.t( + "This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones" + ) + : i18n.t( + "Currently, there are no countries assigned to this shipping zone" + ) + } + onCountryAssign={toggleModal} + onCountryUnassign={countryCode => + change({ + target: { + name: "countries", + value: data.countries.filter( + country => country !== countryCode + ) + } + } as any) + } + title={i18n.t("Countries")} + /> +
+
+ +
+ + change( + { + target: { + name: "default", + value: formData.restOfTheWorld + } + } as any, + () => + change( + { + target: { + name: "countries", + value: formData.restOfTheWorld ? [] : formData.countries + } + } as any, + toggleModal + ) + ) + } + confirmButtonState="default" + countries={countries} + initial={data.countries} + isDefault={data.default} + onClose={toggleModal} + /> + + )} + + ); +}; +ShippingZoneCreatePage.displayName = "ShippingZoneCreatePage"; +export default ShippingZoneCreatePage; diff --git a/src/shipping/components/ShippingZoneCreatePage/index.ts b/src/shipping/components/ShippingZoneCreatePage/index.ts new file mode 100644 index 000000000..6c7ccbdd5 --- /dev/null +++ b/src/shipping/components/ShippingZoneCreatePage/index.ts @@ -0,0 +1,2 @@ +export { default } from './ShippingZoneCreatePage'; +export * from './ShippingZoneCreatePage'; \ No newline at end of file diff --git a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx new file mode 100644 index 000000000..96040ad4e --- /dev/null +++ b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx @@ -0,0 +1,135 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import CountryList from "@saleor/components/CountryList"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { UserError } from "../../../types"; +import { ShippingMethodTypeEnum } from "../../../types/globalTypes"; +import { ShippingZoneDetailsFragment } from "../../types/ShippingZoneDetailsFragment"; +import ShippingZoneInfo from "../ShippingZoneInfo"; +import ShippingZoneRates from "../ShippingZoneRates"; + +export interface FormData { + name: string; +} + +export interface ShippingZoneDetailsPageProps { + disabled: boolean; + errors: UserError[]; + saveButtonBarState: ConfirmButtonTransitionState; + shippingZone: ShippingZoneDetailsFragment; + onBack: () => void; + onCountryAdd: () => void; + onCountryRemove: (code: string) => void; + onDelete: () => void; + onPriceRateAdd: () => void; + onPriceRateEdit: (id: string) => void; + onRateRemove: (rateId: string) => void; + onSubmit: (data: FormData) => void; + onWeightRateAdd: () => void; + onWeightRateEdit: (id: string) => void; +} + +const ShippingZoneDetailsPage: React.StatelessComponent< + ShippingZoneDetailsPageProps +> = ({ + disabled, + errors, + onBack, + onCountryAdd, + onCountryRemove, + onDelete, + onPriceRateAdd, + onPriceRateEdit, + onRateRemove, + onSubmit, + onWeightRateAdd, + onWeightRateEdit, + saveButtonBarState, + shippingZone +}) => { + const initialForm: FormData = { + name: maybe(() => shippingZone.name, "") + }; + return ( +
+ {({ change, data, errors: formErrors, hasChanged, submit }) => ( + + {i18n.t("Shipping")} + shippingZone.name)} /> + +
+ + + shippingZone.countries)} + disabled={disabled} + emptyText={maybe( + () => + shippingZone.default + ? i18n.t( + "This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones" + ) + : i18n.t( + "Currently, there are no countries assigned to this shipping zone" + ), + "..." + )} + onCountryAssign={onCountryAdd} + onCountryUnassign={onCountryRemove} + title={i18n.t("Countries")} + /> + + + shippingZone.shippingMethods.filter( + method => method.type === ShippingMethodTypeEnum.PRICE + ) + )} + variant="price" + /> + + + shippingZone.shippingMethods.filter( + method => method.type === ShippingMethodTypeEnum.WEIGHT + ) + )} + variant="weight" + /> +
+
+ +
+ )} +
+ ); +}; +ShippingZoneDetailsPage.displayName = "ShippingZoneDetailsPage"; +export default ShippingZoneDetailsPage; diff --git a/src/shipping/components/ShippingZoneDetailsPage/index.ts b/src/shipping/components/ShippingZoneDetailsPage/index.ts new file mode 100644 index 000000000..1bfd26b13 --- /dev/null +++ b/src/shipping/components/ShippingZoneDetailsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from './ShippingZoneDetailsPage'; +export * from './ShippingZoneDetailsPage'; \ No newline at end of file diff --git a/src/shipping/components/ShippingZoneInfo/ShippingZoneInfo.tsx b/src/shipping/components/ShippingZoneInfo/ShippingZoneInfo.tsx new file mode 100644 index 000000000..ff17908e5 --- /dev/null +++ b/src/shipping/components/ShippingZoneInfo/ShippingZoneInfo.tsx @@ -0,0 +1,38 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import i18n from "../../../i18n"; +import { FormErrors } from "../../../types"; +import { FormData } from "../ShippingZoneDetailsPage"; + +export interface ShippingZoneInfoProps { + data: FormData; + errors: FormErrors<"name">; + onChange: (event: React.ChangeEvent) => void; +} + +const ShippingZoneInfo: React.StatelessComponent = ({ + data, + errors, + onChange +}) => ( + + + + + + +); +ShippingZoneInfo.displayName = "ShippingZoneInfo"; +export default ShippingZoneInfo; diff --git a/src/shipping/components/ShippingZoneInfo/index.ts b/src/shipping/components/ShippingZoneInfo/index.ts new file mode 100644 index 000000000..a04821eb0 --- /dev/null +++ b/src/shipping/components/ShippingZoneInfo/index.ts @@ -0,0 +1,2 @@ +export { default } from './ShippingZoneInfo'; +export * from './ShippingZoneInfo'; \ No newline at end of file diff --git a/src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx b/src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx new file mode 100644 index 000000000..75c0b05dc --- /dev/null +++ b/src/shipping/components/ShippingZoneRateDialog/ShippingZoneRateDialog.tsx @@ -0,0 +1,301 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import ControlledSwitch from "@saleor/components/ControlledSwitch"; +import Form from "@saleor/components/Form"; +import FormSpacer from "@saleor/components/FormSpacer"; +import Hr from "@saleor/components/Hr"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { FormErrors, UserError } from "../../../types"; +import { ShippingMethodTypeEnum } from "../../../types/globalTypes"; +import { ShippingZoneDetailsFragment_shippingMethods } from "../../types/ShippingZoneDetailsFragment"; + +export interface FormData { + name: string; + noLimits: boolean; + minValue: string; + maxValue: string; + isFree: boolean; + price: string; +} + +export interface ShippingZoneRateDialogProps { + action: "create" | "edit"; + confirmButtonState: ConfirmButtonTransitionState; + defaultCurrency: string; + disabled: boolean; + errors: UserError[]; + open: boolean; + rate: ShippingZoneDetailsFragment_shippingMethods; + variant: ShippingMethodTypeEnum; + onClose: () => void; + onSubmit: (data: FormData) => void; +} + +const styles = (theme: Theme) => + createStyles({ + grid: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridTemplateColumns: "1fr 1fr" + }, + subheading: { + marginBottom: theme.spacing.unit * 2, + marginTop: theme.spacing.unit * 2 + } + }); +const ShippingZoneRateDialog = withStyles(styles, { + name: "ShippingZoneRateDialog" +})( + ({ + action, + classes, + confirmButtonState, + defaultCurrency, + disabled, + errors, + onClose, + onSubmit, + open, + rate, + variant + }: ShippingZoneRateDialogProps & WithStyles) => { + const initialForm: FormData = + action === "create" + ? { + isFree: false, + maxValue: "", + minValue: "", + name: "", + noLimits: false, + price: "" + } + : { + isFree: maybe(() => rate.price.amount === 0, false), + maxValue: + variant === ShippingMethodTypeEnum.PRICE + ? maybe(() => rate.maximumOrderPrice.amount.toString(), "") + : maybe(() => rate.maximumOrderWeight.value.toString(), ""), + minValue: + variant === ShippingMethodTypeEnum.PRICE + ? maybe(() => rate.minimumOrderPrice.amount.toString(), "") + : maybe(() => rate.minimumOrderWeight.value.toString(), ""), + name: maybe(() => rate.name, ""), + noLimits: false, + price: maybe(() => rate.price.amount.toString(), "") + }; + if (action === "edit") { + initialForm.noLimits = !initialForm.maxValue && !initialForm.minValue; + } + + return ( + +
+ {({ change, data, errors: formErrors, hasChanged }) => { + const typedFormErrors: FormErrors< + | "minimumOrderPrice" + | "minimumOrderWeight" + | "maximumOrderPrice" + | "maximumOrderWeight" + | "price" + | "name" + > = formErrors; + return ( + <> + + {variant === ShippingMethodTypeEnum.PRICE + ? action === "create" + ? i18n.t("Add Price Rate") + : i18n.t("Edit Price Rate") + : action === "create" + ? i18n.t("Add Weight Rate") + : i18n.t("Edit Weight Rate")} + + + + +
+ + {!!variant ? ( + <> + + {variant === ShippingMethodTypeEnum.PRICE + ? i18n.t("Value range") + : i18n.t("Weight range")} + + + {i18n.t("There are no value limits")} + + {variant === ShippingMethodTypeEnum.PRICE + ? i18n.t( + "This rate will apply to all orders of all prices" + ) + : i18n.t( + "This rate will apply to all orders of all weights" + )} + + + } + /> + {!data.noLimits && ( + <> + +
+ + +
+ + )} + + ) : ( + + )} +
+
+ + + {i18n.t("Rate")} + + + {!data.isFree && ( + <> + +
+ +
+ + )} +
+ + + + {action === "create" + ? i18n.t("Create rate", { context: "button" }) + : i18n.t("Update rate", { context: "button" })} + + + + ); + }} +
+
+ ); + } +); +ShippingZoneRateDialog.displayName = "ShippingZoneRateDialog"; +export default ShippingZoneRateDialog; diff --git a/src/shipping/components/ShippingZoneRateDialog/index.ts b/src/shipping/components/ShippingZoneRateDialog/index.ts new file mode 100644 index 000000000..3aa84f45e --- /dev/null +++ b/src/shipping/components/ShippingZoneRateDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from './ShippingZoneRateDialog'; +export * from './ShippingZoneRateDialog'; \ No newline at end of file diff --git a/src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx b/src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx new file mode 100644 index 000000000..589edd5b7 --- /dev/null +++ b/src/shipping/components/ShippingZoneRates/ShippingZoneRates.tsx @@ -0,0 +1,163 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import DeleteIcon from "@material-ui/icons/Delete"; +import EditIcon from "@material-ui/icons/Edit"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import IconButtonTableCell from "@saleor/components/IconButtonTableCell"; +import Money from "@saleor/components/Money"; +import MoneyRange from "@saleor/components/MoneyRange"; +import Skeleton from "@saleor/components/Skeleton"; +import WeightRange from "@saleor/components/WeightRange"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ICONBUTTON_SIZE } from "../../../theme"; +import { ShippingZoneDetailsFragment_shippingMethods } from "../../types/ShippingZoneDetailsFragment"; + +export interface ShippingZoneRatesProps { + disabled: boolean; + rates: ShippingZoneDetailsFragment_shippingMethods[]; + variant: "price" | "weight"; + onRateAdd: () => void; + onRateEdit: (id: string) => void; + onRateRemove: (id: string) => void; +} + +const styles = (theme: Theme) => + createStyles({ + alignRight: { + "&:last-child": { + paddingRight: 0 + }, + paddingRight: 0, + width: ICONBUTTON_SIZE + theme.spacing.unit / 2 + }, + nameColumn: { + width: 300 + }, + valueColumn: { + width: 300 + } + }); +const ShippingZoneRates = withStyles(styles, { name: "ShippingZoneRates" })( + ({ + classes, + disabled, + onRateAdd, + onRateEdit, + onRateRemove, + rates, + variant + }: ShippingZoneRatesProps & WithStyles) => ( + + + {i18n.t("Add rate", { + context: "button" + })} + + } + /> + + + + + {i18n.t("Name", { context: "object" })} + + + {variant === "price" + ? i18n.t("Value Range", { context: "object" }) + : i18n.t("Weight Range", { context: "object" })} + + + {i18n.t("Price", { context: "object" })} + + + + + + + {renderCollection( + rates, + rate => ( + onRateEdit(rate.id) : undefined} + > + + {maybe(() => rate.name, )} + + + {maybe( + () => + variant === "price" ? ( + + ) : ( + + ), + + )} + + + {maybe( + () => ( + + ), + + )} + + onRateEdit(rate.id)} + > + + + onRateRemove(rate.id)} + > + + + + ), + () => ( + + + {i18n.t("No shipping rates found")} + + + ) + )} + +
+
+ ) +); +ShippingZoneRates.displayName = "ShippingZoneRates"; +export default ShippingZoneRates; diff --git a/src/shipping/components/ShippingZoneRates/index.ts b/src/shipping/components/ShippingZoneRates/index.ts new file mode 100644 index 000000000..65c1ae1ce --- /dev/null +++ b/src/shipping/components/ShippingZoneRates/index.ts @@ -0,0 +1,2 @@ +export { default } from './ShippingZoneRates'; +export * from './ShippingZoneRates'; \ No newline at end of file diff --git a/src/shipping/components/ShippingZonesList/ShippingZonesList.tsx b/src/shipping/components/ShippingZonesList/ShippingZonesList.tsx new file mode 100644 index 000000000..29974968e --- /dev/null +++ b/src/shipping/components/ShippingZonesList/ShippingZonesList.tsx @@ -0,0 +1,174 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import IconButton from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Checkbox from "@saleor/components/Checkbox"; +import Skeleton from "@saleor/components/Skeleton"; +import TableHead from "@saleor/components/TableHead"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { maybe, renderCollection } from "../../../misc"; +import { ICONBUTTON_SIZE } from "../../../theme"; +import { ListActions, ListProps } from "../../../types"; +import { ShippingZoneFragment } from "../../types/ShippingZoneFragment"; + +export interface ShippingZonesListProps extends ListProps, ListActions { + shippingZones: ShippingZoneFragment[]; + onAdd: () => void; + onRemove: (id: string) => void; +} + +const styles = (theme: Theme) => + createStyles({ + [theme.breakpoints.up("lg")]: { + colCountries: {}, + colName: { width: 200 } + }, + alignRight: { + "&:last-child": { + paddingRight: theme.spacing.unit + }, + width: ICONBUTTON_SIZE + theme.spacing.unit / 2 + }, + colCountries: {}, + colName: {}, + row: { + cursor: "pointer" + } + }); +const ShippingZonesList = withStyles(styles, { name: "ShippingZonesList" })( + ({ + classes, + disabled, + onAdd, + onNextPage, + onPreviousPage, + onRemove, + onRowClick, + pageInfo, + shippingZones, + isChecked, + selected, + toggle, + toggleAll, + toolbar + }: ShippingZonesListProps & WithStyles) => ( + + + {i18n.t("Add shipping zone", { + context: "button" + })} + + } + /> + + + + {i18n.t("Name", { context: "object" })} + + + {i18n.t("Countries", { context: "object" })} + + + + + + + + + {renderCollection( + shippingZones, + shippingZone => { + const isSelected = shippingZone + ? isChecked(shippingZone.id) + : false; + + return ( + + + toggle(shippingZone.id)} + /> + + + {maybe( + () => shippingZone.name, + + )} + + + {maybe( + () => shippingZone.countries.length, + + )} + + + { + event.stopPropagation(); + onRemove(shippingZone.id); + }} + > + + + + + ); + }, + () => ( + + + {i18n.t("No shipping zones found")} + + + ) + )} + +
+
+ ) +); +ShippingZonesList.displayName = "ShippingZonesList"; +export default ShippingZonesList; diff --git a/src/shipping/components/ShippingZonesList/index.ts b/src/shipping/components/ShippingZonesList/index.ts new file mode 100644 index 000000000..f6f03db27 --- /dev/null +++ b/src/shipping/components/ShippingZonesList/index.ts @@ -0,0 +1,2 @@ +export { default } from './ShippingZonesList'; +export * from './ShippingZonesList'; \ No newline at end of file diff --git a/src/shipping/components/ShippingZonesListPage/ShippingZonesListPage.tsx b/src/shipping/components/ShippingZonesListPage/ShippingZonesListPage.tsx new file mode 100644 index 000000000..45042f23c --- /dev/null +++ b/src/shipping/components/ShippingZonesListPage/ShippingZonesListPage.tsx @@ -0,0 +1,47 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import Container from "@saleor/components/Container"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { ListActions, PageListProps } from "../../../types"; +import { WeightUnitsEnum } from "../../../types/globalTypes"; +import { ShippingZoneFragment } from "../../types/ShippingZoneFragment"; +import ShippingWeightUnitForm from "../ShippingWeightUnitForm"; +import ShippingZonesList from "../ShippingZonesList"; + +export interface ShippingZonesListPageProps extends PageListProps, ListActions { + defaultWeightUnit: WeightUnitsEnum; + shippingZones: ShippingZoneFragment[]; + onBack: () => void; + onRemove: (id: string) => void; + onSubmit: (unit: WeightUnitsEnum) => void; +} + +const ShippingZonesListPage: React.StatelessComponent< + ShippingZonesListPageProps +> = ({ defaultWeightUnit, disabled, onBack, onSubmit, ...listProps }) => ( + + {i18n.t("Configuration")} + + +
+ +
+
+ +
+
+
+); +ShippingZonesListPage.displayName = "ShippingZonesListPage"; +export default ShippingZonesListPage; diff --git a/src/shipping/components/ShippingZonesListPage/index.ts b/src/shipping/components/ShippingZonesListPage/index.ts new file mode 100644 index 000000000..199420676 --- /dev/null +++ b/src/shipping/components/ShippingZonesListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from './ShippingZonesListPage'; +export * from './ShippingZonesListPage'; \ No newline at end of file diff --git a/src/shipping/fixtures.ts b/src/shipping/fixtures.ts new file mode 100644 index 000000000..cefe56d87 --- /dev/null +++ b/src/shipping/fixtures.ts @@ -0,0 +1,1648 @@ +import { ShippingMethodTypeEnum } from "../types/globalTypes"; +import { ShippingZoneDetailsFragment } from "./types/ShippingZoneDetailsFragment"; +import { ShippingZoneFragment } from "./types/ShippingZoneFragment"; + +export const shippingZones: ShippingZoneFragment[] = [ + { + __typename: "ShippingZone", + countries: [ + { + __typename: "CountryDisplay", + code: "AX", + country: "Wyspy Alandzkie" + }, + { + __typename: "CountryDisplay", + code: "AL", + country: "Albania" + }, + { + __typename: "CountryDisplay", + code: "AD", + country: "Andora" + }, + { + __typename: "CountryDisplay", + code: "AT", + country: "Austria" + }, + { + __typename: "CountryDisplay", + code: "BY", + country: "Białoruś" + }, + { + __typename: "CountryDisplay", + code: "BE", + country: "Belgia" + }, + { + __typename: "CountryDisplay", + code: "BA", + country: "Bośnia i Hercegowina" + }, + { + __typename: "CountryDisplay", + code: "BG", + country: "Bułgaria" + }, + { + __typename: "CountryDisplay", + code: "HR", + country: "Chorwacja" + }, + { + __typename: "CountryDisplay", + code: "CZ", + country: "Czechy" + }, + { + __typename: "CountryDisplay", + code: "DK", + country: "Dania" + }, + { + __typename: "CountryDisplay", + code: "EE", + country: "Estonia" + }, + { + __typename: "CountryDisplay", + code: "FO", + country: "Wyspy Owcze" + }, + { + __typename: "CountryDisplay", + code: "FI", + country: "Finlandia" + }, + { + __typename: "CountryDisplay", + code: "FR", + country: "Francja" + }, + { + __typename: "CountryDisplay", + code: "DE", + country: "Niemcy" + }, + { + __typename: "CountryDisplay", + code: "GI", + country: "Gibraltar" + }, + { + __typename: "CountryDisplay", + code: "GR", + country: "Grecja" + }, + { + __typename: "CountryDisplay", + code: "GG", + country: "Guernsey" + }, + { + __typename: "CountryDisplay", + code: "VA", + country: "Watykan" + }, + { + __typename: "CountryDisplay", + code: "HU", + country: "Węgry" + }, + { + __typename: "CountryDisplay", + code: "IS", + country: "Islandia" + }, + { + __typename: "CountryDisplay", + code: "IE", + country: "Irlandia" + }, + { + __typename: "CountryDisplay", + code: "IM", + country: "Wyspa Man" + }, + { + __typename: "CountryDisplay", + code: "IT", + country: "Włochy" + }, + { + __typename: "CountryDisplay", + code: "JE", + country: "Jersey" + }, + { + __typename: "CountryDisplay", + code: "LV", + country: "Łotwa" + }, + { + __typename: "CountryDisplay", + code: "LI", + country: "Liechtenstein" + }, + { + __typename: "CountryDisplay", + code: "LT", + country: "Litwa" + }, + { + __typename: "CountryDisplay", + code: "LU", + country: "Luksemburg" + }, + { + __typename: "CountryDisplay", + code: "MK", + country: "Macedonia" + }, + { + __typename: "CountryDisplay", + code: "MT", + country: "Malta" + }, + { + __typename: "CountryDisplay", + code: "MD", + country: "Mołdawia" + }, + { + __typename: "CountryDisplay", + code: "MC", + country: "Monako" + }, + { + __typename: "CountryDisplay", + code: "ME", + country: "Czarnogóra" + }, + { + __typename: "CountryDisplay", + code: "NL", + country: "Holandia" + }, + { + __typename: "CountryDisplay", + code: "NO", + country: "Norwegia" + }, + { + __typename: "CountryDisplay", + code: "PL", + country: "Polska" + }, + { + __typename: "CountryDisplay", + code: "PT", + country: "Portugalia" + }, + { + __typename: "CountryDisplay", + code: "RO", + country: "Rumunia" + }, + { + __typename: "CountryDisplay", + code: "RU", + country: "Rosja" + }, + { + __typename: "CountryDisplay", + code: "SM", + country: "San Marino" + }, + { + __typename: "CountryDisplay", + code: "RS", + country: "Serbia" + }, + { + __typename: "CountryDisplay", + code: "SK", + country: "Słowacja" + }, + { + __typename: "CountryDisplay", + code: "SI", + country: "Słowenia" + }, + { + __typename: "CountryDisplay", + code: "ES", + country: "Hiszpania" + }, + { + __typename: "CountryDisplay", + code: "SJ", + country: "Svalbard i Jan Mayen" + }, + { + __typename: "CountryDisplay", + code: "SE", + country: "Szwecja" + }, + { + __typename: "CountryDisplay", + code: "CH", + country: "Szwajcaria" + }, + { + __typename: "CountryDisplay", + code: "UA", + country: "Ukraina" + }, + { + __typename: "CountryDisplay", + code: "GB", + country: "Wielka Brytania" + } + ], + id: "U2hpcHBpbmdab25lOjE=", + name: "Europe" + }, + { + __typename: "ShippingZone", + countries: [ + { + __typename: "CountryDisplay", + code: "AS", + country: "Samoa Amerykańskie" + }, + { + __typename: "CountryDisplay", + code: "AU", + country: "Australia" + }, + { + __typename: "CountryDisplay", + code: "CX", + country: "Wyspa Bożego Narodzenia" + }, + { + __typename: "CountryDisplay", + code: "CC", + country: "Wyspy Kokosowe" + }, + { + __typename: "CountryDisplay", + code: "CK", + country: "Wyspy Cooka" + }, + { + __typename: "CountryDisplay", + code: "FJ", + country: "Fidżi" + }, + { + __typename: "CountryDisplay", + code: "PF", + country: "Polinezja Francuska" + }, + { + __typename: "CountryDisplay", + code: "GU", + country: "Guam" + }, + { + __typename: "CountryDisplay", + code: "HM", + country: "Wyspy Heard i McDonalda" + }, + { + __typename: "CountryDisplay", + code: "KI", + country: "Kiribati" + }, + { + __typename: "CountryDisplay", + code: "MH", + country: "Wyspy Marshalla" + }, + { + __typename: "CountryDisplay", + code: "FM", + country: "Mikronezja" + }, + { + __typename: "CountryDisplay", + code: "NR", + country: "Nauru" + }, + { + __typename: "CountryDisplay", + code: "NC", + country: "Nowa Kaledonia" + }, + { + __typename: "CountryDisplay", + code: "NZ", + country: "Nowa Zelandia" + }, + { + __typename: "CountryDisplay", + code: "NU", + country: "Niue" + }, + { + __typename: "CountryDisplay", + code: "NF", + country: "Norfolk" + }, + { + __typename: "CountryDisplay", + code: "MP", + country: "Mariany Północne" + }, + { + __typename: "CountryDisplay", + code: "PW", + country: "Palau" + }, + { + __typename: "CountryDisplay", + code: "PG", + country: "Papua-Nowa Gwinea" + }, + { + __typename: "CountryDisplay", + code: "PN", + country: "Pitcairn" + }, + { + __typename: "CountryDisplay", + code: "WS", + country: "Samoa" + }, + { + __typename: "CountryDisplay", + code: "SB", + country: "Wyspy Salomona" + }, + { + __typename: "CountryDisplay", + code: "TK", + country: "Tokelau" + }, + { + __typename: "CountryDisplay", + code: "TO", + country: "Tonga" + }, + { + __typename: "CountryDisplay", + code: "TV", + country: "Tuvalu" + }, + { + __typename: "CountryDisplay", + code: "UM", + country: "Dalekie Wyspy Mniejsze Stanów Zjednoczonych" + }, + { + __typename: "CountryDisplay", + code: "VU", + country: "Vanuatu" + }, + { + __typename: "CountryDisplay", + code: "WF", + country: "Wallis i Futuna" + } + ], + id: "U2hpcHBpbmdab25lOjI=", + name: "Oceania" + }, + { + __typename: "ShippingZone", + + countries: [ + { + __typename: "CountryDisplay", + code: "AF", + country: "Afganistan" + }, + { + __typename: "CountryDisplay", + code: "AM", + country: "Armenia" + }, + { + __typename: "CountryDisplay", + code: "AZ", + country: "Azerbejdżan" + }, + { + __typename: "CountryDisplay", + code: "BH", + country: "Bahrajn" + }, + { + __typename: "CountryDisplay", + code: "BD", + country: "Bangladesz" + }, + { + __typename: "CountryDisplay", + code: "BT", + country: "Bhutan" + }, + { + __typename: "CountryDisplay", + code: "BN", + country: "Brunei" + }, + { + __typename: "CountryDisplay", + code: "KH", + country: "Kambodża" + }, + { + __typename: "CountryDisplay", + code: "CN", + country: "Chiny" + }, + { + __typename: "CountryDisplay", + code: "CY", + country: "Cypr" + }, + { + __typename: "CountryDisplay", + code: "GE", + country: "Gruzja" + }, + { + __typename: "CountryDisplay", + code: "HK", + country: "Hongkong" + }, + { + __typename: "CountryDisplay", + code: "IN", + country: "Indie" + }, + { + __typename: "CountryDisplay", + code: "ID", + country: "Indonezja" + }, + { + __typename: "CountryDisplay", + code: "IR", + country: "Iran" + }, + { + __typename: "CountryDisplay", + code: "IQ", + country: "Irak" + }, + { + __typename: "CountryDisplay", + code: "IL", + country: "Izrael" + }, + { + __typename: "CountryDisplay", + code: "JP", + country: "Japonia" + }, + { + __typename: "CountryDisplay", + code: "JO", + country: "Jordania" + }, + { + __typename: "CountryDisplay", + code: "KZ", + country: "Kazachstan" + }, + { + __typename: "CountryDisplay", + code: "KP", + country: "Korea Północna" + }, + { + __typename: "CountryDisplay", + code: "KR", + country: "Korea Południowa" + }, + { + __typename: "CountryDisplay", + code: "KW", + country: "Kuwejt" + }, + { + __typename: "CountryDisplay", + code: "KG", + country: "Kirgistan" + }, + { + __typename: "CountryDisplay", + code: "LA", + country: "Laos" + }, + { + __typename: "CountryDisplay", + code: "LB", + country: "Liban" + }, + { + __typename: "CountryDisplay", + code: "MO", + country: "Makau" + }, + { + __typename: "CountryDisplay", + code: "MY", + country: "Malezja" + }, + { + __typename: "CountryDisplay", + code: "MV", + country: "Malediwy" + }, + { + __typename: "CountryDisplay", + code: "MN", + country: "Mongolia" + }, + { + __typename: "CountryDisplay", + code: "MM", + country: "Mjanma" + }, + { + __typename: "CountryDisplay", + code: "NP", + country: "Nepal" + }, + { + __typename: "CountryDisplay", + code: "OM", + country: "Oman" + }, + { + __typename: "CountryDisplay", + code: "PK", + country: "Pakistan" + }, + { + __typename: "CountryDisplay", + code: "PS", + country: "Palestyna" + }, + { + __typename: "CountryDisplay", + code: "PH", + country: "Filipiny" + }, + { + __typename: "CountryDisplay", + code: "QA", + country: "Katar" + }, + { + __typename: "CountryDisplay", + code: "SA", + country: "Arabia Saudyjska" + }, + { + __typename: "CountryDisplay", + code: "SG", + country: "Singapur" + }, + { + __typename: "CountryDisplay", + code: "LK", + country: "Sri Lanka" + }, + { + __typename: "CountryDisplay", + code: "SY", + country: "Syria" + }, + { + __typename: "CountryDisplay", + code: "TW", + country: "Tajwan" + }, + { + __typename: "CountryDisplay", + code: "TJ", + country: "Tadżykistan" + }, + { + __typename: "CountryDisplay", + code: "TH", + country: "Tajlandia" + }, + { + __typename: "CountryDisplay", + code: "TL", + country: "Timor Wschodni" + }, + { + __typename: "CountryDisplay", + code: "TR", + country: "Turcja" + }, + { + __typename: "CountryDisplay", + code: "TM", + country: "Turkmenistan" + }, + { + __typename: "CountryDisplay", + code: "AE", + country: "Zjednoczone Emiraty Arabskie" + }, + { + __typename: "CountryDisplay", + code: "UZ", + country: "Uzbekistan" + }, + { + __typename: "CountryDisplay", + code: "VN", + country: "Wietnam" + }, + { + __typename: "CountryDisplay", + code: "YE", + country: "Jemen" + } + ], + id: "U2hpcHBpbmdab25lOjM=", + name: "Asia" + }, + { + __typename: "ShippingZone", + + countries: [ + { + __typename: "CountryDisplay", + code: "AI", + country: "Anguilla" + }, + { + __typename: "CountryDisplay", + code: "AG", + country: "Antigua i Barbuda" + }, + { + __typename: "CountryDisplay", + code: "AR", + country: "Argentyna" + }, + { + __typename: "CountryDisplay", + code: "AW", + country: "Aruba" + }, + { + __typename: "CountryDisplay", + code: "BS", + country: "Bahamy" + }, + { + __typename: "CountryDisplay", + code: "BB", + country: "Barbados" + }, + { + __typename: "CountryDisplay", + code: "BZ", + country: "Belize" + }, + { + __typename: "CountryDisplay", + code: "BM", + country: "Bermudy" + }, + { + __typename: "CountryDisplay", + code: "BO", + country: "Boliwia" + }, + { + __typename: "CountryDisplay", + code: "BQ", + country: "Bonaire, Sint Eustatius i Saba" + }, + { + __typename: "CountryDisplay", + code: "BV", + country: "Wyspa Bouveta" + }, + { + __typename: "CountryDisplay", + code: "BR", + country: "Brazylia" + }, + { + __typename: "CountryDisplay", + code: "CA", + country: "Kanada" + }, + { + __typename: "CountryDisplay", + code: "KY", + country: "Kajmany" + }, + { + __typename: "CountryDisplay", + code: "CL", + country: "Chile" + }, + { + __typename: "CountryDisplay", + code: "CO", + country: "Kolumbia" + }, + { + __typename: "CountryDisplay", + code: "CR", + country: "Kostaryka" + }, + { + __typename: "CountryDisplay", + code: "CU", + country: "Kuba" + }, + { + __typename: "CountryDisplay", + code: "CW", + country: "Curaçao" + }, + { + __typename: "CountryDisplay", + code: "DM", + country: "Dominika" + }, + { + __typename: "CountryDisplay", + code: "DO", + country: "Dominikana" + }, + { + __typename: "CountryDisplay", + code: "EC", + country: "Ekwador" + }, + { + __typename: "CountryDisplay", + code: "SV", + country: "Salwador" + }, + { + __typename: "CountryDisplay", + code: "FK", + country: "Falklandy" + }, + { + __typename: "CountryDisplay", + code: "GF", + country: "Gujana Francuska" + }, + { + __typename: "CountryDisplay", + code: "GL", + country: "Grenlandia" + }, + { + __typename: "CountryDisplay", + code: "GD", + country: "Grenada" + }, + { + __typename: "CountryDisplay", + code: "GP", + country: "Gwadelupa" + }, + { + __typename: "CountryDisplay", + code: "GT", + country: "Gwatemala" + }, + { + __typename: "CountryDisplay", + code: "GY", + country: "Gujana" + }, + { + __typename: "CountryDisplay", + code: "HT", + country: "Haiti" + }, + { + __typename: "CountryDisplay", + code: "HN", + country: "Honduras" + }, + { + __typename: "CountryDisplay", + code: "JM", + country: "Jamajka" + }, + { + __typename: "CountryDisplay", + code: "MQ", + country: "Martynika" + }, + { + __typename: "CountryDisplay", + code: "MX", + country: "Meksyk" + }, + { + __typename: "CountryDisplay", + code: "MS", + country: "Montserrat" + }, + { + __typename: "CountryDisplay", + code: "NI", + country: "Nikaragua" + }, + { + __typename: "CountryDisplay", + code: "PA", + country: "Panama" + }, + { + __typename: "CountryDisplay", + code: "PY", + country: "Paragwaj" + }, + { + __typename: "CountryDisplay", + code: "PE", + country: "Peru" + }, + { + __typename: "CountryDisplay", + code: "PR", + country: "Portoryko" + }, + { + __typename: "CountryDisplay", + code: "BL", + country: "Saint-Barthélemy" + }, + { + __typename: "CountryDisplay", + code: "KN", + country: "Saint Kitts i Nevis" + }, + { + __typename: "CountryDisplay", + code: "LC", + country: "Saint Lucia" + }, + { + __typename: "CountryDisplay", + code: "MF", + country: "Saint-Martin" + }, + { + __typename: "CountryDisplay", + code: "PM", + country: "Saint-Pierre i Miquelon" + }, + { + __typename: "CountryDisplay", + code: "VC", + country: "Saint Vincent i Grenadyny" + }, + { + __typename: "CountryDisplay", + code: "SX", + country: "Sint Maarten" + }, + { + __typename: "CountryDisplay", + code: "GS", + country: "Georgia Południowa i Sandwich Południowy" + }, + { + __typename: "CountryDisplay", + code: "SR", + country: "Surinam" + }, + { + __typename: "CountryDisplay", + code: "TT", + country: "Trynidad i Tobago" + }, + { + __typename: "CountryDisplay", + code: "TC", + country: "Turks i Caicos" + }, + { + __typename: "CountryDisplay", + code: "US", + country: "Stany Zjednoczone Ameryki" + }, + { + __typename: "CountryDisplay", + code: "UY", + country: "Urugwaj" + }, + { + __typename: "CountryDisplay", + code: "VE", + country: "Wenezuela" + }, + { + __typename: "CountryDisplay", + code: "VG", + country: "Brytyjskie Wyspy Dziewicze" + }, + { + __typename: "CountryDisplay", + code: "VI", + country: "Wyspy Dziewicze Stanów Zjednoczonych" + } + ], + id: "U2hpcHBpbmdab25lOjQ=", + name: "Americas" + }, + { + __typename: "ShippingZone", + + countries: [ + { + __typename: "CountryDisplay", + code: "DZ", + country: "Algeria" + }, + { + __typename: "CountryDisplay", + code: "AO", + country: "Angola" + }, + { + __typename: "CountryDisplay", + code: "BJ", + country: "Benin" + }, + { + __typename: "CountryDisplay", + code: "BW", + country: "Botswana" + }, + { + __typename: "CountryDisplay", + code: "IO", + country: "Brytyjskie Terytorium Oceanu Indyjskiego" + }, + { + __typename: "CountryDisplay", + code: "BF", + country: "Burkina Faso" + }, + { + __typename: "CountryDisplay", + code: "BI", + country: "Burundi" + }, + { + __typename: "CountryDisplay", + code: "CV", + country: "Republika Zielonego Przylądka" + }, + { + __typename: "CountryDisplay", + code: "CM", + country: "Kamerun" + }, + { + __typename: "CountryDisplay", + code: "CF", + country: "Republika Środkowoafrykańska" + }, + { + __typename: "CountryDisplay", + code: "TD", + country: "Czad" + }, + { + __typename: "CountryDisplay", + code: "KM", + country: "Komory" + }, + { + __typename: "CountryDisplay", + code: "CG", + country: "Kongo" + }, + { + __typename: "CountryDisplay", + code: "CD", + country: "Kongo" + }, + { + __typename: "CountryDisplay", + code: "CI", + country: "Wybrzeże Kości Słoniowej" + }, + { + __typename: "CountryDisplay", + code: "DJ", + country: "Dżibuti" + }, + { + __typename: "CountryDisplay", + code: "EG", + country: "Egipt" + }, + { + __typename: "CountryDisplay", + code: "GQ", + country: "Gwinea Równikowa" + }, + { + __typename: "CountryDisplay", + code: "ER", + country: "Erytrea" + }, + { + __typename: "CountryDisplay", + code: "SZ", + country: "Suazi" + }, + { + __typename: "CountryDisplay", + code: "ET", + country: "Etiopia" + }, + { + __typename: "CountryDisplay", + code: "TF", + country: "Francuskie Terytoria Południowe i Antarktyczne" + }, + { + __typename: "CountryDisplay", + code: "GA", + country: "Gabon" + }, + { + __typename: "CountryDisplay", + code: "GM", + country: "Gambia" + }, + { + __typename: "CountryDisplay", + code: "GH", + country: "Ghana" + }, + { + __typename: "CountryDisplay", + code: "GN", + country: "Gwinea" + }, + { + __typename: "CountryDisplay", + code: "GW", + country: "Gwinea Bissau" + }, + { + __typename: "CountryDisplay", + code: "KE", + country: "Kenia" + }, + { + __typename: "CountryDisplay", + code: "LS", + country: "Lesotho" + }, + { + __typename: "CountryDisplay", + code: "LR", + country: "Liberia" + }, + { + __typename: "CountryDisplay", + code: "LY", + country: "Libia" + }, + { + __typename: "CountryDisplay", + code: "MG", + country: "Madagaskar" + }, + { + __typename: "CountryDisplay", + code: "MW", + country: "Malawi" + }, + { + __typename: "CountryDisplay", + code: "ML", + country: "Mali" + }, + { + __typename: "CountryDisplay", + code: "MR", + country: "Mauretania" + }, + { + __typename: "CountryDisplay", + code: "MU", + country: "Mauritius" + }, + { + __typename: "CountryDisplay", + code: "YT", + country: "Majotta" + }, + { + __typename: "CountryDisplay", + code: "MA", + country: "Maroko" + }, + { + __typename: "CountryDisplay", + code: "MZ", + country: "Mozambik" + }, + { + __typename: "CountryDisplay", + code: "NA", + country: "Namibia" + }, + { + __typename: "CountryDisplay", + code: "NE", + country: "Niger" + }, + { + __typename: "CountryDisplay", + code: "NG", + country: "Nigeria" + }, + { + __typename: "CountryDisplay", + code: "RE", + country: "Reunion" + }, + { + __typename: "CountryDisplay", + code: "RW", + country: "Rwanda" + }, + { + __typename: "CountryDisplay", + code: "SH", + country: + "Wyspa Świętej Heleny, Wyspa Wniebowstąpienia i Tristan da Cunha" + }, + { + __typename: "CountryDisplay", + code: "ST", + country: "Wyspy Świętego Tomasza i Książęca" + }, + { + __typename: "CountryDisplay", + code: "SN", + country: "Senegal" + }, + { + __typename: "CountryDisplay", + code: "SC", + country: "Seszele" + }, + { + __typename: "CountryDisplay", + code: "SL", + country: "Sierra Leone" + }, + { + __typename: "CountryDisplay", + code: "SO", + country: "Somalia" + }, + { + __typename: "CountryDisplay", + code: "ZA", + country: "Republika Południowej Afryki" + }, + { + __typename: "CountryDisplay", + code: "SS", + country: "Sudan Południowy" + }, + { + __typename: "CountryDisplay", + code: "SD", + country: "Sudan" + }, + { + __typename: "CountryDisplay", + code: "TZ", + country: "Tanzania" + }, + { + __typename: "CountryDisplay", + code: "TG", + country: "Togo" + }, + { + __typename: "CountryDisplay", + code: "TN", + country: "Tunezja" + }, + { + __typename: "CountryDisplay", + code: "UG", + country: "Uganda" + }, + { + __typename: "CountryDisplay", + code: "EH", + country: "Sahara Zachodnia" + }, + { + __typename: "CountryDisplay", + code: "ZM", + country: "Zambia" + }, + { + __typename: "CountryDisplay", + code: "ZW", + country: "Zimbabwe" + } + ], + id: "U2hpcHBpbmdab25lOjU=", + name: "Africa" + } +]; + +export const shippingZone: ShippingZoneDetailsFragment = { + __typename: "ShippingZone", + countries: [ + { + __typename: "CountryDisplay", + code: "AX", + country: "Wyspy Alandzkie" + }, + { + __typename: "CountryDisplay", + code: "AL", + country: "Albania" + }, + { + __typename: "CountryDisplay", + code: "AD", + country: "Andora" + }, + { + __typename: "CountryDisplay", + code: "AT", + country: "Austria" + }, + { + __typename: "CountryDisplay", + code: "BY", + country: "Białoruś" + }, + { + __typename: "CountryDisplay", + code: "BE", + country: "Belgia" + }, + { + __typename: "CountryDisplay", + code: "BA", + country: "Bośnia i Hercegowina" + }, + { + __typename: "CountryDisplay", + code: "BG", + country: "Bułgaria" + }, + { + __typename: "CountryDisplay", + code: "HR", + country: "Chorwacja" + }, + { + __typename: "CountryDisplay", + code: "CZ", + country: "Czechy" + }, + { + __typename: "CountryDisplay", + code: "DK", + country: "Dania" + }, + { + __typename: "CountryDisplay", + code: "EE", + country: "Estonia" + }, + { + __typename: "CountryDisplay", + code: "FO", + country: "Wyspy Owcze" + }, + { + __typename: "CountryDisplay", + code: "FI", + country: "Finlandia" + }, + { + __typename: "CountryDisplay", + code: "FR", + country: "Francja" + }, + { + __typename: "CountryDisplay", + code: "DE", + country: "Niemcy" + }, + { + __typename: "CountryDisplay", + code: "GI", + country: "Gibraltar" + }, + { + __typename: "CountryDisplay", + code: "GR", + country: "Grecja" + }, + { + __typename: "CountryDisplay", + code: "GG", + country: "Guernsey" + }, + { + __typename: "CountryDisplay", + code: "VA", + country: "Watykan" + }, + { + __typename: "CountryDisplay", + code: "HU", + country: "Węgry" + }, + { + __typename: "CountryDisplay", + code: "IS", + country: "Islandia" + }, + { + __typename: "CountryDisplay", + code: "IE", + country: "Irlandia" + }, + { + __typename: "CountryDisplay", + code: "IM", + country: "Wyspa Man" + }, + { + __typename: "CountryDisplay", + code: "IT", + country: "Włochy" + }, + { + __typename: "CountryDisplay", + code: "JE", + country: "Jersey" + }, + { + __typename: "CountryDisplay", + code: "LV", + country: "Łotwa" + }, + { + __typename: "CountryDisplay", + code: "LI", + country: "Liechtenstein" + }, + { + __typename: "CountryDisplay", + code: "LT", + country: "Litwa" + }, + { + __typename: "CountryDisplay", + code: "LU", + country: "Luksemburg" + }, + { + __typename: "CountryDisplay", + code: "MK", + country: "Macedonia" + }, + { + __typename: "CountryDisplay", + code: "MT", + country: "Malta" + }, + { + __typename: "CountryDisplay", + code: "MD", + country: "Mołdawia" + }, + { + __typename: "CountryDisplay", + code: "MC", + country: "Monako" + }, + { + __typename: "CountryDisplay", + code: "ME", + country: "Czarnogóra" + }, + { + __typename: "CountryDisplay", + code: "NL", + country: "Holandia" + }, + { + __typename: "CountryDisplay", + code: "NO", + country: "Norwegia" + }, + { + __typename: "CountryDisplay", + code: "PL", + country: "Polska" + }, + { + __typename: "CountryDisplay", + code: "PT", + country: "Portugalia" + }, + { + __typename: "CountryDisplay", + code: "RO", + country: "Rumunia" + }, + { + __typename: "CountryDisplay", + code: "RU", + country: "Rosja" + }, + { + __typename: "CountryDisplay", + code: "SM", + country: "San Marino" + }, + { + __typename: "CountryDisplay", + code: "RS", + country: "Serbia" + }, + { + __typename: "CountryDisplay", + code: "SK", + country: "Słowacja" + }, + { + __typename: "CountryDisplay", + code: "SI", + country: "Słowenia" + }, + { + __typename: "CountryDisplay", + code: "ES", + country: "Hiszpania" + }, + { + __typename: "CountryDisplay", + code: "SJ", + country: "Svalbard i Jan Mayen" + }, + { + __typename: "CountryDisplay", + code: "SE", + country: "Szwecja" + }, + { + __typename: "CountryDisplay", + code: "CH", + country: "Szwajcaria" + }, + { + __typename: "CountryDisplay", + code: "UA", + country: "Ukraina" + }, + { + __typename: "CountryDisplay", + code: "GB", + country: "Wielka Brytania" + } + ], + default: false, + id: "U2hpcHBpbmdab25lOjE=", + name: "Europe", + shippingMethods: [ + { + __typename: "ShippingMethod", + id: "U2hpcHBpbmdNZXRob2Q6NA==", + maximumOrderPrice: null, + maximumOrderWeight: { + __typename: "Weight", + unit: "kg", + value: 80 + }, + minimumOrderPrice: { + __typename: "Money", + amount: 0, + currency: "USD" + }, + minimumOrderWeight: { + __typename: "Weight", + unit: "kg", + value: 0 + }, + name: "DB Schenker", + price: { + __typename: "Money", + amount: 45.93, + currency: "USD" + }, + type: ShippingMethodTypeEnum.WEIGHT + }, + { + __typename: "ShippingMethod", + id: "U2hpcHBpbmdNZXRob2Q6Mw==", + maximumOrderPrice: null, + maximumOrderWeight: null, + minimumOrderPrice: { + __typename: "Money", + amount: 0, + currency: "USD" + }, + minimumOrderWeight: { + __typename: "Weight", + unit: "kg", + value: 0 + }, + name: "Registred priority", + price: { + __typename: "Money", + amount: 73.87, + currency: "USD" + }, + type: ShippingMethodTypeEnum.WEIGHT + }, + { + __typename: "ShippingMethod", + id: "U2hpcHBpbmdNZXRob2Q6Mg==", + maximumOrderPrice: null, + maximumOrderWeight: null, + minimumOrderPrice: { + __typename: "Money", + amount: 0, + currency: "USD" + }, + minimumOrderWeight: { + __typename: "Weight", + unit: "kg", + value: 0 + }, + + name: "UPS", + price: { + __typename: "Money", + amount: 48.11, + currency: "USD" + }, + type: ShippingMethodTypeEnum.PRICE + }, + { + __typename: "ShippingMethod", + id: "U2hpcHBpbmdNZXRob2Q6MQ==", + maximumOrderPrice: null, + maximumOrderWeight: null, + minimumOrderPrice: { + __typename: "Money", + amount: 0, + currency: "USD" + }, + minimumOrderWeight: { + __typename: "Weight", + unit: "kg", + value: 0 + }, + name: "DHL", + price: { + __typename: "Money", + amount: 95.24, + currency: "USD" + }, + type: ShippingMethodTypeEnum.PRICE + } + ] +}; diff --git a/src/shipping/index.tsx b/src/shipping/index.tsx new file mode 100644 index 000000000..ca38149ef --- /dev/null +++ b/src/shipping/index.tsx @@ -0,0 +1,52 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { WindowTitle } from "../components/WindowTitle"; +import i18n from "../i18n"; +import { + shippingZoneAddPath, + shippingZonePath, + shippingZonesListPath, + ShippingZonesListUrlQueryParams, + ShippingZoneUrlQueryParams +} from "./urls"; +import ShippingZoneCreate from "./views/ShippingZoneCreate"; +import ShippingZoneDetailsComponent from "./views/ShippingZoneDetails"; +import ShippingZonesListComponent from "./views/ShippingZonesList"; + +const ShippingZonesList: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: ShippingZonesListUrlQueryParams = qs; + return ; +}; + +interface ShippingZoneDetailsRouteProps { + id: string; +} +const ShippingZoneDetails: React.StatelessComponent< + RouteComponentProps +> = ({ location, match }) => { + const qs = parseQs(location.search.substr(1)); + const params: ShippingZoneUrlQueryParams = qs; + return ( + + ); +}; + +export const ShippingRouter: React.StatelessComponent = () => ( + <> + + + + + + + +); +export default ShippingRouter; diff --git a/src/shipping/mutations.ts b/src/shipping/mutations.ts new file mode 100644 index 000000000..35966447b --- /dev/null +++ b/src/shipping/mutations.ts @@ -0,0 +1,209 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { countryFragment } from "../taxes/queries"; +import { shippingMethodFragment, shippingZoneDetailsFragment } from "./queries"; +import { + BulkDeleteShippingRate, + BulkDeleteShippingRateVariables +} from "./types/BulkDeleteShippingRate"; +import { + BulkDeleteShippingZone, + BulkDeleteShippingZoneVariables +} from "./types/BulkDeleteShippingZone"; +import { + CreateShippingRate, + CreateShippingRateVariables +} from "./types/CreateShippingRate"; +import { + CreateShippingZone, + CreateShippingZoneVariables +} from "./types/CreateShippingZone"; +import { + DeleteShippingRate, + DeleteShippingRateVariables +} from "./types/DeleteShippingRate"; +import { + DeleteShippingZone, + DeleteShippingZoneVariables +} from "./types/DeleteShippingZone"; +import { + UpdateDefaultWeightUnit, + UpdateDefaultWeightUnitVariables +} from "./types/UpdateDefaultWeightUnit"; +import { + UpdateShippingRate, + UpdateShippingRateVariables +} from "./types/UpdateShippingRate"; +import { + UpdateShippingZone, + UpdateShippingZoneVariables +} from "./types/UpdateShippingZone"; + +const deleteShippingZone = gql` + mutation DeleteShippingZone($id: ID!) { + shippingZoneDelete(id: $id) { + errors { + field + message + } + } + } +`; +export const TypedDeleteShippingZone = TypedMutation< + DeleteShippingZone, + DeleteShippingZoneVariables +>(deleteShippingZone); + +const bulkDeleteShippingZone = gql` + mutation BulkDeleteShippingZone($ids: [ID]!) { + shippingZoneBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedBulkDeleteShippingZone = TypedMutation< + BulkDeleteShippingZone, + BulkDeleteShippingZoneVariables +>(bulkDeleteShippingZone); + +const updateDefaultWeightUnit = gql` + mutation UpdateDefaultWeightUnit($unit: WeightUnitsEnum) { + shopSettingsUpdate(input: { defaultWeightUnit: $unit }) { + errors { + field + message + } + shop { + defaultWeightUnit + } + } + } +`; +export const TypedUpdateDefaultWeightUnit = TypedMutation< + UpdateDefaultWeightUnit, + UpdateDefaultWeightUnitVariables +>(updateDefaultWeightUnit); + +const createShippingZone = gql` + ${countryFragment} + mutation CreateShippingZone($input: ShippingZoneInput!) { + shippingZoneCreate(input: $input) { + errors { + field + message + } + shippingZone { + countries { + ...CountryFragment + } + default + id + name + } + } + } +`; +export const TypedCreateShippingZone = TypedMutation< + CreateShippingZone, + CreateShippingZoneVariables +>(createShippingZone); + +const updateShippingZone = gql` + ${countryFragment} + mutation UpdateShippingZone($id: ID!, $input: ShippingZoneInput!) { + shippingZoneUpdate(id: $id, input: $input) { + errors { + field + message + } + shippingZone { + countries { + ...CountryFragment + } + default + id + name + } + } + } +`; +export const TypedUpdateShippingZone = TypedMutation< + UpdateShippingZone, + UpdateShippingZoneVariables +>(updateShippingZone); + +const updateShippingRate = gql` + ${shippingMethodFragment} + mutation UpdateShippingRate($id: ID!, $input: ShippingPriceInput!) { + shippingPriceUpdate(id: $id, input: $input) { + errors { + field + message + } + shippingMethod { + ...ShippingMethodFragment + } + } + } +`; +export const TypedUpdateShippingRate = TypedMutation< + UpdateShippingRate, + UpdateShippingRateVariables +>(updateShippingRate); + +const createShippingRate = gql` + ${shippingZoneDetailsFragment} + mutation CreateShippingRate($input: ShippingPriceInput!) { + shippingPriceCreate(input: $input) { + errors { + field + message + } + shippingZone { + ...ShippingZoneDetailsFragment + } + } + } +`; +export const TypedCreateShippingRate = TypedMutation< + CreateShippingRate, + CreateShippingRateVariables +>(createShippingRate); + +const deleteShippingRate = gql` + ${shippingZoneDetailsFragment} + mutation DeleteShippingRate($id: ID!) { + shippingPriceDelete(id: $id) { + errors { + field + message + } + shippingZone { + ...ShippingZoneDetailsFragment + } + } + } +`; +export const TypedDeleteShippingRate = TypedMutation< + DeleteShippingRate, + DeleteShippingRateVariables +>(deleteShippingRate); + +const bulkDeleteShippingRate = gql` + mutation BulkDeleteShippingRate($ids: [ID]!) { + shippingPriceBulkDelete(ids: $ids) { + errors { + field + message + } + } + } +`; +export const TypedBulkDeleteShippingRate = TypedMutation< + BulkDeleteShippingRate, + BulkDeleteShippingRateVariables +>(bulkDeleteShippingRate); diff --git a/src/shipping/queries.ts b/src/shipping/queries.ts new file mode 100644 index 000000000..9a4a1b4e9 --- /dev/null +++ b/src/shipping/queries.ts @@ -0,0 +1,93 @@ +import gql from "graphql-tag"; + +import { pageInfoFragment, TypedQuery } from "../queries"; +import { ShippingZone, ShippingZoneVariables } from "./types/ShippingZone"; +import { ShippingZones, ShippingZonesVariables } from "./types/ShippingZones"; + +export const shippingZoneFragment = gql` + fragment ShippingZoneFragment on ShippingZone { + id + countries { + code + country + } + name + } +`; +export const shippingMethodFragment = gql` + fragment ShippingMethodFragment on ShippingMethod { + id + minimumOrderPrice { + amount + currency + } + minimumOrderWeight { + unit + value + } + maximumOrderPrice { + amount + currency + } + maximumOrderWeight { + unit + value + } + name + price { + amount + currency + } + type + } +`; +export const shippingZoneDetailsFragment = gql` + ${shippingZoneFragment} + ${shippingMethodFragment} + fragment ShippingZoneDetailsFragment on ShippingZone { + ...ShippingZoneFragment + default + shippingMethods { + ...ShippingMethodFragment + } + } +`; + +const shippingZones = gql` + ${pageInfoFragment} + ${shippingZoneFragment} + query ShippingZones( + $first: Int + $after: String + $last: Int + $before: String + ) { + shippingZones(first: $first, after: $after, last: $last, before: $before) { + edges { + node { + ...ShippingZoneFragment + } + } + pageInfo { + ...PageInfoFragment + } + } + } +`; +export const TypedShippingZones = TypedQuery< + ShippingZones, + ShippingZonesVariables +>(shippingZones); + +const shippingZone = gql` + ${shippingZoneDetailsFragment} + query ShippingZone($id: ID!) { + shippingZone(id: $id) { + ...ShippingZoneDetailsFragment + } + } +`; +export const TypedShippingZone = TypedQuery< + ShippingZone, + ShippingZoneVariables +>(shippingZone); diff --git a/src/shipping/types/BulkDeleteShippingRate.ts b/src/shipping/types/BulkDeleteShippingRate.ts new file mode 100644 index 000000000..f6e958599 --- /dev/null +++ b/src/shipping/types/BulkDeleteShippingRate.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: BulkDeleteShippingRate +// ==================================================== + +export interface BulkDeleteShippingRate_shippingPriceBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface BulkDeleteShippingRate_shippingPriceBulkDelete { + __typename: "ShippingPriceBulkDelete"; + errors: BulkDeleteShippingRate_shippingPriceBulkDelete_errors[] | null; +} + +export interface BulkDeleteShippingRate { + shippingPriceBulkDelete: BulkDeleteShippingRate_shippingPriceBulkDelete | null; +} + +export interface BulkDeleteShippingRateVariables { + ids: (string | null)[]; +} diff --git a/src/shipping/types/BulkDeleteShippingZone.ts b/src/shipping/types/BulkDeleteShippingZone.ts new file mode 100644 index 000000000..38f30216d --- /dev/null +++ b/src/shipping/types/BulkDeleteShippingZone.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: BulkDeleteShippingZone +// ==================================================== + +export interface BulkDeleteShippingZone_shippingZoneBulkDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface BulkDeleteShippingZone_shippingZoneBulkDelete { + __typename: "ShippingZoneBulkDelete"; + errors: BulkDeleteShippingZone_shippingZoneBulkDelete_errors[] | null; +} + +export interface BulkDeleteShippingZone { + shippingZoneBulkDelete: BulkDeleteShippingZone_shippingZoneBulkDelete | null; +} + +export interface BulkDeleteShippingZoneVariables { + ids: (string | null)[]; +} diff --git a/src/shipping/types/CreateShippingRate.ts b/src/shipping/types/CreateShippingRate.ts new file mode 100644 index 000000000..0d1326c9c --- /dev/null +++ b/src/shipping/types/CreateShippingRate.ts @@ -0,0 +1,86 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ShippingPriceInput, ShippingMethodTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: CreateShippingRate +// ==================================================== + +export interface CreateShippingRate_shippingPriceCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CreateShippingRate_shippingPriceCreate_shippingZone_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_minimumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_minimumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_maximumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_maximumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods { + __typename: "ShippingMethod"; + id: string; + minimumOrderPrice: CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_minimumOrderPrice | null; + minimumOrderWeight: CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_minimumOrderWeight | null; + maximumOrderPrice: CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_maximumOrderPrice | null; + maximumOrderWeight: CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_maximumOrderWeight | null; + name: string; + price: CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_price | null; + type: ShippingMethodTypeEnum | null; +} + +export interface CreateShippingRate_shippingPriceCreate_shippingZone { + __typename: "ShippingZone"; + id: string; + countries: (CreateShippingRate_shippingPriceCreate_shippingZone_countries | null)[] | null; + name: string; + default: boolean; + shippingMethods: (CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods | null)[] | null; +} + +export interface CreateShippingRate_shippingPriceCreate { + __typename: "ShippingPriceCreate"; + errors: CreateShippingRate_shippingPriceCreate_errors[] | null; + shippingZone: CreateShippingRate_shippingPriceCreate_shippingZone | null; +} + +export interface CreateShippingRate { + shippingPriceCreate: CreateShippingRate_shippingPriceCreate | null; +} + +export interface CreateShippingRateVariables { + input: ShippingPriceInput; +} diff --git a/src/shipping/types/CreateShippingZone.ts b/src/shipping/types/CreateShippingZone.ts new file mode 100644 index 000000000..e82ba553e --- /dev/null +++ b/src/shipping/types/CreateShippingZone.ts @@ -0,0 +1,43 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ShippingZoneInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: CreateShippingZone +// ==================================================== + +export interface CreateShippingZone_shippingZoneCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface CreateShippingZone_shippingZoneCreate_shippingZone_countries { + __typename: "CountryDisplay"; + country: string; + code: string; +} + +export interface CreateShippingZone_shippingZoneCreate_shippingZone { + __typename: "ShippingZone"; + countries: (CreateShippingZone_shippingZoneCreate_shippingZone_countries | null)[] | null; + default: boolean; + id: string; + name: string; +} + +export interface CreateShippingZone_shippingZoneCreate { + __typename: "ShippingZoneCreate"; + errors: CreateShippingZone_shippingZoneCreate_errors[] | null; + shippingZone: CreateShippingZone_shippingZoneCreate_shippingZone | null; +} + +export interface CreateShippingZone { + shippingZoneCreate: CreateShippingZone_shippingZoneCreate | null; +} + +export interface CreateShippingZoneVariables { + input: ShippingZoneInput; +} diff --git a/src/shipping/types/DeleteShippingRate.ts b/src/shipping/types/DeleteShippingRate.ts new file mode 100644 index 000000000..cc37e44e2 --- /dev/null +++ b/src/shipping/types/DeleteShippingRate.ts @@ -0,0 +1,86 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ShippingMethodTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: DeleteShippingRate +// ==================================================== + +export interface DeleteShippingRate_shippingPriceDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface DeleteShippingRate_shippingPriceDelete_shippingZone_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_minimumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_minimumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_maximumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_maximumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods { + __typename: "ShippingMethod"; + id: string; + minimumOrderPrice: DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_minimumOrderPrice | null; + minimumOrderWeight: DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_minimumOrderWeight | null; + maximumOrderPrice: DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_maximumOrderPrice | null; + maximumOrderWeight: DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_maximumOrderWeight | null; + name: string; + price: DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_price | null; + type: ShippingMethodTypeEnum | null; +} + +export interface DeleteShippingRate_shippingPriceDelete_shippingZone { + __typename: "ShippingZone"; + id: string; + countries: (DeleteShippingRate_shippingPriceDelete_shippingZone_countries | null)[] | null; + name: string; + default: boolean; + shippingMethods: (DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods | null)[] | null; +} + +export interface DeleteShippingRate_shippingPriceDelete { + __typename: "ShippingPriceDelete"; + errors: DeleteShippingRate_shippingPriceDelete_errors[] | null; + shippingZone: DeleteShippingRate_shippingPriceDelete_shippingZone | null; +} + +export interface DeleteShippingRate { + shippingPriceDelete: DeleteShippingRate_shippingPriceDelete | null; +} + +export interface DeleteShippingRateVariables { + id: string; +} diff --git a/src/shipping/types/DeleteShippingZone.ts b/src/shipping/types/DeleteShippingZone.ts new file mode 100644 index 000000000..5f1cbb176 --- /dev/null +++ b/src/shipping/types/DeleteShippingZone.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: DeleteShippingZone +// ==================================================== + +export interface DeleteShippingZone_shippingZoneDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface DeleteShippingZone_shippingZoneDelete { + __typename: "ShippingZoneDelete"; + errors: DeleteShippingZone_shippingZoneDelete_errors[] | null; +} + +export interface DeleteShippingZone { + shippingZoneDelete: DeleteShippingZone_shippingZoneDelete | null; +} + +export interface DeleteShippingZoneVariables { + id: string; +} diff --git a/src/shipping/types/ShippingMethodFragment.ts b/src/shipping/types/ShippingMethodFragment.ts new file mode 100644 index 000000000..0c33ded59 --- /dev/null +++ b/src/shipping/types/ShippingMethodFragment.ts @@ -0,0 +1,51 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ShippingMethodTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: ShippingMethodFragment +// ==================================================== + +export interface ShippingMethodFragment_minimumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ShippingMethodFragment_minimumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface ShippingMethodFragment_maximumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ShippingMethodFragment_maximumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface ShippingMethodFragment_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ShippingMethodFragment { + __typename: "ShippingMethod"; + id: string; + minimumOrderPrice: ShippingMethodFragment_minimumOrderPrice | null; + minimumOrderWeight: ShippingMethodFragment_minimumOrderWeight | null; + maximumOrderPrice: ShippingMethodFragment_maximumOrderPrice | null; + maximumOrderWeight: ShippingMethodFragment_maximumOrderWeight | null; + name: string; + price: ShippingMethodFragment_price | null; + type: ShippingMethodTypeEnum | null; +} diff --git a/src/shipping/types/ShippingZone.ts b/src/shipping/types/ShippingZone.ts new file mode 100644 index 000000000..7b8dc090b --- /dev/null +++ b/src/shipping/types/ShippingZone.ts @@ -0,0 +1,74 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ShippingMethodTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: ShippingZone +// ==================================================== + +export interface ShippingZone_shippingZone_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface ShippingZone_shippingZone_shippingMethods_minimumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ShippingZone_shippingZone_shippingMethods_minimumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface ShippingZone_shippingZone_shippingMethods_maximumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ShippingZone_shippingZone_shippingMethods_maximumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface ShippingZone_shippingZone_shippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ShippingZone_shippingZone_shippingMethods { + __typename: "ShippingMethod"; + id: string; + minimumOrderPrice: ShippingZone_shippingZone_shippingMethods_minimumOrderPrice | null; + minimumOrderWeight: ShippingZone_shippingZone_shippingMethods_minimumOrderWeight | null; + maximumOrderPrice: ShippingZone_shippingZone_shippingMethods_maximumOrderPrice | null; + maximumOrderWeight: ShippingZone_shippingZone_shippingMethods_maximumOrderWeight | null; + name: string; + price: ShippingZone_shippingZone_shippingMethods_price | null; + type: ShippingMethodTypeEnum | null; +} + +export interface ShippingZone_shippingZone { + __typename: "ShippingZone"; + id: string; + countries: (ShippingZone_shippingZone_countries | null)[] | null; + name: string; + default: boolean; + shippingMethods: (ShippingZone_shippingZone_shippingMethods | null)[] | null; +} + +export interface ShippingZone { + shippingZone: ShippingZone_shippingZone | null; +} + +export interface ShippingZoneVariables { + id: string; +} diff --git a/src/shipping/types/ShippingZoneDetailsFragment.ts b/src/shipping/types/ShippingZoneDetailsFragment.ts new file mode 100644 index 000000000..981e085a9 --- /dev/null +++ b/src/shipping/types/ShippingZoneDetailsFragment.ts @@ -0,0 +1,66 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ShippingMethodTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: ShippingZoneDetailsFragment +// ==================================================== + +export interface ShippingZoneDetailsFragment_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface ShippingZoneDetailsFragment_shippingMethods_minimumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ShippingZoneDetailsFragment_shippingMethods_minimumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface ShippingZoneDetailsFragment_shippingMethods_maximumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ShippingZoneDetailsFragment_shippingMethods_maximumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface ShippingZoneDetailsFragment_shippingMethods_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface ShippingZoneDetailsFragment_shippingMethods { + __typename: "ShippingMethod"; + id: string; + minimumOrderPrice: ShippingZoneDetailsFragment_shippingMethods_minimumOrderPrice | null; + minimumOrderWeight: ShippingZoneDetailsFragment_shippingMethods_minimumOrderWeight | null; + maximumOrderPrice: ShippingZoneDetailsFragment_shippingMethods_maximumOrderPrice | null; + maximumOrderWeight: ShippingZoneDetailsFragment_shippingMethods_maximumOrderWeight | null; + name: string; + price: ShippingZoneDetailsFragment_shippingMethods_price | null; + type: ShippingMethodTypeEnum | null; +} + +export interface ShippingZoneDetailsFragment { + __typename: "ShippingZone"; + id: string; + countries: (ShippingZoneDetailsFragment_countries | null)[] | null; + name: string; + default: boolean; + shippingMethods: (ShippingZoneDetailsFragment_shippingMethods | null)[] | null; +} diff --git a/src/shipping/types/ShippingZoneFragment.ts b/src/shipping/types/ShippingZoneFragment.ts new file mode 100644 index 000000000..c5523d418 --- /dev/null +++ b/src/shipping/types/ShippingZoneFragment.ts @@ -0,0 +1,20 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: ShippingZoneFragment +// ==================================================== + +export interface ShippingZoneFragment_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface ShippingZoneFragment { + __typename: "ShippingZone"; + id: string; + countries: (ShippingZoneFragment_countries | null)[] | null; + name: string; +} diff --git a/src/shipping/types/ShippingZones.ts b/src/shipping/types/ShippingZones.ts new file mode 100644 index 000000000..fc56f06d9 --- /dev/null +++ b/src/shipping/types/ShippingZones.ts @@ -0,0 +1,50 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: ShippingZones +// ==================================================== + +export interface ShippingZones_shippingZones_edges_node_countries { + __typename: "CountryDisplay"; + code: string; + country: string; +} + +export interface ShippingZones_shippingZones_edges_node { + __typename: "ShippingZone"; + id: string; + countries: (ShippingZones_shippingZones_edges_node_countries | null)[] | null; + name: string; +} + +export interface ShippingZones_shippingZones_edges { + __typename: "ShippingZoneCountableEdge"; + node: ShippingZones_shippingZones_edges_node; +} + +export interface ShippingZones_shippingZones_pageInfo { + __typename: "PageInfo"; + endCursor: string | null; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; +} + +export interface ShippingZones_shippingZones { + __typename: "ShippingZoneCountableConnection"; + edges: ShippingZones_shippingZones_edges[]; + pageInfo: ShippingZones_shippingZones_pageInfo; +} + +export interface ShippingZones { + shippingZones: ShippingZones_shippingZones | null; +} + +export interface ShippingZonesVariables { + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/shipping/types/UpdateDefaultWeightUnit.ts b/src/shipping/types/UpdateDefaultWeightUnit.ts new file mode 100644 index 000000000..b24aab1ab --- /dev/null +++ b/src/shipping/types/UpdateDefaultWeightUnit.ts @@ -0,0 +1,34 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { WeightUnitsEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: UpdateDefaultWeightUnit +// ==================================================== + +export interface UpdateDefaultWeightUnit_shopSettingsUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface UpdateDefaultWeightUnit_shopSettingsUpdate_shop { + __typename: "Shop"; + defaultWeightUnit: WeightUnitsEnum | null; +} + +export interface UpdateDefaultWeightUnit_shopSettingsUpdate { + __typename: "ShopSettingsUpdate"; + errors: UpdateDefaultWeightUnit_shopSettingsUpdate_errors[] | null; + shop: UpdateDefaultWeightUnit_shopSettingsUpdate_shop | null; +} + +export interface UpdateDefaultWeightUnit { + shopSettingsUpdate: UpdateDefaultWeightUnit_shopSettingsUpdate | null; +} + +export interface UpdateDefaultWeightUnitVariables { + unit?: WeightUnitsEnum | null; +} diff --git a/src/shipping/types/UpdateShippingRate.ts b/src/shipping/types/UpdateShippingRate.ts new file mode 100644 index 000000000..70f1ad65c --- /dev/null +++ b/src/shipping/types/UpdateShippingRate.ts @@ -0,0 +1,72 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ShippingPriceInput, ShippingMethodTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: UpdateShippingRate +// ==================================================== + +export interface UpdateShippingRate_shippingPriceUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_minimumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_minimumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_maximumOrderPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_maximumOrderWeight { + __typename: "Weight"; + unit: string; + value: number; +} + +export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_price { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod { + __typename: "ShippingMethod"; + id: string; + minimumOrderPrice: UpdateShippingRate_shippingPriceUpdate_shippingMethod_minimumOrderPrice | null; + minimumOrderWeight: UpdateShippingRate_shippingPriceUpdate_shippingMethod_minimumOrderWeight | null; + maximumOrderPrice: UpdateShippingRate_shippingPriceUpdate_shippingMethod_maximumOrderPrice | null; + maximumOrderWeight: UpdateShippingRate_shippingPriceUpdate_shippingMethod_maximumOrderWeight | null; + name: string; + price: UpdateShippingRate_shippingPriceUpdate_shippingMethod_price | null; + type: ShippingMethodTypeEnum | null; +} + +export interface UpdateShippingRate_shippingPriceUpdate { + __typename: "ShippingPriceUpdate"; + errors: UpdateShippingRate_shippingPriceUpdate_errors[] | null; + shippingMethod: UpdateShippingRate_shippingPriceUpdate_shippingMethod | null; +} + +export interface UpdateShippingRate { + shippingPriceUpdate: UpdateShippingRate_shippingPriceUpdate | null; +} + +export interface UpdateShippingRateVariables { + id: string; + input: ShippingPriceInput; +} diff --git a/src/shipping/types/UpdateShippingZone.ts b/src/shipping/types/UpdateShippingZone.ts new file mode 100644 index 000000000..f6ef4621c --- /dev/null +++ b/src/shipping/types/UpdateShippingZone.ts @@ -0,0 +1,44 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ShippingZoneInput } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: UpdateShippingZone +// ==================================================== + +export interface UpdateShippingZone_shippingZoneUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface UpdateShippingZone_shippingZoneUpdate_shippingZone_countries { + __typename: "CountryDisplay"; + country: string; + code: string; +} + +export interface UpdateShippingZone_shippingZoneUpdate_shippingZone { + __typename: "ShippingZone"; + countries: (UpdateShippingZone_shippingZoneUpdate_shippingZone_countries | null)[] | null; + default: boolean; + id: string; + name: string; +} + +export interface UpdateShippingZone_shippingZoneUpdate { + __typename: "ShippingZoneUpdate"; + errors: UpdateShippingZone_shippingZoneUpdate_errors[] | null; + shippingZone: UpdateShippingZone_shippingZoneUpdate_shippingZone | null; +} + +export interface UpdateShippingZone { + shippingZoneUpdate: UpdateShippingZone_shippingZoneUpdate | null; +} + +export interface UpdateShippingZoneVariables { + id: string; + input: ShippingZoneInput; +} diff --git a/src/shipping/urls.ts b/src/shipping/urls.ts new file mode 100644 index 000000000..c622da0a7 --- /dev/null +++ b/src/shipping/urls.ts @@ -0,0 +1,39 @@ +import { stringify as stringifyQs } from "qs"; +import * as urlJoin from "url-join"; + +import { BulkAction, Dialog, Pagination, SingleAction } from "../types"; +import { ShippingMethodTypeEnum } from "../types/globalTypes"; + +export const shippingSection = "/shipping/"; + +export const shippingZonesListPath = shippingSection; +export type ShippingZonesListUrlDialog = "remove" | "remove-many"; +export type ShippingZonesListUrlQueryParams = BulkAction & + Dialog & + Pagination & + SingleAction; +export const shippingZonesListUrl = ( + params?: ShippingZonesListUrlQueryParams +) => shippingZonesListPath + "?" + stringifyQs(params); + +export const shippingZonePath = (id: string) => + urlJoin(shippingZonesListPath, id); +export type ShippingZoneUrlDialog = + | "add-rate" + | "assign-country" + | "edit-rate" + | "remove" + | "remove-rate" + | "unassign-country"; +export type ShippingZoneUrlQueryParams = Dialog & + SingleAction & + Partial<{ + type: ShippingMethodTypeEnum; + }>; +export const shippingZoneUrl = ( + id: string, + params?: ShippingZoneUrlQueryParams +) => shippingZonePath(encodeURIComponent(id)) + "?" + stringifyQs(params); + +export const shippingZoneAddPath = urlJoin(shippingZonesListPath, "add"); +export const shippingZoneAddUrl = shippingZoneAddPath; diff --git a/src/shipping/views/ShippingZoneCreate.tsx b/src/shipping/views/ShippingZoneCreate.tsx new file mode 100644 index 000000000..f185d026b --- /dev/null +++ b/src/shipping/views/ShippingZoneCreate.tsx @@ -0,0 +1,59 @@ +import * as React from "react"; + +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import ShippingZoneCreatePage from "../components/ShippingZoneCreatePage"; +import { TypedCreateShippingZone } from "../mutations"; +import { CreateShippingZone } from "../types/CreateShippingZone"; +import { shippingZonesListUrl, shippingZoneUrl } from "../urls"; + +const ShippingZoneCreate: React.StatelessComponent<{}> = () => { + const navigate = useNavigator(); + const pushMessage = useNotifier(); + const shop = useShop(); + + const onShippingZoneCreate = (data: CreateShippingZone) => { + if (data.shippingZoneCreate.errors.length === 0) { + pushMessage({ + text: i18n.t("Successfully created new shipping zone", { + context: "notification" + }) + }); + navigate(shippingZoneUrl(data.shippingZoneCreate.shippingZone.id)); + } + }; + return ( + + {(createShippingZone, createShippingZoneOpts) => { + const formTransitionState = getMutationState( + createShippingZoneOpts.called, + createShippingZoneOpts.loading, + maybe(() => createShippingZoneOpts.data.shippingZoneCreate.errors, []) + ); + + return ( + shop.countries, [])} + disabled={createShippingZoneOpts.loading} + errors={maybe( + () => createShippingZoneOpts.data.shippingZoneCreate.errors + )} + onBack={() => navigate(shippingZonesListUrl())} + onSubmit={formData => + createShippingZone({ + variables: { + input: formData + } + }) + } + saveButtonBarState={formTransitionState} + /> + ); + }} + + ); +}; +export default ShippingZoneCreate; diff --git a/src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx b/src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx new file mode 100644 index 000000000..228ff0063 --- /dev/null +++ b/src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx @@ -0,0 +1,240 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useShop from "@saleor/hooks/useShop"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { ShippingMethodTypeEnum } from "../../../types/globalTypes"; +import ShippingZoneCountriesAssignDialog from "../../components/ShippingZoneCountriesAssignDialog"; +import ShippingZoneRateDialog from "../../components/ShippingZoneRateDialog"; +import { ShippingZoneDetailsFragment } from "../../types/ShippingZoneDetailsFragment"; +import { shippingZoneUrl, ShippingZoneUrlQueryParams } from "../../urls"; +import { ShippingZoneOperationsOutput } from "./ShippingZoneOperations"; + +export interface ShippingZoneDetailsDialogsProps { + assignCountryTransitionState: ConfirmButtonTransitionState; + createRateTransitionState: ConfirmButtonTransitionState; + deleteRateTransitionState: ConfirmButtonTransitionState; + deleteZoneTransitionState: ConfirmButtonTransitionState; + id: string; + ops: ShippingZoneOperationsOutput; + params: ShippingZoneUrlQueryParams; + shippingZone: ShippingZoneDetailsFragment; + unassignCountryTransitionState: ConfirmButtonTransitionState; + updateRateTransitionState: ConfirmButtonTransitionState; +} + +const ShippingZoneDetailsDialogs: React.StatelessComponent< + ShippingZoneDetailsDialogsProps +> = ({ + assignCountryTransitionState, + createRateTransitionState, + deleteRateTransitionState, + deleteZoneTransitionState, + id, + ops, + params, + shippingZone, + unassignCountryTransitionState, + updateRateTransitionState +}) => { + const navigate = useNavigator(); + const shop = useShop(); + + const closeModal = () => navigate(shippingZoneUrl(id), true); + + const rate = maybe(() => + shippingZone.shippingMethods.find(rate => rate.id === params.id) + ); + + return ( + <> + shop.defaultCurrency)} + disabled={ops.shippingRateUpdate.opts.loading} + errors={maybe( + () => ops.shippingRateUpdate.opts.data.shippingPriceUpdate.errors, + [] + )} + onClose={closeModal} + onSubmit={formData => + ops.shippingRateUpdate.mutate({ + id: params.id, + input: { + maximumOrderPrice: formData.noLimits + ? null + : parseFloat(formData.maxValue), + minimumOrderPrice: formData.noLimits + ? null + : parseFloat(formData.minValue), + name: formData.name, + price: formData.isFree ? 0 : parseFloat(formData.price), + shippingZone: id, + type: maybe(() => rate.type) + } + }) + } + open={params.action === "edit-rate"} + rate={rate} + variant={maybe(() => rate.type)} + /> + + ops.shippingRateDelete.mutate({ + id: params.id + }) + } + open={params.action === "remove-rate"} + title={i18n.t("Delete Shipping Method")} + variant="delete" + > + {{ name }}?", + { + context: "remove shipping method", + name: maybe(() => rate.name, "...") + } + ) + }} + /> + + shop.defaultCurrency)} + disabled={ops.shippingRateCreate.opts.loading} + errors={maybe( + () => ops.shippingRateCreate.opts.data.shippingPriceCreate.errors, + [] + )} + onClose={closeModal} + onSubmit={formData => + ops.shippingRateCreate.mutate({ + input: { + maximumOrderPrice: + params.type === ShippingMethodTypeEnum.PRICE + ? formData.noLimits + ? null + : parseFloat(formData.maxValue) + : null, + maximumOrderWeight: + params.type === ShippingMethodTypeEnum.WEIGHT + ? formData.noLimits + ? null + : parseFloat(formData.maxValue) + : null, + + minimumOrderPrice: + params.type === ShippingMethodTypeEnum.PRICE + ? formData.noLimits + ? null + : parseFloat(formData.minValue) + : null, + minimumOrderWeight: + params.type === ShippingMethodTypeEnum.WEIGHT + ? formData.noLimits + ? null + : parseFloat(formData.minValue) + : null, + name: formData.name, + price: formData.isFree ? 0 : parseFloat(formData.price), + shippingZone: id, + type: ShippingMethodTypeEnum.PRICE + } + }) + } + open={params.action === "add-rate"} + rate={undefined} + variant={params.type} + /> + + ops.shippingZoneDelete.mutate({ + id + }) + } + open={params.action === "remove"} + title={i18n.t("Delete Shipping Zone")} + variant="delete" + > + {{ name }}?", + { + context: "remove shipping zone", + name: maybe(() => shippingZone.name) + } + ) + }} + /> + + shop.countries, [])} + initial={maybe( + () => shippingZone.countries.map(country => country.code), + [] + )} + isDefault={maybe(() => shippingZone.default, false)} + onClose={closeModal} + onConfirm={formData => + ops.shippingZoneUpdate.mutate({ + id, + input: { + countries: formData.countries, + default: formData.restOfTheWorld + } + }) + } + open={params.action === "assign-country"} + /> + + ops.shippingZoneUpdate.mutate({ + id, + input: { + countries: shippingZone.countries + .filter(country => country.code !== params.id) + .map(country => country.code) + } + }) + } + open={params.action === "unassign-country"} + title={i18n.t("Remove from shipping zone")} + variant="delete" + > + {{ name }} from this shipping zone?", + { + context: "unassign country", + name: maybe( + () => + shippingZone.countries.find( + country => country.code === params.id + ).country + ) + } + ) + }} + /> + + + ); +}; +export default ShippingZoneDetailsDialogs; diff --git a/src/shipping/views/ShippingZoneDetails/ShippingZoneOperations.tsx b/src/shipping/views/ShippingZoneDetails/ShippingZoneOperations.tsx new file mode 100644 index 000000000..59d3909ad --- /dev/null +++ b/src/shipping/views/ShippingZoneDetails/ShippingZoneOperations.tsx @@ -0,0 +1,113 @@ +import * as React from "react"; + +import { getMutationProviderData } from "../../../misc"; +import { PartialMutationProviderOutput } from "../../../types"; +import { + TypedCreateShippingRate, + TypedDeleteShippingRate, + TypedDeleteShippingZone, + TypedUpdateShippingRate, + TypedUpdateShippingZone +} from "../../mutations"; +import { + CreateShippingRate, + CreateShippingRateVariables +} from "../../types/CreateShippingRate"; +import { + DeleteShippingRate, + DeleteShippingRateVariables +} from "../../types/DeleteShippingRate"; +import { + DeleteShippingZone, + DeleteShippingZoneVariables +} from "../../types/DeleteShippingZone"; +import { + UpdateShippingRate, + UpdateShippingRateVariables +} from "../../types/UpdateShippingRate"; +import { + UpdateShippingZone, + UpdateShippingZoneVariables +} from "../../types/UpdateShippingZone"; + +export interface ShippingZoneOperationsOutput { + shippingRateCreate: PartialMutationProviderOutput< + CreateShippingRate, + CreateShippingRateVariables + >; + shippingRateDelete: PartialMutationProviderOutput< + DeleteShippingRate, + DeleteShippingRateVariables + >; + shippingRateUpdate: PartialMutationProviderOutput< + UpdateShippingRate, + UpdateShippingRateVariables + >; + shippingZoneDelete: PartialMutationProviderOutput< + DeleteShippingZone, + DeleteShippingZoneVariables + >; + shippingZoneUpdate: PartialMutationProviderOutput< + UpdateShippingZone, + UpdateShippingZoneVariables + >; +} +interface ShippingZoneOperationsProps { + children: (props: ShippingZoneOperationsOutput) => React.ReactNode; + onShippingRateCreate: (data: CreateShippingRate) => void; + onShippingRateDelete: (data: DeleteShippingRate) => void; + onShippingRateUpdate: (data: UpdateShippingRate) => void; + onShippingZoneDelete: (data: DeleteShippingZone) => void; + onShippingZoneUpdate: (data: UpdateShippingZone) => void; +} + +const ShippingZoneOperations: React.StatelessComponent< + ShippingZoneOperationsProps +> = ({ + children, + onShippingRateCreate, + onShippingRateDelete, + onShippingRateUpdate, + onShippingZoneDelete, + onShippingZoneUpdate +}) => ( + + {(...shippingRateCreate) => ( + + {(...shippingRateDelete) => ( + + {(...shippingRateUpdate) => ( + + {(...shippingZoneDelete) => ( + + {(...shippingZoneUpdate) => + children({ + shippingRateCreate: getMutationProviderData( + ...shippingRateCreate + ), + shippingRateDelete: getMutationProviderData( + ...shippingRateDelete + ), + shippingRateUpdate: getMutationProviderData( + ...shippingRateUpdate + ), + shippingZoneDelete: getMutationProviderData( + ...shippingZoneDelete + ), + shippingZoneUpdate: getMutationProviderData( + ...shippingZoneUpdate + ) + }) + } + + )} + + )} + + )} + + )} + +); +ShippingZoneOperations.displayName = "ShippingZoneOperations"; +export default ShippingZoneOperations; diff --git a/src/shipping/views/ShippingZoneDetails/index.tsx b/src/shipping/views/ShippingZoneDetails/index.tsx new file mode 100644 index 000000000..e898c0113 --- /dev/null +++ b/src/shipping/views/ShippingZoneDetails/index.tsx @@ -0,0 +1,239 @@ +import * as React from "react"; + +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import i18n from "../../../i18n"; +import { getMutationState, maybe } from "../../../misc"; +import { ShippingMethodTypeEnum } from "../../../types/globalTypes"; +import ShippingZoneDetailsPage from "../../components/ShippingZoneDetailsPage"; +import { TypedShippingZone } from "../../queries"; +import { CreateShippingRate } from "../../types/CreateShippingRate"; +import { DeleteShippingRate } from "../../types/DeleteShippingRate"; +import { DeleteShippingZone } from "../../types/DeleteShippingZone"; +import { UpdateShippingRate } from "../../types/UpdateShippingRate"; +import { UpdateShippingZone } from "../../types/UpdateShippingZone"; +import { + shippingZonesListUrl, + shippingZoneUrl, + ShippingZoneUrlQueryParams +} from "../../urls"; +import ShippingZoneDetailsDialogs from "./ShippingZoneDetailsDialogs"; +import ShippingZoneOperations from "./ShippingZoneOperations"; + +export interface ShippingZoneDetailsProps { + id: string; + params: ShippingZoneUrlQueryParams; +} + +const ShippingZoneDetails: React.StatelessComponent< + ShippingZoneDetailsProps +> = ({ id, params }) => { + const navigate = useNavigator(); + const notify = useNotifier(); + + const closeModal = () => navigate(shippingZoneUrl(id)); + + const onShippingRateCreate = (data: CreateShippingRate) => { + if (data.shippingPriceCreate.errors.length === 0) { + notify({ + text: i18n.t("Successfully created rate", { + context: "shipping method" + }) + }); + closeModal(); + } + }; + + const onShippingRateUpdate = (data: UpdateShippingRate) => { + if (data.shippingPriceUpdate.errors.length === 0) { + notify({ + text: i18n.t("Successfully updated rate", { + context: "shipping method" + }) + }); + closeModal(); + } + }; + + const onShippingRateDelete = (data: DeleteShippingRate) => { + if (data.shippingPriceDelete.errors.length === 0) { + notify({ + text: i18n.t("Successfully deleted rate", { + context: "shipping method" + }) + }); + closeModal(); + } + }; + + const onShippingZoneDelete = (data: DeleteShippingZone) => { + if (data.shippingZoneDelete.errors.length === 0) { + notify({ + text: i18n.t("Successfully deleted shipping zone") + }); + navigate(shippingZonesListUrl(), true); + } + }; + + const onShippingZoneUpdate = (data: UpdateShippingZone) => { + if (data.shippingZoneUpdate.errors.length === 0) { + notify({ + text: i18n.t("Successfully updated shipping zone") + }); + closeModal(); + } + }; + + return ( + + {ops => ( + + {({ data, loading }) => { + const formTransitionState = getMutationState( + ops.shippingZoneUpdate.opts.called, + ops.shippingZoneUpdate.opts.loading, + maybe( + () => ops.shippingZoneUpdate.opts.data.shippingZoneUpdate.errors + ) + ); + const createRateTransitionState = getMutationState( + ops.shippingRateCreate.opts.called, + ops.shippingRateCreate.opts.loading, + maybe( + () => + ops.shippingRateCreate.opts.data.shippingPriceCreate.errors + ) + ); + const deleteRateTransitionState = getMutationState( + ops.shippingRateDelete.opts.called, + ops.shippingRateDelete.opts.loading, + maybe( + () => + ops.shippingRateDelete.opts.data.shippingPriceDelete.errors + ) + ); + const updateRateTransitionState = getMutationState( + ops.shippingRateUpdate.opts.called, + ops.shippingRateUpdate.opts.loading, + maybe( + () => + ops.shippingRateUpdate.opts.data.shippingPriceUpdate.errors + ) + ); + const deleteZoneTransitionState = getMutationState( + ops.shippingZoneDelete.opts.called, + ops.shippingZoneDelete.opts.loading, + maybe( + () => ops.shippingZoneDelete.opts.data.shippingZoneDelete.errors + ) + ); + + return ( + <> + + ops.shippingZoneUpdate.opts.data.shippingZoneUpdate.errors + )} + onBack={() => navigate(shippingZonesListUrl())} + onCountryAdd={() => + navigate( + shippingZoneUrl(id, { + action: "assign-country" + }) + ) + } + onCountryRemove={code => + navigate( + shippingZoneUrl(id, { + action: "unassign-country", + id: code + }) + ) + } + onDelete={() => + navigate( + shippingZoneUrl(id, { + action: "remove" + }) + ) + } + onPriceRateAdd={() => + navigate( + shippingZoneUrl(id, { + action: "add-rate", + type: ShippingMethodTypeEnum.PRICE + }) + ) + } + onPriceRateEdit={rateId => + navigate( + shippingZoneUrl(id, { + action: "edit-rate", + id: rateId + }) + ) + } + onRateRemove={rateId => + navigate( + shippingZoneUrl(id, { + action: "remove-rate", + id: rateId + }) + ) + } + onSubmit={formData => + ops.shippingZoneUpdate.mutate({ + id, + input: { + name: formData.name + } + }) + } + onWeightRateAdd={() => + navigate( + shippingZoneUrl(id, { + action: "add-rate", + type: ShippingMethodTypeEnum.WEIGHT + }) + ) + } + onWeightRateEdit={rateId => + navigate( + shippingZoneUrl(id, { + action: "edit-rate", + id: rateId + }) + ) + } + saveButtonBarState={formTransitionState} + shippingZone={maybe(() => data.shippingZone)} + /> + + + ); + }} + + )} + + ); +}; +export default ShippingZoneDetails; diff --git a/src/shipping/views/ShippingZonesList.tsx b/src/shipping/views/ShippingZonesList.tsx new file mode 100644 index 000000000..1debefce2 --- /dev/null +++ b/src/shipping/views/ShippingZonesList.tsx @@ -0,0 +1,272 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import useBulkActions from "@saleor/hooks/useBulkActions"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import useShop from "@saleor/hooks/useShop"; +import { PAGINATE_BY } from "../../config"; +import { configurationMenuUrl } from "../../configuration"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import ShippingZonesListPage from "../components/ShippingZonesListPage"; +import { + TypedBulkDeleteShippingZone, + TypedDeleteShippingZone, + TypedUpdateDefaultWeightUnit +} from "../mutations"; +import { TypedShippingZones } from "../queries"; +import { BulkDeleteShippingZone } from "../types/BulkDeleteShippingZone"; +import { DeleteShippingZone } from "../types/DeleteShippingZone"; +import { UpdateDefaultWeightUnit } from "../types/UpdateDefaultWeightUnit"; +import { + shippingZoneAddUrl, + shippingZonesListUrl, + ShippingZonesListUrlQueryParams, + shippingZoneUrl +} from "../urls"; + +interface ShippingZonesListProps { + params: ShippingZonesListUrlQueryParams; +} + +export const ShippingZonesList: React.StatelessComponent< + ShippingZonesListProps +> = ({ params }) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + const shop = useShop(); + const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( + params.ids + ); + + const paginationState = createPaginationState(PAGINATE_BY, params); + + return ( + + {({ data, loading, refetch }) => { + const handleUpdateDefaultWeightUnit = ( + data: UpdateDefaultWeightUnit + ) => { + if (data.shopSettingsUpdate.errors.length === 0) { + notify({ + text: i18n.t("Updated default weight unit", { + context: "notification" + }) + }); + } + }; + + const closeModal = () => + navigate( + shippingZonesListUrl({ + ...params, + action: undefined, + ids: undefined + }), + true + ); + + const handleShippingZoneDelete = (data: DeleteShippingZone) => { + if (data.shippingZoneDelete.errors.length === 0) { + notify({ + text: i18n.t("Updated default weight unit", { + context: "notification" + }) + }); + closeModal(); + refetch(); + } + }; + + const handleBulkDeleteShippingZone = (data: BulkDeleteShippingZone) => { + if (data.shippingZoneBulkDelete.errors.length === 0) { + notify({ + text: i18n.t("Removed shipping zones", { + context: "notification" + }) + }); + closeModal(); + reset(); + refetch(); + } + }; + return ( + + {(deleteShippingZone, deleteShippingZoneOpts) => ( + + {(updateDefaultWeightUnit, updateDefaultWeightUnitOpts) => ( + + {(bulkDeleteShippingZone, bulkDeleteShippingZoneOpts) => { + const deleteTransitionState = getMutationState( + deleteShippingZoneOpts.called, + deleteShippingZoneOpts.loading, + maybe( + () => + deleteShippingZoneOpts.data.shippingZoneDelete + .errors + ) + ); + + const bulkDeleteTransitionState = getMutationState( + bulkDeleteShippingZoneOpts.called, + bulkDeleteShippingZoneOpts.loading, + maybe( + () => + bulkDeleteShippingZoneOpts.data + .shippingZoneBulkDelete.errors + ) + ); + + const { + loadNextPage, + loadPreviousPage, + pageInfo + } = paginate( + maybe(() => data.shippingZones.pageInfo), + paginationState, + params + ); + + return ( + <> + shop.defaultWeightUnit + )} + disabled={ + loading || + deleteShippingZoneOpts.loading || + updateDefaultWeightUnitOpts.loading + } + shippingZones={maybe(() => + data.shippingZones.edges.map(edge => edge.node) + )} + pageInfo={pageInfo} + onAdd={() => navigate(shippingZoneAddUrl)} + onBack={() => navigate(configurationMenuUrl)} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRemove={id => + navigate( + shippingZonesListUrl({ + ...params, + action: "remove", + id + }) + ) + } + onRowClick={id => () => + navigate(shippingZoneUrl(id))} + onSubmit={unit => + updateDefaultWeightUnit({ + variables: { unit } + }) + } + isChecked={isSelected} + selected={listElements.length} + toggle={toggle} + toggleAll={toggleAll} + toolbar={ + + navigate( + shippingZonesListUrl({ + action: "remove-many", + ids: listElements + }) + ) + } + > + + + } + /> + + + deleteShippingZone({ + variables: { id: params.id } + }) + } + > + {{ name }} shipping zone?", + { + context: "shipping zone removal", + name: maybe( + () => + data.shippingZones.edges.find( + edge => edge.node.id === params.id + ).node.name, + "..." + ) + } + ) + }} + /> + + + bulkDeleteShippingZone({ + variables: { ids: params.ids } + }) + } + > + {{ number }} shipping zones?", + { + number: maybe( + () => params.ids.length.toString(), + "..." + ) + } + ) + }} + /> + + + ); + }} + + )} + + )} + + ); + }} + + ); +}; +ShippingZonesList.displayName = "ShippingZonesList"; +export default ShippingZonesList; diff --git a/src/siteSettings/components/SiteSettingsDetails/SiteSettingsDetails.tsx b/src/siteSettings/components/SiteSettingsDetails/SiteSettingsDetails.tsx new file mode 100644 index 000000000..136f9c1be --- /dev/null +++ b/src/siteSettings/components/SiteSettingsDetails/SiteSettingsDetails.tsx @@ -0,0 +1,81 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import FormSpacer from "@saleor/components/FormSpacer"; +import i18n from "../../../i18n"; +import { SiteSettingsPageFormData } from "../SiteSettingsPage"; + +interface SiteSettingsDetailsProps { + data: SiteSettingsPageFormData; + errors: Partial<{ + description: string; + domain: string; + name: string; + }>; + disabled: boolean; + onChange: (event: React.ChangeEvent) => void; +} + +const SiteSettingsDetails: React.StatelessComponent< + SiteSettingsDetailsProps +> = ({ data, disabled, errors, onChange }) => ( + + + + + + + + + + +); +SiteSettingsDetails.displayName = "SiteSettingsDetails"; +export default SiteSettingsDetails; diff --git a/src/siteSettings/components/SiteSettingsDetails/index.ts b/src/siteSettings/components/SiteSettingsDetails/index.ts new file mode 100644 index 000000000..ae552a229 --- /dev/null +++ b/src/siteSettings/components/SiteSettingsDetails/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SiteSettingsDetails"; +export * from "./SiteSettingsDetails"; diff --git a/src/siteSettings/components/SiteSettingsKeyDialog/SiteSettingsKeyDialog.tsx b/src/siteSettings/components/SiteSettingsKeyDialog/SiteSettingsKeyDialog.tsx new file mode 100644 index 000000000..37c0bdab0 --- /dev/null +++ b/src/siteSettings/components/SiteSettingsKeyDialog/SiteSettingsKeyDialog.tsx @@ -0,0 +1,102 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import TextField from "@material-ui/core/TextField"; +import * as React from "react"; + +import Form, { FormProps } from "@saleor/components/Form"; +import { FormSpacer } from "@saleor/components/FormSpacer"; +import SingleSelectField from "@saleor/components/SingleSelectField"; +import i18n from "../../../i18n"; +import { translatedAuthorizationKeyTypes } from "../../../misc"; +import { AuthorizationKeyType } from "../../../types/globalTypes"; + +export interface SiteSettingsKeyDialogForm { + key: string; + password: string; + type: AuthorizationKeyType; +} + +export interface SiteSettingsKeyDialogProps + extends Pick< + FormProps, + Exclude, "children"> + > { + open: boolean; + onClose: () => void; +} + +const SiteSettingsKeyDialog: React.StatelessComponent< + SiteSettingsKeyDialogProps +> = ({ errors, initial, open, onClose, onSubmit }) => { + const keyTypes = translatedAuthorizationKeyTypes(); + return ( + +
+ {({ change, data, errors }) => ( + <> + + {i18n.t("Add New Authorization Key", { + context: "modal title" + })} + + + ({ + label: keyTypes[key], + value: key + }))} + error={!!errors.keyType} + label={i18n.t("Authentication type", { + context: "input label" + })} + hint={errors.keyType} + name="type" + onChange={change} + value={data.type} + /> + + + + + + + + + + + )} +
+
+ ); +}; +SiteSettingsKeyDialog.displayName = "SiteSettingsKeyDialog"; +export default SiteSettingsKeyDialog; diff --git a/src/siteSettings/components/SiteSettingsKeyDialog/index.ts b/src/siteSettings/components/SiteSettingsKeyDialog/index.ts new file mode 100644 index 000000000..3e571551b --- /dev/null +++ b/src/siteSettings/components/SiteSettingsKeyDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SiteSettingsKeyDialog"; +export * from "./SiteSettingsKeyDialog"; diff --git a/src/siteSettings/components/SiteSettingsKeys/SiteSettingsKeys.tsx b/src/siteSettings/components/SiteSettingsKeys/SiteSettingsKeys.tsx new file mode 100644 index 000000000..8dcbd39c0 --- /dev/null +++ b/src/siteSettings/components/SiteSettingsKeys/SiteSettingsKeys.tsx @@ -0,0 +1,118 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import IconButton from "@material-ui/core/IconButton"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import DeleteIcon from "@material-ui/icons/Delete"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { + maybe, + renderCollection, + translatedAuthorizationKeyTypes +} from "../../../misc"; +import { ICONBUTTON_SIZE } from "../../../theme"; +import { AuthorizationKeyType } from "../../../types/globalTypes"; +import { SiteSettings_shop_authorizationKeys } from "../../types/SiteSettings"; + +const styles = (theme: Theme) => + createStyles({ + iconCell: { + "&:last-child": { + paddingRight: 0 + }, + width: ICONBUTTON_SIZE + theme.spacing.unit / 2 + } + }); + +interface SiteSettingsKeysProps extends WithStyles { + disabled: boolean; + keys: SiteSettings_shop_authorizationKeys[]; + onAdd: () => void; + onRemove: (name: AuthorizationKeyType) => void; +} + +const SiteSettingsKeys = withStyles(styles, { name: "SiteSettingsKeys" })( + ({ classes, disabled, keys, onAdd, onRemove }: SiteSettingsKeysProps) => { + const keyTypes = translatedAuthorizationKeyTypes(); + return ( + + + {i18n.t("Add key", { + context: "button" + })} + + } + /> + + + + + {i18n.t("Authentication Type", { context: "table header" })} + + + {i18n.t("Key", { context: "table header" })} + + + + + + {renderCollection( + keys, + key => ( + key.name)} + > + + {maybe( + () => keyTypes[key.name], + + )} + + + {maybe(() => key.key, )} + + + onRemove(key.name)}> + + + + + ), + () => ( + + {i18n.t("No keys")} + + ) + )} + +
+
+ ); + } +); +SiteSettingsKeys.displayName = "SiteSettingsKeys"; +export default SiteSettingsKeys; diff --git a/src/siteSettings/components/SiteSettingsKeys/index.ts b/src/siteSettings/components/SiteSettingsKeys/index.ts new file mode 100644 index 000000000..cb3400edf --- /dev/null +++ b/src/siteSettings/components/SiteSettingsKeys/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SiteSettingsKeys"; +export * from "./SiteSettingsKeys"; diff --git a/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx b/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx new file mode 100644 index 000000000..9bc9a9694 --- /dev/null +++ b/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx @@ -0,0 +1,98 @@ +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { maybe } from "../../../misc"; +import { AuthorizationKeyType } from "../../../types/globalTypes"; +import { SiteSettings_shop } from "../../types/SiteSettings"; +import SiteSettingsDetails from "../SiteSettingsDetails/SiteSettingsDetails"; +import SiteSettingsKeys from "../SiteSettingsKeys/SiteSettingsKeys"; + +export interface SiteSettingsPageFormData { + description: string; + domain: string; + name: string; +} + +export interface SiteSettingsPageProps { + disabled: boolean; + errors: Array<{ + field: string; + message: string; + }>; + shop: SiteSettings_shop; + saveButtonBarState: ConfirmButtonTransitionState; + onBack: () => void; + onKeyAdd: () => void; + onKeyRemove: (keyType: AuthorizationKeyType) => void; + onSubmit: (data: SiteSettingsPageFormData) => void; +} + +const SiteSettingsPage: React.StatelessComponent = ({ + disabled, + errors, + saveButtonBarState, + shop, + onBack, + onKeyAdd, + onKeyRemove, + onSubmit +}) => { + const initialForm: SiteSettingsPageFormData = { + description: maybe(() => shop.description, ""), + domain: maybe(() => shop.domain.host, ""), + name: maybe(() => shop.name, "") + }; + return ( +
+ {({ change, data, errors: formErrors, hasChanged, submit }) => ( + + {i18n.t("Configuration")} + + + {i18n.t("Site Settings")} + + + {i18n.t("Authentication keys")} + + shop.authorizationKeys)} + onAdd={onKeyAdd} + onRemove={onKeyRemove} + /> + + + + )} +
+ ); +}; +SiteSettingsPage.displayName = "SiteSettingsPage"; +export default SiteSettingsPage; diff --git a/src/siteSettings/components/SiteSettingsPage/index.ts b/src/siteSettings/components/SiteSettingsPage/index.ts new file mode 100644 index 000000000..d10967cb4 --- /dev/null +++ b/src/siteSettings/components/SiteSettingsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./SiteSettingsPage"; +export * from "./SiteSettingsPage"; diff --git a/src/siteSettings/fixtures.ts b/src/siteSettings/fixtures.ts new file mode 100644 index 000000000..b41da4c79 --- /dev/null +++ b/src/siteSettings/fixtures.ts @@ -0,0 +1,19 @@ +import { AuthorizationKeyType } from "../types/globalTypes"; +import { SiteSettings_shop } from "./types/SiteSettings"; + +export const shop: SiteSettings_shop = { + __typename: "Shop", + authorizationKeys: [ + { + __typename: "AuthorizationKey", + key: "n1n62jkn2123:123n", + name: AuthorizationKeyType.FACEBOOK + } + ], + description: "Lorem ipsum dolor sit amet", + domain: { + __typename: "Domain", + host: "localhost:8000" + }, + name: "Saleor e-commerce" +}; diff --git a/src/siteSettings/index.tsx b/src/siteSettings/index.tsx new file mode 100644 index 000000000..14598e14c --- /dev/null +++ b/src/siteSettings/index.tsx @@ -0,0 +1,18 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps } from "react-router-dom"; + +import { siteSettingsPath, SiteSettingsUrlQueryParams } from "./urls"; +import SiteSettingsComponent from "./views/"; + +const SiteSettings: React.FC> = ({ location }) => { + const qs = parseQs(location.search.substr(1)); + const params: SiteSettingsUrlQueryParams = qs; + + return ; +}; + +export const SiteSettingsSection: React.FC = () => { + return ; +}; +export default SiteSettingsSection; diff --git a/src/siteSettings/mutations.ts b/src/siteSettings/mutations.ts new file mode 100644 index 000000000..31b531d85 --- /dev/null +++ b/src/siteSettings/mutations.ts @@ -0,0 +1,91 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { shopFragment } from "./queries"; +import { + AuthorizationKeyAdd, + AuthorizationKeyAddVariables +} from "./types/AuthorizationKeyAdd"; +import { + AuthorizationKeyDelete, + AuthorizationKeyDeleteVariables +} from "./types/AuthorizationKeyDelete"; +import { + ShopSettingsUpdate, + ShopSettingsUpdateVariables +} from "./types/ShopSettingsUpdate"; + +const authorizationKeyAdd = gql` + ${shopFragment} + mutation AuthorizationKeyAdd( + $input: AuthorizationKeyInput! + $keyType: AuthorizationKeyType! + ) { + authorizationKeyAdd(input: $input, keyType: $keyType) { + errors { + field + message + } + shop { + ...ShopFragment + } + } + } +`; +export const TypedAuthorizationKeyAdd = TypedMutation< + AuthorizationKeyAdd, + AuthorizationKeyAddVariables +>(authorizationKeyAdd); + +const authorizationKeyDelete = gql` + ${shopFragment} + mutation AuthorizationKeyDelete($keyType: AuthorizationKeyType!) { + authorizationKeyDelete(keyType: $keyType) { + errors { + field + message + } + shop { + ...ShopFragment + } + } + } +`; +export const TypedAuthorizationKeyDelete = TypedMutation< + AuthorizationKeyDelete, + AuthorizationKeyDeleteVariables +>(authorizationKeyDelete); + +const shopSettingsUpdate = gql` + ${shopFragment} + mutation ShopSettingsUpdate( + $shopDomainInput: SiteDomainInput! + $shopSettingsInput: ShopSettingsInput! + ) { + shopSettingsUpdate(input: $shopSettingsInput) { + errors { + field + message + } + shop { + ...ShopFragment + } + } + shopDomainUpdate(input: $shopDomainInput) { + errors { + field + message + } + shop { + domain { + host + url + } + } + } + } +`; +export const TypedShopSettingsUpdate = TypedMutation< + ShopSettingsUpdate, + ShopSettingsUpdateVariables +>(shopSettingsUpdate); diff --git a/src/siteSettings/queries.ts b/src/siteSettings/queries.ts new file mode 100644 index 000000000..07128b873 --- /dev/null +++ b/src/siteSettings/queries.ts @@ -0,0 +1,28 @@ +import gql from "graphql-tag"; +import { TypedQuery } from "../queries"; +import { SiteSettings } from "./types/SiteSettings"; + +export const shopFragment = gql` + fragment ShopFragment on Shop { + authorizationKeys { + key + name + } + description + domain { + host + } + name + } +`; +const siteSettings = gql` + ${shopFragment} + query SiteSettings { + shop { + ...ShopFragment + } + } +`; +export const TypedSiteSettingsQuery = TypedQuery( + siteSettings +); diff --git a/src/siteSettings/types/AuthorizationKeyAdd.ts b/src/siteSettings/types/AuthorizationKeyAdd.ts new file mode 100644 index 000000000..c6524fdbf --- /dev/null +++ b/src/siteSettings/types/AuthorizationKeyAdd.ts @@ -0,0 +1,49 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AuthorizationKeyInput, AuthorizationKeyType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AuthorizationKeyAdd +// ==================================================== + +export interface AuthorizationKeyAdd_authorizationKeyAdd_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface AuthorizationKeyAdd_authorizationKeyAdd_shop_authorizationKeys { + __typename: "AuthorizationKey"; + key: string; + name: AuthorizationKeyType; +} + +export interface AuthorizationKeyAdd_authorizationKeyAdd_shop_domain { + __typename: "Domain"; + host: string; +} + +export interface AuthorizationKeyAdd_authorizationKeyAdd_shop { + __typename: "Shop"; + authorizationKeys: (AuthorizationKeyAdd_authorizationKeyAdd_shop_authorizationKeys | null)[]; + description: string | null; + domain: AuthorizationKeyAdd_authorizationKeyAdd_shop_domain; + name: string; +} + +export interface AuthorizationKeyAdd_authorizationKeyAdd { + __typename: "AuthorizationKeyAdd"; + errors: AuthorizationKeyAdd_authorizationKeyAdd_errors[] | null; + shop: AuthorizationKeyAdd_authorizationKeyAdd_shop | null; +} + +export interface AuthorizationKeyAdd { + authorizationKeyAdd: AuthorizationKeyAdd_authorizationKeyAdd | null; +} + +export interface AuthorizationKeyAddVariables { + input: AuthorizationKeyInput; + keyType: AuthorizationKeyType; +} diff --git a/src/siteSettings/types/AuthorizationKeyDelete.ts b/src/siteSettings/types/AuthorizationKeyDelete.ts new file mode 100644 index 000000000..a79185000 --- /dev/null +++ b/src/siteSettings/types/AuthorizationKeyDelete.ts @@ -0,0 +1,48 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AuthorizationKeyType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AuthorizationKeyDelete +// ==================================================== + +export interface AuthorizationKeyDelete_authorizationKeyDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface AuthorizationKeyDelete_authorizationKeyDelete_shop_authorizationKeys { + __typename: "AuthorizationKey"; + key: string; + name: AuthorizationKeyType; +} + +export interface AuthorizationKeyDelete_authorizationKeyDelete_shop_domain { + __typename: "Domain"; + host: string; +} + +export interface AuthorizationKeyDelete_authorizationKeyDelete_shop { + __typename: "Shop"; + authorizationKeys: (AuthorizationKeyDelete_authorizationKeyDelete_shop_authorizationKeys | null)[]; + description: string | null; + domain: AuthorizationKeyDelete_authorizationKeyDelete_shop_domain; + name: string; +} + +export interface AuthorizationKeyDelete_authorizationKeyDelete { + __typename: "AuthorizationKeyDelete"; + errors: AuthorizationKeyDelete_authorizationKeyDelete_errors[] | null; + shop: AuthorizationKeyDelete_authorizationKeyDelete_shop | null; +} + +export interface AuthorizationKeyDelete { + authorizationKeyDelete: AuthorizationKeyDelete_authorizationKeyDelete | null; +} + +export interface AuthorizationKeyDeleteVariables { + keyType: AuthorizationKeyType; +} diff --git a/src/siteSettings/types/ShopFragment.ts b/src/siteSettings/types/ShopFragment.ts new file mode 100644 index 000000000..dcea4c527 --- /dev/null +++ b/src/siteSettings/types/ShopFragment.ts @@ -0,0 +1,28 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AuthorizationKeyType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: ShopFragment +// ==================================================== + +export interface ShopFragment_authorizationKeys { + __typename: "AuthorizationKey"; + key: string; + name: AuthorizationKeyType; +} + +export interface ShopFragment_domain { + __typename: "Domain"; + host: string; +} + +export interface ShopFragment { + __typename: "Shop"; + authorizationKeys: (ShopFragment_authorizationKeys | null)[]; + description: string | null; + domain: ShopFragment_domain; + name: string; +} diff --git a/src/siteSettings/types/ShopSettingsUpdate.ts b/src/siteSettings/types/ShopSettingsUpdate.ts new file mode 100644 index 000000000..e78f9c121 --- /dev/null +++ b/src/siteSettings/types/ShopSettingsUpdate.ts @@ -0,0 +1,73 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { SiteDomainInput, ShopSettingsInput, AuthorizationKeyType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: ShopSettingsUpdate +// ==================================================== + +export interface ShopSettingsUpdate_shopSettingsUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ShopSettingsUpdate_shopSettingsUpdate_shop_authorizationKeys { + __typename: "AuthorizationKey"; + key: string; + name: AuthorizationKeyType; +} + +export interface ShopSettingsUpdate_shopSettingsUpdate_shop_domain { + __typename: "Domain"; + host: string; +} + +export interface ShopSettingsUpdate_shopSettingsUpdate_shop { + __typename: "Shop"; + authorizationKeys: (ShopSettingsUpdate_shopSettingsUpdate_shop_authorizationKeys | null)[]; + description: string | null; + domain: ShopSettingsUpdate_shopSettingsUpdate_shop_domain; + name: string; +} + +export interface ShopSettingsUpdate_shopSettingsUpdate { + __typename: "ShopSettingsUpdate"; + errors: ShopSettingsUpdate_shopSettingsUpdate_errors[] | null; + shop: ShopSettingsUpdate_shopSettingsUpdate_shop | null; +} + +export interface ShopSettingsUpdate_shopDomainUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface ShopSettingsUpdate_shopDomainUpdate_shop_domain { + __typename: "Domain"; + host: string; + url: string; +} + +export interface ShopSettingsUpdate_shopDomainUpdate_shop { + __typename: "Shop"; + domain: ShopSettingsUpdate_shopDomainUpdate_shop_domain; +} + +export interface ShopSettingsUpdate_shopDomainUpdate { + __typename: "ShopDomainUpdate"; + errors: ShopSettingsUpdate_shopDomainUpdate_errors[] | null; + shop: ShopSettingsUpdate_shopDomainUpdate_shop | null; +} + +export interface ShopSettingsUpdate { + shopSettingsUpdate: ShopSettingsUpdate_shopSettingsUpdate | null; + shopDomainUpdate: ShopSettingsUpdate_shopDomainUpdate | null; +} + +export interface ShopSettingsUpdateVariables { + shopDomainInput: SiteDomainInput; + shopSettingsInput: ShopSettingsInput; +} diff --git a/src/siteSettings/types/SiteSettings.ts b/src/siteSettings/types/SiteSettings.ts new file mode 100644 index 000000000..873124078 --- /dev/null +++ b/src/siteSettings/types/SiteSettings.ts @@ -0,0 +1,32 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AuthorizationKeyType } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: SiteSettings +// ==================================================== + +export interface SiteSettings_shop_authorizationKeys { + __typename: "AuthorizationKey"; + key: string; + name: AuthorizationKeyType; +} + +export interface SiteSettings_shop_domain { + __typename: "Domain"; + host: string; +} + +export interface SiteSettings_shop { + __typename: "Shop"; + authorizationKeys: (SiteSettings_shop_authorizationKeys | null)[]; + description: string | null; + domain: SiteSettings_shop_domain; + name: string; +} + +export interface SiteSettings { + shop: SiteSettings_shop | null; +} diff --git a/src/siteSettings/urls.ts b/src/siteSettings/urls.ts new file mode 100644 index 000000000..201d086a7 --- /dev/null +++ b/src/siteSettings/urls.ts @@ -0,0 +1,11 @@ +import { stringify as stringifyQs } from "qs"; + +import { Dialog } from "../types"; + +const siteSettingsSection = "/site-settings"; + +export const siteSettingsPath = siteSettingsSection; +export type SiteSettingsUrlDialog = "add-key"; +export type SiteSettingsUrlQueryParams = Dialog; +export const siteSettingsUrl = (params?: SiteSettingsUrlQueryParams) => + siteSettingsPath + "?" + stringifyQs(params); diff --git a/src/siteSettings/views/index.tsx b/src/siteSettings/views/index.tsx new file mode 100644 index 000000000..b0db5c7ea --- /dev/null +++ b/src/siteSettings/views/index.tsx @@ -0,0 +1,201 @@ +import * as React from "react"; + +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import { configurationMenuUrl } from "../../configuration"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import { AuthorizationKeyType } from "../../types/globalTypes"; +import SiteSettingsKeyDialog, { + SiteSettingsKeyDialogForm +} from "../components/SiteSettingsKeyDialog"; +import SiteSettingsPage, { + SiteSettingsPageFormData +} from "../components/SiteSettingsPage"; +import { + TypedAuthorizationKeyAdd, + TypedAuthorizationKeyDelete, + TypedShopSettingsUpdate +} from "../mutations"; +import { TypedSiteSettingsQuery } from "../queries"; +import { AuthorizationKeyAdd } from "../types/AuthorizationKeyAdd"; +import { AuthorizationKeyDelete } from "../types/AuthorizationKeyDelete"; +import { ShopSettingsUpdate } from "../types/ShopSettingsUpdate"; +import { siteSettingsUrl, SiteSettingsUrlQueryParams } from "../urls"; + +export interface SiteSettingsProps { + params: SiteSettingsUrlQueryParams; +} + +export const SiteSettings: React.StatelessComponent = ({ + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + + const handleAddKeySuccess = (data: AuthorizationKeyAdd) => { + if (!maybe(() => data.authorizationKeyAdd.errors.length)) { + notify({ + text: i18n.t("Authorization key added", { + context: "notification" + }) + }); + navigate(siteSettingsUrl()); + } + }; + const handleDeleteKeySuccess = (data: AuthorizationKeyDelete) => { + if (!maybe(() => data.authorizationKeyDelete.errors.length)) { + notify({ + text: i18n.t("Authorization key deleted", { + context: "notification" + }) + }); + } else { + notify({ + text: i18n.t("Could not delete authorization key: {{ message }}", { + context: "notification", + message: data.authorizationKeyDelete.errors[0].message + }) + }); + } + }; + const handleSiteSettingsSuccess = (data: ShopSettingsUpdate) => { + if ( + (!data.shopDomainUpdate.errors || + data.shopDomainUpdate.errors.length === 0) && + (!data.shopSettingsUpdate.errors || + data.shopSettingsUpdate.errors.length === 0) + ) { + notify({ + text: i18n.t("Site settings updated", { + context: "notification" + }) + }); + } + }; + return ( + + {siteSettings => ( + + {(addAuthorizationKey, addAuthorizationKeyOpts) => ( + + {(deleteAuthorizationKey, _) => ( + + {(updateShopSettings, updateShopSettingsOpts) => { + const errors = [ + ...maybe( + () => + updateShopSettingsOpts.data.shopDomainUpdate.errors, + [] + ), + ...maybe( + () => + updateShopSettingsOpts.data.shopSettingsUpdate.errors, + [] + ) + ]; + const loading = + siteSettings.loading || + addAuthorizationKeyOpts.loading || + updateShopSettingsOpts.loading; + + const handleAuthenticationKeyAdd = ( + data: SiteSettingsKeyDialogForm + ) => + addAuthorizationKey({ + variables: { + input: { + key: data.key, + password: data.password + }, + keyType: data.type + } + }); + const handleUpdateShopSettings = ( + data: SiteSettingsPageFormData + ) => + updateShopSettings({ + variables: { + shopDomainInput: { + domain: data.domain, + name: data.name + }, + shopSettingsInput: { + description: data.description + } + } + }); + + const formTransitionState = getMutationState( + updateShopSettingsOpts.called, + updateShopSettingsOpts.loading, + [ + ...maybe( + () => + updateShopSettingsOpts.data.shopDomainUpdate.errors, + [] + ), + ...maybe( + () => + updateShopSettingsOpts.data.shopSettingsUpdate + .errors, + [] + ) + ] + ); + + return ( + <> + + siteSettings.data.shop)} + onBack={() => navigate(configurationMenuUrl)} + onKeyAdd={() => + navigate( + siteSettingsUrl({ + action: "add-key" + }) + ) + } + onKeyRemove={keyType => + deleteAuthorizationKey({ + variables: { keyType } + }) + } + onSubmit={handleUpdateShopSettings} + saveButtonBarState={formTransitionState} + /> + + addAuthorizationKeyOpts.data.authorizationKeyAdd + .errors, + [] + )} + initial={{ + key: "", + password: "", + type: AuthorizationKeyType.FACEBOOK + }} + open={params.action === "add-key"} + onClose={() => navigate(siteSettingsUrl())} + onSubmit={handleAuthenticationKeyAdd} + /> + + ); + }} + + )} + + )} + + )} + + ); +}; +export default SiteSettings; diff --git a/src/staff/components/StaffAddMemberDialog/StaffAddMemberDialog.tsx b/src/staff/components/StaffAddMemberDialog/StaffAddMemberDialog.tsx new file mode 100644 index 000000000..0d97ee9b0 --- /dev/null +++ b/src/staff/components/StaffAddMemberDialog/StaffAddMemberDialog.tsx @@ -0,0 +1,154 @@ +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import ConfirmButton, { + ConfirmButtonTransitionState +} from "@saleor/components/ConfirmButton"; +import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; +import Form from "@saleor/components/Form"; +import FormSpacer from "@saleor/components/FormSpacer"; +import i18n from "../../../i18n"; +import { UserError } from "../../../types"; + +export interface FormData { + email: string; + firstName: string; + fullAccess: boolean; + lastName: string; +} + +const initialForm: FormData = { + email: "", + firstName: "", + fullAccess: false, + lastName: "" +}; + +const styles = (theme: Theme) => + createStyles({ + hr: { + backgroundColor: "#eaeaea", + border: "none", + height: 1, + marginBottom: 0 + }, + sectionTitle: { + fontWeight: 600 as 600, + marginBottom: theme.spacing.unit, + marginTop: theme.spacing.unit * 2 + }, + textFieldGrid: { + display: "grid", + gridColumnGap: `${theme.spacing.unit * 2}px`, + gridTemplateColumns: "1fr 1fr" + } + }); + +interface StaffAddMemberDialogProps extends WithStyles { + confirmButtonState: ConfirmButtonTransitionState; + errors: UserError[]; + open: boolean; + onClose: () => void; + onConfirm: (data: FormData) => void; +} + +const StaffAddMemberDialog = withStyles(styles, { + name: "StaffAddMemberDialog" +})( + ({ + classes, + confirmButtonState, + errors, + open, + onClose, + onConfirm + }: StaffAddMemberDialogProps) => ( + +
+ {({ change, data, errors: formErrors, hasChanged }) => ( + <> + {i18n.t("Add Staff Member")} + +
+ + +
+ + +
+
+ + + {i18n.t("Permissions")} + + + {i18n.t( + "Expand or restrict user’s permissions to access certain part of saleor system." + )} + + + + + + + {i18n.t("Send invite", { context: "button" })} + + + + )} +
+
+ ) +); +StaffAddMemberDialog.displayName = "StaffAddMemberDialog"; +export default StaffAddMemberDialog; diff --git a/src/staff/components/StaffAddMemberDialog/index.ts b/src/staff/components/StaffAddMemberDialog/index.ts new file mode 100644 index 000000000..d01805760 --- /dev/null +++ b/src/staff/components/StaffAddMemberDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./StaffAddMemberDialog"; +export * from "./StaffAddMemberDialog"; diff --git a/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx b/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx new file mode 100644 index 000000000..9083b22a0 --- /dev/null +++ b/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx @@ -0,0 +1,125 @@ +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import Container from "@saleor/components/Container"; +import Form from "@saleor/components/Form"; +import Grid from "@saleor/components/Grid"; +import PageHeader from "@saleor/components/PageHeader"; +import SaveButtonBar from "@saleor/components/SaveButtonBar"; +import i18n from "../../../i18n"; +import { getUserName, maybe } from "../../../misc"; +import { PermissionEnum } from "../../../types/globalTypes"; +import { + StaffMemberDetails_shop_permissions, + StaffMemberDetails_user +} from "../../types/StaffMemberDetails"; +import StaffPermissions from "../StaffPermissions/StaffPermissions"; +import StaffProperties from "../StaffProperties/StaffProperties"; +import StaffStatus from "../StaffStatus/StaffStatus"; + +interface FormData { + hasFullAccess: boolean; + isActive: boolean; + permissions: PermissionEnum[]; + firstName: string; + lastName: string; + email: string; +} + +export interface StaffDetailsPageProps { + canEditAvatar: boolean; + canEditStatus: boolean; + canRemove: boolean; + disabled: boolean; + permissions: StaffMemberDetails_shop_permissions[]; + saveButtonBarState: ConfirmButtonTransitionState; + staffMember: StaffMemberDetails_user; + onBack: () => void; + onDelete: () => void; + onImageDelete: () => void; + onSubmit: (data: FormData) => void; + onImageUpload(file: File); +} + +const StaffDetailsPage: React.StatelessComponent = ({ + canEditAvatar, + canEditStatus, + canRemove, + disabled, + permissions, + saveButtonBarState, + staffMember, + onBack, + onDelete, + onImageDelete, + onImageUpload, + onSubmit +}: StaffDetailsPageProps) => { + const initialForm: FormData = { + email: maybe(() => staffMember.email), + firstName: maybe(() => staffMember.firstName), + hasFullAccess: maybe( + () => + permissions.filter( + perm => + maybe(() => staffMember.permissions, []).filter( + userPerm => userPerm.code === perm.code + ).length === 0 + ).length === 0, + false + ), + isActive: maybe(() => staffMember.isActive, false), + lastName: maybe(() => staffMember.lastName), + permissions: maybe(() => staffMember.permissions, []).map(perm => perm.code) + }; + return ( +
+ {({ data, change, hasChanged, submit }) => ( + + {i18n.t("Staff Members")} + + +
+ +
+ {canEditStatus && ( +
+ + + +
+ )} +
+ +
+ )} +
+ ); +}; +StaffDetailsPage.displayName = "StaffDetailsPage"; +export default StaffDetailsPage; diff --git a/src/staff/components/StaffDetailsPage/index.ts b/src/staff/components/StaffDetailsPage/index.ts new file mode 100644 index 000000000..310f38a21 --- /dev/null +++ b/src/staff/components/StaffDetailsPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./StaffDetailsPage"; +export * from "./StaffDetailsPage"; diff --git a/src/staff/components/StaffList/StaffList.tsx b/src/staff/components/StaffList/StaffList.tsx new file mode 100644 index 000000000..0216dd234 --- /dev/null +++ b/src/staff/components/StaffList/StaffList.tsx @@ -0,0 +1,172 @@ +import Card from "@material-ui/core/Card"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import * as classNames from "classnames"; +import * as React from "react"; + +import Skeleton from "@saleor/components/Skeleton"; +import TablePagination from "@saleor/components/TablePagination"; +import i18n from "../../../i18n"; +import { + getUserInitials, + getUserName, + maybe, + renderCollection +} from "../../../misc"; +import { ListProps } from "../../../types"; +import { StaffList_staffUsers_edges_node } from "../../types/StaffList"; + +const styles = (theme: Theme) => + createStyles({ + avatar: { + alignItems: "center", + borderRadius: "100%", + display: "grid", + float: "left", + height: 47, + justifyContent: "center", + marginRight: theme.spacing.unit * 1 + "px", + overflow: "hidden", + width: 47 + }, + avatarDefault: { + "& p": { + color: "#fff", + lineHeight: "47px" + }, + background: theme.palette.primary.main, + height: 47, + textAlign: "center", + width: 47 + }, + avatarImage: { + pointerEvents: "none", + width: "100%" + }, + statusText: { + color: "#9E9D9D" + }, + tableRow: { + cursor: "pointer" + }, + wideColumn: { + width: "80%" + } + }); + +interface StaffListProps extends ListProps, WithStyles { + staffMembers: StaffList_staffUsers_edges_node[]; +} + +const StaffList = withStyles(styles, { name: "StaffList" })( + ({ + classes, + disabled, + onNextPage, + onPreviousPage, + onRowClick, + pageInfo, + staffMembers + }: StaffListProps) => ( + + + + + + {i18n.t("Name", { context: "object" })} + + + {i18n.t("Email Address", { context: "object" })} + + + + + + + + + + {renderCollection( + staffMembers, + staffMember => ( + + +
+ {maybe(() => staffMember.avatar.url) ? ( + staffMember.avatar.url)} + /> + ) : ( +
+ {getUserInitials(staffMember)} +
+ )} +
+ + {getUserName(staffMember) || } + + + {maybe( + () => + staffMember.isActive + ? i18n.t("Active", { context: "status" }) + : i18n.t("Inactive", { context: "status" }), + + )} + +
+ + {maybe( + () => staffMember.email, + + )} + +
+ ), + () => ( + + + {i18n.t("No staff members found")} + + + ) + )} +
+
+
+ ) +); +StaffList.displayName = "StaffList"; +export default StaffList; diff --git a/src/staff/components/StaffList/index.ts b/src/staff/components/StaffList/index.ts new file mode 100644 index 000000000..524579391 --- /dev/null +++ b/src/staff/components/StaffList/index.ts @@ -0,0 +1,2 @@ +export { default } from "./StaffList"; +export * from "./StaffList"; diff --git a/src/staff/components/StaffListPage/StaffListPage.tsx b/src/staff/components/StaffListPage/StaffListPage.tsx new file mode 100644 index 000000000..b5a5f0fd1 --- /dev/null +++ b/src/staff/components/StaffListPage/StaffListPage.tsx @@ -0,0 +1,42 @@ +import Button from "@material-ui/core/Button"; +import AddIcon from "@material-ui/icons/Add"; +import * as React from "react"; + +import AppHeader from "@saleor/components/AppHeader"; +import { Container } from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import i18n from "../../../i18n"; +import { ListProps } from "../../../types"; +import { StaffList_staffUsers_edges_node } from "../../types/StaffList"; +import StaffList from "../StaffList/StaffList"; + +export interface StaffListPageProps extends ListProps { + staffMembers: StaffList_staffUsers_edges_node[]; + onAdd: () => void; + onBack: () => void; +} + +const StaffListPage: React.StatelessComponent = ({ + disabled, + onAdd, + onBack, + ...listProps +}) => ( + + {i18n.t("Configuration")} + + + + + +); +StaffListPage.displayName = "StaffListPage"; +export default StaffListPage; diff --git a/src/staff/components/StaffListPage/index.ts b/src/staff/components/StaffListPage/index.ts new file mode 100644 index 000000000..acbe4f3df --- /dev/null +++ b/src/staff/components/StaffListPage/index.ts @@ -0,0 +1,2 @@ +export { default } from "./StaffListPage"; +export * from "./StaffListPage"; diff --git a/src/staff/components/StaffPermissions/StaffPermissions.tsx b/src/staff/components/StaffPermissions/StaffPermissions.tsx new file mode 100644 index 000000000..f992b6051 --- /dev/null +++ b/src/staff/components/StaffPermissions/StaffPermissions.tsx @@ -0,0 +1,121 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; +import Skeleton from "@saleor/components/Skeleton"; +import i18n from "../../../i18n"; +import { StaffMemberDetails_shop_permissions } from "../../types/StaffMemberDetails"; + +const styles = (theme: Theme) => + createStyles({ + checkboxContainer: { + marginTop: theme.spacing.unit + }, + hr: { + backgroundColor: "#eaeaea", + border: "none", + height: 1, + marginBottom: 0, + marginTop: 0 + } + }); + +interface StaffPermissionsProps extends WithStyles { + permissions: StaffMemberDetails_shop_permissions[]; + data: { + hasFullAccess: boolean; + permissions: string[]; + }; + disabled: boolean; + onChange: (event: React.ChangeEvent, cb?: () => void) => void; +} + +const StaffPermissions = withStyles(styles, { name: "StaffPermissions" })( + ({ + classes, + data, + disabled, + permissions, + onChange + }: StaffPermissionsProps) => { + const handleFullAccessChange = (event: React.ChangeEvent) => + onChange(event, () => + onChange({ + target: { + name: "permissions", + value: event.target.value ? permissions.map(perm => perm.code) : [] + } + } as any) + ); + const handlePermissionChange = (event: React.ChangeEvent) => { + onChange({ + target: { + name: "permissions", + value: event.target.value + ? data.permissions.concat([event.target.name]) + : data.permissions.filter(perm => perm !== event.target.name) + } + } as any); + }; + return ( + + + + + {i18n.t( + "Expand or restrict user's permissions to access certain part of saleor system." + )} + +
+ +
+
+ {!data.hasFullAccess && ( + <> +
+ + {permissions === undefined ? ( + + ) : ( + permissions.map(perm => ( +
+ userPerm === perm.code + ).length === 1 + } + disabled={disabled} + label={perm.name.replace(/\./, "")} + name={perm.code} + onChange={handlePermissionChange} + /> +
+ )) + )} +
+ + )} +
+ ); + } +); +StaffPermissions.displayName = "StaffPermissions"; +export default StaffPermissions; diff --git a/src/staff/components/StaffPermissions/index.ts b/src/staff/components/StaffPermissions/index.ts new file mode 100644 index 000000000..82993ead1 --- /dev/null +++ b/src/staff/components/StaffPermissions/index.ts @@ -0,0 +1,2 @@ +export { default } from "./StaffPermissions"; +export * from "./StaffPermissions"; diff --git a/src/staff/components/StaffProperties/StaffProperties.tsx b/src/staff/components/StaffProperties/StaffProperties.tsx new file mode 100644 index 000000000..b58a5cc18 --- /dev/null +++ b/src/staff/components/StaffProperties/StaffProperties.tsx @@ -0,0 +1,201 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import { + createStyles, + Theme, + withStyles, + WithStyles +} from "@material-ui/core/styles"; +import TextField from "@material-ui/core/TextField"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; +import SVG from "react-inlinesvg"; + +import CardTitle from "@saleor/components/CardTitle"; +import i18n from "../../../i18n"; +import { getUserInitials, maybe } from "../../../misc"; +import { StaffMemberDetails_user } from "../../types/StaffMemberDetails"; + +import * as photoIcon from "@assets/images/photo-icon.svg"; + +const styles = (theme: Theme) => + createStyles({ + avatar: { + "& svg": { + fill: "#fff" + }, + "&:hover $avatarHover": { + opacity: 1 + }, + alignItems: "center", + borderRadius: "100%", + display: "grid", + height: 120, + justifyContent: "center", + overflow: "hidden", + position: "relative", + width: 120 + }, + avatarDefault: { + "& p": { + color: "#fff", + fontSize: 35, + fontWeight: "bold", + lineHeight: "120px" + }, + background: theme.palette.primary.main, + height: 120, + textAlign: "center", + width: 120 + }, + avatarHover: { + "& p": { + "&:hover": { + textDecoration: "underline" + }, + color: theme.palette.primary.main, + cursor: "pointer", + fontSize: 12, + fontWeight: 500 + }, + background: "#00000080", + borderRadius: "100%", + height: 120, + opacity: 0, + padding: `${theme.spacing.unit * 2.5}px 0`, + position: "absolute", + textAlign: "center", + textTransform: "uppercase", + transition: "opacity 0.5s", + width: 120 + }, + avatarImage: { + pointerEvents: "none", + width: "100%" + }, + fileField: { + display: "none" + }, + prop: { + marginBottom: theme.spacing.unit * 2 + "px" + }, + propGrid: { + display: "grid", + gridColumnGap: theme.spacing.unit * 2 + "px", + gridRowGap: theme.spacing.unit + "px", + gridTemplateColumns: "1fr 1fr", + [theme.breakpoints.down("xs")]: { + gridTemplateColumns: "1fr" + } + }, + root: { + display: "grid", + gridColumnGap: theme.spacing.unit * 4 + "px", + gridTemplateColumns: "120px 1fr" + } + }); + +interface StaffPropertiesProps extends WithStyles { + canEditAvatar: boolean; + className?: string; + data: { + email: string; + firstName: string; + lastName: string; + }; + disabled: boolean; + staffMember: StaffMemberDetails_user; + onChange: (event: React.ChangeEvent) => void; + onImageDelete: () => void; + onImageUpload: (file: File) => void; +} + +const StaffProperties = withStyles(styles, { name: "StaffProperties" })( + ({ + canEditAvatar, + classes, + className, + data, + staffMember, + onChange, + onImageDelete, + onImageUpload + }: StaffPropertiesProps) => { + const imgInputAnchor = React.createRef(); + const clickImgInput = () => imgInputAnchor.current.click(); + return ( + + + +
+
+
+ {maybe(() => staffMember.avatar.url) ? ( + staffMember.avatar.url)} + /> + ) : ( +
+ {getUserInitials(data)} +
+ )} + {canEditAvatar && ( +
+ + + {i18n.t("Change photo")} + + + {i18n.t("Delete photo")} + + onImageUpload(event.target.files[0])} + type="file" + ref={imgInputAnchor} + /> +
+ )} +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ ); + } +); +StaffProperties.displayName = "StaffProperties"; +export default StaffProperties; diff --git a/src/staff/components/StaffProperties/index.ts b/src/staff/components/StaffProperties/index.ts new file mode 100644 index 000000000..eadc2b079 --- /dev/null +++ b/src/staff/components/StaffProperties/index.ts @@ -0,0 +1,2 @@ +export { default } from "./StaffProperties"; +export * from "./StaffProperties"; diff --git a/src/staff/components/StaffStatus/StaffStatus.tsx b/src/staff/components/StaffStatus/StaffStatus.tsx new file mode 100644 index 000000000..20fab8d68 --- /dev/null +++ b/src/staff/components/StaffStatus/StaffStatus.tsx @@ -0,0 +1,40 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Typography from "@material-ui/core/Typography"; +import * as React from "react"; + +import CardTitle from "@saleor/components/CardTitle"; +import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; +import i18n from "../../../i18n"; + +interface StaffStatusProps { + data: { + isActive: boolean; + }; + disabled: boolean; + onChange: (event: React.ChangeEvent) => void; +} + +const StaffStatus: React.StatelessComponent = ({ + data, + disabled, + onChange +}) => ( + + + + + {i18n.t("If you want to disable this account uncheck the box below")} + + + + +); +StaffStatus.displayName = "StaffStatus"; +export default StaffStatus; diff --git a/src/staff/components/StaffStatus/index.ts b/src/staff/components/StaffStatus/index.ts new file mode 100644 index 000000000..2372b443b --- /dev/null +++ b/src/staff/components/StaffStatus/index.ts @@ -0,0 +1,2 @@ +export { default } from "./StaffStatus"; +export * from "./StaffStatus"; diff --git a/src/staff/fixtures.ts b/src/staff/fixtures.ts new file mode 100644 index 000000000..9141f284f --- /dev/null +++ b/src/staff/fixtures.ts @@ -0,0 +1,238 @@ +import * as avatarImage from "../../images/avatars/avatar1.png"; +import { PermissionEnum } from "../types/globalTypes"; +import { StaffList_staffUsers_edges_node } from "./types/StaffList"; +import { StaffMemberDetails_user } from "./types/StaffMemberDetails"; + +export const permissions = [ + { + code: PermissionEnum.IMPERSONATE_USERS, + name: "Impersonate customers." + }, + { + code: PermissionEnum.MANAGE_DISCOUNTS, + name: "Manage sales and vouchers." + }, + { + code: PermissionEnum.MANAGE_MENUS, + name: "Manage navigation." + }, + { + code: PermissionEnum.MANAGE_ORDERS, + name: "Manage orders." + }, + { + code: PermissionEnum.MANAGE_PAGES, + name: "Manage pages." + }, + { + code: PermissionEnum.MANAGE_PRODUCTS, + name: "Manage products." + }, + { + code: PermissionEnum.MANAGE_SETTINGS, + name: "Manage settings." + }, + { + code: PermissionEnum.MANAGE_SHIPPING, + name: "Manage shipping." + }, + { + code: PermissionEnum.MANAGE_STAFF, + name: "Manage staff." + }, + { + code: PermissionEnum.MANAGE_USERS, + name: "Manage customers." + } +].map(perm => ({ + __typename: "PermissionDisplay" as "PermissionDisplay", + ...perm +})); +export const staffMembers: StaffList_staffUsers_edges_node[] = [ + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Chris", + id: "VXNlcjoyMQ==", + isActive: true, + lastName: "Cooper" + }, + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: false, + lastName: "Smith" + }, + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: true, + lastName: "Smith" + }, + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: true, + lastName: "Smith" + }, + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: true, + lastName: "Smith" + }, + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: true, + lastName: "Smith" + }, + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: false, + lastName: "Smith" + }, + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: true, + lastName: "Smith" + }, + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: true, + lastName: "Smith" + }, + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: false, + lastName: "Smith" + }, + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: false, + lastName: "Smith" + }, + { + avatar: { + __typename: "Image" as "Image", + url: avatarImage + }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: true, + lastName: "Smith" + } +].map(staffMember => ({ __typename: "User" as "User", ...staffMember })); +export const staffMember: StaffMemberDetails_user = { + __typename: "User", + avatar: { __typename: "Image" as "Image", url: avatarImage }, + email: "admin@example.com", + firstName: "Jacob", + id: "VXNlcjoyMQ==", + isActive: true, + lastName: "Smith", + permissions: [ + { + code: PermissionEnum.IMPERSONATE_USERS, + name: "Impersonate customers." + }, + { + code: PermissionEnum.MANAGE_DISCOUNTS, + name: "Manage sales and vouchers." + }, + { + code: PermissionEnum.MANAGE_MENUS, + name: "Manage navigation." + }, + { + code: PermissionEnum.MANAGE_ORDERS, + name: "Manage orders." + }, + { + code: PermissionEnum.MANAGE_PAGES, + name: "Manage pages." + }, + { + code: PermissionEnum.MANAGE_PRODUCTS, + name: "Manage products." + }, + { + code: PermissionEnum.MANAGE_SETTINGS, + name: "Manage settings." + }, + { + code: PermissionEnum.MANAGE_SHIPPING, + name: "Manage shipping." + }, + { + code: PermissionEnum.MANAGE_STAFF, + name: "Manage staff." + }, + { + code: PermissionEnum.MANAGE_USERS, + name: "Manage customers." + } + ].map(perm => ({ + __typename: "PermissionDisplay" as "PermissionDisplay", + ...perm + })) +}; diff --git a/src/staff/index.tsx b/src/staff/index.tsx new file mode 100644 index 000000000..5413b5995 --- /dev/null +++ b/src/staff/index.tsx @@ -0,0 +1,51 @@ +import { parse as parseQs } from "qs"; +import * as React from "react"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { WindowTitle } from "../components/WindowTitle"; +import i18n from "../i18n"; +import { + staffListPath, + StaffListUrlQueryParams, + staffMemberDetailsPath, + StaffMemberDetailsUrlQueryParams +} from "./urls"; +import StaffDetailsComponent from "./views/StaffDetails"; +import StaffListComponent from "./views/StaffList"; + +const StaffList: React.StatelessComponent> = ({ + location +}) => { + const qs = parseQs(location.search.substr(1)); + const params: StaffListUrlQueryParams = qs; + return ; +}; + +interface StaffDetailsRouteProps { + id: string; +} +const StaffDetails: React.StatelessComponent< + RouteComponentProps +> = ({ match }) => { + const qs = parseQs(location.search.substr(1)); + const params: StaffMemberDetailsUrlQueryParams = qs; + + return ( + + ); +}; + +const Component = () => ( + <> + + + + + + +); + +export default Component; diff --git a/src/staff/mutations.ts b/src/staff/mutations.ts new file mode 100644 index 000000000..a3939ecc3 --- /dev/null +++ b/src/staff/mutations.ts @@ -0,0 +1,116 @@ +import gql from "graphql-tag"; + +import { TypedMutation } from "../mutations"; +import { staffMemberDetailsFragment } from "./queries"; +import { StaffAvatarDelete } from "./types/StaffAvatarDelete"; +import { + StaffAvatarUpdate, + StaffAvatarUpdateVariables +} from "./types/StaffAvatarUpdate"; +import { + StaffMemberAdd, + StaffMemberAddVariables +} from "./types/StaffMemberAdd"; +import { + StaffMemberDelete, + StaffMemberDeleteVariables +} from "./types/StaffMemberDelete"; +import { + StaffMemberUpdate, + StaffMemberUpdateVariables +} from "./types/StaffMemberUpdate"; + +const staffMemberAddMutation = gql` + ${staffMemberDetailsFragment} + mutation StaffMemberAdd($input: StaffCreateInput!) { + staffCreate(input: $input) { + errors { + field + message + } + user { + ...StaffMemberDetailsFragment + } + } + } +`; +export const TypedStaffMemberAddMutation = TypedMutation< + StaffMemberAdd, + StaffMemberAddVariables +>(staffMemberAddMutation); + +const staffMemberUpdateMutation = gql` + ${staffMemberDetailsFragment} + mutation StaffMemberUpdate($id: ID!, $input: StaffInput!) { + staffUpdate(id: $id, input: $input) { + errors { + field + message + } + user { + ...StaffMemberDetailsFragment + } + } + } +`; +export const TypedStaffMemberUpdateMutation = TypedMutation< + StaffMemberUpdate, + StaffMemberUpdateVariables +>(staffMemberUpdateMutation); + +const staffMemberDeleteMutation = gql` + mutation StaffMemberDelete($id: ID!) { + staffDelete(id: $id) { + errors { + field + message + } + } + } +`; +export const TypedStaffMemberDeleteMutation = TypedMutation< + StaffMemberDelete, + StaffMemberDeleteVariables +>(staffMemberDeleteMutation); + +const staffAvatarUpdateMutation = gql` + mutation StaffAvatarUpdate($image: Upload!) { + userAvatarUpdate(image: $image) { + errors { + field + message + } + user { + id + avatar { + url + } + } + } + } +`; +export const TypedStaffAvatarUpdateMutation = TypedMutation< + StaffAvatarUpdate, + StaffAvatarUpdateVariables +>(staffAvatarUpdateMutation); + +const staffAvatarDeleteMutation = gql` + mutation StaffAvatarDelete { + userAvatarDelete { + errors { + field + message + } + user { + id + avatar { + url + } + } + } + } +`; +export const TypedStaffAvatarDeleteMutation = TypedMutation< + StaffAvatarDelete, + StaffMemberDeleteVariables +>(staffAvatarDeleteMutation); diff --git a/src/staff/queries.ts b/src/staff/queries.ts new file mode 100644 index 000000000..994b2f47c --- /dev/null +++ b/src/staff/queries.ts @@ -0,0 +1,77 @@ +import gql from "graphql-tag"; +import { TypedQuery } from "../queries"; +import { StaffList, StaffListVariables } from "./types/StaffList"; +import { + StaffMemberDetails, + StaffMemberDetailsVariables +} from "./types/StaffMemberDetails"; + +export const staffMemberFragment = gql` + fragment StaffMemberFragment on User { + id + email + firstName + isActive + lastName + avatar { + url + } + } +`; +export const staffMemberDetailsFragment = gql` + ${staffMemberFragment} + fragment StaffMemberDetailsFragment on User { + ...StaffMemberFragment + permissions { + code + name + } + } +`; +const staffList = gql` + ${staffMemberFragment} + query StaffList($first: Int, $after: String, $last: Int, $before: String) { + staffUsers(before: $before, after: $after, first: $first, last: $last) { + edges { + cursor + node { + ...StaffMemberFragment + } + } + pageInfo { + hasPreviousPage + hasNextPage + startCursor + endCursor + } + } + shop { + permissions { + code + name + } + } + } +`; +export const TypedStaffListQuery = TypedQuery( + staffList +); + +export const staffMemberDetails = gql` + ${staffMemberDetailsFragment} + query StaffMemberDetails($id: ID!) { + user(id: $id) { + ...StaffMemberDetailsFragment + } + shop { + permissions { + code + name + } + } + } +`; +export const TypedStaffMemberDetailsQuery = TypedQuery< + StaffMemberDetails, + StaffMemberDetailsVariables +>(staffMemberDetails); diff --git a/src/staff/types/StaffAvatarDelete.ts b/src/staff/types/StaffAvatarDelete.ts new file mode 100644 index 000000000..763ee71e6 --- /dev/null +++ b/src/staff/types/StaffAvatarDelete.ts @@ -0,0 +1,34 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: StaffAvatarDelete +// ==================================================== + +export interface StaffAvatarDelete_userAvatarDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface StaffAvatarDelete_userAvatarDelete_user_avatar { + __typename: "Image"; + url: string; +} + +export interface StaffAvatarDelete_userAvatarDelete_user { + __typename: "User"; + id: string; + avatar: StaffAvatarDelete_userAvatarDelete_user_avatar | null; +} + +export interface StaffAvatarDelete_userAvatarDelete { + __typename: "UserAvatarDelete"; + errors: StaffAvatarDelete_userAvatarDelete_errors[] | null; + user: StaffAvatarDelete_userAvatarDelete_user | null; +} + +export interface StaffAvatarDelete { + userAvatarDelete: StaffAvatarDelete_userAvatarDelete | null; +} diff --git a/src/staff/types/StaffAvatarUpdate.ts b/src/staff/types/StaffAvatarUpdate.ts new file mode 100644 index 000000000..847f5c80d --- /dev/null +++ b/src/staff/types/StaffAvatarUpdate.ts @@ -0,0 +1,38 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: StaffAvatarUpdate +// ==================================================== + +export interface StaffAvatarUpdate_userAvatarUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface StaffAvatarUpdate_userAvatarUpdate_user_avatar { + __typename: "Image"; + url: string; +} + +export interface StaffAvatarUpdate_userAvatarUpdate_user { + __typename: "User"; + id: string; + avatar: StaffAvatarUpdate_userAvatarUpdate_user_avatar | null; +} + +export interface StaffAvatarUpdate_userAvatarUpdate { + __typename: "UserAvatarUpdate"; + errors: StaffAvatarUpdate_userAvatarUpdate_errors[] | null; + user: StaffAvatarUpdate_userAvatarUpdate_user | null; +} + +export interface StaffAvatarUpdate { + userAvatarUpdate: StaffAvatarUpdate_userAvatarUpdate | null; +} + +export interface StaffAvatarUpdateVariables { + image: any; +} diff --git a/src/staff/types/StaffList.ts b/src/staff/types/StaffList.ts new file mode 100644 index 000000000..2a3663628 --- /dev/null +++ b/src/staff/types/StaffList.ts @@ -0,0 +1,67 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: StaffList +// ==================================================== + +export interface StaffList_staffUsers_edges_node_avatar { + __typename: "Image"; + url: string; +} + +export interface StaffList_staffUsers_edges_node { + __typename: "User"; + id: string; + email: string; + firstName: string; + isActive: boolean; + lastName: string; + avatar: StaffList_staffUsers_edges_node_avatar | null; +} + +export interface StaffList_staffUsers_edges { + __typename: "UserCountableEdge"; + cursor: string; + node: StaffList_staffUsers_edges_node; +} + +export interface StaffList_staffUsers_pageInfo { + __typename: "PageInfo"; + hasPreviousPage: boolean; + hasNextPage: boolean; + startCursor: string | null; + endCursor: string | null; +} + +export interface StaffList_staffUsers { + __typename: "UserCountableConnection"; + edges: StaffList_staffUsers_edges[]; + pageInfo: StaffList_staffUsers_pageInfo; +} + +export interface StaffList_shop_permissions { + __typename: "PermissionDisplay"; + code: PermissionEnum; + name: string; +} + +export interface StaffList_shop { + __typename: "Shop"; + permissions: (StaffList_shop_permissions | null)[]; +} + +export interface StaffList { + staffUsers: StaffList_staffUsers | null; + shop: StaffList_shop | null; +} + +export interface StaffListVariables { + first?: number | null; + after?: string | null; + last?: number | null; + before?: string | null; +} diff --git a/src/staff/types/StaffMemberAdd.ts b/src/staff/types/StaffMemberAdd.ts new file mode 100644 index 000000000..b19fcddb3 --- /dev/null +++ b/src/staff/types/StaffMemberAdd.ts @@ -0,0 +1,51 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { StaffCreateInput, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: StaffMemberAdd +// ==================================================== + +export interface StaffMemberAdd_staffCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface StaffMemberAdd_staffCreate_user_avatar { + __typename: "Image"; + url: string; +} + +export interface StaffMemberAdd_staffCreate_user_permissions { + __typename: "PermissionDisplay"; + code: PermissionEnum; + name: string; +} + +export interface StaffMemberAdd_staffCreate_user { + __typename: "User"; + id: string; + email: string; + firstName: string; + isActive: boolean; + lastName: string; + avatar: StaffMemberAdd_staffCreate_user_avatar | null; + permissions: (StaffMemberAdd_staffCreate_user_permissions | null)[] | null; +} + +export interface StaffMemberAdd_staffCreate { + __typename: "StaffCreate"; + errors: StaffMemberAdd_staffCreate_errors[] | null; + user: StaffMemberAdd_staffCreate_user | null; +} + +export interface StaffMemberAdd { + staffCreate: StaffMemberAdd_staffCreate | null; +} + +export interface StaffMemberAddVariables { + input: StaffCreateInput; +} diff --git a/src/staff/types/StaffMemberDelete.ts b/src/staff/types/StaffMemberDelete.ts new file mode 100644 index 000000000..7a238232f --- /dev/null +++ b/src/staff/types/StaffMemberDelete.ts @@ -0,0 +1,26 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL mutation operation: StaffMemberDelete +// ==================================================== + +export interface StaffMemberDelete_staffDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface StaffMemberDelete_staffDelete { + __typename: "StaffDelete"; + errors: StaffMemberDelete_staffDelete_errors[] | null; +} + +export interface StaffMemberDelete { + staffDelete: StaffMemberDelete_staffDelete | null; +} + +export interface StaffMemberDeleteVariables { + id: string; +} diff --git a/src/staff/types/StaffMemberDetails.ts b/src/staff/types/StaffMemberDetails.ts new file mode 100644 index 000000000..d7cc5b763 --- /dev/null +++ b/src/staff/types/StaffMemberDetails.ts @@ -0,0 +1,51 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: StaffMemberDetails +// ==================================================== + +export interface StaffMemberDetails_user_avatar { + __typename: "Image"; + url: string; +} + +export interface StaffMemberDetails_user_permissions { + __typename: "PermissionDisplay"; + code: PermissionEnum; + name: string; +} + +export interface StaffMemberDetails_user { + __typename: "User"; + id: string; + email: string; + firstName: string; + isActive: boolean; + lastName: string; + avatar: StaffMemberDetails_user_avatar | null; + permissions: (StaffMemberDetails_user_permissions | null)[] | null; +} + +export interface StaffMemberDetails_shop_permissions { + __typename: "PermissionDisplay"; + code: PermissionEnum; + name: string; +} + +export interface StaffMemberDetails_shop { + __typename: "Shop"; + permissions: (StaffMemberDetails_shop_permissions | null)[]; +} + +export interface StaffMemberDetails { + user: StaffMemberDetails_user | null; + shop: StaffMemberDetails_shop | null; +} + +export interface StaffMemberDetailsVariables { + id: string; +} diff --git a/src/staff/types/StaffMemberDetailsFragment.ts b/src/staff/types/StaffMemberDetailsFragment.ts new file mode 100644 index 000000000..332de7b4a --- /dev/null +++ b/src/staff/types/StaffMemberDetailsFragment.ts @@ -0,0 +1,31 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: StaffMemberDetailsFragment +// ==================================================== + +export interface StaffMemberDetailsFragment_avatar { + __typename: "Image"; + url: string; +} + +export interface StaffMemberDetailsFragment_permissions { + __typename: "PermissionDisplay"; + code: PermissionEnum; + name: string; +} + +export interface StaffMemberDetailsFragment { + __typename: "User"; + id: string; + email: string; + firstName: string; + isActive: boolean; + lastName: string; + avatar: StaffMemberDetailsFragment_avatar | null; + permissions: (StaffMemberDetailsFragment_permissions | null)[] | null; +} diff --git a/src/staff/types/StaffMemberFragment.ts b/src/staff/types/StaffMemberFragment.ts new file mode 100644 index 000000000..f5098fcdf --- /dev/null +++ b/src/staff/types/StaffMemberFragment.ts @@ -0,0 +1,22 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL fragment: StaffMemberFragment +// ==================================================== + +export interface StaffMemberFragment_avatar { + __typename: "Image"; + url: string; +} + +export interface StaffMemberFragment { + __typename: "User"; + id: string; + email: string; + firstName: string; + isActive: boolean; + lastName: string; + avatar: StaffMemberFragment_avatar | null; +} diff --git a/src/staff/types/StaffMemberUpdate.ts b/src/staff/types/StaffMemberUpdate.ts new file mode 100644 index 000000000..158b084db --- /dev/null +++ b/src/staff/types/StaffMemberUpdate.ts @@ -0,0 +1,52 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { StaffInput, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: StaffMemberUpdate +// ==================================================== + +export interface StaffMemberUpdate_staffUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + +export interface StaffMemberUpdate_staffUpdate_user_avatar { + __typename: "Image"; + url: string; +} + +export interface StaffMemberUpdate_staffUpdate_user_permissions { + __typename: "PermissionDisplay"; + code: PermissionEnum; + name: string; +} + +export interface StaffMemberUpdate_staffUpdate_user { + __typename: "User"; + id: string; + email: string; + firstName: string; + isActive: boolean; + lastName: string; + avatar: StaffMemberUpdate_staffUpdate_user_avatar | null; + permissions: (StaffMemberUpdate_staffUpdate_user_permissions | null)[] | null; +} + +export interface StaffMemberUpdate_staffUpdate { + __typename: "StaffUpdate"; + errors: StaffMemberUpdate_staffUpdate_errors[] | null; + user: StaffMemberUpdate_staffUpdate_user | null; +} + +export interface StaffMemberUpdate { + staffUpdate: StaffMemberUpdate_staffUpdate | null; +} + +export interface StaffMemberUpdateVariables { + id: string; + input: StaffInput; +} diff --git a/src/staff/urls.ts b/src/staff/urls.ts new file mode 100644 index 000000000..56c2211a6 --- /dev/null +++ b/src/staff/urls.ts @@ -0,0 +1,25 @@ +import { stringify as stringifyQs } from "qs"; +import * as urlJoin from "url-join"; + +import { BulkAction, Dialog, Pagination } from "../types"; + +const staffSection = "/staff/"; + +export const staffListPath = staffSection; +export type StaffListUrlDialog = "add" | "remove"; +export type StaffListUrlQueryParams = BulkAction & + Dialog & + Pagination; +export const staffListUrl = (params?: StaffListUrlQueryParams) => + staffListPath + "?" + stringifyQs(params); + +export const staffMemberDetailsPath = (id: string) => urlJoin(staffSection, id); +export type StaffMemberDetailsUrlDialog = "remove" | "remove-avatar"; +export type StaffMemberDetailsUrlQueryParams = Dialog< + StaffMemberDetailsUrlDialog +>; + +export const staffMemberDetailsUrl = ( + id: string, + params?: StaffMemberDetailsUrlQueryParams +) => staffMemberDetailsPath(encodeURIComponent(id)) + "?" + stringifyQs(params); diff --git a/src/staff/views/StaffDetails.tsx b/src/staff/views/StaffDetails.tsx new file mode 100644 index 000000000..9dfb77312 --- /dev/null +++ b/src/staff/views/StaffDetails.tsx @@ -0,0 +1,226 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import * as React from "react"; + +import ActionDialog from "@saleor/components/ActionDialog"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useUser from "@saleor/hooks/useUser"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import StaffDetailsPage from "../components/StaffDetailsPage/StaffDetailsPage"; +import { + TypedStaffAvatarDeleteMutation, + TypedStaffAvatarUpdateMutation, + TypedStaffMemberDeleteMutation, + TypedStaffMemberUpdateMutation +} from "../mutations"; +import { TypedStaffMemberDetailsQuery } from "../queries"; +import { StaffAvatarDelete } from "../types/StaffAvatarDelete"; +import { StaffAvatarUpdate } from "../types/StaffAvatarUpdate"; +import { StaffMemberDelete } from "../types/StaffMemberDelete"; +import { StaffMemberUpdate } from "../types/StaffMemberUpdate"; +import { + staffListUrl, + staffMemberDetailsUrl, + StaffMemberDetailsUrlQueryParams +} from "../urls"; + +interface OrderListProps { + id: string; + params: StaffMemberDetailsUrlQueryParams; +} + +export const StaffDetails: React.StatelessComponent = ({ + id, + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const user = useUser(); + + return ( + + {({ data, loading }) => { + const handleStaffMemberUpdate = (data: StaffMemberUpdate) => { + if (!maybe(() => data.staffUpdate.errors.length !== 0)) { + notify({ + text: i18n.t("Succesfully updated staff member account") + }); + } + }; + const handleStaffMemberDelete = (data: StaffMemberDelete) => { + if (!maybe(() => data.staffDelete.errors.length !== 0)) { + notify({ + text: i18n.t("Succesfully removed staff member") + }); + navigate(staffListUrl()); + } + }; + const handleStaffMemberAvatarUpdate = (data: StaffAvatarUpdate) => { + if (!maybe(() => data.userAvatarUpdate.errors.length !== 0)) { + notify({ + text: i18n.t("Succesfully updated staff member avatar") + }); + } + }; + const handleStaffMemberAvatarDelete = (data: StaffAvatarDelete) => { + if (!maybe(() => data.userAvatarDelete.errors.length !== 0)) { + notify({ + text: i18n.t("Succesfully removed staff member avatar") + }); + navigate(staffMemberDetailsUrl(id)); + } + }; + return ( + + {(updateStaffMember, updateResult) => ( + + {(deleteStaffMember, deleteResult) => ( + + {updateStaffAvatar => ( + + {(deleteStaffAvatar, deleteAvatarResult) => { + const formTransitionState = getMutationState( + updateResult.called, + updateResult.loading, + maybe(() => updateResult.data.staffUpdate.errors) + ); + const deleteTransitionState = getMutationState( + deleteResult.called, + deleteResult.loading, + maybe(() => deleteResult.data.staffDelete.errors) + ); + const deleteAvatarTransitionState = getMutationState( + deleteAvatarResult.called, + deleteAvatarResult.loading, + maybe( + () => + deleteAvatarResult.data.userAvatarDelete.errors + ) + ); + const isUserSameAsViewer = maybe( + () => user.user.id === data.user.id, + true + ); + + return ( + <> + data.user.email)} + /> + navigate(staffListUrl())} + onDelete={() => + navigate( + staffMemberDetailsUrl(id, { + action: "remove" + }) + ) + } + onSubmit={variables => + updateStaffMember({ + variables: { + id, + input: { + email: variables.email, + firstName: variables.firstName, + isActive: variables.isActive, + lastName: variables.lastName, + permissions: variables.permissions + } + } + }) + } + onImageUpload={file => + updateStaffAvatar({ + variables: { + image: file + } + }) + } + onImageDelete={() => + navigate( + staffMemberDetailsUrl(id, { + action: "remove-avatar" + }) + ) + } + permissions={maybe(() => data.shop.permissions)} + staffMember={maybe(() => data.user)} + saveButtonBarState={formTransitionState} + /> + + navigate(staffMemberDetailsUrl(id)) + } + onConfirm={deleteStaffMember} + > + {{ email }} from staff members?", + { + email: maybe(() => data.user.email) + } + ) + }} + /> + + + navigate(staffMemberDetailsUrl(id)) + } + onConfirm={deleteStaffAvatar} + > + {{ email }} avatar?", + { + email: maybe(() => data.user.email) + } + ) + }} + /> + + + ); + }} + + )} + + )} + + )} + + ); + }} + + ); +}; + +export default StaffDetails; diff --git a/src/staff/views/StaffList.tsx b/src/staff/views/StaffList.tsx new file mode 100644 index 000000000..4a33bfbc4 --- /dev/null +++ b/src/staff/views/StaffList.tsx @@ -0,0 +1,130 @@ +import * as React from "react"; + +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { PAGINATE_BY } from "../../config"; +import { configurationMenuUrl } from "../../configuration"; +import i18n from "../../i18n"; +import { getMutationState, maybe } from "../../misc"; +import StaffAddMemberDialog, { + FormData as AddStaffMemberForm +} from "../components/StaffAddMemberDialog"; +import StaffListPage from "../components/StaffListPage"; +import { TypedStaffMemberAddMutation } from "../mutations"; +import { TypedStaffListQuery } from "../queries"; +import { StaffMemberAdd } from "../types/StaffMemberAdd"; +import { + staffListUrl, + StaffListUrlQueryParams, + staffMemberDetailsUrl +} from "../urls"; + +interface StaffListProps { + params: StaffListUrlQueryParams; +} + +export const StaffList: React.StatelessComponent = ({ + params +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const paginate = usePaginator(); + + const closeModal = () => + navigate( + staffListUrl({ + ...params, + action: undefined, + ids: undefined + }), + true + ); + + const paginationState = createPaginationState(PAGINATE_BY, params); + return ( + + {({ data, loading }) => { + const handleStaffMemberAddSuccess = (data: StaffMemberAdd) => { + if (data.staffCreate.errors.length === 0) { + notify({ + text: i18n.t("Succesfully added staff member") + }); + navigate(staffMemberDetailsUrl(data.staffCreate.user.id)); + } + }; + + return ( + + {(addStaffMember, addStaffMemberData) => { + const handleStaffMemberAdd = (variables: AddStaffMemberForm) => + addStaffMember({ + variables: { + input: { + email: variables.email, + firstName: variables.firstName, + lastName: variables.lastName, + permissions: variables.fullAccess + ? data.shop.permissions.map(perm => perm.code) + : undefined, + sendPasswordEmail: true + } + } + }); + const addTransitionState = getMutationState( + addStaffMemberData.called, + addStaffMemberData.loading, + maybe(() => addStaffMemberData.data.staffCreate.errors) + ); + + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + maybe(() => data.staffUsers.pageInfo), + paginationState, + params + ); + + return ( + <> + + data.staffUsers.edges.map(edge => edge.node) + )} + onAdd={() => + navigate( + staffListUrl({ + action: "add" + }) + ) + } + onBack={() => navigate(configurationMenuUrl)} + onNextPage={loadNextPage} + onPreviousPage={loadPreviousPage} + onRowClick={id => () => navigate(staffMemberDetailsUrl(id))} + /> + addStaffMemberData.data.staffCreate.errors, + [] + )} + open={params.action === "add"} + onClose={closeModal} + onConfirm={handleStaffMemberAdd} + /> + + ); + }} + + ); + }} + + ); +}; + +export default StaffList; diff --git a/src/storybook/.babelrc b/src/storybook/.babelrc new file mode 100644 index 000000000..2b7bafa5f --- /dev/null +++ b/src/storybook/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/preset-env", "@babel/preset-react"] +} diff --git a/src/storybook/CardDecorator.tsx b/src/storybook/CardDecorator.tsx new file mode 100644 index 000000000..e00a37481 --- /dev/null +++ b/src/storybook/CardDecorator.tsx @@ -0,0 +1,16 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import * as React from "react"; + +const CardDecorator = storyFn => ( + + {storyFn()} + +); +export default CardDecorator; diff --git a/src/storybook/Decorator.tsx b/src/storybook/Decorator.tsx new file mode 100644 index 000000000..beb127ca6 --- /dev/null +++ b/src/storybook/Decorator.tsx @@ -0,0 +1,28 @@ +import * as React from "react"; + +import { Provider as DateProvider } from "../components/Date/DateContext"; +import { FormProvider } from "../components/Form"; +import { MessageManager } from "../components/messages"; +import ThemeProvider from "../components/Theme"; +import { TimezoneProvider } from "../components/Timezone"; + +export const Decorator = storyFn => ( + + + + + +
+ {storyFn()} +
+
+
+
+
+
+); +export default Decorator; diff --git a/src/storybook/Stories.test.ts b/src/storybook/Stories.test.ts new file mode 100644 index 000000000..197179e68 --- /dev/null +++ b/src/storybook/Stories.test.ts @@ -0,0 +1,27 @@ +import createGenerateClassName from "@material-ui/core/styles/createGenerateClassName"; +import initStoryshots from "@storybook/addon-storyshots"; +// tslint:disable no-submodule-imports +import * as generateRandomKey from "draft-js/lib/generateRandomKey"; +import { configure, render } from "enzyme"; +import * as Adapter from "enzyme-adapter-react-16"; +import toJSON from "enzyme-to-json"; + +configure({ adapter: new Adapter() }); + +jest.mock("@material-ui/core/styles/createGenerateClassName"); +(createGenerateClassName as any).mockImplementation( + () => (rule, stylesheet) => { + return [stylesheet.options.meta, rule.key, "id"].join("-"); + } +); + +jest.mock("draft-js/lib/generateRandomKey"); +(generateRandomKey as any).mockImplementation(() => "testKey"); + +initStoryshots({ + configPath: "saleor/static/dashboard-next/storybook/", + test({ story }) { + const result = render(story.render() as any); + expect(toJSON(result)).toMatchSnapshot(); + } +}); diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap new file mode 100644 index 000000000..17bd0d0a3 --- /dev/null +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -0,0 +1,83985 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Storyshots Categories / CategoryProducts when loading data 1`] = ` +
+
+
+ + Products + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + +
+ + Name + + Type +
+
+ +
+
+ + ‌ + + + + ‌ + +
+
+
+`; + +exports[`Storyshots Categories / CategoryProducts with clickable rows 1`] = ` +
+
+
+ + Products + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Name + + Type +
+
+ +
+
+ + Gardner, Graham and King + + + T-Shirt +
+
+ +
+
+ + Gardner, Graham and King + + + T-Shirt +
+
+ +
+
+ + Gardner, Graham and King + + + T-Shirt +
+
+ +
+
+ + Gardner, Graham and King + + + T-Shirt +
+
+
+`; + +exports[`Storyshots Categories / CategoryProducts with initial data 1`] = ` +
+
+
+ + Products + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Name + + Type +
+
+ +
+
+ + Gardner, Graham and King + + + T-Shirt +
+
+ +
+
+ + Gardner, Graham and King + + + T-Shirt +
+
+ +
+
+ + Gardner, Graham and King + + + T-Shirt +
+
+ +
+
+ + Gardner, Graham and King + + + T-Shirt +
+
+
+`; + +exports[`Storyshots Categories / CategoryProducts without initial data 1`] = ` +
+
+
+ + Products + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + +
+ Name + + Type +
+ No products found +
+
+
+`; + +exports[`Storyshots Customers / Address editing dialog default 1`] = ` +
+`; + +exports[`Storyshots Customers / Address editing dialog edit 1`] = ` +
+`; + +exports[`Storyshots Discounts / Select countries default 1`] = ` +
+`; + +exports[`Storyshots Generics / ActionDialog default 1`] = ` +
+`; + +exports[`Storyshots Generics / AddressEdit default 1`] = ` +
+
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / AddressFormatter default 1`] = ` +
+
+
+
+ + Elizabeth Vaughn + + + 419 Ruiz Orchard Apt. 199 +
+
+ + 52203 Port Danielshire + + + Szwecja + +
+
+
+
+`; + +exports[`Storyshots Generics / AddressFormatter when loading 1`] = ` +
+
+
+ + ‌ + +
+
+
+`; + +exports[`Storyshots Generics / Autocomplete Menu default 1`] = ` +
+
+
+
+
+ +
+ +
+
+
+
+
+
+`; + +exports[`Storyshots Generics / Autocomplete Menu error 1`] = ` +
+
+
+
+
+ +
+ +
+

+ Generic form error +

+
+
+
+
+
+`; + +exports[`Storyshots Generics / Autocomplete Menu interactive 1`] = ` +
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / Autocomplete Menu loading 1`] = ` +
+
+
+
+
+ +
+ +
+ + + +
+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / Card menu default 1`] = ` +
+
+ +
+
+`; + +exports[`Storyshots Generics / Checkbox checked 1`] = ` +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / Checkbox disabled 1`] = ` +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / Checkbox interactive 1`] = ` +
+
+
+
+ +
+
+
+
+`; + +exports[`Storyshots Generics / Checkbox unchecked 1`] = ` +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / Checkbox undeterminate 1`] = ` +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / Chip default 1`] = ` +
+
+
+
+ + Lorem Ipsum + +
+
+
+
+`; + +exports[`Storyshots Generics / Chip with x 1`] = ` +
+
+
+
+ + Lorem Ipsum + + +
+
+
+
+`; + +exports[`Storyshots Generics / Date default 1`] = ` +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / Date plain 1`] = ` +
+
+
+ Apr 7, 2018 +
+
+
+`; + +exports[`Storyshots Generics / DateTime default 1`] = ` +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / DateTime plain 1`] = ` +
+
+
+ Apr 7, 2018 6:44 AM +
+
+
+`; + +exports[`Storyshots Generics / Delete filter tab default 1`] = ` +
+`; + +exports[`Storyshots Generics / EditableTableCell default 1`] = ` +
+
+
+ + + + + + + + + + + + + + + +
+ Some header + + Some header + + Some header +
+ Some value + +
+ + Some editable text + +
+
+ Some value +
+
+
+
+`; + +exports[`Storyshots Generics / ErrorMessageCard default 1`] = ` +
+
+

+ Error +

+

+ Loren ipsum dolor sit amet! +

+
+
+`; + +exports[`Storyshots Generics / External Link default 1`] = ` + +`; + +exports[`Storyshots Generics / External Link new tab 1`] = ` + +`; + +exports[`Storyshots Generics / Filter default 1`] = ` +
+
+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / Global messages default 1`] = ` +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / Global messages with undo action 1`] = ` +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / Money formatting default 1`] = ` +
+
+
+ €14.00 +
+
+
+`; + +exports[`Storyshots Generics / Money range from 1`] = ` +
+
+
+ from $5.20 +
+
+
+`; + +exports[`Storyshots Generics / Money range range 1`] = ` +
+
+
+ $5.20 - $10.60 +
+
+
+`; + +exports[`Storyshots Generics / Money range to 1`] = ` +
+
+
+ to $10.60 +
+
+
+`; + +exports[`Storyshots Generics / MultiAutocompleteSelectField with loaded data 1`] = ` +
+
+
+
+
+
+ + +

+ Value: afghanistan +

+
+
+
+

+ Afghanistan +

+
+ +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / MultiAutocompleteSelectField with loading data 1`] = ` +
+
+
+
+
+
+ + +

+ Value: afghanistan +

+
+
+
+

+ Afghanistan +

+
+ +
+
+
+ +
+
+
+`; + +exports[`Storyshots Generics / MultiSelectField interactive 1`] = ` +
+
+
+
+
+ +
+
+
+ Apparel +
+ + +
+
+

+ Ipsum +

+
+
+
+
+
+`; + +exports[`Storyshots Generics / MultiSelectField with error hint 1`] = ` +
+
+
+
+
+
+
+ + ​ + +
+ + +
+
+

+ Lorem error +

+
+
+
+
+`; + +exports[`Storyshots Generics / MultiSelectField with hint 1`] = ` +
+
+
+
+
+
+
+ + ​ + +
+ + +
+
+

+ Lorem ipsum +

+
+
+
+
+`; + +exports[`Storyshots Generics / MultiSelectField with label 1`] = ` +
+
+
+
+ +
+
+
+ + ​ + +
+ + +
+
+
+
+
+
+`; + +exports[`Storyshots Generics / MultiSelectField with label and hint 1`] = ` +
+
+
+
+ +
+
+
+ + ​ + +
+ + +
+
+

+ Ipsum +

+
+
+
+
+`; + +exports[`Storyshots Generics / MultiSelectField with no value 1`] = ` +
+
+
+
+
+
+
+ + ​ + +
+ + +
+
+
+
+
+
+`; + +exports[`Storyshots Generics / MultiSelectField with value 1`] = ` +
+
+
+
+
+
+
+ Apparel +
+ + +
+
+
+
+
+
+`; + +exports[`Storyshots Generics / MultiSelectField with value, label and hint 1`] = ` +
+
+
+
+ +
+
+
+ Apparel +
+ + +
+
+

+ Ipsum +

+
+
+
+
+`; + +exports[`Storyshots Generics / PageHeader with title 1`] = ` +
+
+
+ Lorem ipsum +
+
+
+
+`; + +exports[`Storyshots Generics / PageHeader with title icon bar 1`] = ` +
+
+
+ Lorem ipsum +
+
+ +
+
+
+`; + +exports[`Storyshots Generics / PageHeader without title 1`] = ` +
+
+
+ + ‌ + +
+
+
+
+`; + +exports[`Storyshots Generics / Percent formatting default 1`] = ` +
+
+
+ 96.14% +
+
+
+`; + +exports[`Storyshots Generics / PhoneField default 1`] = ` +
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+`; + +exports[`Storyshots Generics / Price input disabled 1`] = ` +
+
+
+
+
+ + +
+
+
+
+
+`; + +exports[`Storyshots Generics / Price input with currency symbol 1`] = ` +
+
+
+
+
+ +
+

+ $ +

+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / Price input with hint 1`] = ` +
+
+
+
+
+ + +
+

+ Lorem ipsum +

+
+
+
+
+`; + +exports[`Storyshots Generics / Price input with label 1`] = ` +
+
+
+
+ +
+ + +
+
+
+
+
+`; + +exports[`Storyshots Generics / Price input with label and hint 1`] = ` +
+
+
+
+ +
+ + +
+

+ Ipsum +

+
+
+
+
+`; + +exports[`Storyshots Generics / Price input with no value 1`] = ` +
+
+
+
+
+ + +
+
+
+
+
+`; + +exports[`Storyshots Generics / Price input with value 1`] = ` +
+
+
+
+
+ + +
+
+
+
+
+`; + +exports[`Storyshots Generics / Price input with value, label, currency symbol and error 1`] = ` +
+
+
+
+ +
+ +
+

+ $ +

+
+
+

+ Ipsum +

+
+
+
+
+`; + +exports[`Storyshots Generics / Price input with value, label, currency symbol and hint 1`] = ` +
+
+
+
+ +
+ +
+

+ $ +

+
+
+

+ Ipsum +

+
+
+
+
+`; + +exports[`Storyshots Generics / Rich text editor default 1`] = ` +
+
+
+
+
+ + Content + +
+ +
+
+
+
+
+
+ + + bold + + +
+
+
+
+ + + italic + + +
+
+
+
+ + + strikethrough + + +
+
+

+
+ + + h1 + + +
+

+

+
+ + + h2 + + +
+

+

+
+ + + h3 + + +
+

+
+
+ + + blockquote + + +
+
+
    +
  • +
    + + + ul + + +
    +
  • +
+
    +
  1. +
    + + + ol + + +
    +
  2. +
+
+ +
+
+
+
+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / Save filter tab default 1`] = ` +
+`; + +exports[`Storyshots Generics / SaveButtonBar disabled 1`] = ` +
+`; + +exports[`Storyshots Generics / SaveButtonBar error 1`] = ` +
+`; + +exports[`Storyshots Generics / SaveButtonBar idle 1`] = ` +
+`; + +exports[`Storyshots Generics / SaveButtonBar interactive error 1`] = ` +
+`; + +exports[`Storyshots Generics / SaveButtonBar interactive success 1`] = ` +
+`; + +exports[`Storyshots Generics / SaveButtonBar loading 1`] = ` +
+`; + +exports[`Storyshots Generics / SaveButtonBar success 1`] = ` +
+`; + +exports[`Storyshots Generics / SingleAutocompleteSelectField with custom option 1`] = ` +
+
+
+
+
+
+ + +

+ Value: afghanistan +

+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / SingleAutocompleteSelectField with loaded data 1`] = ` +
+
+
+
+
+
+ + +

+ Value: afghanistan +

+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / SingleAutocompleteSelectField with loading data 1`] = ` +
+
+
+
+
+
+ + +

+ Value: afghanistan +

+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / SingleSelectField with error hint 1`] = ` +
+
+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / SingleSelectField with hint 1`] = ` +
+
+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / SingleSelectField with label 1`] = ` +
+
+
+
+ +
+
+
+ + ​ + +
+ + +
+
+
+
+
+
+`; + +exports[`Storyshots Generics / SingleSelectField with label and hint 1`] = ` +
+
+
+
+ +
+
+
+ + ​ + +
+ + +
+
+

+ Ipsum +

+
+
+
+
+`; + +exports[`Storyshots Generics / SingleSelectField with no value 1`] = ` +
+
+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / SingleSelectField with value 1`] = ` +
+
+
+
+
+
+
+
+`; + +exports[`Storyshots Generics / SingleSelectField with value, label and hint 1`] = ` +
+
+
+
+ +
+
+
+ Apparel +
+ + +
+
+

+ Ipsum +

+
+
+
+
+`; + +exports[`Storyshots Generics / Skeleton default 1`] = ` +
+
+
+ + ‌ + +
+
+
+`; + +exports[`Storyshots Generics / StatusLabel when error 1`] = ` +
+
+
+
+ Example label +
+
+
+
+`; + +exports[`Storyshots Generics / StatusLabel when neutral 1`] = ` +
+
+
+
+ Example label +
+
+
+
+`; + +exports[`Storyshots Generics / StatusLabel when success 1`] = ` +
+
+
+
+ Example label +
+
+
+
+`; + +exports[`Storyshots Generics / TablePagination both previous and next pages are available 1`] = ` +
+
+
+ + + + + + +
+
+
+
+ + +
+
+
+
+
+
+`; + +exports[`Storyshots Generics / TablePagination next page available 1`] = ` +
+
+
+ + + + + + +
+
+
+
+ + +
+
+
+
+
+
+`; + +exports[`Storyshots Generics / TablePagination no previous / next page 1`] = ` +
+
+
+ + + + + + +
+
+
+
+ + +
+
+
+
+
+
+`; + +exports[`Storyshots Generics / TablePagination previous page available 1`] = ` +
+
+
+ + + + + + +
+
+
+
+ + +
+
+
+
+
+
+`; + +exports[`Storyshots Generics / Timeline default 1`] = ` +
+
+
+ +
+

+ Expansion panel 1 +

+

+ +

+
+
+
+ +
+

+ Expansion panel 2 +

+

+ +

+
+
+
+ +
+

+ Expansion panel 3 +

+

+ +

+
+
+
+
+`; + +exports[`Storyshots Generics / Timeline with expansion panels 1`] = ` +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+`; + +exports[`Storyshots Generics / Timeline with order notes 1`] = ` +
+
+
+ +
+ + +
+
+
+
+ +
+
+
+
+

+ admin@example.com +

+

+ +

+
+
+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse +
+ malesuada lacus ex, sit amet blandit leo lobortis eget. +

+
+
+
+
+
+ +
+
+
+
+

+ ceo@example.com +

+

+ +

+
+
+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse +
+ malesuada lacus ex, sit amet blandit leo lobortis eget. +

+
+
+
+
+ +
+ + +
+
+
+
+`; + +exports[`Storyshots Generics / Weight default 1`] = ` +
+
+
+ 8.4 kg +
+
+
+`; + +exports[`Storyshots Generics / Weight range from 1`] = ` +
+
+
+ from 4.2 kg +
+
+
+`; + +exports[`Storyshots Generics / Weight range range 1`] = ` +
+
+
+ 4.2 kg - 81.9 kg +
+
+
+`; + +exports[`Storyshots Generics / Weight range to 1`] = ` +
+
+
+ to 81.9 kg +
+
+
+`; + +exports[`Storyshots Navigation / Menu create default 1`] = ` +
+`; + +exports[`Storyshots Navigation / Menu create loading 1`] = ` +
+`; + +exports[`Storyshots Navigation / Menu item create default 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderAddressEditDialog billing address 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderAddressEditDialog shipping address 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderBulkCancelDialog default 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderCancelDialog default 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderCustomer default 1`] = ` +
+
+
+ + Customer + +
+ +
+
+
+
+
+

+ Anonymous user +

+
+
+
+
+

+ Contact information +

+
+ +

+ melissa.simon@example.com +

+
+
+
+
+
+

+ Shipping Address +

+
+

+ Melissa Simon +

+

+ 487 Roberto Shores +
+

+

+ 66272 West Patriciastad +

+

+ Wyspy Salomona +

+

+

+
+
+
+

+ Billing Address +

+
+

+ Same as shipping address +

+
+
+
+`; + +exports[`Storyshots Orders / OrderCustomer editable 1`] = ` +
+
+
+ + Customer + +
+ +
+
+
+
+
+

+ Anonymous user +

+
+
+
+
+

+ Contact information +

+
+ +

+ melissa.simon@example.com +

+
+
+
+
+
+

+ Shipping Address +

+
+ +
+
+

+ Melissa Simon +

+

+ 487 Roberto Shores +
+

+

+ 66272 West Patriciastad +

+

+ Wyspy Salomona +

+

+

+
+
+
+

+ Billing Address +

+
+ +
+
+

+ Same as shipping address +

+
+
+
+`; + +exports[`Storyshots Orders / OrderCustomer loading 1`] = ` +
+
+
+ + Customer + +
+ +
+
+
+
+
+ + ‌ + +
+
+
+
+

+ Contact information +

+
+ + ‌ + +
+
+
+
+

+ Shipping Address +

+
+ + ‌ + +
+
+
+
+

+ Billing Address +

+
+ + ‌ + +
+
+
+`; + +exports[`Storyshots Orders / OrderCustomer with different addresses 1`] = ` +
+
+
+ + Customer + +
+ +
+
+
+
+
+

+ Anonymous user +

+
+
+
+
+

+ Contact information +

+
+ +

+ melissa.simon@example.com +

+
+
+
+
+
+

+ Shipping Address +

+
+

+ Melissa Simon +

+

+ 487 Roberto Shores +
+

+

+ 66272 West Patriciastad +

+

+ Wyspy Salomona +

+

+

+
+
+
+

+ Billing Address +

+
+

+ Melissa Simon +

+

+ 487 Roberto Shores +
+

+

+ 66272 West Patriciastad +

+

+ Wyspy Salomona +

+

+

+
+
+`; + +exports[`Storyshots Orders / OrderCustomerEditDialog default 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderDraftCancelDialog default 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderDraftFinalizeDialog default 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderDraftFinalizeDialog with warnings 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderFulfillmentCancelDialog default 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderFulfillmentDialog default 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderFulfillmentTrackingDialog default 1`] = ` +
+`; + +exports[`Storyshots Orders / OrderHistory default 1`] = ` +
+
+

+ Order History +

+
+
+
+
+
+
+ +
+
+
+
+ + +
+
+

+ Optional +

+
+
+
+
+
+
+ + Search Engine Preview + +
+ +
+
+
+
+
+

+ Add search engine title and description to make this category easier to find +

+
+
+
+
+ + Subcategories + + + Products + +
+
+
+
+ + All Subcategories + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + +
+ + Category Name + + Subcategories + + No. Products +
+ No subcategories found +
+
+
+ +
+`; + +exports[`Storyshots Views / Categories / Update category loading 1`] = ` +
+
+
+
+
+ + ‌ + +
+
+
+
+
+ + General information + +
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + Description + +
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + Background image (optional) + +
+ + +
+
+
+
+
+
+
+ + ‌ + +
+
+
+
+
+
+
+ + Search Engine Preview + +
+ +
+
+
+
+
+

+ Add search engine title and description to make this category easier to find +

+
+
+
+
+ + Subcategories + + + Products + +
+
+
+
+ + All Subcategories + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+ + Category Name + + Subcategories + + No. Products +
+ + + + ‌ + + + + ‌ + + + + ‌ + +
+
+
+ +
+`; + +exports[`Storyshots Views / Categories / Update category no background 1`] = ` +
+
+
+
+
+ Coffees +
+
+
+
+
+ + General information + +
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + Description + +
+ +
+
+
+
+
+
+ + + bold + + +
+
+
+
+ + + italic + + +
+
+
+
+ + + strikethrough + + +
+
+

+
+ + + h1 + + +
+

+

+
+ + + h2 + + +
+

+

+
+ + + h3 + + +
+

+
+
+ + + blockquote + + +
+
+
    +
  • +
    + + + ul + + +
    +
  • +
+
    +
  1. +
    + + + ol + + +
    +
  2. +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ + Background image (optional) + +
+ + +
+
+
+
+
+
+
+
+ +
+
+ Alt text +
+
+
+
+
+ +
+
+ + +
+
+

+ Optional +

+
+
+
+
+
+
+ + Search Engine Preview + +
+ +
+
+
+
+
+

+ Add search engine title and description to make this category easier to find +

+
+
+
+
+ + Subcategories + + + Products + +
+
+
+
+ + All Subcategories + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + +
+ + Category Name + + Subcategories + + No. Products +
+ No subcategories found +
+
+
+ +
+`; + +exports[`Storyshots Views / Categories / Update category no products 1`] = ` +
+
+
+
+
+ Coffees +
+
+
+
+
+ + General information + +
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + Description + +
+ +
+
+
+
+
+
+ + + bold + + +
+
+
+
+ + + italic + + +
+
+
+
+ + + strikethrough + + +
+
+

+
+ + + h1 + + +
+

+

+
+ + + h2 + + +
+

+

+
+ + + h3 + + +
+

+
+
+ + + blockquote + + +
+
+
    +
  • +
    + + + ul + + +
    +
  • +
+
    +
  1. +
    + + + ol + + +
    +
  2. +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ + Background image (optional) + +
+ + +
+
+
+
+
+
+
+
+ +
+
+ Alt text +
+
+
+
+
+ +
+
+ + +
+
+

+ Optional +

+
+
+
+
+
+
+ + Search Engine Preview + +
+ +
+
+
+
+
+

+ Add search engine title and description to make this category easier to find +

+
+
+
+
+ + Subcategories + + + Products + +
+
+
+
+ + Products in Coffees + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + +
+ + + Name + + Type + + Published + + Price +
+ No products found +
+
+
+ +
+`; + +exports[`Storyshots Views / Categories / Update category no subcategories 1`] = ` +
+
+
+
+
+ Coffees +
+
+
+
+
+ + General information + +
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + Description + +
+ +
+
+
+
+
+
+ + + bold + + +
+
+
+
+ + + italic + + +
+
+
+
+ + + strikethrough + + +
+
+

+
+ + + h1 + + +
+

+

+
+ + + h2 + + +
+

+

+
+ + + h3 + + +
+

+
+
+ + + blockquote + + +
+
+
    +
  • +
    + + + ul + + +
    +
  • +
+
    +
  1. +
    + + + ol + + +
    +
  2. +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ + Background image (optional) + +
+ + +
+
+
+
+
+
+
+
+ +
+
+ Alt text +
+
+
+
+
+ +
+
+ + +
+
+

+ Optional +

+
+
+
+
+
+
+ + Search Engine Preview + +
+ +
+
+
+
+
+

+ Add search engine title and description to make this category easier to find +

+
+
+
+
+ + Subcategories + + + Products + +
+
+
+
+ + All Subcategories + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + +
+ + Category Name + + Subcategories + + No. Products +
+ No subcategories found +
+
+
+ +
+`; + +exports[`Storyshots Views / Collections / Collection details default 1`] = ` +
+
+
+
+
+ Summer collection +
+
+
+
+
+
+
+ + General information + +
+
+
+
+
+
+ +
+ +
+
+
+
+
+ + Description + +
+ +
+
+
+
+
+
+ + + bold + + +
+
+
+
+ + + italic + + +
+
+
+
+ + + strikethrough + + +
+
+

+
+ + + h1 + + +
+

+

+
+ + + h2 + + +
+

+

+
+ + + h3 + + +
+

+
+
+ + + blockquote + + +
+
+
    +
  • +
    + + + ul + + +
    +
  • +
+
    +
  1. +
    + + + ol + + +
    +
  2. +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ + Background image (optional) + +
+ + +
+
+
+
+
+
+
+
+ +
+
+ Alt text +
+
+
+
+
+ +
+
+ + +
+
+

+ Optional +

+
+
+
+
+
+
+ + Products in Summer collection + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Name + + Type + + Published +
+ + +
+ +
+
+ Murray Inc + + Mugs + +
+ Published +
+
+ +
+ + +
+ +
+
+ Williams-Taylor + + Coffee + +
+ Published +
+
+ +
+ + +
+ +
+
+ Hebert-Sherman + + Coffee + +
+ Published +
+
+ +
+ + +
+ +
+
+ Estes, Johnson and Graham + + Books + +
+ Published +
+
+ +
+
+
+
+
+ + Search Engine Preview + +
+ +
+
+
+
+
+

+ Add search engine title and description to make this collection easier to find +

+
+
+
+
+
+
+
+ + Visibility + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Collections / Collection details loading 1`] = ` +
+
+
+
+
+ + ‌ + +
+
+
+
+
+
+
+ + General information + +
+
+
+
+
+
+ +
+ +
+
+
+
+
+ + Description + +
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + Background image (optional) + +
+ + +
+
+
+
+
+
+
+ + ‌ + +
+
+
+
+
+
+
+ + + ‌ + + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + Name + + Type + + Published +
+ + +
+ +
+
+ + ‌ + + + + ‌ + + + + ‌ + + + +
+
+
+
+
+ + Search Engine Preview + +
+ +
+
+
+
+
+

+ Add search engine title and description to make this collection easier to find +

+
+
+
+
+
+
+
+ + Visibility + +
+
+
+
+
+
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Collections / Collection details no products 1`] = ` +
+
+
+
+
+ Summer collection +
+
+
+
+
+
+
+ + General information + +
+
+
+
+
+
+ +
+ +
+
+
+
+
+ + Description + +
+ +
+
+
+
+
+
+ + + bold + + +
+
+
+
+ + + italic + + +
+
+
+
+ + + strikethrough + + +
+
+

+
+ + + h1 + + +
+

+

+
+ + + h2 + + +
+

+

+
+ + + h3 + + +
+

+
+
+ + + blockquote + + +
+
+
    +
  • +
    + + + ul + + +
    +
  • +
+
    +
  1. +
    + + + ol + + +
    +
  2. +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ + Background image (optional) + +
+ + +
+
+
+
+
+
+
+
+ +
+
+ Alt text +
+
+
+
+
+ +
+
+ + +
+
+

+ Optional +

+
+
+
+
+
+
+ + Products in Summer collection + +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + +
+ + Name + + Type + + Published +
+ + No products found +
+
+
+
+
+ + Search Engine Preview + +
+ +
+
+
+
+
+

+ Add search engine title and description to make this collection easier to find +

+
+
+
+
+
+
+
+ + Visibility + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Collections / Collection list default 1`] = ` +
+
+
+
+ Collections +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Category Name + + No. Products + + Availability +
+ + + Summer collection + + 4 + +
+ Published +
+
+ + + Winter sale + + 4 + +
+ Published +
+
+
+
+
+`; + +exports[`Storyshots Views / Collections / Collection list loading 1`] = ` +
+
+
+
+ Collections +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+ + Category Name + + No. Products + + Availability +
+ + + + ‌ + + + + ‌ + + + + ‌ + +
+
+
+
+`; + +exports[`Storyshots Views / Collections / Create collection default 1`] = ` +
+
+
+
+
+ Add collection +
+
+
+
+
+
+
+ + General information + +
+
+
+
+
+
+ +
+ +
+
+
+
+
+ + Description + +
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + Background image (optional) + +
+ + +
+
+
+
+
+
+ + +

+ Drop here to upload +

+
+
+
+
+
+
+ + Search Engine Preview + +
+ +
+
+
+
+
+

+ Add search engine title and description to make this collection easier to find +

+
+
+
+
+
+
+
+ + Availability + +
+
+
+
+
+
+
+ + Visibility + +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Collections / Create collection loading 1`] = ` +
+
+
+
+
+ Add collection +
+
+
+
+
+
+
+ + General information + +
+
+
+
+
+
+ +
+ +
+
+
+
+
+ + Description + +
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + Background image (optional) + +
+ + +
+
+
+
+
+
+ + +

+ Drop here to upload +

+
+
+
+
+
+
+ + Search Engine Preview + +
+ +
+
+
+
+
+

+ Add search engine title and description to make this collection easier to find +

+
+
+
+
+
+
+
+ + Availability + +
+
+
+
+
+
+
+ + Visibility + +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Configuration default 1`] = ` +
+
+
+
+ Configure +
+
+
+
+
+
+
+ +
+
+

+ Product Types +

+

+ Define types of products you sell +

+
+
+
+
+
+
+ +
+
+

+ Staff Members +

+

+ Manage your employees and their permissions +

+
+
+
+
+
+
+ +
+
+

+ Shipping Methods +

+

+ Manage how you ship out orders. +

+
+
+
+
+
+
+ +
+
+

+ Taxes +

+

+ Manage how your store charges tax +

+
+
+
+
+
+
+ +
+
+

+ Navigation +

+

+ Define how users can navigate through your store +

+
+
+
+
+
+
+ +
+
+

+ Site Settings +

+

+ View and update your site settings +

+
+
+
+
+
+
+ +
+
+

+ Pages +

+

+ Manage and add additional pages +

+
+
+
+
+
+
+`; + +exports[`Storyshots Views / Configuration partial access 1`] = ` +
+
+
+
+ Configure +
+
+
+
+
+
+
+ +
+
+

+ Product Types +

+

+ Define types of products you sell +

+
+
+
+
+
+
+ +
+
+

+ Taxes +

+

+ Manage how your store charges tax +

+
+
+
+
+
+
+ +
+
+

+ Navigation +

+

+ Define how users can navigate through your store +

+
+
+
+
+
+
+ +
+
+

+ Pages +

+

+ Manage and add additional pages +

+
+
+
+
+
+
+`; + +exports[`Storyshots Views / Customers / Address Book default 1`] = ` +
+
+
+
+ Tom Cooper Address Book +
+
+ +
+
+
+
+
+ + Address 1 + + Default Address + + +
+
+ +
+
+
+
+
+
+
+ + Elizabeth Vaughn + + + 419 Ruiz Orchard Apt. 199 +
+ 0238 Cremin Freeway +
+ + 52203 Port Danielshire + + + Szwecja + +
+
+
+
+ + +
+
+
+
+
+ + Address 2 + + +
+
+ +
+
+
+
+
+
+
+ + Timmy Macejkovic + + + 0238 Cremin Freeway +
+
+ + 15926 West Feliciamouth, Montana + + + Japan + +
+
+
+
+ + +
+
+
+
+
+
+`; + +exports[`Storyshots Views / Customers / Address Book loading 1`] = ` +
+
+
+
+ + ‌ + +
+
+ +
+
+
+
+
+ + + ‌ + + +
+
+ +
+
+
+
+
+
+ + ‌ + +
+
+
+ + +
+
+
+
+
+
+`; + +exports[`Storyshots Views / Customers / Address Book no data 1`] = ` +
+
+
+
+ There is no address to show for this customer +
+

+ This customer doesn’t have any adresses added to his address book. You can add address using the button below. +

+ +
+
+
+`; + +exports[`Storyshots Views / Customers / Create customer default 1`] = ` +
+
+
+
+
+ Add customer +
+
+
+
+
+
+
+ + Customer overview + +
+
+
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+
+
+
+ + Primary address + +
+
+
+
+
+

+ The primary address of this customer. +

+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+
+ + Notes + +
+
+
+
+
+

+ Enter any extra infotmation regarding this customer. +

+
+
+ +
+
+ + +
+
+

+ Optional +

+
+
+
+
+
+
+
+ + Photo View + +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Products / Product image details when loading data 1`] = ` +
+
+
+
+
+ Edit Photo +
+
+
+
+
+
+
+ + All photos + +
+
+
+
+
+ + ‌ + +
+
+
+
+ + Photo Information + +
+
+
+
+
+
+ +
+
+