diff --git a/.gitignore b/.gitignore index 4957178e1f..9fdc282cfe 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,10 @@ web/yarn-error.log* web/src/**/*.css +plugins/dist +plugins/json +plugins/config + #HollaEx CLI related templates/local/nginx/conf.d/* templates/local/logs/* diff --git a/.sequelizerc b/.sequelizerc deleted file mode 100644 index 5dba470f5b..0000000000 --- a/.sequelizerc +++ /dev/null @@ -1,9 +0,0 @@ -const path = require('path'); - -// NOTE: __dirname doesn't work with binary building tools for nodejs projects -module.exports = { - 'config': path.resolve(__dirname, 'server/config', 'db.js'), - 'migrations-path': path.resolve(__dirname, 'server/db', 'migrations'), - 'models-path': path.resolve(__dirname, 'server/db', 'models'), - 'seeders-path': path.resolve(__dirname, 'server/db', 'seeders'), -}; diff --git a/Dockerfile.webtest b/Dockerfile.webtest deleted file mode 100644 index 171328f62d..0000000000 --- a/Dockerfile.webtest +++ /dev/null @@ -1,18 +0,0 @@ -FROM node:10.24.1-buster-slim - -RUN apt-get update && \ - apt-get install -y --no-install-recommends curl openssl ca-certificates git python build-essential && \ - rm -rf /var/lib/apt/lists/* && \ - npm config set unsafe-perm true && \ - npm install mocha -g --loglevel=error - -ENV NODE_ENV=production - -COPY . /app - -WORKDIR /app - -RUN npm install --save chai - -ENTRYPOINT ["mocha"] -CMD ["test/selenium/Scenario/newUser.js"] diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 2719a4b60a..0000000000 --- a/LICENSE.md +++ /dev/null @@ -1,137 +0,0 @@ -# HollaEx Kit License - -This License Agreement (Agreement) is between HollaEx. and its subsidiaries and affiliated companies (“HollaEx,” ‘’The Company’’, “we” or “us”), and the entity or individual entering into this Agreement (User, Users). This HollaEx Kit software, materials and documentation provided to User (Software, materials, products, Works) are licensed and are not directly sold or assigned in any manner. -This Agreement is part of a package that includes the Software, materials and certain electronic and/or written content. -This Agreement covers the permitted use of the licensed materials, products and/or the Software provided by us. By "using" our products the user acknowledges and agrees that she/he has read all the terms and conditions of this agreement, understand them, and agree to be legally bound by them. -HollaEx Kit includes tools and services to develop and run a crypto exchange node all subject to this license. If the user does not agree with the terms of this license, she/he may not use any of our licensed products. - -## 1. SCOPE. - -This Agreement describes the licensing of our products provided to User on a non-commercial basis. You are not allowed to take our materials and commercialize them as it were developed by you. -If User desires to use our products on a commercial basis, it must notify us and provide a potential offer. The provision of a potential offer does not guarantee our acceptance of such a proposal. - -## 2. LICENSE. - -Subject to the user’s compliance with all of the terms and conditions of this Agreement, we grant to our users a revocable, non-exclusive, non-transferable, non-sublicensable, non-commercial perpetual right and license (i) for Designated User(s) to use our products to contribute and create Modifications and Applications. - -The user may: - -Copy and Contribute to the Work. -Create one or more Derivative Works. -Incorporate the Work into one or more Collective Works. -Copy Derivative Works or the Work as incorporated in any Collective Work; and -Publish, distribute, archive, perform or otherwise disseminate the Work, Derivative Works or the Work as incorporated in any Collective Work, to the public in any material form in any media whether now known or hereafter created. - -The user must do: - -When the user uses the source code, she/he must retain the above copyright notice, this list of conditions and the following disclaimer. -The user must give any other recipients of the Work or Derivative Works a copy of this License; and -The user must cause any modified files to carry prominent notices stating that it changed the files; and -The user must retain, in the Source form of any Derivative Works that she/he distributes, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works. -The user must retain all attribution to us regarding any Derivative Work. -The user may add its own copyright statement to the modifications performed and may provide additional or different license terms and conditions for use, reproduction, or distribution of the modifications, or for any such Derivative Works as a whole, provided the use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. -Wallet Integration: the wallet integration is made with HollaEx Network, that allows our HollaExKit function properly. By using HollaExKit you need to comply with HollaEx Network requests as a proprietary software. - -The user is not permitted to: - -Impose any terms on the use to be made of the Work, the Derivative Work or the Work as incorporated in a Collective Work that alter or restrict the terms of this License or any rights granted under it or has the effect or intent of restricting the ability to exercise those rights. -Impose any digital rights management technology on the Work, the Derivative Work or the Work as incorporated in a Collective Work that alters or restricts the terms of this License or any rights granted under it or has the effect or intent of restricting the ability to exercise those rights. -Sublicense, sell, resell, or commercialize or Software without our permission. - -## 3. NO ENDORSEMENT. - -Nothing in this Public License constitutes or may be construed as permission to assert or imply that the user is, or that the use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution. - -## 4. OTHER RIGHTS. - -We reserve ownership of all intellectual property rights inherent in or relating to the Software or any material, which include, but are not limited to, all copyright, patent rights, all rights in relation to registered and unregistered trademarks (including service marks), confidential information (including trade secrets and know-how) and all rights other than those expressly granted by this Agreement. - -Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow users to exercise the Licensed Rights, but not otherwise. - -Patent and trademark rights are not licensed under this Public License. - -To the extent possible, this Company waives any right to collect royalties from users under this non-commercial license, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases this Company expressly reserves any right to collect such royalties, including when the Licensed Material is used for Commercial purposes. - -## 5. SUBMISSION OF CONTRIBUTIONS. - -Unless the user explicitly states otherwise, any Contribution intentionally submitted for inclusion in the Work by the user to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement users may have executed with Licensor regarding such Contributions. - -## 6. TRADEMARKS. - -This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the contributions and reproducing the content of the NOTICE file. - -## 7. DISCLAIMER OF WARRANTY. - -Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. The user is solely responsible for determining the appropriateness of using the software, or any other material and assume any risks associated with its exercise of permissions under this License. - -## 8. LIMITATION OF LIABILITY. - -In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall HollaEx be liable to the users for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, loss of data, work stoppage, computer failure or malfunction, business interruption or any and all other damages or losses), even if HollaEx has been advised of the possibility of such damages. - -## 9. RESTRICTIONS. - -The license granted to the users is expressly made subject to and limited by the following restrictions: - -Users agree not to remove any of the original copyright, patent, trademark, and attribution notices and associated disclaimers that may appear in the Source Code or Executable Files. - -Users agree not to advertise or in any way imply that this Work is a product of their own. - -The name of this company may not be used to endorse or promote products derived from the Work made by users without our prior written consent. - -Users agree not to sell, lease, or rent any part of the Work. This does not restrict users from including the Work or any part of the Work inside a larger products distribution that itself is being sold. The Work by itself, though, cannot be sold, leased, or rented. - -Users may use the Executable Files and Source Code only under the terms of this License, and they must include a copy of, or the Uniform Resource Identifier for, this License with every copy of the Executable Files or Source Code users disclose and ensure that anyone receiving such Executable Files and Source Code agrees that the terms of this License apply to such Executable Files and/or Source Code. - -Users may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. Users may not sublicense the Work. - -Users must keep intact all notices that refer to this License and to the disclaimer of warranties. Users may not distribute the Executable Files or Source Code with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License. - -Users agree not to use the Work for illegal, immoral, or improper purposes, or on pages containing illegal, immoral, or improper material. The Work is subject to applicable export laws. Users agree to comply with all such laws and regulations that may apply to the Work after their receipt of the Work. - -## 10. REPRESENTATIONS, WARRANTIES AND DISCLAIMER. - -This work is provided "AS IS", "where is" and "as available", without any express or implied warranties or conditions or guarantees. The users, assume all risk in its use, including copyright infringement, patent infringement, suitability, etc. This company expressly disclaims all express, implied, or statutory warranties or conditions, including without limitation, warranties or conditions of merchantability, merchantable quality or fitness for a particular purpose, or any warranty of title or non-infringement, or that the work (or any portion thereof) is correct, useful, bug-free, or free of viruses. The users must pass this disclaimer on whenever users distribute the work or derivative works. - -## 11. INDEMNITY. - -The users agree to defend, indemnify, and hold harmless this company from and against any claims, suits, losses, damages, liabilities, costs, and expenses (including reasonable legal or attorneys' fees) resulting from or relating to any use of the Work by users. - -## 12. TERMINATION. - -This License and the rights granted hereunder will terminate automatically upon any breach by users of any term of this License. Individuals or entities who have received Derivative Works from users under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. - -Subject to the above terms and conditions, this License is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, this company reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. - -## 13. COMMERCIAL USE. - -Rights granted herein apply only to those using our products for non-commercial purposes. In the case an individual or a company desires to use our products for commercial purposes, or if there is existence of a potential commercial opportunity, the interested party must contact our company to inform about the proposal and pay the applicable fee for the commercial license offered under that new agreement. This company reserves the right to accept or decline such a request. - -## 14. COPYRIGHT (C) 2022 HollaEx. - -Permission is hereby granted, free of charge, to any person obtaining a copy of our products, and associated documentation files, to deal in our products without restriction, including the rights to use, copy, modify, merge, publish, distribute, with a limitation to sublicense, and/or sell copies of our products, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of our products. This copyright notice is extended to all the products produced by HollaEx including, but not limited to: HollaEx Kit, HollaEx Network: (HollaEx Core), Vault, and Robolla. - -THE PRODUCTS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE PRODUCTS OR THE USE OR OTHER DEALINGS RELATED TO THE PRODUCTS. - -## 15. MISCELLANEOUS. - -If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this License, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. - -No term or provision of this License shall be deemed waived, and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. - -This License constitutes the entire agreement between the parties with respect to the products licensed herein. There are no understandings, agreements, or representations with respect to the products not specified herein. The Company shall not be bound by any additional provisions that may appear in any communication from the users. - -The work (as defined below) is provided under the terms of this creative commons public license ("CCPL" or "license"). The work is protected by copyright and/or other applicable law. Any use of the work other than as authorized under this license or copyright law is prohibited. By exercising any rights to the work provided here, users accept and agree to be bound by the terms of this license. The licensor grants users the rights contained here in consideration of their acceptance of such terms and conditions. - -Compliance with Law. User represents and warrants that it will comply in all material respects with all local, state, and international laws and regulations relating to its activities hereunder, including the development, and fair use of Licensed Products. Without limiting the foregoing, Licensee represents and warrants that it shall comply with all laws and regulations controlling the export of technical data. - -Support. The Company will provide to Users the following support with respect to the Products: (i) If during the term of this Agreement, user notifies this company of a substantial program error respecting any of our products, or this Company has reason to believe that error exists in the products and so notifies Licensee, Licensor shall at its expense verify and attempt to correct such error. If the User is not satisfied with the correction provided, then he/she may terminate this Agreement, without the right to any monetary or material claim; and (ii) In the case that User has technical questions in the use of our products. - -This Creative Commons Public License enables the users to view, edit, and modify, works worldwide, under the terms of this license, provided that, users credit the Original Author (HollaEx). - -This License may not be modified without the mutual written agreement of this Company. - - - - diff --git a/README.md b/README.md index 7588069021..a80af1ebac 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # HollaEx Kit [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-green.svg)](https://github.com/facebook/create-react-app/pulls) -HollaEx Kit is an open source while label crypto software suite with a range of features from exchange and trading to user management and onboarding as well as wallet system. In order to run the HollaEx Kit, you need to run the Server as the back-end and Web as your front-end user interface. HollaEx Kit runs as a stand alone node and for trading and blockchain functionalities require to connect to HollaEx Network. By default the node connects o the public HollaEx Network. +HollaEx Kit is an open source while label crypto software suite with a range of features from exchange and trading to user management and onboarding as well as wallet system. In order to run the HollaEx Kit, you need to run the Server as the back-end and Web as your front-end user interface. HollaEx Kit runs as a stand alone node and for trading and blockchain functionalities require to connect to HollaEx Network. By default the node connects to the public HollaEx Network. ## Get Started @@ -22,6 +22,10 @@ Check out [Plugins](https://github.com/hollaex/hollaex-kit/tree/2.0-develop/serv Check out [HollaEx CLI](https://github.com/hollaex/hollaex-cli) (Command Line Interface) for interacting and deploying your exchange. +Check out [HollaEx Network Library](https://github.com/hollaex/hollaex-kit/tree/master/server/utils/hollaex-network-lib) for tools and functions used to communicate with HollaEx Network. + +Check out [HollaEx Tools Library](https://github.com/hollaex/hollaex-kit/tree/master/server/utils/hollaex-tools-lib) for developers as a suite of all useful functions in the HollaEx Kit. + ## Community Join us on the [Forum](https://forum.hollaex.com), [Discord](https://discord.gg/RkRHU8RbyM) and [Twitter](http://www.twitter.com/hollaex). diff --git a/plugins/.babelrc b/plugins/.babelrc new file mode 100644 index 0000000000..864bd1ed98 --- /dev/null +++ b/plugins/.babelrc @@ -0,0 +1,42 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "useBuiltIns": "usage", + "debug": false + } + ], + "@babel/preset-react" + ], + "plugins": [ + [ + "@babel/plugin-transform-runtime", + { + "regenerator": true + } + ], + [ + "@babel/plugin-proposal-class-properties", + { + "loose": true + } + ], + [ + "transform-react-remove-prop-types", + { + "removeImport": true + } + ] + ], + "env": { + "development": { + "sourceMaps": true, + "retainLines": true + }, + "test": { + "sourceMaps": true, + "retainLines": true + } + } +} \ No newline at end of file diff --git a/plugins/.eslintignore b/plugins/.eslintignore new file mode 100644 index 0000000000..d64c4ca286 --- /dev/null +++ b/plugins/.eslintignore @@ -0,0 +1,2 @@ +coverage/ +dist/ diff --git a/plugins/.eslintrc.json b/plugins/.eslintrc.json new file mode 100644 index 0000000000..84befc479e --- /dev/null +++ b/plugins/.eslintrc.json @@ -0,0 +1,35 @@ +{ + "env": { + "browser": true, + "commonjs": true, + "es6": true, + "node": true, + "mocha": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "ecmaVersion": 9, + "sourceType": "module" + }, + "rules": { + "indent": [ + "warn", + "tab", + { + "SwitchCase": 1 + } + ], + "linebreak-style": [ + "warn", + "unix" + ], + "quotes": [ + "warn", + "single" + ], + "semi": [ + "warn", + "always" + ] + } +} \ No newline at end of file diff --git a/plugins/README.md b/plugins/README.md new file mode 100644 index 0000000000..f6a5888973 --- /dev/null +++ b/plugins/README.md @@ -0,0 +1,58 @@ +# hollaex-plugins + +Usage: + +1. Install dependencies: + + ```bash + npm install + cd web/ && npm install + ``` +2. Run `npm run build --plugin=` to generate plugin JSON object: + + ```bash + npm run build --plugin=hello-exchange + + /* + { + "name": "hello-exchange", + "version": 1, + "type": null, + "author": "bitHolla", + "bio": "Say hello from an exchange", + "description": "Demo plugin for proof of concept", + "documentation": null, + "logo": null, + "icon": null, + "url": null, + "meta": { + "private": { + "type": "string", + "required": false, + "description": "A secret", + "value": "hello exchange..." + } + }, + "public_meta": { + "public": { + "type": "string", + "required": false, + "description": "Not a secret", + "value": "Hello Exchange!" + } + }, + "prescript": { + "install": [ + "hello-world-npm" + ], + "run": null + }, + "postscript": { + "run": null + }, + "web_view": null, + "admin_view": null, + "script": "const helloWorld=installedLibraries[\"hello-world-npm\"];app.get(\"/plugins/hello-exchange\",(e,l)=>l.json({publicMessage:publicMeta.public.value,privateMessage:meta.private.value,libraryMessage:helloWorld(),timestamp:moment().toISOString()}));" + } + */ + ``` diff --git a/plugins/README_WEB_VIEW.md b/plugins/README_WEB_VIEW.md new file mode 100644 index 0000000000..f2a876de65 --- /dev/null +++ b/plugins/README_WEB_VIEW.md @@ -0,0 +1,155 @@ +# Hollaex Plugin Starter + +Hollaex plugin starter is a package with some pre-defined configurations out of the box to create custom plugins for the [Hollaex kit software](https://github.com/bitholla/hollaex-kit). These plugins can be installed on the fly to add features to your exchange. + +Creating plugins has two different aspects, the server-side script and the client-side component. + +# Client-side component + +Client side codes in the plugins are actually nothing but a remote react component that is injected into the kit on the fly. We are using a package called [remote component](https://github.com/Paciolan/remote-component) to get a component by providing the url for that which is the address of the commonjs module bundle and add it to the kit using the smart target component. + + +## Smart Target component +To decide where to inject remote components, we are using the [smart target](https://github.com/bitholla/hollaex-kit/blob/master/web/src/components/SmartTarget/index.js) component in the kit. + +Smart target is actually a react component with a unique target id that renders a remote bundle when the id matches. + +Smart targets are also responsible for passing props to the remote components. These props are divided into two different categories. + +### Common props +Common props are passed to all remote components within the smart target component. They include but not limited to strings, icons, generateId function, renderFields function to generate forms, store values, edit and config context. +You can always check the latest available common props for remote components by checking the [smart target](https://github.com/bitholla/hollaex-kit/blob/master/web/src/components/SmartTarget/index.js) component in codebase. + +### Target specific props +Target specific props are passed to the smart target component from the parent component and may be different for each target. +To get the latest available target-specific props, you can check the parent component of each smart target component below: + +- [New Page](https://github.com/bitholla/hollaex-kit/blob/8e617abf15c503e2e8483ffc5f4ae3e7befa4401/web/src/routes.js#L240) +- Fiat Wallet + - [Deposit](https://github.com/bitholla/hollaex-kit/blob/8e617abf15c503e2e8483ffc5f4ae3e7befa4401/web/src/containers/Deposit/utils.js#L169) + - [Withdraw](https://github.com/bitholla/hollaex-kit/blob/8e617abf15c503e2e8483ffc5f4ae3e7befa4401/web/src/containers/Withdraw/form.js#L257) +- New Verification Tab + - [Home](https://github.com/bitholla/hollaex-kit/blob/8e617abf15c503e2e8483ffc5f4ae3e7befa4401/web/src/containers/Verification/index.js#L234) + - [Page Content](https://github.com/bitholla/hollaex-kit/blob/8e617abf15c503e2e8483ffc5f4ae3e7befa4401/web/src/containers/Verification/index.js#L256) +- Bank Verification Tab + - [Home](https://github.com/bitholla/hollaex-kit/blob/8e617abf15c503e2e8483ffc5f4ae3e7befa4401/web/src/containers/Verification/index.js#L355) + - [Page Content](https://github.com/bitholla/hollaex-kit/blob/8e617abf15c503e2e8483ffc5f4ae3e7befa4401/web/src/containers/Verification/index.js#L506) +- KYC Verification Tab + - [Home](https://github.com/bitholla/hollaex-kit/blob/8e617abf15c503e2e8483ffc5f4ae3e7befa4401/web/src/containers/Verification/index.js#L380) + - [Page Content](https://github.com/bitholla/hollaex-kit/blob/8e617abf15c503e2e8483ffc5f4ae3e7befa4401/web/src/containers/Verification/index.js#L523) + + +## Targets + +### Static Targets + +- Verification Page Bank Tab + - REMOTE_COMPONENT__BANK_VERIFICATION + - REMOTE_COMPONENT__BANK_VERIFICATION_HOME + +- Verification Page KYC Tab + - REMOTE_COMPONENT__KYC_VERIFICATION + - REMOTE_COMPONENT__KYC_VERIFICATION_HOME + + +### Dynamic Targets + +- New Page +- New verification tab +- Fiat wallet deposit and withdrawal page + +# Meta Object +Dynamic targets are generated based on meta object values. Below you can see essential fields to deine each plugin type. These values should be added to the meta object under the view.json file to define the type of the plugin. These valuse are already set when you are using templates. See Develop section for more information. + +#### New page: +```sh +{ + "meta": { + "is_page": true, + "path": "/route-name" + } +} +``` + +#### New verification tab: + +```sh + "meta": { + "is_verification_tab": true, + "type": "home" or "verification", + } +``` + +#### Fiat Wallet +```sh + "meta": { + "is_wallet": true, + "type": "deposit" or "withdraw", + "currency": "USD" /* currency symbol /* + } +``` + +# Develop +To start developing a plugin, you first need to decide about the type of the plugin. Below is the list of available plugin types: + +| Type | | +| ------ | ------ | +| page | adds a new page with customizable access from the side and top menus | +| verification-tab | adds a new verification tab to the user verification page | +| fiat-wallet | adds a deposit and withdraw page for a fiat currency | +| kyc | adds KYC tab to the user verification page | +| bank | adds bank verification tab to the user verification page | +| raw | adds a template without initial meta object values | + +To initialize a plugin template run: +```sh +npm run add-page --plugin= --type= +``` + +To add a view to a plugin template run: +```sh +npm run add-view --plugin= --webveiw= +``` + +Once the plugin is initialized, run the following commands: + +On the starter kit: + +```sh +npm start --plugin= +``` + +On the main kit: +```sh +npm run dev:plugin --plugin= +``` + +A page reload is required to reflect bundle changes in the browser. + +## Strings and icons + +You can use strings and icons from the main kit. + +You also can define new strings and icons by adding them to strings.json and icons.json under the assets folder respectively. + +These values are added to the kit strings and icons object during kit initialization. To use local assets in your component, you should convert the local id to the global one by using generateId function from the kit context. See kit context. + +## Kit context + +We can always directly use props passed from the kit to the remote component. However in order to prevent passing some props through many levels, a context is provided to make these props globally accessible. +You can partially subscribe to the context to access props from the kit in a more efficient way. + +```sh +import React from "react"; +import { withKit } from 'components/KitContext'; + +const Title = ({ user: { username } = {}, strings: STRINGS }) => ( +
+ {STRINGS.formatString(STRINGS[generateId('hello')], username)} +
+); + +const mapContextToProps = ({ user, generateId, strings }) => ({ user, generateId, strings }); + +export default withKit(mapContextToProps)(Title); +``` \ No newline at end of file diff --git a/plugins/media/icon-large.png b/plugins/media/icon-large.png new file mode 100644 index 0000000000..06bc4d2565 Binary files /dev/null and b/plugins/media/icon-large.png differ diff --git a/plugins/media/icon-small.png b/plugins/media/icon-small.png new file mode 100644 index 0000000000..f0a8c81fdd Binary files /dev/null and b/plugins/media/icon-small.png differ diff --git a/plugins/package-lock.json b/plugins/package-lock.json new file mode 100644 index 0000000000..7966f37aab --- /dev/null +++ b/plugins/package-lock.json @@ -0,0 +1,9467 @@ +{ + "name": "hollaex-plugins", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@ant-design/colors": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.2.2.tgz", + "integrity": "sha512-YKgNbG2dlzqMhA9NtI3/pbY16m3Yl/EeWBRa+lB1X1YaYxHrxNexiQYCLTWO/uDvAjLFMEDU+zR901waBtMtjQ==", + "requires": { + "tinycolor2": "^1.4.1" + } + }, + "@ant-design/css-animation": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@ant-design/css-animation/-/css-animation-1.7.3.tgz", + "integrity": "sha512-LrX0OGZtW+W6iLnTAqnTaoIsRelYeuLZWsrmBJFUXDALQphPsN8cE5DCsmoSlL0QYb94BQxINiuS70Ar/8BNgA==" + }, + "@ant-design/icons": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-4.2.2.tgz", + "integrity": "sha512-DrVV+wcupnHS7PehJ6KiTcJtAR5c25UMgjGECCc6pUT9rsvw0AuYG+a4HDjfxEQuDqKTHwW+oX/nIvCymyLE8Q==", + "requires": { + "@ant-design/colors": "^3.1.0", + "@ant-design/icons-svg": "^4.0.0", + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.6", + "insert-css": "^2.0.0", + "rc-util": "^5.0.1" + } + }, + "@ant-design/icons-svg": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.1.0.tgz", + "integrity": "sha512-Fi03PfuUqRs76aI3UWYpP864lkrfPo0hluwGqh7NJdLhvH4iRDc3jbJqZIvRDLHKbXrvAfPPV3+zjUccfFvWOQ==" + }, + "@ant-design/react-slick": { + "version": "0.27.14", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-0.27.14.tgz", + "integrity": "sha512-s6JVexqFmU5rs5Pm828ojtm5rCp8jDXyrc5OxEtCE2z58SIyQlkpnU9BJh98LEeBZyj02WFkGN8CWpSaD+G4PA==", + "requires": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "lodash": "^4.17.15", + "resize-observer-polyfill": "^1.5.0" + } + }, + "@babel/cli": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.12.10.tgz", + "integrity": "sha512-+y4ZnePpvWs1fc/LhZRTHkTesbXkyBYuOB+5CyodZqrEuETXi3zOVfpAQIdgC3lXbHLTDG9dQosxR9BhvLKDLQ==", + "dev": true, + "requires": { + "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents", + "chokidar": "^3.4.0", + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.19", + "make-dir": "^2.1.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + } + }, + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz", + "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==", + "dev": true + }, + "@babel/core": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", + "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.10", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.10", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "@babel/generator": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz", + "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==", + "dev": true, + "requires": { + "@babel/types": "^7.18.13", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", + "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", + "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz", + "integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz", + "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.1.0" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", + "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", + "dev": true, + "requires": { + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", + "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz", + "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", + "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz", + "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==", + "dev": true, + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.11.tgz", + "integrity": "sha512-oBUlbv+rjZLh2Ks9SKi4aL7eKaAXBWleHzU89mP0G6BMUlRxSckk9tSIkgDGydhgFxHuGSlBQZfnaD47oBEB7w==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.18.9", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.11", + "@babel/types": "^7.18.10" + } + }, + "@babel/helpers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", + "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", + "dev": true, + "requires": { + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz", + "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz", + "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", + "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", + "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz", + "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.18.8" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", + "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", + "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", + "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz", + "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz", + "integrity": "sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", + "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz", + "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", + "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", + "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", + "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", + "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", + "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", + "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz", + "integrity": "sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-identifier": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz", + "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", + "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", + "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.10.tgz", + "integrity": "sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-jsx": "^7.18.6", + "@babel/types": "^7.18.10" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", + "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", + "dev": true, + "requires": { + "@babel/plugin-transform-react-jsx": "^7.18.6" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", + "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", + "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "regenerator-transform": "^0.15.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz", + "integrity": "sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.5", + "@babel/helper-plugin-utils": "^7.10.4", + "semver": "^5.5.1" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz", + "integrity": "sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", + "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", + "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", + "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/preset-env": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.10.tgz", + "integrity": "sha512-Gz9hnBT/tGeTE2DBNDkD7BiWRELZt+8lSysHuDwmYXUIvtwZl0zI+D6mZgXZX0u8YBlLS4tmai9ONNY9tjRgRA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.12.7", + "@babel/helper-compilation-targets": "^7.12.5", + "@babel/helper-module-imports": "^7.12.5", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-option": "^7.12.1", + "@babel/plugin-proposal-async-generator-functions": "^7.12.1", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-dynamic-import": "^7.12.1", + "@babel/plugin-proposal-export-namespace-from": "^7.12.1", + "@babel/plugin-proposal-json-strings": "^7.12.1", + "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-numeric-separator": "^7.12.7", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.12.1", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-async-to-generator": "^7.12.1", + "@babel/plugin-transform-block-scoped-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.1", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-computed-properties": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-dotall-regex": "^7.12.1", + "@babel/plugin-transform-duplicate-keys": "^7.12.1", + "@babel/plugin-transform-exponentiation-operator": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-function-name": "^7.12.1", + "@babel/plugin-transform-literals": "^7.12.1", + "@babel/plugin-transform-member-expression-literals": "^7.12.1", + "@babel/plugin-transform-modules-amd": "^7.12.1", + "@babel/plugin-transform-modules-commonjs": "^7.12.1", + "@babel/plugin-transform-modules-systemjs": "^7.12.1", + "@babel/plugin-transform-modules-umd": "^7.12.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1", + "@babel/plugin-transform-new-target": "^7.12.1", + "@babel/plugin-transform-object-super": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-property-literals": "^7.12.1", + "@babel/plugin-transform-regenerator": "^7.12.1", + "@babel/plugin-transform-reserved-words": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/plugin-transform-sticky-regex": "^7.12.7", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/plugin-transform-typeof-symbol": "^7.12.10", + "@babel/plugin-transform-unicode-escapes": "^7.12.1", + "@babel/plugin-transform-unicode-regex": "^7.12.1", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.12.10", + "core-js-compat": "^3.8.0", + "semver": "^5.5.0" + } + }, + "@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-react": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz", + "integrity": "sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-transform-react-display-name": "^7.12.1", + "@babel/plugin-transform-react-jsx": "^7.12.10", + "@babel/plugin-transform-react-jsx-development": "^7.12.7", + "@babel/plugin-transform-react-pure-annotations": "^7.12.1" + } + }, + "@babel/runtime": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", + "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + } + }, + "@babel/traverse": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz", + "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.13", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.13", + "@babel/types": "^7.18.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "@babel/types": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz", + "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "@blakeembrey/deque": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@blakeembrey/deque/-/deque-1.0.5.tgz", + "integrity": "sha512-6xnwtvp9DY1EINIKdTfvfeAtCYw4OqBZJhtiqkT3ivjnEfa25VQ3TsKvaFfKm8MyGIEfE95qLe+bNEt3nB0Ylg==", + "dev": true + }, + "@blakeembrey/template": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@blakeembrey/template/-/template-1.1.0.tgz", + "integrity": "sha512-iZf+UWfL+DogJVpd/xMQyP6X6McYd6ArdYoPMiv/zlOTzeXXfQbYxBNJJBF6tThvsjLMbA8tLjkCdm9RWMFCCw==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", + "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.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 + } + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@material/animation": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-0.4.1.tgz", + "integrity": "sha1-v4tQrtrUz/zopbQo/cqPGruvF24=" + }, + "@material/base": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@material/base/-/base-0.2.6.tgz", + "integrity": "sha1-MAPz3ywG0XIVHUFguMiy5sZefAE=" + }, + "@material/button": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@material/button/-/button-0.7.0.tgz", + "integrity": "sha512-T2Gcn8IJOJtzSU8mHN7HMqGbvkOy5lEWDZ/dLmVviGKeip22XR9pjm8sO52dCcs1rJJxsJPCl9UnaQUmT8Shaw==", + "requires": { + "@material/elevation": "^0.1.12", + "@material/ripple": "^0.8.7", + "@material/theme": "^0.3.1", + "@material/typography": "^0.3.0" + } + }, + "@material/elevation": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-0.1.13.tgz", + "integrity": "sha1-o4iF88r0OYymp0aMMIiH1wvUYFs=", + "requires": { + "@material/animation": "^0.4.1" + } + }, + "@material/ripple": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-0.8.8.tgz", + "integrity": "sha1-Irie2eY4g/F/pPANEjcOMuDEWbc=", + "requires": { + "@material/base": "^0.2.6", + "@material/theme": "^0.4.0" + }, + "dependencies": { + "@material/theme": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-0.4.0.tgz", + "integrity": "sha1-Cu8aAnm2XBWZBYT7i47KCVxzRkE=" + } + } + }, + "@material/theme": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-0.3.1.tgz", + "integrity": "sha512-0PRLqMPCL3mEaUXyc/SWZWDHWjfyS7xXT64h7dT4lwwA0oHpq0OdQaqemYWkI1h+CVHeT0qSwirRNJ0jxBlhtA==" + }, + "@material/typography": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-0.3.0.tgz", + "integrity": "sha1-+CjC0yFb/WbFgHJwm0JgxkElOQo=" + }, + "@nicolo-ribaudo/chokidar-2": { + "version": "2.1.8-no-fsevents", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz", + "integrity": "sha512-+nb9vWloHNNMFHjGofEam3wopE3m1yuambrrd/fnPc+lFOMB9ROTqQlche9ByFWNkdNqfSgR/kkQtQ8DzEWt2w==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "@paciolan/eslint-config": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@paciolan/eslint-config/-/eslint-config-1.5.0.tgz", + "integrity": "sha512-yCMwYYtULaqr06TDpKIWstm39F2EpWYRB+VI09uYSVbjOJo+NE+zxLqBFT96fqcMPDT5GPDVEfyu13YgFv/UEA==", + "dev": true + }, + "@paciolan/eslint-config-react": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@paciolan/eslint-config-react/-/eslint-config-react-1.0.4.tgz", + "integrity": "sha512-CWY0M7b73Oqzz9N3LOOQfQOT4dg4m8HxRiCio1yXapqEb3QTT4a5247PCiyQ3sYktQJsqLFrqCSAFCqb0YjC0w==", + "dev": true, + "requires": { + "@paciolan/eslint-config": "^1.4.0" + } + }, + "@paciolan/remote-component": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@paciolan/remote-component/-/remote-component-2.10.2.tgz", + "integrity": "sha512-TNfC543fIVfPGrPwG02gFBZZtn4UDUBChwD5rKHoKkQ8LpxA+0pt/uuco048LgU9eszRkPO71LScY2mb8/xqRA==", + "dev": true, + "requires": { + "@paciolan/remote-module-loader": "^2.6.0" + } + }, + "@paciolan/remote-module-loader": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@paciolan/remote-module-loader/-/remote-module-loader-2.6.2.tgz", + "integrity": "sha512-A49c4kX70zNpjFNuLwa53+xMlGf1W/DXMqBFR1JOMGTIpfZ6KJLpfonRG+2eA1c3CFZNvn+j99QWFEd6lgKSMA==", + "dev": true + }, + "@tanem/svg-injector": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/@tanem/svg-injector/-/svg-injector-8.2.5.tgz", + "integrity": "sha512-jQ6UPPY2oSu2d0YLngtvnOIoKheYsB/s2bNP/QdsLrsvlz+PzUUO4RUWBN3+8clZPi2SI5OMF/YoTiTKt5v2xw==", + "requires": { + "@babel/runtime": "^7.12.13", + "content-type": "^1.0.4", + "tslib": "^2.1.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", + "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + } + } + }, + "@types/html-minifier-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz", + "integrity": "sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "@types/node": { + "version": "18.7.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz", + "integrity": "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw==", + "dev": true + }, + "@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true + }, + "@types/tapable": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", + "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==", + "dev": true + }, + "@types/uglify-js": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.17.0.tgz", + "integrity": "sha512-3HO6rm0y+/cqvOyA8xcYLweF0TKXlAxmQASjbOi49Co51A1N4nR4bEwBgRoD9kNM+rqFGArjKr654SLp2CoGmQ==", + "dev": true, + "requires": { + "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 + } + } + }, + "@types/webpack": { + "version": "4.41.32", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", + "integrity": "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "anymatch": "^3.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "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 + } + } + }, + "@types/webpack-sources": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + } + } + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@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.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "add-dom-event-listener": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz", + "integrity": "sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw==", + "requires": { + "object-assign": "4.x" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "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" + } + }, + "antd": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/antd/-/antd-4.6.2.tgz", + "integrity": "sha512-6hmSRiSV3Lzz/1fKGOLHld7gf0d+MW7fg7MNGCAAceGmxtG1WEaaOtV8dZeL2WXq0SGH4wY4GytN6chRrtatfw==", + "requires": { + "@ant-design/colors": "^4.0.5", + "@ant-design/css-animation": "^1.7.2", + "@ant-design/icons": "^4.2.1", + "@ant-design/react-slick": "~0.27.0", + "@babel/runtime": "^7.10.4", + "array-tree-filter": "^2.1.0", + "classnames": "^2.2.6", + "copy-to-clipboard": "^3.2.0", + "lodash": "^4.17.20", + "moment": "^2.25.3", + "omit.js": "^2.0.2", + "raf": "^3.4.1", + "rc-animate": "~3.1.0", + "rc-cascader": "~1.3.0", + "rc-checkbox": "~2.3.0", + "rc-collapse": "~2.0.0", + "rc-dialog": "~8.1.0", + "rc-drawer": "~4.1.0", + "rc-dropdown": "~3.1.2", + "rc-field-form": "~1.10.0", + "rc-image": "~3.0.2", + "rc-input-number": "~6.0.0", + "rc-mentions": "~1.4.0", + "rc-menu": "~8.5.2", + "rc-motion": "^1.0.0", + "rc-notification": "~4.4.0", + "rc-pagination": "~3.0.3", + "rc-picker": "~2.0.6", + "rc-progress": "~3.0.0", + "rc-rate": "~2.8.2", + "rc-resize-observer": "^0.2.3", + "rc-select": "~11.1.0", + "rc-slider": "~9.3.0", + "rc-steps": "~4.1.0", + "rc-switch": "~3.2.0", + "rc-table": "~7.9.2", + "rc-tabs": "~11.6.0", + "rc-textarea": "~0.3.0", + "rc-tooltip": "~4.2.0", + "rc-tree": "~3.9.0", + "rc-tree-select": "~4.1.1", + "rc-trigger": "~4.4.0", + "rc-upload": "~3.2.1", + "rc-util": "^5.1.0", + "scroll-into-view-if-needed": "^2.2.25", + "warning": "^4.0.3" + }, + "dependencies": { + "@ant-design/colors": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-4.0.5.tgz", + "integrity": "sha512-3mnuX2prnWOWvpFTS2WH2LoouWlOgtnIpc6IarWN6GOzzLF8dW/U8UctuvIPhoboETehZfJ61XP+CGakBEPJ3Q==", + "requires": { + "tinycolor2": "^1.4.1" + } + }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + } + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "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": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "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": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "dev": true + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "array-includes": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", + "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + } + }, + "array-tree-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", + "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true + }, + "array.prototype.flatmap": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", + "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.reduce": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz", + "integrity": "sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "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.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true, + "optional": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "async-validator": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-3.5.2.tgz", + "integrity": "sha512-8eLCg00W9pIRZSB781UUX/H6Oskmm8xloZfr09lz5bikRpBVDlJ3hRVuxxP1SxcwsEYfJ4IU8Q19Y8/893r3rQ==" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "requires": { + "follow-redirects": "^1.10.0" + } + }, + "babel-eslint": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + } + }, + "babel-loader": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", + "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", + "dev": true, + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "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": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "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" + } + } + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bfj": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz", + "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "check-types": "^8.0.3", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "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" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "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" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "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" + } + }, + "browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "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": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "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 + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.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==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "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" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, + "caniuse-lite": { + "version": "1.0.30001382", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001382.tgz", + "integrity": "sha512-2rtJwDmSZ716Pxm1wCtbPvHtbDWAreTPxXbkc5RkKglow3Ig/4GNGazDI9/BVnXbG/wnv6r3B5FEbkfg9OcTGg==", + "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" + } + }, + "check-types": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz", + "integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "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": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "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.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "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==" + } + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "complex.js": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.0.11.tgz", + "integrity": "sha512-6IArJLApNtdg1P1dFtn3dnyzoZBEF0MwMnrfF1exSBRpZYoy4yieMkpZhQDC0uwctw48vii0CFVyHfpgZ/DfGw==" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "compute-scroll-into-view": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz", + "integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "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" + } + }, + "concurrently": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.3.0.tgz", + "integrity": "sha512-IiDwm+8DOcFEInca494A8V402tNTQlJaYq78RF2rijOrKEk/AOHTxhN4U1cp7GYKYX5Q6Ymh1dLTBlzIMN0ikA==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "date-fns": "^2.16.1", + "lodash": "^4.17.21", + "rxjs": "^7.0.0", + "shell-quote": "^1.7.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^17.3.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + } + } + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "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" + } + }, + "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.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "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 + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "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" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", + "dev": true + }, + "copy-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", + "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==", + "dev": true + }, + "copy-to-clipboard": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz", + "integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==", + "requires": { + "toggle-selection": "^1.0.6" + } + }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "dev": true + }, + "core-js-compat": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.24.1.tgz", + "integrity": "sha512-XhdNAGeRnTpp8xbD+sR/HFDK9CbeeeqXT6TuofXh3urqEevzkWmLRgrVoykodsw8okqo2pu1BOmuCKrHx63zdw==", + "dev": true, + "requires": { + "browserslist": "^4.21.3", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", + "dev": true + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "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" + } + }, + "cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "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-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=" + }, + "css-loader": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.6.tgz", + "integrity": "sha512-0wyN5vXMQZu6BvjbrPdUJvkCzGEO24HC7IS7nW4llc6BBFC+zwR9CKtYGv63Puzsg10L/o12inMY5/2ByzfD6w==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.5" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-to-react-native": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.3.2.tgz", + "integrity": "sha512-VOFaeZA053BqvvvqIA8c9n0+9vFppVBAHCp6JgFTtTMU3Mzi+XnelJ9XC9ul3BqFzZyQ5N+H0SnwsWT2Ebchxw==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^3.3.0" + }, + "dependencies": { + "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==" + } + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==", + "dev": true + }, + "date-fns": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz", + "integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ==" + }, + "dayjs": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz", + "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==" + }, + "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" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true + }, + "decimal.js": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.0.tgz", + "integrity": "sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw==" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==", + "dev": true + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "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" + } + } + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "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": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "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" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-align": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.2.tgz", + "integrity": "sha512-pHuazgqrsTFrGU2WLDdXxCFabkdQDx72ddkraZNih1KsMcN5qsRSTR9O4VJRlwTPCPb5COYg3LOfiMHHcPInHg==" + }, + "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-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "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": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "ejs": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", + "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.4.228", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.228.tgz", + "integrity": "sha512-XfDHCvou7CsDMlFwb0WZ1tWmW48e7Sn7VBRyPfZsZZila9esRsJl1trO+OqDNV97GggFSt0ISbWslKXfQkG//g==", + "dev": true + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "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 + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "escape-latex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", + "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "eslint": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.15.0.tgz", + "integrity": "sha512-Vr64xFDT8w30wFll643e7cGrIkPEU50yIiI36OdSIDoSGguIeaLzBo0vpGvzo9RECUqq7htURfwEtKqwytkqzA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.2.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^6.0.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "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 + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "eslint-config-prettier": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz", + "integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + }, + "eslint-plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-babel/-/eslint-plugin-babel-5.3.1.tgz", + "integrity": "sha512-VsQEr6NH3dj664+EyxJwO4FCYm/00JhYb3Sk3ft8o+fpKuIfQ9TaW6uVUfvwMXHcf/lsnRIoyFPsLMyiWCSL/g==", + "dev": true, + "requires": { + "eslint-rule-composer": "^0.3.0" + } + }, + "eslint-plugin-prettier": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.0.tgz", + "integrity": "sha512-tMTwO8iUWlSRZIwS9k7/E4vrTsfvsrcM5p1eftyuqWH25nKsz/o6/54I7jwQ/3zobISyC7wMy9ZsFwgTxOcOpQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-plugin-react": { + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz", + "integrity": "sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "object.entries": "^1.1.2", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.18.1", + "string.prototype.matchall": "^4.0.2" + }, + "dependencies": { + "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" + } + } + } + }, + "eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "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" + } + }, + "exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=" + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "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": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "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": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "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": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "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" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "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": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "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": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "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" + } + } + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "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.18" + }, + "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.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "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": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "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": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "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" + } + }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "dev": true + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, + "fraction.js": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.0.12.tgz", + "integrity": "sha512-8Z1K0VTG4hzYY7kA/1sj4/r1/RWLBD3xwReT/RCrUCbzPszjNQCCsy3ktkU/eaEqX3MYa4pY37a52eiBlPMlhA==" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "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": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "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": "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==", + "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": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "dev": true + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "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" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "optional": 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": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + }, + "dependencies": { + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "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" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "gzip-size": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", + "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "pify": "^4.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" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, + "hollaex-web-lib": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/hollaex-web-lib/-/hollaex-web-lib-0.3.0.tgz", + "integrity": "sha512-DDMFM5cVNAgWYwmsgJTck30xSBfCQB/Xe+kK2liVfQgkOeoFVj7F65uLi72IB7LBO55hfxmPj2bSt8XkN87ydA==", + "requires": { + "@material/button": "0.7.0", + "keycode": "2.2.0", + "react-copy-to-clipboard": "5.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "requires": { + "whatwg-encoding": "^2.0.0" + } + }, + "html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "requires": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + } + }, + "html-webpack-plugin": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.5.0.tgz", + "integrity": "sha512-MouoXEYSjTzCrjIxWwg8gxL5fE2X2WZJLmBYXlaJhQUH5K/b5OrqmV7T4dB7iu0xkmJ6JlUuV6fFVtnqbPopZw==", + "dev": true, + "requires": { + "@types/html-minifier-terser": "^5.0.0", + "@types/tapable": "^1.0.5", + "@types/webpack": "^4.41.8", + "html-minifier-terser": "^5.0.1", + "loader-utils": "^1.2.3", + "lodash": "^4.17.15", + "pretty-error": "^2.1.1", + "tapable": "^1.1.3", + "util.promisify": "1.0.0" + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "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" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + } + } + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-server": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.0.0.tgz", + "integrity": "sha512-XTePIXAo5x72bI8SlKFSqsg7UuSHwsOa4+RJIe56YeMUvfTvGDy7TxFkTEhfIRmM/Dnf6x29ut541ythSBZdkQ==", + "dev": true, + "requires": { + "basic-auth": "^2.0.1", + "colors": "^1.4.0", + "corser": "^2.0.1", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", + "minimist": "^1.2.5", + "opener": "^1.5.1", + "portfinder": "^1.0.28", + "secure-compare": "3.0.1", + "union": "~0.5.0", + "url-join": "^4.0.1" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "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" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.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" + }, + "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-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" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "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": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "insert-css": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/insert-css/-/insert-css-2.0.0.tgz", + "integrity": "sha1-610Ql7dUL0x56jBg067gfQU4gPQ=" + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "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" + } + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "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": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "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-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "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": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "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-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "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": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true + }, + "is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "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": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "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" + } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "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.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "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": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "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" + } + }, + "javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k=" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-beautify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/json-beautify/-/json-beautify-1.1.1.tgz", + "integrity": "sha512-17j+Hk2lado0xqKtUcyAjK0AtoHnPSIgktWRsEXgdFQFG9UnaGw6CHa0J7xsvulxRpFl6CrkDFHght1p5ZJc4A==", + "dev": true + }, + "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==", + "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 + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha1-tje9O6nqvhIsg+lyBIOusQ0skEo=", + "requires": { + "string-convert": "^0.2.0" + } + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "jsx-ast-utils": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", + "dev": true, + "requires": { + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" + } + }, + "keycode": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz", + "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ=" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "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" + } + } + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, + "lodash.has": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", + "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "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" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "requires": { + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "mathjs": { + "version": "5.10.3", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-5.10.3.tgz", + "integrity": "sha512-ySjg30BC3dYjQm73ILZtwcWzFJde0VU6otkXW/57IjjuYRa3Qaf0Kb8pydEuBZYtqW2OxreAtsricrAmOj3jIw==", + "requires": { + "complex.js": "2.0.11", + "decimal.js": "10.2.0", + "escape-latex": "1.2.0", + "fraction.js": "4.0.12", + "javascript-natural-sort": "0.7.1", + "seed-random": "2.2.0", + "tiny-emitter": "2.1.0", + "typed-function": "1.1.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "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" + } + }, + "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" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "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.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, + "mini-store": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/mini-store/-/mini-store-3.0.6.tgz", + "integrity": "sha512-YzffKHbYsMQGUWQRKdsearR79QsMzzJcDDmZKlJBqt5JNkqpyJHYlK6gP61O36X+sLf76sO9G6mhKBe83gIZIQ==", + "requires": { + "hoist-non-react-statics": "^3.3.2", + "shallowequal": "^1.0.2" + } + }, + "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": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "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" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "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" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==", + "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" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "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-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" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "nocache": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.1.tgz", + "integrity": "sha512-Gh39xwJwBKy0OvFmWfBs/vDO4Nl7JhnJtkqNP76OUinQz7BiMoszHYrIDHHAaqVl/QKVxCEy4ZxC/XZninu7nQ==", + "dev": true + }, + "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-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "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": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "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.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + } + } + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": 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 + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "numbro": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/numbro/-/numbro-1.11.1.tgz", + "integrity": "sha512-qL0Etqbunz4RtPx4bNjMONe9HyUpgbrM4Sa3VpWY5oRdp9ry5DufAj6lCvnIcluRBA9QUacrllYc73QK0G6VAw==" + }, + "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": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "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": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "object.fromentries": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", + "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz", + "integrity": "sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ==", + "dev": true, + "requires": { + "array.prototype.reduce": "^1.0.4", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "omit.js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/omit.js/-/omit.js-2.0.2.tgz", + "integrity": "sha512-hJmu9D+bNB40YpL9jYebQl4lsTW6yEHRTroJzNLqQJYHm7c+NQnJGfZmIWh8S3q3KoaxV1aLhV6B3+0N0/kyJg==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onchange": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/onchange/-/onchange-7.1.0.tgz", + "integrity": "sha512-ZJcqsPiWUAUpvmnJri5TPBooqJOPmC0ttN65juhN15Q8xA+Nbg3BaxBHXQ45EistKKlKElb0edmbPWnKSBkvMg==", + "dev": true, + "requires": { + "@blakeembrey/deque": "^1.0.5", + "@blakeembrey/template": "^1.0.0", + "arg": "^4.1.3", + "chokidar": "^3.3.1", + "cross-spawn": "^7.0.1", + "ignore": "^5.1.4", + "tree-kill": "^1.2.2" + }, + "dependencies": { + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + } + } + }, + "opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.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 + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", + "dev": true + }, + "path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "dev": true, + "requires": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "dev": true, + "optional": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "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": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "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": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "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=" + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "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 + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "portfinder": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", + "dev": true, + "requires": { + "async": "^2.6.4", + "debug": "^3.2.7", + "mkdirp": "^0.5.6" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", + "dev": true + }, + "postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-error": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", + "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^2.0.4" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "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": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "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" + } + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "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", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "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" + } + }, + "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" + }, + "dependencies": { + "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" + } + } + } + }, + "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 + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "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" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "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.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" + } + }, + "rc-align": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.11.tgz", + "integrity": "sha512-n9mQfIYQbbNTbefyQnRHZPWuTEwG1rY4a9yKlIWHSTbgwI+XUMGRYd0uJ5pE2UbrNX0WvnMBA1zJ3Lrecpra/A==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "dom-align": "^1.7.0", + "lodash": "^4.17.21", + "rc-util": "^5.3.0", + "resize-observer-polyfill": "^1.5.1" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + } + } + }, + "rc-animate": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.1.tgz", + "integrity": "sha512-8wg2Zg3EETy0k/9kYuis30NJNQg1D6/WSQwnCiz6SvyxQXNet/rVraRz3bPngwY6rcU2nlRvoShiYOorXyF7Sg==", + "requires": { + "@ant-design/css-animation": "^1.7.2", + "classnames": "^2.2.6", + "raf": "^3.4.0", + "rc-util": "^4.15.3" + }, + "dependencies": { + "rc-util": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.21.1.tgz", + "integrity": "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==", + "requires": { + "add-dom-event-listener": "^1.1.0", + "prop-types": "^15.5.10", + "react-is": "^16.12.0", + "react-lifecycles-compat": "^3.0.4", + "shallowequal": "^1.1.0" + } + } + } + }, + "rc-cascader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-1.3.0.tgz", + "integrity": "sha512-wayuMo/dSZixvdpiRFZB4Q6A3omKRXQcJ3CxN02+PNiTEcRnK2KDqKUzrx7GwgMsyH5tz90lUZ91lLaEPNFv0A==", + "requires": { + "array-tree-filter": "^2.1.0", + "rc-trigger": "^4.0.0", + "rc-util": "^5.0.1", + "warning": "^4.0.1" + } + }, + "rc-checkbox": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.3.2.tgz", + "integrity": "sha512-afVi1FYiGv1U0JlpNH/UaEXdh6WUJjcWokj/nUN2TgG80bfG+MDdbfHKlLcNNba94mbjy2/SXJ1HDgrOkXGAjg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1" + } + }, + "rc-collapse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-2.0.1.tgz", + "integrity": "sha512-sRNqwQovzQoptTh7dCwj3kfxrdor2oNXrGSBz+QJxSFS7N3Ujgf8X/KlN2ElCkwBKf7nNv36t9dwH0HEku4wJg==", + "requires": { + "@ant-design/css-animation": "^1.7.2", + "classnames": "2.x", + "rc-animate": "3.x", + "rc-util": "^5.2.1", + "shallowequal": "^1.1.0" + } + }, + "rc-dialog": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-8.1.2.tgz", + "integrity": "sha512-yhyy3bxnornjrUPOiCXFdTt/nRKjQ/qhR+MMcQavRYWh1LPcxB8y1LbgrvYX7SV/lY/Mib237xf2q6WYXQ1kpA==", + "requires": { + "rc-animate": "3.x", + "rc-util": "^5.0.1" + } + }, + "rc-drawer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-4.1.0.tgz", + "integrity": "sha512-kjeQFngPjdzAFahNIV0EvEBoIKMOnvUsAxpkSPELoD/1DuR4nLafom5ryma+TIxGwkFJ92W6yjsMi1U9aiOTeQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.0.1" + } + }, + "rc-dropdown": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-3.1.3.tgz", + "integrity": "sha512-sqVMDZcyV32y2YIEUBfxzgRzOLXqi/v5JB1GPe0CMyGMadPvbi+YIRF8toKdQf26tcHZobZUOyFk8OOV2BRusw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-trigger": "^4.0.0" + } + }, + "rc-field-form": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.10.1.tgz", + "integrity": "sha512-aosTtNTqLYX2jsG5GyCv7axe+b57XH73T7TmmrX/cmhemhtFjvNE6RkRkmtP9VOJnZg5YGC5HfK172cnJ1Ij7Q==", + "requires": { + "@babel/runtime": "^7.8.4", + "async-validator": "^3.0.3", + "rc-util": "^5.0.0" + } + }, + "rc-image": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-3.0.6.tgz", + "integrity": "sha512-Dn8mTSlcgKJko417OX8+6yyNIL9+DEa81aexBfT78qWlEpcxtR4GgdsU0+zJLNqa2rnGZyjaBLFtaPw9tUuxYA==", + "requires": { + "@ant-design/icons": "^4.2.2", + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "rc-dialog": "~8.2.2", + "rc-util": "^5.0.6" + }, + "dependencies": { + "rc-dialog": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-8.2.2.tgz", + "integrity": "sha512-U4jR5bE7XpIbMC20JAIv91254b+vQ8LODd8Kxco0XvkL+eJ1aCYkOfRqevJ1ipOIzF3s6F08jSH8YvJqxvpAvA==", + "requires": { + "@babel/runtime": "^7.10.1", + "rc-animate": "3.x", + "rc-util": "^5.0.1" + } + } + } + }, + "rc-input-number": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-6.0.1.tgz", + "integrity": "sha512-cS1k6IB/V84VUQd5qWzGFrLHvZjWGHGmYbrvR0QP/C1Ju1SlBqlhqhOBTc6w+dpPs84PCH5caZtNzsHeWZ1zYA==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + } + }, + "rc-mentions": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.4.2.tgz", + "integrity": "sha512-wSmHRF9kFwrbj59mR+u4yVr0KtcrfPw53PYOVizYxYeDfmwaCcSgk29F8OjlDy5jVqUaMhHX5nIiYCePu5Aytg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-menu": "^8.0.1", + "rc-textarea": "^0.3.0", + "rc-trigger": "^4.3.0", + "rc-util": "^5.0.1" + } + }, + "rc-menu": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-8.5.3.tgz", + "integrity": "sha512-OLdN+jwhabgyRZDvWYjYpO7RP7wLybhNuAulgGqx1oUPBJrtgVlG/X4HtPb7nypRx/n+eicj6H8CtbCs0L4m/Q==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "mini-store": "^3.0.1", + "omit.js": "^2.0.0", + "rc-motion": "^1.0.1", + "rc-trigger": "^4.4.0", + "rc-util": "^5.0.1", + "resize-observer-polyfill": "^1.5.0", + "shallowequal": "^1.1.0" + } + }, + "rc-motion": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-1.1.2.tgz", + "integrity": "sha512-YC/E7SSWKBFakYg4PENhSRWD4ZLDqkI7FKmutJcrMewZ91/ZIWfoZSDvPaBdKO0hsFrrzWepFhXQIq0FNnCMWA==", + "requires": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "raf": "^3.4.1", + "rc-util": "^5.0.6" + } + }, + "rc-notification": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-4.4.0.tgz", + "integrity": "sha512-IDeNAFGVeOsy1tv4zNVqMAXB9tianR80ewQbtObaAQfjwAjWfONdqdyjFkEU6nc6UQhSUYA5OcTGb7kwwbnh0g==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-animate": "3.x", + "rc-util": "^5.0.1" + } + }, + "rc-pagination": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-3.0.4.tgz", + "integrity": "sha512-9v9mmB7FTWS4kWRLFfWafm6LtvB+xdNi+pTIwUODSevzImrlrmMOIhDrOB3u2tEXiy8LyqvCnoyPYt5jQBapxA==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1" + } + }, + "rc-picker": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-2.0.11.tgz", + "integrity": "sha512-pUEne2fikHvzqmOjWNLa1P/ss4/1J9lpHrtSU1IrueRiEbUPLIgXmnzoUeVt3syOZGBnWok6nNDu1FvIQfVMCw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "date-fns": "^2.15.0", + "dayjs": "^1.8.30", + "moment": "^2.24.0", + "rc-trigger": "^4.0.0", + "rc-util": "^5.0.1", + "shallowequal": "^1.1.0" + } + }, + "rc-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.0.0.tgz", + "integrity": "sha512-dQv1KU3o6Vay604FMYMF4S0x4GNXAgXf1tbQ1QoxeIeQt4d5fUeB7Ri82YPu+G+aRvH/AtxYAlEcnxyVZ1/4Hw==", + "requires": { + "classnames": "^2.2.6" + } + }, + "rc-rate": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.8.2.tgz", + "integrity": "sha512-f9T/D+ZwWQrWHkpidpQbnXpnVMGMC4eSRAkwuu88a8Qv1C/9LNc4AErazoh8tpnZBFqq19F3j0Glv+sDgkfEig==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + } + }, + "rc-resize-observer": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-0.2.6.tgz", + "integrity": "sha512-YX6nYnd6fk7zbuvT6oSDMKiZjyngjHoy+fz+vL3Tez38d/G5iGdaDJa2yE7345G6sc4Mm1IGRUIwclvltddhmA==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.0.0", + "resize-observer-polyfill": "^1.5.1" + } + }, + "rc-select": { + "version": "11.1.7", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-11.1.7.tgz", + "integrity": "sha512-HZozKGhFbLDI995OUKQW2uZ2ZcGyzNhWN6gTQqpW5/Z0rae1zftpgkI1yxZ79LukOc8lO2NKlDDKCGH/SJH2Cg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^1.0.1", + "rc-trigger": "^4.3.0", + "rc-util": "^5.0.1", + "rc-virtual-list": "^3.0.3", + "warning": "^4.0.3" + } + }, + "rc-slider": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-9.3.1.tgz", + "integrity": "sha512-c52PWPyrfJWh28K6dixAm0906L3/4MUIxqrNQA4TLnC/Z+cBNycWJUZoJerpwSOE1HdM3XDwixCsmtFc/7aWlQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-tooltip": "^4.0.0", + "rc-util": "^5.0.0", + "shallowequal": "^1.1.0" + } + }, + "rc-steps": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-4.1.4.tgz", + "integrity": "sha512-qoCqKZWSpkh/b03ASGx1WhpKnuZcRWmvuW+ZUu4mvMdfvFzVxblTwUM+9aBd0mlEUFmt6GW8FXhMpHkK3Uzp3w==", + "requires": { + "@babel/runtime": "^7.10.2", + "classnames": "^2.2.3", + "rc-util": "^5.0.1" + } + }, + "rc-switch": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-3.2.2.tgz", + "integrity": "sha512-+gUJClsZZzvAHGy1vZfnwySxj+MjLlGRyXKXScrtCTcmiYNPzxDFOxdQ/3pK1Kt/0POvwJ/6ALOR8gwdXGhs+A==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.0.1" + } + }, + "rc-table": { + "version": "7.9.10", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.9.10.tgz", + "integrity": "sha512-WtPBxYsBU/a5MIglilbMlVkiXkPKXpUM/CPCFaqA2veh1b7J40mbTGQmU8VT6S0FClkI5jm0QBtSp6LstPkOMQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "raf": "^3.4.1", + "rc-resize-observer": "^0.2.0", + "rc-util": "^5.0.4", + "shallowequal": "^1.1.0" + } + }, + "rc-tabs": { + "version": "11.6.2", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-11.6.2.tgz", + "integrity": "sha512-7Z5Lg+nP/H4V7dIlewrOC0+aogRVH3ASjTy4VIletYOeStGPWYSfwBnUTBdcCXcUuWuyyKnNkYrUD0yaRqUCIA==", + "requires": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "raf": "^3.4.1", + "rc-dropdown": "^3.1.3", + "rc-menu": "^8.6.1", + "rc-resize-observer": "^0.2.1", + "rc-util": "^5.0.0" + }, + "dependencies": { + "rc-menu": { + "version": "8.10.8", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-8.10.8.tgz", + "integrity": "sha512-0gnSR0nmR/60NnK+72EGd+QheHyPSQ3wYg1TwX1zl0JJ9Gm0purFFykCXVv/G0Jynpt0QySPAos+bpHpjMZdoQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "mini-store": "^3.0.1", + "rc-motion": "^2.0.1", + "rc-trigger": "^5.1.2", + "rc-util": "^5.7.0", + "resize-observer-polyfill": "^1.5.0", + "shallowequal": "^1.1.0" + } + }, + "rc-motion": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.4.4.tgz", + "integrity": "sha512-ms7n1+/TZQBS0Ydd2Q5P4+wJTSOrhIrwNxLXCZpR7Fa3/oac7Yi803HDALc2hLAKaCTQtw9LmQeB58zcwOsqlQ==", + "requires": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.2.1" + } + }, + "rc-trigger": { + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-5.2.10.tgz", + "integrity": "sha512-FkUf4H9BOFDaIwu42fvRycXMAvkttph9AlbCZXssZDVzz2L+QZ0ERvfB/4nX3ZFPh1Zd+uVGr1DEDeXxq4J1TA==", + "requires": { + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "rc-align": "^4.0.0", + "rc-motion": "^2.0.0", + "rc-util": "^5.5.0" + } + } + } + }, + "rc-textarea": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-0.3.5.tgz", + "integrity": "sha512-qa+k5vDn9ct65qr+SgD2KwJ9Xz6P84lG2z+TDht/RBr71WnM/K61PqHUAcUyU6YqTJD26IXgjPuuhZR7HMw7eA==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.7.0" + }, + "dependencies": { + "rc-resize-observer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.0.1.tgz", + "integrity": "sha512-OxO2mJI9e8610CAWBFfm52SPvWib0eNKjaSsRbbKHmLaJIxw944P+D61DlLJ/w2vuOjGNcalJu8VdqyNm/XCRg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.0.0", + "resize-observer-polyfill": "^1.5.1" + } + } + } + }, + "rc-tooltip": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-4.2.3.tgz", + "integrity": "sha512-7ySkaPGeqLLM4a/QYrKQ280aDthPxyvjJqQMstWX/AWX7/b1p23HIdHXdjBkziuvcnvXkW4lgZdFTVsylDiX1w==", + "requires": { + "@babel/runtime": "^7.11.2", + "rc-trigger": "^4.2.1" + } + }, + "rc-tree": { + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-3.9.5.tgz", + "integrity": "sha512-ZGVl1o83hZoz971pzY9Y7yZM+f9qcia1Gym+QNyc3zMGQVshbr6CX2WZ8xUK18tTkdRSqbTXmZFnvYf1lfqT8A==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^1.0.0", + "rc-util": "^5.0.0", + "rc-virtual-list": "^3.0.1" + } + }, + "rc-tree-select": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-4.1.3.tgz", + "integrity": "sha512-vk/T1vHNvuBZyoq8CvOF6iaiyVe6Y8QmQflTYFgabVsTJ1d/obkO9tAXOvJELZgKJ9ljduDVaAZAgcq0Yap+mg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-select": "^11.1.1", + "rc-tree": "^3.8.0", + "rc-util": "^5.0.5" + } + }, + "rc-trigger": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-4.4.3.tgz", + "integrity": "sha512-yq/WyuiPwxd2q6jy+VPyy0GUCRFJ2eFqAaCwPE27AOftXeIupOcJ/2t1wakSq63cfk7qtzev5DKHUAjb8LOJCw==", + "requires": { + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "raf": "^3.4.1", + "rc-align": "^4.0.0", + "rc-motion": "^1.0.0", + "rc-util": "^5.0.1" + } + }, + "rc-upload": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-3.2.1.tgz", + "integrity": "sha512-gmIy08tco2YFTSiru9zgeTmUcDKPyUMUUBdUIjG2CcHz4jdbpaPx/RL/Wz9CMD6ppQizK0gES0rcQ1+o5frK2Q==", + "requires": { + "classnames": "^2.2.5" + } + }, + "rc-util": { + "version": "5.13.2", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.13.2.tgz", + "integrity": "sha512-eYc71XXGlp96RMzg01Mhq/T3BL6OOVTDSS0urFEuvpi+e7slhJRhaHGCKy2hqJm18m9ff7VoRoptplKu60dYog==", + "requires": { + "@babel/runtime": "^7.12.5", + "react-is": "^16.12.0", + "shallowequal": "^1.1.0" + } + }, + "rc-virtual-list": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.4.2.tgz", + "integrity": "sha512-OyVrrPvvFcHvV0ssz5EDZ+7Rf5qLat/+mmujjchNw5FfbJWNDwkpQ99EcVE6+FtNRmX9wFa1LGNpZLUTvp/4GQ==", + "requires": { + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.0.7" + }, + "dependencies": { + "rc-resize-observer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.0.1.tgz", + "integrity": "sha512-OxO2mJI9e8610CAWBFfm52SPvWib0eNKjaSsRbbKHmLaJIxw944P+D61DlLJ/w2vuOjGNcalJu8VdqyNm/XCRg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.0.0", + "resize-observer-polyfill": "^1.5.1" + } + } + } + }, + "react": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", + "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-copy-to-clipboard": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.1.tgz", + "integrity": "sha512-ELKq31/E3zjFs5rDWNCfFL4NvNFQvGRoJdAKReD/rUPA+xxiLPQmZBZBvy2vgH7V0GE9isIQpT9WXbwIVErYdA==", + "requires": { + "copy-to-clipboard": "^3", + "prop-types": "^15.5.8" + } + }, + "react-device-detect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/react-device-detect/-/react-device-detect-1.6.2.tgz", + "integrity": "sha512-XIBgwIfpGAknm7tXe/YNbx4ieIR7IyFI3KNfSQk4UjHVy97UHe/nB7iJj8R/dDsI+I/ZzPR4HJ39Gh5tI4nhxw==" + }, + "react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, + "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" + } + }, + "react-ionicons": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/react-ionicons/-/react-ionicons-2.1.6.tgz", + "integrity": "sha1-ycRywkL0HyKKYmH9bOFW1U4Odnc=", + "requires": { + "prop-types": "15.5.10", + "react": "15.4.2", + "react-dom": "15.4.2", + "styled-components": "2.2.3" + }, + "dependencies": { + "prop-types": { + "version": "15.5.10", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", + "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", + "requires": { + "fbjs": "^0.8.9", + "loose-envify": "^1.3.1" + } + }, + "react": { + "version": "15.4.2", + "resolved": "https://registry.npmjs.org/react/-/react-15.4.2.tgz", + "integrity": "sha1-QfeZGyYYU5K6m66WyIiefgGDl+8=", + "requires": { + "fbjs": "^0.8.4", + "loose-envify": "^1.1.0", + "object-assign": "^4.1.0" + } + }, + "react-dom": { + "version": "15.4.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.4.2.tgz", + "integrity": "sha1-AVNj8FsKH9Uq6e/dOgBg2QaVII8=", + "requires": { + "fbjs": "^0.8.1", + "loose-envify": "^1.1.0", + "object-assign": "^4.1.0" + } + } + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "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==", + "requires": { + "exenv": "^1.2.0", + "prop-types": "^15.5.10", + "react-lifecycles-compat": "^3.0.0", + "warning": "^3.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "react-redux": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-6.0.1.tgz", + "integrity": "sha512-T52I52Kxhbqy/6TEfBv85rQSDz6+Y28V/pf52vDWs1YRXG19mcFOGfHnY2HsNFHyhP+ST34Aih98fvt6tqwVcQ==", + "requires": { + "@babel/runtime": "^7.3.1", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.8.2" + } + }, + "react-svg": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/react-svg/-/react-svg-11.2.2.tgz", + "integrity": "sha512-Q9lAuUgaI8c55OluftgrAyE4GAmIvmqVHJXt1fIzXFHcuIauKqVjhUH/BiizOqjPmY+R27kiTkv9g7AxY7O+wA==", + "requires": { + "@babel/runtime": "^7.12.5", + "@tanem/svg-injector": "^8.2.1", + "prop-types": "^15.7.2" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "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" + } + }, + "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, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "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" + } + }, + "redux-form": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/redux-form/-/redux-form-8.1.0.tgz", + "integrity": "sha512-d2+0OaJpSq3kwkbPtFlG3W/HENWLxX8NqqTHSOnfgIrID/9faH/rxejLa1X3HChilCTm71zWe/g9zaLPCMCofQ==", + "requires": { + "@babel/runtime": "^7.2.0", + "es6-error": "^4.1.1", + "hoist-non-react-statics": "^3.2.1", + "invariant": "^2.2.4", + "is-promise": "^2.1.0", + "lodash": "^4.17.11", + "lodash-es": "^4.17.11", + "prop-types": "^15.6.1", + "react-is": "^16.7.0", + "react-lifecycles-compat": "^3.0.4" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "dev": true, + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, + "regenerator-transform": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "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.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "regexpu-core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz", + "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==", + "dev": true, + "requires": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + } + }, + "regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", + "dev": true + }, + "regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==" + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true, + "optional": true + }, + "renderkid": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", + "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg==", + "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": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "dev": true + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "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 + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "dev": true + }, + "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 + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "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" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", + "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "dev": true, + "requires": { + "tslib": "^2.1.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 + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "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==" + }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "scroll-into-view-if-needed": { + "version": "2.2.28", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.28.tgz", + "integrity": "sha512-8LuxJSuFVc92+0AdNv4QOxRL4Abeo1DgLnGNkn1XlaujPH/3cCFz3QI60r2VNu4obJJROzgnIUw5TKQkZvZI1w==", + "requires": { + "compute-scroll-into-view": "^1.0.17" + } + }, + "secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", + "dev": true + }, + "seed-random": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz", + "integrity": "sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ=" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "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": { + "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 + } + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "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" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "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": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "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.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "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==", + "dev": true, + "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": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "shell-quote": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.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": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "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": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "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": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "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" + } + } + } + }, + "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" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "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.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", + "dev": true + }, + "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": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "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": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "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.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c=" + }, + "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==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + } + }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "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" + } + }, + "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" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "styled-components": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-2.2.3.tgz", + "integrity": "sha512-KzdZv4zyZPLoM4V90Tu+3evqTBZt1quFC1DBt5SA7k4dY3ANWmK+LZiIk/Q99GzLisBiEjV+Fn9nyty9rrZ1jw==", + "requires": { + "buffer": "^5.0.3", + "css-to-react-native": "^2.0.3", + "fbjs": "^0.8.9", + "hoist-non-react-statics": "^1.2.0", + "is-function": "^1.0.1", + "is-plain-object": "^2.0.1", + "prop-types": "^15.5.4", + "stylis": "3.x", + "supports-color": "^3.2.3" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "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=" + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "stylis": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", + "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==" + }, + "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-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "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==" + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^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 + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.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" + } + }, + "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-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" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "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" + } + }, + "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 + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "tinycolor2": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", + "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==" + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", + "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": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "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": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "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": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "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": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", + "dev": true + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "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" + } + }, + "typed-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-1.1.0.tgz", + "integrity": "sha512-TuQzwiT4DDg19beHam3E66oRXhyqlyfgjHB/5fcvsRXbfmWPJfto9B4a0TBdTrQAPGlGmXh/k7iUI+WsObgORA==" + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.28", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.28.tgz", + "integrity": "sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g==" + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "requires": { + "commander": "~2.13.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "dev": true + }, + "union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dev": true, + "requires": { + "qs": "^6.4.0" + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", + "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": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "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": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "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": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "optional": true + }, + "update-browserslist-db": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", + "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "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": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "dev": true + } + } + }, + "url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "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" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "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==", + "dev": true, + "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": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "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" + } + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + }, + "watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + }, + "dependencies": { + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": 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" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true + } + } + }, + "webpack": { + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", + "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.3.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "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" + } + } + } + }, + "webpack-assets-manifest": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/webpack-assets-manifest/-/webpack-assets-manifest-3.1.1.tgz", + "integrity": "sha512-JV9V2QKc5wEWQptdIjvXDUL1ucbPLH2f27toAY3SNdGZp+xSaStAgpoMcvMZmqtFrBc9a5pTS1058vxyMPOzRQ==", + "dev": true, + "requires": { + "chalk": "^2.0", + "lodash.get": "^4.0", + "lodash.has": "^4.0", + "mkdirp": "^0.5", + "schema-utils": "^1.0.0", + "tapable": "^1.0.0", + "webpack-sources": "^1.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "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" + } + } + } + }, + "webpack-bundle-analyzer": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz", + "integrity": "sha512-Ob8amZfCm3rMB1ScjQVlbYYUEJyEjdEtQ92jqiFUYt5VkEeO2v5UMbv49P/gnmCZm3A6yaFQzCBvpZqN4MUsdA==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1", + "bfj": "^6.1.1", + "chalk": "^2.4.1", + "commander": "^2.18.0", + "ejs": "^2.6.1", + "express": "^4.16.3", + "filesize": "^3.6.1", + "gzip-size": "^5.0.0", + "lodash": "^4.17.19", + "mkdirp": "^0.5.1", + "opener": "^1.5.1", + "ws": "^6.0.0" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + } + } + }, + "webpack-cli": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", + "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.1", + "findup-sync": "^3.0.0", + "global-modules": "^2.0.0", + "import-local": "^2.0.0", + "interpret": "^1.4.0", + "loader-utils": "^1.4.0", + "supports-color": "^6.1.0", + "v8-compile-cache": "^2.1.1", + "yargs": "^13.3.2" + }, + "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" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "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": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "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" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "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 + } + } + }, + "whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "requires": { + "iconv-lite": "0.6.3" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "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-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" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/plugins/package.json b/plugins/package.json new file mode 100644 index 0000000000..df71b8305a --- /dev/null +++ b/plugins/package.json @@ -0,0 +1,110 @@ +{ + "name": "hollaex-plugins", + "version": "1.0.0", + "description": "HollaEx Official Plugins Repo", + "private": true, + "browser": "dist/main.js", + "repository": { + "type": "git", + "url": "git+https://github.com/bitholla/hollaex-plugins.git" + }, + "author": "bitHolla", + "license": "ISC", + "scripts": { + "kill-8080": "lsof -ti:8080 | xargs kill || exit 0", + "generate:bundle:production": "npm run remove:dist && cross-env NODE_ENV=production webpack --env.plugin=$npm_config_plugin --mode production", + "generate:bundle:development": "npm run remove:dist && cross-env NODE_ENV=development webpack --env.plugin=$npm_config_plugin --mode development", + "plugin:development": "cross-env NODE_ENV=development concurrently \"npm run webpack:development --plugin=$npm_config_plugin\" \"npm run watch:webview:json --plugin=$npm_config_plugin\" \"npm run watch:config:json --plugin=$npm_config_plugin\" \"npm run server\"", + "webpack:development": "npm run remove:dist && cross-env NODE_ENV=development webpack --env.plugin=$npm_config_plugin --mode development --config webpack-dev.config.js", + "remove:dist": "rimraf dist", + "remove:json": "rimraf json", + "remove:config": "rimraf config", + "generate:webview:json": "PLUGIN=$npm_config_plugin node scripts/generateJson.js", + "generate:webview:json:clean": "npm run remove:json && npm run generate:webview:json --plugin=$npm_config_plugin", + "generate:config:json": "PLUGIN=$npm_config_plugin node scripts/generateConfig.js", + "add:plugin": "PLUGIN=$npm_config_plugin TYPE=$npm_config_type node scripts/addPlugin.js", + "add:view": "PLUGIN=$npm_config_plugin WEB_VIEW=$npm_config_webview node scripts/addView.js", + "generate:webview:production": "npm run generate:bundle:production --plugin=$npm_config_plugin && npm run generate:webview:json:clean --plugin=$npm_config_plugin", + "generate:webview:development": "npm run generate:bundle:development --plugin=$npm_config_plugin && npm run generate:webview:json:clean --plugin=$npm_config_plugin", + "watch:webview:json": "npm run remove:json && onchange -i 'src/plugins/**/assets/*.json' 'src/plugins/**/views/**/*.json' -- npm run generate:webview:json --plugin=$npm_config_plugin", + "watch:config:json": "npm run remove:config && onchange -i 'src/plugins/**/assets/*.json' 'src/plugins/**/views/**/*.json' 'src/plugins/**/server/*' -- npm run generate:config:json --plugin=$npm_config_plugin", + "server": "npm run kill-8080 && node server.js", + "build": "npm run build:webview --plugin=$npm_config_plugin && npm run generate:plugin:json --plugin=$npm_config_plugin", + "generate:plugin:json": "PLUGIN=$npm_config_plugin node scripts/generatePlugin.js", + "add:webview:bundles": "node scripts/addBundles.js", + "add:webview:jsons": "node scripts/addJsons.js", + "build:webview": "npm run generate:webview:production --plugin=$npm_config_plugin && npm run add:webview:bundles && npm run add:webview:jsons", + "start": "concurrently \"npm run --prefix ../web dev:plugin --plugin=$npm_config_plugin\" \"npm run plugin:development --plugin=$npm_config_plugin\"" + }, + "dependencies": { + "@ant-design/icons": "4.2.2", + "antd": "4.6.2", + "axios": "0.21.1", + "classnames": "2.2.6", + "hollaex-web-lib": "0.3.0", + "html-minifier-terser": "5.1.1", + "lodash.debounce": "4.0.8", + "mathjs": "5.10.3", + "moment": "2.24.0", + "numbro": "1.11.1", + "prop-types": "15.7.2", + "react": "16.13.1", + "react-device-detect": "1.6.2", + "react-event-listener": "0.6.6", + "react-ionicons": "2.1.6", + "react-modal": "3.8.1", + "react-redux": "6.0.1", + "react-svg": "11.2.2", + "redux": "4.0.1", + "redux-form": "8.1.0", + "uglify-es": "3.3.9", + "validator": "10.11.0" + }, + "devDependencies": { + "@babel/cli": "7.12.10", + "@babel/core": "7.12.10", + "@babel/plugin-proposal-class-properties": "7.12.1", + "@babel/plugin-transform-runtime": "7.12.10", + "@babel/preset-env": "7.12.10", + "@babel/preset-react": "7.12.10", + "@babel/runtime": "7.12.5", + "@paciolan/eslint-config-react": "1.0.4", + "@paciolan/remote-component": "2.10.2", + "babel-eslint": "10.1.0", + "babel-loader": "8.2.2", + "babel-plugin-transform-react-remove-prop-types": "0.4.24", + "concurrently": "7.3.0", + "copy-dir": "1.3.0", + "core-js": "2.6.12", + "cross-env": "7.0.3", + "css-loader": "5.2.6", + "eslint": "7.15.0", + "eslint-config-prettier": "6.15.0", + "eslint-plugin-babel": "5.3.1", + "eslint-plugin-prettier": "3.3.0", + "eslint-plugin-react": "7.21.5", + "express": "4.17.1", + "glob": "7.1.7", + "html-webpack-plugin": "4.5.0", + "http-server": "14.0.0", + "json-beautify": "1.1.1", + "lodash.merge": "4.6.2", + "mkdirp": "1.0.4", + "nocache": "3.0.1", + "onchange": "7.1.0", + "path": "0.12.7", + "prettier": "2.2.1", + "react-dom": "16.14.0", + "regenerator-runtime": "0.13.7", + "rimraf": "3.0.2", + "style-loader": "2.0.0", + "webpack": "4.44.2", + "webpack-assets-manifest": "3.1.1", + "webpack-bundle-analyzer": "3.9.0", + "webpack-cli": "3.3.12" + }, + "bugs": { + "url": "https://github.com/bitholla/hollaex-plugins/issues" + }, + "homepage": "https://github.com/bitholla/hollaex-plugins#readme" +} diff --git a/plugins/remote-component.config.js b/plugins/remote-component.config.js new file mode 100644 index 0000000000..8b9f079fb7 --- /dev/null +++ b/plugins/remote-component.config.js @@ -0,0 +1,25 @@ +/** + * Dependencies for Remote Components + */ + +module.exports = { + resolve: { + axios: require('axios'), + classnames: require('classnames'), + mathjs: require('mathjs'), + numbro: require('numbro'), + 'prop-types': require('prop-types'), + react: require('react'), + 'react-device-detect': require('react-device-detect'), + 'react-redux': require('react-redux'), + 'react-svg': require('react-svg'), + redux: require('redux'), + 'redux-form': require('redux-form'), + validator: require('validator'), + '@ant-design/icons': require('@ant-design/icons'), + 'react-event-listener': require('react-event-listener'), + 'hollaex-web-lib': require('hollaex-web-lib'), + 'antd': require('antd'), + moment: require('moment'), + } +}; diff --git a/plugins/scripts/addBundles.js b/plugins/scripts/addBundles.js new file mode 100644 index 0000000000..cfbb6fb85f --- /dev/null +++ b/plugins/scripts/addBundles.js @@ -0,0 +1,28 @@ +const fs = require("fs"); +const path = require("path"); +const glob = require("glob"); +const mkdirp = require('mkdirp'); +const { PATTERNS, PATHS } = require("./patterns"); + +const bundles = glob.sync(PATTERNS.BUNDLES); + +bundles.forEach((pathname) => { + const bundle = path.basename(pathname, '.js'); + const [plugin, view] = bundle.split('__'); + const pluginPath = path.resolve(__dirname, '..', PATHS.ROOT, plugin); + const bundlesPath = path.resolve(__dirname, '..', PATHS.ROOT, plugin, PATHS.BUNDLES); + + if (view) { + const destinationPath = path.resolve(bundlesPath, `${bundle}.js`); + + if (!fs.existsSync(pluginPath)) { + mkdirp.sync(pluginPath); + } + + if (!fs.existsSync(bundlesPath)) { + mkdirp.sync(bundlesPath); + } + + fs.copyFileSync(pathname, destinationPath); + } +}) \ No newline at end of file diff --git a/plugins/scripts/addJsons.js b/plugins/scripts/addJsons.js new file mode 100644 index 0000000000..2e193bde87 --- /dev/null +++ b/plugins/scripts/addJsons.js @@ -0,0 +1,24 @@ +const fs = require("fs"); +const path = require("path"); +const glob = require("glob"); +const mkdirp = require('mkdirp'); +const { PATTERNS, FILES, PATHS } = require("./patterns"); + +const jsons = glob.sync(PATTERNS.JSONS); + +jsons.forEach((pathname) => { + const plugin = path.basename(pathname, '.json'); + const pluginPath = path.resolve(__dirname, '..', PATHS.ROOT, plugin); + const serverPath = path.resolve(__dirname, '..', PATHS.ROOT, plugin, PATHS.SERVER); + const destinationPath = path.resolve(__dirname, '..', PATHS.ROOT, plugin, PATHS.SERVER, FILES.WEB_VIEW); + + if (!fs.existsSync(pluginPath)) { + mkdirp.sync(pluginPath); + } + + if (!fs.existsSync(serverPath)) { + mkdirp.sync(serverPath); + } + + fs.copyFileSync(pathname, destinationPath); +}) \ No newline at end of file diff --git a/plugins/scripts/addPlugin.js b/plugins/scripts/addPlugin.js new file mode 100644 index 0000000000..2644d2bfa5 --- /dev/null +++ b/plugins/scripts/addPlugin.js @@ -0,0 +1,67 @@ +const glob = require("glob"); +const path = require("path"); +const copydir = require('copy-dir'); +const mkdirp = require('mkdirp'); +const { PATTERNS, TEMPLATES, PATHS } = require("./patterns"); + +const { env: { PLUGIN: plugin, TYPE } } = process; +const type = TYPE ? TYPE.toLowerCase() : TYPE; + +if (!plugin) { + console.log('You must pass plugin argument'); + console.log('npm run add-plugin --plugin=PLUGIN_NAME --type=PLUGIN_TYPE'); +} else if (!type) { + console.log('You must pass type argument'); + console.log('npm run add-plugin --plugin=PLUGIN_NAME --type=PLUGIN_TYPE'); +} else { + const plugins = glob.sync(PATTERNS.PLUGINS) + .reduce((acc, curr) => { + const pluginName = curr.split(path.sep)[2]; + return [...acc, pluginName]; + }, []) + + if (plugins.includes(plugin)) { + console.log('This plugin already exists, try another plugin name'); + } else { + switch (type) { + case TEMPLATES.RAW.type: + return ( + mkdirp(`${PATHS.ROOT}/${plugin}/views`) + .then(() => { + mkdirp(`${PATHS.ROOT}/${plugin}/${PATHS.SERVER}`) + .then(() => { + copydir.sync(TEMPLATES.RAW.template.VIEW, `${PATHS.ROOT}/${plugin}/views/view`); + copydir.sync(TEMPLATES.RAW.template.ASSETS, `${PATHS.ROOT}/${plugin}/assets`); + console.log('Plugin has been added successfully'); + }) + }) + ); + case TEMPLATES.PAGE.type: + case TEMPLATES.VERIFICATION_TAB.type: + case TEMPLATES.FIAT_WALLET.type: + case TEMPLATES.KYC.type: + case TEMPLATES.BANK.type: + case TEMPLATES.ONRAMP.type: + case TEMPLATES.APP.type: + return ( + mkdirp(`${PATHS.ROOT}/${plugin}`) + .then(() => { + mkdirp(`${PATHS.ROOT}/${plugin}/${PATHS.SERVER}`) + .then(() => { + const [, { template }] = Object.entries(TEMPLATES).find(([, { type: templateType }]) => type === templateType); + copydir.sync(template, `${PATHS.ROOT}/${plugin}`); + console.log('Plugin has been added successfully'); + }) + }) + ); + case TEMPLATES.SERVER.type: + return ( + mkdirp(`${PATHS.ROOT}/${plugin}/${PATHS.SERVER}`) + ); + default: + return ( + console.log(`type ${type} does not exist, try another type. See doc for supported plugin types.`) + ); + } + } +} \ No newline at end of file diff --git a/plugins/scripts/addView.js b/plugins/scripts/addView.js new file mode 100644 index 0000000000..2d16a7cee3 --- /dev/null +++ b/plugins/scripts/addView.js @@ -0,0 +1,36 @@ +const glob = require("glob"); +const path = require("path"); +const copydir = require('copy-dir'); +const { PATTERNS, PATHS } = require("./patterns") + +const { env: { PLUGIN: plugin, WEB_VIEW: view = 'view' } } = process; +const viewsPattern = `${PATHS.ROOT}/${plugin}/views/*`; + + +if (!plugin) { + console.log('You must pass plugin argument') + console.log('npm run add-view --plugin=PLUGIN_NAME'); +} else { + const plugins = glob.sync(PATTERNS.PLUGINS) + .reduce((acc, curr) => { + const pluginName = curr.split(path.sep)[2]; + return [...acc, pluginName]; + }, []) + + if (plugins.includes(plugin)) { + const views = glob.sync(viewsPattern) + .reduce((acc, curr) => { + const viewName = curr.split(path.sep)[4]; + return [...acc, viewName]; + }, []); + + if (views.includes(view)) { + console.log('This view already exists, try another view name'); + } else { + copydir.sync('src/templates/view', `${PATHS.ROOT}/${plugin}/views/${view}`); + console.log(`A view has been successfully added to ${plugin} plugin`); + } + } else { + console.log(`Plugin ${plugin} does not exist`); + } +} \ No newline at end of file diff --git a/plugins/scripts/generateConfig.js b/plugins/scripts/generateConfig.js new file mode 100644 index 0000000000..ad3184d453 --- /dev/null +++ b/plugins/scripts/generateConfig.js @@ -0,0 +1,76 @@ +const fs = require('fs'); +const path = require('path'); +const uglifyEs = require('uglify-es'); +const mkdirp = require('mkdirp'); +const { minify: htmlMinify } = require('html-minifier-terser'); +const { FILES, PATHS } = require('./patterns'); +const { getWebView } = require('./utils') + +const { env: { PLUGIN: plugin } } = process; + +if (!fs.existsSync('config')) { + mkdirp.sync('config') +} + +if (!plugin) { + console.error('No plugin name given'); + process.exit(1); +} + +const pluginPath = path.resolve(__dirname, '..', PATHS.ROOT, plugin, PATHS.SERVER); + +if (!fs.existsSync(pluginPath)) { + console.error(`Plugin ${plugin} does not exist`); + process.exit(1); +} + +const scriptPath = path.resolve(pluginPath, FILES.SCRIPT); +const adminViewPath = path.resolve(pluginPath, FILES.ADMIN_VIEW); + +console.log(`Generating plugin JSON object for plugin ${plugin}...\n`); + +const config = fs.readFileSync(path.resolve(pluginPath, FILES.CONFIG)); +let script = null; +let admin_view = null; + +if (fs.existsSync(scriptPath)) { + const rawScript = fs.readFileSync(scriptPath, 'utf-8'); + script = uglifyEs.minify(rawScript); + + if (script.error) { + console.error('Error occured while minifying script\n'); + console.error(script.error); + process.exit(1); + } + + script = script.code; +} + +if (fs.existsSync(adminViewPath)) { + const rawAdminView = fs.readFileSync(adminViewPath, 'utf-8'); + + try { + admin_view = htmlMinify(rawAdminView, { + minifyJS: true, + minifyCSS: true, + collapseWhitespace: true + }); + } catch (err) { + console.error('Error occured while minifying admin_view\n'); + console.error(err); + process.exit(1); + } +} + +const pluginJson = JSON.stringify({ + ...JSON.parse(config), + script, + admin_view, + web_view: getWebView(plugin) +}, null, '\t'); + +fs.writeFileSync('config/config.json', pluginJson); + +console.log(pluginJson); + +process.exit(0); \ No newline at end of file diff --git a/plugins/scripts/generateJson.js b/plugins/scripts/generateJson.js new file mode 100644 index 0000000000..2b7368a6e5 --- /dev/null +++ b/plugins/scripts/generateJson.js @@ -0,0 +1,25 @@ +const fs = require("fs"); +const path = require("path"); +const glob = require("glob"); +const mkdirp = require('mkdirp'); +const { PATTERNS, PATHS } = require("./patterns"); +const { saveFile, getWebView } = require("./utils"); + +const { env: { PLUGIN: plugin }} = process; +const pluginsPattern = plugin ? `${PATHS.ROOT}/${plugin}` : PATTERNS.PLUGINS; + +const plugins = glob.sync(pluginsPattern); + +if (!fs.existsSync('json')) { + mkdirp.sync('json') +} + +plugins.forEach((pluginPath) => { + const plugin = pluginPath.split(path.sep)[2] + + const content = { + web_view: getWebView(plugin) + } + + saveFile(`json/${plugin}.json`, content); +}); \ No newline at end of file diff --git a/plugins/scripts/generatePlugin.js b/plugins/scripts/generatePlugin.js new file mode 100644 index 0000000000..5c80621776 --- /dev/null +++ b/plugins/scripts/generatePlugin.js @@ -0,0 +1,80 @@ +const fs = require('fs'); +const path = require('path'); +const uglifyEs = require('uglify-es'); +const { minify: htmlMinify } = require('html-minifier-terser'); +const { FILES, PATHS } = require('./patterns'); + +const { env: { PLUGIN: plugin } } = process; + +if (!plugin) { + console.error('No plugin name given'); + process.exit(1); +} + +const pluginPath = path.resolve(__dirname, '..', PATHS.ROOT, plugin, PATHS.SERVER); + +if (!fs.existsSync(pluginPath)) { + console.error(`Plugin ${plugin} does not exist`); + process.exit(1); +} + +const scriptPath = path.resolve(pluginPath, FILES.SCRIPT); +const adminViewPath = path.resolve(pluginPath, FILES.ADMIN_VIEW); +const webViewPath = path.resolve(pluginPath, FILES.WEB_VIEW); + +console.log(`Generating plugin JSON object for plugin ${plugin}...\n`); + +const config = fs.readFileSync(path.resolve(pluginPath, FILES.CONFIG)); +let script = null; +let admin_view = null; +let web_view = null; + +if (fs.existsSync(scriptPath)) { + const rawScript = fs.readFileSync(scriptPath, 'utf-8'); + script = uglifyEs.minify(rawScript); + + if (script.error) { + console.error('Error occured while minifying script\n'); + console.error(script.error); + process.exit(1); + } + + script = script.code; +} + +if (fs.existsSync(adminViewPath)) { + const rawAdminView = fs.readFileSync(adminViewPath, 'utf-8'); + + try { + admin_view = htmlMinify(rawAdminView, { + minifyJS: true, + minifyCSS: true, + collapseWhitespace: true + }); + } catch (err) { + console.error('Error occured while minifying admin_view\n'); + console.error(err); + process.exit(1); + } +} + +if (fs.existsSync(webViewPath)) { + const web_view_json = fs.readFileSync(webViewPath); + const { web_view: view } = JSON.parse(web_view_json); + web_view = view +} + +const pluginJson = JSON.stringify({ + ...JSON.parse(config), + script, + admin_view, + web_view +}, null, '\t'); + +const finalJsonPath = path.resolve(pluginPath, `${plugin}.json`); + +fs.writeFileSync(finalJsonPath, pluginJson); + +console.log(pluginJson); + +process.exit(0); \ No newline at end of file diff --git a/plugins/scripts/patterns.js b/plugins/scripts/patterns.js new file mode 100644 index 0000000000..ae795fb798 --- /dev/null +++ b/plugins/scripts/patterns.js @@ -0,0 +1,74 @@ +const PLUGINS_PATH = 'https://bitholla.s3.ap-northeast-2.amazonaws.com/scripts/plugins'; + +const PATTERNS = { + BUNDLES: "dist/**.js", + JSONS: "json/**.json", + PLUGINS: "src/plugins/*", + VIEW: "views/**/index.js" +}; + +const FILES = { + SCRIPT: 'script.js', + ADMIN_VIEW: 'admin_view.html', + WEB_VIEW: 'web_view.json', + CONFIG: 'config.json', + STRINGS: "strings.json", + ICONS: "icons.json", + VIEW: "view.json", +}; + +const PATHS = { + ROOT: 'src/plugins', + SERVER: 'server', + BUNDLES: 'bundles', + ASSETS: 'assets', +}; + +const TEMPLATES = { + RAW: { + type: 'raw', + template: { + VIEW: "src/templates/view", + ASSETS: "src/templates/assets", + }, + }, + PAGE: { + type: 'page', + template: 'src/templates/new-page', + }, + VERIFICATION_TAB: { + type: 'verification-tab', + template: 'src/templates/verification-tab', + }, + FIAT_WALLET: { + type: 'fiat-wallet', + template: 'src/templates/fiat-wallet', + }, + KYC: { + type: 'kyc', + template: 'src/templates/kyc-verification', + }, + BANK: { + type: 'bank', + template: 'src/templates/bank-verification', + }, + ONRAMP: { + type: 'onramp', + template: 'src/templates/onramp', + }, + APP: { + type: 'app', + template: 'src/templates/app', + }, + SERVER: { + type: 'server', + } +}; + +module.exports = { + PLUGINS_PATH, + FILES, + TEMPLATES, + PATHS, + PATTERNS, +} \ No newline at end of file diff --git a/plugins/scripts/utils.js b/plugins/scripts/utils.js new file mode 100644 index 0000000000..4afbbdaebb --- /dev/null +++ b/plugins/scripts/utils.js @@ -0,0 +1,68 @@ +const fs = require("fs"); +const path = require("path"); +const beautify = require("json-beautify"); +const glob = require("glob"); +const merge = require("lodash.merge"); +const { PLUGINS_PATH, PATHS, FILES, PATTERNS } = require("./patterns"); + +const saveFile = (output, content) => { + fs.writeFileSync(output, beautify(content, null, 4, 100)); +} + +const readFile = (pathname) => { + try { + const contents = fs.readFileSync(pathname, "utf-8") + return JSON.parse(contents); + } catch(err) { + console.log(err); + return {}; + } +} + +const getBundlePath = (pathname) => { + const dir = pathname.split(path.sep); + const pluginName = dir[2]; + const bundleName = `${dir[2]}__${dir[4]}`; + + if(process.env.NODE_ENV === "development") { + return `http://localhost:8080/${bundleName}.js` + } + + const configFile = path.resolve(__dirname, '..', PATHS.ROOT, pluginName, PATHS.SERVER, FILES.CONFIG); + const { version = 0 } = fs.existsSync(configFile) ? readFile(configFile) : {}; + + return `${PLUGINS_PATH}/${pluginName}/v${version}/${bundleName}.js` +} + +const getWebView = (plugin) => { + const assetsPath = `${PATHS.ROOT}/${plugin}/${PATHS.ASSETS}`; + const viewsPattern = `${PATHS.ROOT}/${plugin}/${PATTERNS.VIEW}`; + + let assetsAdded = false; + const assets = { + strings: readFile(`${assetsPath}/${FILES.STRINGS}`), + icons: readFile(`${assetsPath}/${FILES.ICONS}`), + }; + + const webViews = glob.sync(viewsPattern, { noglobstar: true }) + .reduce((acc, curr) => { + const view = readFile(`${path.dirname(curr)}/${FILES.VIEW}`); + const generatedView = { + src: getBundlePath(curr), + ...(assetsAdded ? {} : { meta: { ...assets }}), + }; + + const webView = merge({}, generatedView, view); + + assetsAdded = true; + + return [...acc, webView] + }, []); + + return webViews.length !== 0 ? webViews : null; +} + +module.exports = { + saveFile, + getWebView, +} \ No newline at end of file diff --git a/plugins/server.js b/plugins/server.js new file mode 100644 index 0000000000..9266217980 --- /dev/null +++ b/plugins/server.js @@ -0,0 +1,11 @@ +const express = require('express'); +const nocache = require('nocache'); +const app = express(); +const PORT = 8080; + +app.use(nocache()); +app.use(express.static('dist')); +app.use(express.static('json')); +app.use(express.static('config')); + +app.listen(PORT, () => console.log(`Server listening on port: ${PORT}`)); \ No newline at end of file diff --git a/plugins/src/components/Dialog/DesktopDialog.js b/plugins/src/components/Dialog/DesktopDialog.js new file mode 100644 index 0000000000..1cdd7afd9b --- /dev/null +++ b/plugins/src/components/Dialog/DesktopDialog.js @@ -0,0 +1,87 @@ +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Modal from 'react-modal'; +import Ionicon from 'react-ionicons'; +import { ActionNotification, Button } from 'hollaex-web-lib'; + +class Dialog extends PureComponent { + static propTypes = { + isOpen: PropTypes.bool.isRequired, + label: PropTypes.string.isRequired, + closeButton: PropTypes.func, + onCloseDialog: PropTypes.func, + children: PropTypes.node.isRequired, + disableTheme: PropTypes.bool, + }; + + onRequestClose = (e) => { + if (this.props.onCloseDialog) { + this.props.onCloseDialog(e); + } + }; + + render() { + const { + isOpen, + children, + label, + closeButton, + shouldCloseOnOverlayClick, + showCloseText, + dialogId, + theme, + className, + disableTheme, + bodyOpenClassName, + strings: STRINGS, + } = this.props; + + return ( + + {showCloseText && !closeButton && ( + + } + onClick={this.onRequestClose} + className="close-button" + /> + )} + {children} + {closeButton && ( +
+
+ )} +
+ ); + } +} + +Modal.setAppElement('#root'); + +Dialog.defaultProps = { + disableTheme: false, + shouldCloseOnOverlayClick: true, + showCloseText: true, + theme: '', + className: '', + strings: {}, +}; + +export default Dialog; diff --git a/plugins/src/components/Dialog/MobileDialog.js b/plugins/src/components/Dialog/MobileDialog.js new file mode 100644 index 0000000000..8fa31921b4 --- /dev/null +++ b/plugins/src/components/Dialog/MobileDialog.js @@ -0,0 +1,73 @@ +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Modal from 'react-modal'; + +const RegularContent = ({ children }) => { + return ( +
+
{children}
+
+ ); +}; + +class Dialog extends PureComponent { + static propTypes = { + isOpen: PropTypes.bool.isRequired, + label: PropTypes.string.isRequired, + closeButton: PropTypes.func, + onCloseDialog: PropTypes.func, + children: PropTypes.node.isRequired, + }; + + onRequestClose = (e) => { + if (this.props.onCloseDialog) { + this.props.onCloseDialog(e); + } + }; + + render() { + const { + isOpen, + children, + label, + dialogId, + className, + useFullScreen = false, + compressed = false, + } = this.props; + + return ( + + + {children} + + + ); + } +} + +Modal.setAppElement('#root'); + +Dialog.defaultProps = { + shouldCloseOnOverlayClick: true, + showCloseText: true, + theme: '', + className: '', +}; + +export default Dialog; diff --git a/plugins/src/components/Dialog/index.js b/plugins/src/components/Dialog/index.js new file mode 100644 index 0000000000..ef0da3afcb --- /dev/null +++ b/plugins/src/components/Dialog/index.js @@ -0,0 +1,14 @@ +import React from 'react'; +import { isMobile } from 'react-device-detect'; +import MobileDialog from './MobileDialog'; +import DesktopDialog from './DesktopDialog'; + +const Dialog = (props) => { + if (isMobile) { + return ; + } else { + return ; + } +}; + +export default Dialog; diff --git a/plugins/src/components/Form/factoryFields.js b/plugins/src/components/Form/factoryFields.js new file mode 100644 index 0000000000..c419dc03d0 --- /dev/null +++ b/plugins/src/components/Form/factoryFields.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { Field } from 'redux-form'; +import { getFormFieldComponentByType } from 'hollaex-web-lib'; + +const renderFields = (fields = {}, callback) => { + return ( +
+ {Object.keys(fields).map((key, index) => { + const { type, validate = [], ishorizontalfield, ...rest } = fields[key]; + const commonProps = { + callback, + key, + name: key, + type, + validate, + ishorizontalfield, + ...rest, + }; + + const component = getFormFieldComponentByType(type); + return () + })} +
+ ); +}; + +export default renderFields; diff --git a/plugins/src/components/HeaderSection/index.js b/plugins/src/components/HeaderSection/index.js new file mode 100644 index 0000000000..966eff5d7d --- /dev/null +++ b/plugins/src/components/HeaderSection/index.js @@ -0,0 +1,45 @@ +import React from "react"; +import { Image, ActionNotification, Editable } from "hollaex-web-lib"; + +export const HeaderSection = ({ + title, + children, + openContactForm, + icon, + strings: STRINGS = {}, + icons: ICONS = {}, + stringId + }) => { + return ( +
+
+ {!!icon && ( +
+ +
+ )} +
+
+
+ {title} + {stringId && } +
+ {!!openContactForm && ( +
+ +
+ )} +
+ {children &&
{children}
} +
+
+
+ ); +}; diff --git a/plugins/src/components/KitContext/KitContextProvider.js b/plugins/src/components/KitContext/KitContextProvider.js new file mode 100644 index 0000000000..8594a4a570 --- /dev/null +++ b/plugins/src/components/KitContext/KitContextProvider.js @@ -0,0 +1,15 @@ +import React, { Component } from 'react'; +import { KitContext } from './index'; + +class KitContextProvider extends Component { + render() { + const { children, ...rest } = this.props; + return ( + + {children} + + ); + } +} + +export default KitContextProvider; diff --git a/plugins/src/components/KitContext/index.js b/plugins/src/components/KitContext/index.js new file mode 100644 index 0000000000..267c1c595a --- /dev/null +++ b/plugins/src/components/KitContext/index.js @@ -0,0 +1,4 @@ +import { createContext } from 'react'; +export { default as KitContextProvider } from './KitContextProvider'; +export { default as withKit } from './withKit'; +export const KitContext = createContext(); \ No newline at end of file diff --git a/plugins/src/components/KitContext/withKit.js b/plugins/src/components/KitContext/withKit.js new file mode 100644 index 0000000000..cf5b4d59ea --- /dev/null +++ b/plugins/src/components/KitContext/withKit.js @@ -0,0 +1,17 @@ +import React from 'react'; +import { KitContext } from './index'; + +const withKit = (mapContextToProps) => (Component) => { + return (props) => ( + + {(context) => ( + + )} + + ); +}; + +export default withKit; diff --git a/plugins/src/components/OtpForm/index.js b/plugins/src/components/OtpForm/index.js new file mode 100644 index 0000000000..d6e8d6afaa --- /dev/null +++ b/plugins/src/components/OtpForm/index.js @@ -0,0 +1,93 @@ +import React, { Component } from 'react'; +import { reduxForm } from 'redux-form'; +import { required, validateOtp } from 'utils'; +import renderFields from 'components/Form/factoryFields'; +import { Button, IconTitle } from 'hollaex-web-lib'; + +class Form extends Component { + state = { + formValues: {}, + }; + + componentWillMount() { + this.setFormValues(); + } + + UNSAFE_componentWillReceiveProps = (nextProps) => { + if ( + this.props.dirty !== nextProps.dirty || + this.props.submitFailed !== nextProps.submitFailed || + this.props.valid !== nextProps.valid + ) { + if (nextProps.dirty && nextProps.submitFailed && !nextProps.valid) { + this.setFormRef(this.otpFormRef); + } + } + }; + setFormValues = () => { + const { strings: STRINGS } = this.props; + const formValues = { + otp_code: { + type: 'number', + stringId: + 'OTP_FORM.OTP_LABEL,OTP_FORM.OTP_PLACEHOLDER,OTP_FORM.ERROR_INVALID', + label: STRINGS['OTP_FORM.OTP_LABEL'], + placeholder: STRINGS['OTP_FORM.OTP_PLACEHOLDER'], + validate: [required, validateOtp(STRINGS['OTP_FORM.ERROR_INVALID'])], + fullWidth: true, + }, + }; + + this.setState({ formValues }); + }; + + setFormRef = (el) => { + if (el) { + this.otpFormRef = el; + el.getElementsByTagName('input')[0].focus(); + } + }; + + render() { + const { + handleSubmit, + submitting, + pristine, + error, + valid, + icons: ICONS = {}, + strings: STRINGS = {}, + } = this.props; + const { formValues } = this.state; + + return ( +
+ +
+ + {STRINGS['OTP_FORM.OTP_FORM_TITLE']} + +
+
+
+ {renderFields(formValues)} + {error &&
{error}
} +
+
+ ); + } +} + +export default reduxForm({ + form: 'FiatOtpForm', +})(Form); diff --git a/plugins/src/components/Tab/index.js b/plugins/src/components/Tab/index.js new file mode 100644 index 0000000000..400dd32fba --- /dev/null +++ b/plugins/src/components/Tab/index.js @@ -0,0 +1,30 @@ +import React from 'react'; +import { Image } from 'hollaex-web-lib'; +import classnames from 'classnames'; + +export const Tab = ({ + icon, + title, + className, + }) => { + return ( +
+
+ +
+ {title && ( +
+ {title} +
+ )} +
+ ); +}; \ No newline at end of file diff --git a/plugins/src/components/Title.js b/plugins/src/components/Title.js new file mode 100644 index 0000000000..31fc6170fd --- /dev/null +++ b/plugins/src/components/Title.js @@ -0,0 +1,11 @@ +import React from "react"; +import { withKit } from 'components/KitContext'; + +const Title = ({ user: { username } = {}, strings: STRINGS, generateId }) => ( +
+ {STRINGS.formatString(STRINGS[generateId('hello')], username)} +
+); + +const mapContextToProps = ({ user, generateId, strings }) => ({ user, generateId, strings }); +export default withKit(mapContextToProps)(Title); diff --git a/plugins/src/constants/index.js b/plugins/src/constants/index.js new file mode 100644 index 0000000000..595768ca02 --- /dev/null +++ b/plugins/src/constants/index.js @@ -0,0 +1 @@ +export const verifiedBankStatus = 3; \ No newline at end of file diff --git a/plugins/src/index.html b/plugins/src/index.html new file mode 100644 index 0000000000..132678c44d --- /dev/null +++ b/plugins/src/index.html @@ -0,0 +1,9 @@ + + + + + + +
+ + diff --git a/plugins/src/lib/__tests__/prop.test.js b/plugins/src/lib/__tests__/prop.test.js new file mode 100644 index 0000000000..b9fcbb947a --- /dev/null +++ b/plugins/src/lib/__tests__/prop.test.js @@ -0,0 +1,39 @@ +const { prop } = require("../prop"); + +describe("lib/prop", () => { + test("prop on undefined returns undefined", () => { + const expected = undefined; + const actual = prop(["a"], undefined); + expect(actual).toBe(expected); + }); + + test("prop on null returns undefined", () => { + const expected = undefined; + const actual = prop(["a"], null); + expect(actual).toBe(expected); + }); + + test("prop[] returns object", () => { + const expected = {}; + const actual = prop([], expected); + expect(actual).toBe(expected); + }); + + test("prop[a] returns object[a]", () => { + const expected = "SUCCESS"; + const actual = prop(["a"], { a: expected }); + expect(actual).toBe(expected); + }); + + test("prop missing prop returns undefined", () => { + const expected = undefined; + const actual = prop(["a", "b"], { a: 123 }); + expect(actual).toBe(expected); + }); + + test("prop nested returns value", () => { + const expected = "SUCCESS"; + const actual = prop(["a", "b"], { a: { b: expected } }); + expect(actual).toBe(expected); + }); +}); diff --git a/plugins/src/lib/prop.js b/plugins/src/lib/prop.js new file mode 100644 index 0000000000..6ec0da268b --- /dev/null +++ b/plugins/src/lib/prop.js @@ -0,0 +1,10 @@ +/** + * Safely gets nested properties from an object + * @param {Array} key List of properties + * @param {object} object Object to query + * @returns {*} value + */ +export const prop = ([key, ...rest], object) => + key == null ? object + : object == null ? undefined + : prop(rest, object[key]); // prettier-ignore diff --git a/plugins/src/plugins/hello-exchange/assets/icons.json b/plugins/src/plugins/hello-exchange/assets/icons.json new file mode 100644 index 0000000000..3815a2bd63 --- /dev/null +++ b/plugins/src/plugins/hello-exchange/assets/icons.json @@ -0,0 +1,3 @@ +{ + "dark": {} +} \ No newline at end of file diff --git a/plugins/src/plugins/hello-exchange/assets/strings.json b/plugins/src/plugins/hello-exchange/assets/strings.json new file mode 100644 index 0000000000..3aec9ffdd3 --- /dev/null +++ b/plugins/src/plugins/hello-exchange/assets/strings.json @@ -0,0 +1,6 @@ +{ + "en": { + "title": "Hello exchange", + "hello": "Hello {0}" + } +} \ No newline at end of file diff --git a/plugins/src/plugins/hello-exchange/server/config.json b/plugins/src/plugins/hello-exchange/server/config.json new file mode 100644 index 0000000000..6345223a3d --- /dev/null +++ b/plugins/src/plugins/hello-exchange/server/config.json @@ -0,0 +1,35 @@ +{ + "name": "hello-exchange", + "version": 1, + "type": null, + "author": "bitHolla", + "bio": "Say hello from an exchange", + "description": "Demo plugin for proof of concept", + "documentation": null, + "logo": null, + "icon": null, + "url": null, + "public_meta": { + "public_message": { + "type": "string", + "required": false, + "description": "Not a secret", + "value": "Hello Exchange!" + } + }, + "meta": { + "private_message": { + "type": "string", + "required": false, + "description": "A secret", + "value": "hello exchange..." + } + }, + "prescript": { + "install": ["hello-world-npm"], + "run": null + }, + "postscript": { + "run": null + } +} \ No newline at end of file diff --git a/plugins/src/plugins/hello-exchange/server/hello-exchange.json b/plugins/src/plugins/hello-exchange/server/hello-exchange.json new file mode 100644 index 0000000000..97701b3788 --- /dev/null +++ b/plugins/src/plugins/hello-exchange/server/hello-exchange.json @@ -0,0 +1,40 @@ +{ + "name": "hello-exchange", + "version": 1, + "type": null, + "author": "bitHolla", + "bio": "Say hello from an exchange", + "description": "Demo plugin for proof of concept", + "documentation": null, + "logo": null, + "icon": null, + "url": null, + "public_meta": { + "public_message": { + "type": "string", + "required": false, + "description": "Not a secret", + "value": "Hello Exchange!" + } + }, + "meta": { + "private_message": { + "type": "string", + "required": false, + "description": "A secret", + "value": "hello exchange..." + } + }, + "prescript": { + "install": [ + "hello-world-npm" + ], + "run": null + }, + "postscript": { + "run": null + }, + "script": "\"use strict\";const{publicMeta:publicMeta,meta:meta}=this.configValues,{app:app,loggerPlugin:loggerPlugin,toolsLib:toolsLib}=this.pluginLibraries,helloWorld=require(\"hello-world-npm\"),moment=require(\"moment\"),init=async()=>{if(loggerPlugin.info(\"HELLO-EXCHANGE PLUGIN initializing...\"),!meta.private.value)throw new Error(\"Configuration value private required\")};init().then(()=>{app.get(\"/plugins/hello-exchange/info\",(e,i)=>(loggerPlugin.verbose(e.uuid,\"GET /plugins/hello-exchange/info\"),i.json({public_message:publicMeta.public.value,private_message:meta.private.value,library_message:helloWorld(),moment_timestamp:moment().toISOString(),exchange_info:toolsLib.getKitConfig().info})))}).catch(e=>{loggerPlugin.error(\"HELLO-EXCHANGE PLUGIN error during initialization\",e.message)});", + "admin_view": null, + "web_view": null +} \ No newline at end of file diff --git a/plugins/src/plugins/hello-exchange/server/script.js b/plugins/src/plugins/hello-exchange/server/script.js new file mode 100644 index 0000000000..29de80528b --- /dev/null +++ b/plugins/src/plugins/hello-exchange/server/script.js @@ -0,0 +1,44 @@ +'use strict'; + +const { publicMeta, meta } = this.configValues; +const { + app, + loggerPlugin, + toolsLib +} = this.pluginLibraries; +const helloWorld = require('hello-world-npm'); +const moment = require('moment'); + +const init = async () => { + loggerPlugin.info( + 'HELLO-EXCHANGE PLUGIN initializing...' + ); + + if (!meta.private_message.value) { + throw new Error('Configuration value private required'); + } +}; + +init() + .then(() => { + app.get('/plugins/hello-exchange/info', (req, res) => { + loggerPlugin.verbose( + req.uuid, + 'GET /plugins/hello-exchange/info' + ); + + return res.json({ + public_message: publicMeta.public_message.value, + private_message: meta.private_message.value, + library_message: helloWorld(), + moment_timestamp: moment().toISOString(), + exchange_info: toolsLib.getKitConfig().info + }); + }); + }) + .catch((err) => { + loggerPlugin.error( + 'HELLO-EXCHANGE PLUGIN error during initialization', + err.message + ); + }); diff --git a/plugins/src/plugins/hello-exchange/views/view/App.js b/plugins/src/plugins/hello-exchange/views/view/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/plugins/hello-exchange/views/view/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + + +
+ + + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/plugins/hello-exchange/views/view/Form.js b/plugins/src/plugins/hello-exchange/views/view/Form.js new file mode 100644 index 0000000000..73bd0b7c97 --- /dev/null +++ b/plugins/src/plugins/hello-exchange/views/view/Form.js @@ -0,0 +1,62 @@ +import React, { useEffect, useState } from 'react'; +import { IconTitle, PanelInformationRow } from 'hollaex-web-lib'; +import { withKit } from 'components/KitContext'; +import Title from 'components/Title'; +import axios from 'axios'; + +const Form = ({ + strings: STRINGS, + icons: ICONS, + generateId, + plugin_url: PLUGIN_URL +}) => { + + const [info, setInfo] = useState(); + + useEffect(() => { + axios.get(`${PLUGIN_URL}/plugins/hello-exchange/info`).then(({ data: { exchange_info = {} }}) => { + setInfo(exchange_info); + }) + }, []) + + return ( +
+ + +
+
+ + <div className="py-4"> + {info ? Object.entries(info).map(([key, value]) => ( + <PanelInformationRow + key={key} + label={key} + information={value} + className="title-font" + disable + /> + )) : ( + <div className="pt-4">Loading ...</div> + )} + </div> + </div> + </div> + </form> + </div> + ) +} + +const mapContextToProps = ({ strings, activeLanguage, icons, generateId, plugin_url }) => ({ + strings, + activeLanguage, + icons, + generateId, + plugin_url +}); + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/plugins/hello-exchange/views/view/index.js b/plugins/src/plugins/hello-exchange/views/view/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/plugins/hello-exchange/views/view/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/plugins/hello-exchange/views/view/view.json b/plugins/src/plugins/hello-exchange/views/view/view.json new file mode 100644 index 0000000000..b4b2b347de --- /dev/null +++ b/plugins/src/plugins/hello-exchange/views/view/view.json @@ -0,0 +1,18 @@ +{ + "meta": { + "is_page": true, + "path": "/hello-exchange", + "hide_from_appbar": true, + "hide_from_sidebar": false, + "hide_from_menulist": false, + "hide_from_bottom_nav": true, + "string": { + "id": "title", + "is_global": false + }, + "icon": { + "id": "SIDEBAR_HELP", + "is_global": true + } + } +} \ No newline at end of file diff --git a/plugins/src/store/index.js b/plugins/src/store/index.js new file mode 100644 index 0000000000..3dbd7fd70d --- /dev/null +++ b/plugins/src/store/index.js @@ -0,0 +1,11 @@ +import { createStore, combineReducers } from "redux"; +import { reducer as formReducer } from "redux-form"; + +const rootReducer = combineReducers({ + // ...your other reducers here + // you have to pass formReducer under 'form' key, + // for custom keys look up the docs for 'getFormState' + form: formReducer +}); + +export default createStore(rootReducer); diff --git a/plugins/src/templates/app/assets/icons.json b/plugins/src/templates/app/assets/icons.json new file mode 100644 index 0000000000..3815a2bd63 --- /dev/null +++ b/plugins/src/templates/app/assets/icons.json @@ -0,0 +1,3 @@ +{ + "dark": {} +} \ No newline at end of file diff --git a/plugins/src/templates/app/assets/strings.json b/plugins/src/templates/app/assets/strings.json new file mode 100644 index 0000000000..a112fb80ad --- /dev/null +++ b/plugins/src/templates/app/assets/strings.json @@ -0,0 +1,6 @@ +{ + "en": { + "title": "App", + "content": "{0} content" + } +} \ No newline at end of file diff --git a/plugins/src/templates/app/views/admin/App.js b/plugins/src/templates/app/views/admin/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/app/views/admin/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/app/views/admin/Form.js b/plugins/src/templates/app/views/admin/Form.js new file mode 100644 index 0000000000..f3e639a46c --- /dev/null +++ b/plugins/src/templates/app/views/admin/Form.js @@ -0,0 +1,34 @@ +import React, { Fragment } from 'react'; +import { Breadcrumb } from 'antd'; +import { withKit } from 'components/KitContext'; + +const { Item } = Breadcrumb; + +const Form = ({ onBack: goToApps }) => { + + const renderBreadcrumb = () => { + return ( + <Breadcrumb> + <Item> + <span onClick={goToApps}>Apps</span> + </Item> + <Item>app name</Item> + </Breadcrumb> + ); + }; + + return ( + <Fragment> + {renderBreadcrumb()} + <div className="my-4 py-4"> + Admin Content + </div> + </Fragment> + ) +} + +const mapContextToProps = ({ onBack }) => ({ + onBack, +}); + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/app/views/admin/index.js b/plugins/src/templates/app/views/admin/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/app/views/admin/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/app/views/admin/view.json b/plugins/src/templates/app/views/admin/view.json new file mode 100644 index 0000000000..2f888a02b3 --- /dev/null +++ b/plugins/src/templates/app/views/admin/view.json @@ -0,0 +1,6 @@ +{ + "meta": { + "is_app": "true", + "type": "admin" + } +} \ No newline at end of file diff --git a/plugins/src/templates/app/views/kit/App.js b/plugins/src/templates/app/views/kit/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/app/views/kit/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/app/views/kit/Form.js b/plugins/src/templates/app/views/kit/Form.js new file mode 100644 index 0000000000..eddefb22d3 --- /dev/null +++ b/plugins/src/templates/app/views/kit/Form.js @@ -0,0 +1,28 @@ +import React from 'react'; +import { withKit } from 'components/KitContext'; + +const Form = ({ + strings: STRINGS, + generateId +}) => { + + return ( + <div className="presentation_container apply_rtl verification_container"> + <form className="d-flex flex-column w-100 verification_content-form-wrapper"> + <div className="verification-form-panel mt-3 mb-5"> + <div className="my-4 py-4"> + {STRINGS.formatString(STRINGS[generateId('content')], STRINGS[generateId('title')])} + </div> + </div> + </form> + </div> + ) +} + +const mapContextToProps = ({ strings, activeLanguage, generateId }) => ({ + strings, + activeLanguage, + generateId, +}); + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/app/views/kit/index.js b/plugins/src/templates/app/views/kit/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/app/views/kit/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/app/views/kit/view.json b/plugins/src/templates/app/views/kit/view.json new file mode 100644 index 0000000000..41eb14b374 --- /dev/null +++ b/plugins/src/templates/app/views/kit/view.json @@ -0,0 +1,6 @@ +{ + "meta": { + "is_app": "true", + "type": "kit" + } +} \ No newline at end of file diff --git a/plugins/src/templates/assets/icons.json b/plugins/src/templates/assets/icons.json new file mode 100644 index 0000000000..3815a2bd63 --- /dev/null +++ b/plugins/src/templates/assets/icons.json @@ -0,0 +1,3 @@ +{ + "dark": {} +} \ No newline at end of file diff --git a/plugins/src/templates/assets/strings.json b/plugins/src/templates/assets/strings.json new file mode 100644 index 0000000000..6a691ed1b8 --- /dev/null +++ b/plugins/src/templates/assets/strings.json @@ -0,0 +1,5 @@ +{ + "en": { + "hello": "Hello {0}" + } +} \ No newline at end of file diff --git a/plugins/src/templates/bank-verification/assets/icons.json b/plugins/src/templates/bank-verification/assets/icons.json new file mode 100644 index 0000000000..3815a2bd63 --- /dev/null +++ b/plugins/src/templates/bank-verification/assets/icons.json @@ -0,0 +1,3 @@ +{ + "dark": {} +} \ No newline at end of file diff --git a/plugins/src/templates/bank-verification/assets/strings.json b/plugins/src/templates/bank-verification/assets/strings.json new file mode 100644 index 0000000000..c85476dd7f --- /dev/null +++ b/plugins/src/templates/bank-verification/assets/strings.json @@ -0,0 +1,8 @@ +{ + "en": { + "title": "Bank verification", + "go_to_tab": "Go to {0}", + "content": "{0} content", + "home-content": "{0} home content" + } +} \ No newline at end of file diff --git a/plugins/src/templates/bank-verification/views/home/App.js b/plugins/src/templates/bank-verification/views/home/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/bank-verification/views/home/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/bank-verification/views/home/Form.js b/plugins/src/templates/bank-verification/views/home/Form.js new file mode 100644 index 0000000000..f201372eee --- /dev/null +++ b/plugins/src/templates/bank-verification/views/home/Form.js @@ -0,0 +1,32 @@ +import React from 'react'; +import { Button, Editable as EditWrapper } from 'hollaex-web-lib'; +import { withKit } from 'components/KitContext'; + +export const PLUGIN_NAME = 'bank'; + +const Form = ({ setActivePageContent, strings: STRINGS, generateId }) => { + return ( + <div> + <div className="secondary-text d-flex content-center m-4"> + {STRINGS.formatString(STRINGS[generateId('home-content')], STRINGS[generateId('title')])} + </div> + <div className="my-2 btn-wrapper"> + <div className="holla-verification-button pt-4"> + <EditWrapper stringId={generateId('go_to_tab')} /> + <Button + label={STRINGS.formatString(STRINGS[generateId('go_to_tab')], STRINGS[generateId('title')])} + onClick={() => setActivePageContent(PLUGIN_NAME)} + /> + </div> + </div> + </div> + ) +} + +const mapContextToProps = ({ setActivePageContent, strings, generateId }) => ({ + setActivePageContent, + strings, + generateId +}); + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/bank-verification/views/home/index.js b/plugins/src/templates/bank-verification/views/home/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/bank-verification/views/home/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/bank-verification/views/home/view.json b/plugins/src/templates/bank-verification/views/home/view.json new file mode 100644 index 0000000000..9f9d14cfc1 --- /dev/null +++ b/plugins/src/templates/bank-verification/views/home/view.json @@ -0,0 +1,4 @@ +{ + "target": "REMOTE_COMPONENT__BANK_VERIFICATION_HOME", + "meta": {} +} \ No newline at end of file diff --git a/plugins/src/templates/bank-verification/views/verification/App.js b/plugins/src/templates/bank-verification/views/verification/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/bank-verification/views/verification/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/bank-verification/views/verification/Form.js b/plugins/src/templates/bank-verification/views/verification/Form.js new file mode 100644 index 0000000000..1ccc583c71 --- /dev/null +++ b/plugins/src/templates/bank-verification/views/verification/Form.js @@ -0,0 +1,54 @@ +import React from 'react'; +import { Button, IconTitle, Editable as EditWrapper } from 'hollaex-web-lib'; +import { withKit } from 'components/KitContext'; +import { PLUGIN_NAME } from '../home/Form'; + +const Form = ({ + strings: STRINGS, + handleBack, + generateId, + setActivePageContent, +}) => { + + const onGoBack = () => { + setActivePageContent('email'); + handleBack(PLUGIN_NAME); + }; + + return ( + <div className="presentation_container apply_rtl verification_container"> + <IconTitle + stringId={generateId('title')} + text={STRINGS[generateId('title')]} + textType="title" + /> + <form className="d-flex flex-column w-100 verification_content-form-wrapper"> + <div className="verification-form-panel mt-3 mb-5"> + <div className="my-4 py-4"> + {STRINGS.formatString(STRINGS[generateId('content')], STRINGS[generateId('title')])} + </div> + </div> + <div className="d-flex justify-content-center align-items-center mt-2"> + <div className="f-1 d-flex justify-content-end verification-buttons-wrapper"> + <EditWrapper stringId="USER_VERIFICATION.GO_BACK" /> + <Button + label={STRINGS['USER_VERIFICATION.GO_BACK']} + onClick={onGoBack} + /> + </div> + </div> + </form> + </div> + ) +} + +const mapContextToProps = ({ strings, handleBack, activeLanguage, icons, generateId, setActivePageContent }) => ({ + strings, + handleBack, + activeLanguage, + icons, + generateId, + setActivePageContent, +}); + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/bank-verification/views/verification/index.js b/plugins/src/templates/bank-verification/views/verification/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/bank-verification/views/verification/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/bank-verification/views/verification/view.json b/plugins/src/templates/bank-verification/views/verification/view.json new file mode 100644 index 0000000000..a7faa5b752 --- /dev/null +++ b/plugins/src/templates/bank-verification/views/verification/view.json @@ -0,0 +1,4 @@ +{ + "target": "REMOTE_COMPONENT__BANK_VERIFICATION", + "meta": {} +} \ No newline at end of file diff --git a/plugins/src/templates/fiat-wallet/assets/icons.json b/plugins/src/templates/fiat-wallet/assets/icons.json new file mode 100644 index 0000000000..3815a2bd63 --- /dev/null +++ b/plugins/src/templates/fiat-wallet/assets/icons.json @@ -0,0 +1,3 @@ +{ + "dark": {} +} \ No newline at end of file diff --git a/plugins/src/templates/fiat-wallet/assets/strings.json b/plugins/src/templates/fiat-wallet/assets/strings.json new file mode 100644 index 0000000000..6a691ed1b8 --- /dev/null +++ b/plugins/src/templates/fiat-wallet/assets/strings.json @@ -0,0 +1,5 @@ +{ + "en": { + "hello": "Hello {0}" + } +} \ No newline at end of file diff --git a/plugins/src/templates/fiat-wallet/views/deposit/App.js b/plugins/src/templates/fiat-wallet/views/deposit/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/fiat-wallet/views/deposit/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/fiat-wallet/views/deposit/Form.js b/plugins/src/templates/fiat-wallet/views/deposit/Form.js new file mode 100644 index 0000000000..ec24b3d832 --- /dev/null +++ b/plugins/src/templates/fiat-wallet/views/deposit/Form.js @@ -0,0 +1,26 @@ +import React from 'react'; +import { Image } from 'hollaex-web-lib'; +import { withKit } from 'components/KitContext'; + + +const Form = ({ icons: ICONS, currency, titleSection }) => { + return ( + <div className="withdraw-form-wrapper"> + <div className="withdraw-form"> + <Image + icon={ICONS[`${currency.toUpperCase()}_ICON`]} + wrapperClassName="form_currency-ball" + /> + {titleSection} + </div> + </div> + ) +} + +const mapContextToProps = ({ icons, currency, titleSection }) => ({ + icons, + currency, + titleSection, +}) + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/fiat-wallet/views/deposit/index.js b/plugins/src/templates/fiat-wallet/views/deposit/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/fiat-wallet/views/deposit/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/fiat-wallet/views/deposit/view.json b/plugins/src/templates/fiat-wallet/views/deposit/view.json new file mode 100644 index 0000000000..063cfb71c0 --- /dev/null +++ b/plugins/src/templates/fiat-wallet/views/deposit/view.json @@ -0,0 +1,7 @@ +{ + "meta": { + "is_wallet": true, + "type": "deposit", + "currency": "USD" + } +} \ No newline at end of file diff --git a/plugins/src/templates/fiat-wallet/views/withdraw/App.js b/plugins/src/templates/fiat-wallet/views/withdraw/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/fiat-wallet/views/withdraw/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/fiat-wallet/views/withdraw/Form.js b/plugins/src/templates/fiat-wallet/views/withdraw/Form.js new file mode 100644 index 0000000000..ec24b3d832 --- /dev/null +++ b/plugins/src/templates/fiat-wallet/views/withdraw/Form.js @@ -0,0 +1,26 @@ +import React from 'react'; +import { Image } from 'hollaex-web-lib'; +import { withKit } from 'components/KitContext'; + + +const Form = ({ icons: ICONS, currency, titleSection }) => { + return ( + <div className="withdraw-form-wrapper"> + <div className="withdraw-form"> + <Image + icon={ICONS[`${currency.toUpperCase()}_ICON`]} + wrapperClassName="form_currency-ball" + /> + {titleSection} + </div> + </div> + ) +} + +const mapContextToProps = ({ icons, currency, titleSection }) => ({ + icons, + currency, + titleSection, +}) + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/fiat-wallet/views/withdraw/index.js b/plugins/src/templates/fiat-wallet/views/withdraw/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/fiat-wallet/views/withdraw/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/fiat-wallet/views/withdraw/view.json b/plugins/src/templates/fiat-wallet/views/withdraw/view.json new file mode 100644 index 0000000000..79e02c426a --- /dev/null +++ b/plugins/src/templates/fiat-wallet/views/withdraw/view.json @@ -0,0 +1,7 @@ +{ + "meta": { + "is_wallet": true, + "type": "withdraw", + "currency": "USD" + } +} \ No newline at end of file diff --git a/plugins/src/templates/kyc-verification/assets/icons.json b/plugins/src/templates/kyc-verification/assets/icons.json new file mode 100644 index 0000000000..3815a2bd63 --- /dev/null +++ b/plugins/src/templates/kyc-verification/assets/icons.json @@ -0,0 +1,3 @@ +{ + "dark": {} +} \ No newline at end of file diff --git a/plugins/src/templates/kyc-verification/assets/strings.json b/plugins/src/templates/kyc-verification/assets/strings.json new file mode 100644 index 0000000000..a3cd5e0beb --- /dev/null +++ b/plugins/src/templates/kyc-verification/assets/strings.json @@ -0,0 +1,8 @@ +{ + "en": { + "title": "KYC", + "go_to_tab": "Go to {0}", + "content": "{0} content", + "home-content": "{0} home content" + } +} \ No newline at end of file diff --git a/plugins/src/templates/kyc-verification/views/home/App.js b/plugins/src/templates/kyc-verification/views/home/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/kyc-verification/views/home/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/kyc-verification/views/home/Form.js b/plugins/src/templates/kyc-verification/views/home/Form.js new file mode 100644 index 0000000000..0b122adf6c --- /dev/null +++ b/plugins/src/templates/kyc-verification/views/home/Form.js @@ -0,0 +1,32 @@ +import React from 'react'; +import { Button, Editable as EditWrapper } from 'hollaex-web-lib'; +import { withKit } from 'components/KitContext'; + +export const PLUGIN_NAME = 'kyc'; + +const Form = ({ setActivePageContent, strings: STRINGS, generateId }) => { + return ( + <div> + <div className="secondary-text d-flex content-center m-4"> + {STRINGS.formatString(STRINGS[generateId('home-content')], STRINGS[generateId('title')])} + </div> + <div className="my-2 btn-wrapper"> + <div className="holla-verification-button pt-4"> + <EditWrapper stringId={generateId('go_to_tab')} /> + <Button + label={STRINGS.formatString(STRINGS[generateId('go_to_tab')], STRINGS[generateId('title')])} + onClick={() => setActivePageContent(PLUGIN_NAME)} + /> + </div> + </div> + </div> + ) +} + +const mapContextToProps = ({ setActivePageContent, strings, generateId }) => ({ + setActivePageContent, + strings, + generateId +}); + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/kyc-verification/views/home/index.js b/plugins/src/templates/kyc-verification/views/home/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/kyc-verification/views/home/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/kyc-verification/views/home/view.json b/plugins/src/templates/kyc-verification/views/home/view.json new file mode 100644 index 0000000000..94d8ab5c9f --- /dev/null +++ b/plugins/src/templates/kyc-verification/views/home/view.json @@ -0,0 +1,4 @@ +{ + "target": "REMOTE_COMPONENT__KYC_VERIFICATION_HOME", + "meta": {} +} \ No newline at end of file diff --git a/plugins/src/templates/kyc-verification/views/verification/App.js b/plugins/src/templates/kyc-verification/views/verification/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/kyc-verification/views/verification/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/kyc-verification/views/verification/Form.js b/plugins/src/templates/kyc-verification/views/verification/Form.js new file mode 100644 index 0000000000..8d71a2fab5 --- /dev/null +++ b/plugins/src/templates/kyc-verification/views/verification/Form.js @@ -0,0 +1,56 @@ +import React from 'react'; +import { Button, IconTitle, Editable as EditWrapper } from 'hollaex-web-lib'; +import { withKit } from 'components/KitContext'; +import { PLUGIN_NAME } from '../home/Form'; + +const Form = ({ + strings: STRINGS, + handleBack, + icons: ICONS, + generateId, + setActivePageContent, +}) => { + + const onGoBack = () => { + setActivePageContent('email'); + handleBack(PLUGIN_NAME); + }; + + return ( + <div className="presentation_container apply_rtl verification_container"> + <IconTitle + stringId={generateId('title')} + text={STRINGS[generateId('title')]} + textType="title" + iconPath={ICONS['VERIFICATION_ID_NEW']} + /> + <form className="d-flex flex-column w-100 verification_content-form-wrapper"> + <div className="verification-form-panel mt-3 mb-5"> + <div className="my-4 py-4"> + {STRINGS.formatString(STRINGS[generateId('content')], STRINGS[generateId('title')])} + </div> + </div> + <div className="d-flex justify-content-center align-items-center mt-2"> + <div className="f-1 d-flex justify-content-end verification-buttons-wrapper"> + <EditWrapper stringId="USER_VERIFICATION.GO_BACK" /> + <Button + label={STRINGS['USER_VERIFICATION.GO_BACK']} + onClick={onGoBack} + /> + </div> + </div> + </form> + </div> + ) +} + +const mapContextToProps = ({ strings, handleBack, activeLanguage, icons, generateId, setActivePageContent }) => ({ + strings, + handleBack, + activeLanguage, + icons, + generateId, + setActivePageContent, +}); + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/kyc-verification/views/verification/index.js b/plugins/src/templates/kyc-verification/views/verification/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/kyc-verification/views/verification/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/kyc-verification/views/verification/view.json b/plugins/src/templates/kyc-verification/views/verification/view.json new file mode 100644 index 0000000000..de8e6ec7eb --- /dev/null +++ b/plugins/src/templates/kyc-verification/views/verification/view.json @@ -0,0 +1,4 @@ +{ + "target": "REMOTE_COMPONENT__KYC_VERIFICATION", + "meta": {} +} \ No newline at end of file diff --git a/plugins/src/templates/new-page/assets/icons.json b/plugins/src/templates/new-page/assets/icons.json new file mode 100644 index 0000000000..3815a2bd63 --- /dev/null +++ b/plugins/src/templates/new-page/assets/icons.json @@ -0,0 +1,3 @@ +{ + "dark": {} +} \ No newline at end of file diff --git a/plugins/src/templates/new-page/assets/strings.json b/plugins/src/templates/new-page/assets/strings.json new file mode 100644 index 0000000000..ab9c4de4f6 --- /dev/null +++ b/plugins/src/templates/new-page/assets/strings.json @@ -0,0 +1,6 @@ +{ + "en": { + "title": "New Page", + "content": "{0} content" + } +} \ No newline at end of file diff --git a/plugins/src/templates/new-page/views/view/App.js b/plugins/src/templates/new-page/views/view/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/new-page/views/view/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/new-page/views/view/Form.js b/plugins/src/templates/new-page/views/view/Form.js new file mode 100644 index 0000000000..ab0498fcb5 --- /dev/null +++ b/plugins/src/templates/new-page/views/view/Form.js @@ -0,0 +1,37 @@ +import React from 'react'; +import { IconTitle } from 'hollaex-web-lib'; +import { withKit } from 'components/KitContext'; + +const Form = ({ + strings: STRINGS, + icons: ICONS, + generateId +}) => { + + return ( + <div className="presentation_container apply_rtl verification_container"> + <IconTitle + stringId={generateId('title')} + text={STRINGS[generateId('title')]} + textType="title" + iconPath={ICONS['SIDEBAR_HELP']} + /> + <form className="d-flex flex-column w-100 verification_content-form-wrapper"> + <div className="verification-form-panel mt-3 mb-5"> + <div className="my-4 py-4"> + {STRINGS.formatString(STRINGS[generateId('content')], STRINGS[generateId('title')])} + </div> + </div> + </form> + </div> + ) +} + +const mapContextToProps = ({ strings, activeLanguage, icons, generateId }) => ({ + strings, + activeLanguage, + icons, + generateId, +}); + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/new-page/views/view/index.js b/plugins/src/templates/new-page/views/view/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/new-page/views/view/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/new-page/views/view/view.json b/plugins/src/templates/new-page/views/view/view.json new file mode 100644 index 0000000000..9bf040d9de --- /dev/null +++ b/plugins/src/templates/new-page/views/view/view.json @@ -0,0 +1,18 @@ +{ + "meta": { + "is_page": true, + "path": "/custom-route", + "hide_from_appbar": true, + "hide_from_sidebar": false, + "hide_from_menulist": false, + "hide_from_bottom_nav": true, + "string": { + "id": "title", + "is_global": false + }, + "icon": { + "id": "SIDEBAR_HELP", + "is_global": true + } + } +} \ No newline at end of file diff --git a/plugins/src/templates/onramp/assets/icons.json b/plugins/src/templates/onramp/assets/icons.json new file mode 100644 index 0000000000..3815a2bd63 --- /dev/null +++ b/plugins/src/templates/onramp/assets/icons.json @@ -0,0 +1,3 @@ +{ + "dark": {} +} \ No newline at end of file diff --git a/plugins/src/templates/onramp/assets/strings.json b/plugins/src/templates/onramp/assets/strings.json new file mode 100644 index 0000000000..cc9964b402 --- /dev/null +++ b/plugins/src/templates/onramp/assets/strings.json @@ -0,0 +1,6 @@ +{ + "en": { + "title": "Onramp plugin", + "content": "{0} content" + } +} \ No newline at end of file diff --git a/plugins/src/templates/onramp/views/view/App.js b/plugins/src/templates/onramp/views/view/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/onramp/views/view/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/onramp/views/view/Form.js b/plugins/src/templates/onramp/views/view/Form.js new file mode 100644 index 0000000000..63699e74a3 --- /dev/null +++ b/plugins/src/templates/onramp/views/view/Form.js @@ -0,0 +1,23 @@ +import React from 'react'; +import { withKit } from 'components/KitContext'; + +const Form = ({ + strings: STRINGS, + generateId +}) => { + return ( + <div> + <div className="bold my-4 py-4"> + {STRINGS.formatString(STRINGS[generateId('content')], STRINGS[generateId('title')])} + </div> + </div> + ) +} + +const mapContextToProps = ({ strings, activeLanguage, generateId }) => ({ + strings, + activeLanguage, + generateId, +}); + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/onramp/views/view/index.js b/plugins/src/templates/onramp/views/view/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/onramp/views/view/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/onramp/views/view/view.json b/plugins/src/templates/onramp/views/view/view.json new file mode 100644 index 0000000000..c73b426aec --- /dev/null +++ b/plugins/src/templates/onramp/views/view/view.json @@ -0,0 +1,6 @@ +{ + "meta": { + "is_ultimate_fiat": true, + "type": "onramp" + } +} \ No newline at end of file diff --git a/plugins/src/templates/verification-tab/assets/icons.json b/plugins/src/templates/verification-tab/assets/icons.json new file mode 100644 index 0000000000..3815a2bd63 --- /dev/null +++ b/plugins/src/templates/verification-tab/assets/icons.json @@ -0,0 +1,3 @@ +{ + "dark": {} +} \ No newline at end of file diff --git a/plugins/src/templates/verification-tab/assets/strings.json b/plugins/src/templates/verification-tab/assets/strings.json new file mode 100644 index 0000000000..9e26c53970 --- /dev/null +++ b/plugins/src/templates/verification-tab/assets/strings.json @@ -0,0 +1,8 @@ +{ + "en": { + "title": "Verification", + "go_to_tab": "Go to {0}", + "content": "{0} content", + "home-content": "{0} home content" + } +} \ No newline at end of file diff --git a/plugins/src/templates/verification-tab/views/home/App.js b/plugins/src/templates/verification-tab/views/home/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/verification-tab/views/home/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/verification-tab/views/home/Form.js b/plugins/src/templates/verification-tab/views/home/Form.js new file mode 100644 index 0000000000..c59d7adf85 --- /dev/null +++ b/plugins/src/templates/verification-tab/views/home/Form.js @@ -0,0 +1,32 @@ +import React from 'react'; +import { Button, Editable as EditWrapper } from 'hollaex-web-lib'; +import { withKit } from 'components/KitContext'; + +export const PLUGIN_NAME = 'verification-tab'; + +const Form = ({ setActivePageContent, strings: STRINGS, generateId }) => { + return ( + <div> + <div className="secondary-text d-flex content-center m-4"> + {STRINGS.formatString(STRINGS[generateId('home-content')], STRINGS[generateId('title')])} + </div> + <div className="my-2 btn-wrapper"> + <div className="holla-verification-button pt-4"> + <EditWrapper stringId={generateId('go_to_tab')} /> + <Button + label={STRINGS.formatString(STRINGS[generateId('go_to_tab')], STRINGS[generateId('title')])} + onClick={() => setActivePageContent(PLUGIN_NAME)} + /> + </div> + </div> + </div> + ) +} + +const mapContextToProps = ({ setActivePageContent, strings, generateId }) => ({ + setActivePageContent, + strings, + generateId +}); + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/verification-tab/views/home/index.js b/plugins/src/templates/verification-tab/views/home/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/verification-tab/views/home/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/verification-tab/views/home/view.json b/plugins/src/templates/verification-tab/views/home/view.json new file mode 100644 index 0000000000..70ad04103b --- /dev/null +++ b/plugins/src/templates/verification-tab/views/home/view.json @@ -0,0 +1,14 @@ +{ + "meta": { + "is_verification_tab": true, + "type": "home", + "string": { + "id": "title", + "is_global": false + }, + "icon": { + "id": "SIDEBAR_HELP", + "is_global": true + } + } +} \ No newline at end of file diff --git a/plugins/src/templates/verification-tab/views/verification/App.js b/plugins/src/templates/verification-tab/views/verification/App.js new file mode 100644 index 0000000000..3c337b271f --- /dev/null +++ b/plugins/src/templates/verification-tab/views/verification/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Form from './Form'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Form /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/verification-tab/views/verification/Form.js b/plugins/src/templates/verification-tab/views/verification/Form.js new file mode 100644 index 0000000000..e4e9a96df4 --- /dev/null +++ b/plugins/src/templates/verification-tab/views/verification/Form.js @@ -0,0 +1,56 @@ +import React from 'react'; +import { Button, IconTitle, Editable as EditWrapper } from 'hollaex-web-lib'; +import { withKit } from 'components/KitContext'; +import { PLUGIN_NAME } from '../home/Form'; + +const Form = ({ + strings: STRINGS, + handleBack, + icons: ICONS, + generateId, + setActivePageContent, +}) => { + + const onGoBack = () => { + setActivePageContent('email'); + handleBack(PLUGIN_NAME); + }; + + return ( + <div className="presentation_container apply_rtl verification_container"> + <IconTitle + stringId={generateId('title')} + text={STRINGS[generateId('title')]} + textType="title" + iconPath={ICONS['SIDEBAR_HELP']} + /> + <form className="d-flex flex-column w-100 verification_content-form-wrapper"> + <div className="verification-form-panel mt-3 mb-5"> + <div className="my-4 py-4"> + {STRINGS.formatString(STRINGS[generateId('content')], STRINGS[generateId('title')])} + </div> + </div> + <div className="d-flex justify-content-center align-items-center mt-2"> + <div className="f-1 d-flex justify-content-end verification-buttons-wrapper"> + <EditWrapper stringId="USER_VERIFICATION.GO_BACK" /> + <Button + label={STRINGS['USER_VERIFICATION.GO_BACK']} + onClick={onGoBack} + /> + </div> + </div> + </form> + </div> + ) +} + +const mapContextToProps = ({ strings, handleBack, activeLanguage, icons, generateId, setActivePageContent }) => ({ + strings, + handleBack, + activeLanguage, + icons, + generateId, + setActivePageContent, +}); + +export default withKit(mapContextToProps)(Form); \ No newline at end of file diff --git a/plugins/src/templates/verification-tab/views/verification/index.js b/plugins/src/templates/verification-tab/views/verification/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/verification-tab/views/verification/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/verification-tab/views/verification/view.json b/plugins/src/templates/verification-tab/views/verification/view.json new file mode 100644 index 0000000000..c99e7e3a89 --- /dev/null +++ b/plugins/src/templates/verification-tab/views/verification/view.json @@ -0,0 +1,6 @@ +{ + "meta": { + "is_verification_tab": true, + "type": "verification" + } +} \ No newline at end of file diff --git a/plugins/src/templates/view/App.js b/plugins/src/templates/view/App.js new file mode 100644 index 0000000000..fbe8743c25 --- /dev/null +++ b/plugins/src/templates/view/App.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import { Provider } from "react-redux"; +import store from "store"; +import Title from 'components/Title'; +import { KitContextProvider } from "components/KitContext"; + +class App extends Component { + render() { + const { children: defaultView, ...rest } = this.props; + return ( + <Provider store={store}> + <KitContextProvider {...rest} defaultView={defaultView}> + <Title /> + </KitContextProvider> + </Provider> + ); + } +}; + +export { App }; \ No newline at end of file diff --git a/plugins/src/templates/view/index.js b/plugins/src/templates/view/index.js new file mode 100644 index 0000000000..7ea636958d --- /dev/null +++ b/plugins/src/templates/view/index.js @@ -0,0 +1 @@ +export { App as default } from "./App"; diff --git a/plugins/src/templates/view/view.json b/plugins/src/templates/view/view.json new file mode 100644 index 0000000000..c123454499 --- /dev/null +++ b/plugins/src/templates/view/view.json @@ -0,0 +1,4 @@ +{ + "target": "", + "meta": {} +} \ No newline at end of file diff --git a/plugins/src/utils/index.js b/plugins/src/utils/index.js new file mode 100644 index 0000000000..f5aa416850 --- /dev/null +++ b/plugins/src/utils/index.js @@ -0,0 +1,154 @@ +import React from 'react'; +import math from 'mathjs'; +import numbro from 'numbro'; +import validator from 'validator'; +import isEmail from 'validator/lib/isEmail'; + +export const required = value => (!value ? "Required" : undefined); + +export const editableRequired = (string) => (value) => (!value ? (string || "Required") : undefined); + +export const validateOtp = (message) => ( + value = '' +) => { + let error = undefined; + if (value.length !== 6 || !validator.isNumeric(value)) { + error = message; + } + return error; +}; + +export const DEFAULT_COIN_DATA = { + fullname: '', + symbol: '', + min: 0.001, +}; + +const local_base_currnecy = localStorage.getItem('base_currnecy'); + +export const BASE_CURRENCY = local_base_currnecy + ? local_base_currnecy.toLowerCase() + : 'usdt'; + +export const CURRENCY_PRICE_FORMAT = '{0} {1}'; + +export const formatToCurrency = (amount = 0, min = 0, fullFormat = false) => { + let formatObj = getFormat(min, fullFormat); + return numbro(roundNumber(amount, formatObj.digit)).format(formatObj.format); +}; + +export const roundNumber = (number = 0, decimals = 4) => { + if (number === 0) { + return 0; + } else if (decimals > 0) { + const multipliedNumber = math.multiply( + math.fraction(number), + math.pow(10, decimals) + ); + const dividedNumber = math.divide( + math.floor(multipliedNumber), + math.pow(10, decimals) + ); + return math.number(dividedNumber); + } else { + return math.floor(number); + } +}; + +export const getFormat = (min = 0, fullFormat) => { + let value = math.format(min, { notation: 'fixed' }); + if (fullFormat) { + return { digit: 8, format: '0,0.[00000000]' }; + } else if (min % 1) { + let point = value.toString().split('.')[1] + ? value.toString().split('.')[1] + : ''; + let res = point + .split('') + .map((val) => 0) + .join(''); + return { digit: point.length, format: `0,0.[${res}]` }; + } else { + return { digit: 4, format: `0,0.[0000]` }; + } +}; + +export const getDecimals = (value = 0) => { + let result = math.format(math.number(value), { notation: 'fixed' }); + return value % 1 + ? result.toString().split('.')[1] + ? result.toString().split('.')[1].length + : 0 + : 0; +}; + +export const normalizeBTC = (value = 0) => (value ? roundNumber(value, 8) : ''); + +export const maxValue = (maxValue, message) => (value = 0) => + value > maxValue + ? message + : undefined; + +export const minValue = (minValue, message) => (value = 0) => + value < minValue + ? message + : undefined; + +export const checkBalance = (available, message, fee = 0) => (value = 0) => { + const operation = + fee > 0 + ? math.number( + math.add( + math.fraction(value), + math.multiply(math.fraction(value), math.fraction(fee)) + ) + ) + : value; + + if (operation > available) { + return message; + } + return undefined; +}; + +export const checkBalance_new = (available, message, fee = 0) => (value = 0) => { + const operation = + fee > 0 + ? math.number( + math.add( + math.fraction(value), + math.fraction(fee) + ) + ) + : value; + + if (operation > available) { + return message; + } + return undefined; +}; + +export const toFixed = (exponential) => { + if (Math.abs(exponential) < 1.0) { + let e = parseInt(exponential.toString().split('e-')[1], 10); + if (e) { + exponential *= Math.pow(10, e - 1); + exponential = + '0.' + new Array(e).join('0') + exponential.toString().substring(2); + } + } else { + let e = parseInt(exponential.toString().split('+')[1], 10); + if (e > 20) { + e -= 20; + exponential /= Math.pow(10, e); + exponential += new Array(e + 1).join('0'); + } + } + return exponential; +}; + +export const email = (value = '') => + value && !isEmail(value) ? 'Invalid email address' : undefined; + +export const maxLength = (length, message) => (value = "") => + value.length > length ? message : undefined; \ No newline at end of file diff --git a/plugins/src/utils/link.js b/plugins/src/utils/link.js new file mode 100644 index 0000000000..0f8ee72a88 --- /dev/null +++ b/plugins/src/utils/link.js @@ -0,0 +1,11 @@ +export const open = (url, target = '_blank') => { + const a = document.createElement('a'); + a.style = 'display: none'; + a.href = url; + a.target = target; + a.rel = 'noopener noreferrer'; + + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); +}; \ No newline at end of file diff --git a/plugins/webpack-dev.config.js b/plugins/webpack-dev.config.js new file mode 100644 index 0000000000..49b4119e80 --- /dev/null +++ b/plugins/webpack-dev.config.js @@ -0,0 +1,96 @@ +/** + * generates: + * - dist/main.js + * - dist/manifest.json + * - dist/webpack-bundle-analyzer-report.html + */ +const webpack = require("webpack"); +const fs = require('fs'); +const WebpackAssetsManifest = require("webpack-assets-manifest"); +const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); +const glob = require("glob") +const path = require("path") +const remoteComponentConfig = require("./remote-component.config").resolve; + +const generateEntires = (plugin) => { + const pattern = `src/plugins/${plugin ? plugin : '**'}/views/**/index.js`; + const entry = glob.sync(pattern, { noglobstar: true }) + .reduce((x, y) => { + const dir = y.split(path.sep); + + if (fs.existsSync(y)) { + return Object.assign(x, { + [`${dir[2]}__${dir[4]}`]: `./${y}`, + }) + } else { + return Object.assign(x, {}) + } + + }, {}); + + if ( Object.keys(entry).length === 0) { + process.exit(); + } else { + return entry; + } +} + +const externals = Object.keys(remoteComponentConfig).reduce( + (obj, key) => ({ ...obj, [key]: key }), + {} +); + +module.exports = (env) => { + const { plugin } = env; + const entry = generateEntires(plugin); + return { + plugins: [ + new webpack.EnvironmentPlugin({ + "process.env.NODE_ENV": process.env.NODE_ENV + }), + new BundleAnalyzerPlugin({ + analyzerMode: "static", + openAnalyzer: false, + reportFilename: "webpack-bundle-analyzer-report.html" + }), + new WebpackAssetsManifest() + ], + entry, + watch: true, + watchOptions: { + aggregateTimeout: 200, + poll: 1000, + ignored: /node_modules/, + }, + output: { + libraryTarget: "commonjs" + }, + externals: { + ...externals, + "remote-component.config.js": "remote-component.config.js" + }, + module: { + rules: [ + { + test: /\.m?js$/, + exclude: /(node_modules|bower_components)/, + use: { + loader: "babel-loader" + } + }, + { + test: /\.(sass|less|css)$/, + use: ["style-loader", "css-loader"] + }, + ] + }, + resolve: { + alias: { + "components": path.resolve(__dirname, "src/components"), + "utils": path.resolve(__dirname, "src/utils"), + "store": path.resolve(__dirname, "src/store"), + "constants": path.resolve(__dirname, "src/constants") + } + } + } +}; diff --git a/plugins/webpack-main.config.js b/plugins/webpack-main.config.js new file mode 100644 index 0000000000..9448ca9bc3 --- /dev/null +++ b/plugins/webpack-main.config.js @@ -0,0 +1,90 @@ +/** + * generates: + * - dist/main.js + * - dist/manifest.json + * - dist/webpack-bundle-analyzer-report.html + */ +const webpack = require("webpack"); +const fs = require('fs'); +const WebpackAssetsManifest = require("webpack-assets-manifest"); +const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); +const glob = require("glob") +const path = require("path") +const remoteComponentConfig = require("./remote-component.config").resolve; + +const generateEntires = (plugin) => { + const pattern = `src/plugins/${plugin ? plugin : '**'}/views/**/index.js`; + const entry = glob.sync(pattern, { noglobstar: true }) + .reduce((x, y) => { + const dir = y.split(path.sep); + + if (fs.existsSync(y)) { + return Object.assign(x, { + [`${dir[2]}__${dir[4]}`]: `./${y}`, + }) + } else { + return Object.assign(x, {}) + } + + }, {}); + + if ( Object.keys(entry).length === 0) { + process.exit(); + } else { + return entry; + } +} + +const externals = Object.keys(remoteComponentConfig).reduce( + (obj, key) => ({ ...obj, [key]: key }), + {} +); + +module.exports = (env) => { + const { plugin } = env; + const entry = generateEntires(plugin); + return { + plugins: [ + new webpack.EnvironmentPlugin({ + "process.env.NODE_ENV": process.env.NODE_ENV + }), + new BundleAnalyzerPlugin({ + analyzerMode: "static", + openAnalyzer: false, + reportFilename: "webpack-bundle-analyzer-report.html" + }), + new WebpackAssetsManifest() + ], + entry, + output: { + libraryTarget: "commonjs" + }, + externals: { + ...externals, + "remote-component.config.js": "remote-component.config.js" + }, + module: { + rules: [ + { + test: /\.m?js$/, + exclude: /(node_modules|bower_components)/, + use: { + loader: "babel-loader" + } + }, + { + test: /\.(sass|less|css)$/, + use: ["style-loader", "css-loader"] + }, + ] + }, + resolve: { + alias: { + "components": path.resolve(__dirname, "src/components"), + "utils": path.resolve(__dirname, "src/utils"), + "store": path.resolve(__dirname, "src/store"), + "constants": path.resolve(__dirname, "src/constants") + } + } + } +}; diff --git a/plugins/webpack.config.js b/plugins/webpack.config.js new file mode 100644 index 0000000000..aea8894bd1 --- /dev/null +++ b/plugins/webpack.config.js @@ -0,0 +1,3 @@ +const webpackMainConfig = require("./webpack-main.config"); + +module.exports = [webpackMainConfig]; diff --git a/server/api/controllers/admin.js b/server/api/controllers/admin.js index e4632a7e02..e5fc73512f 100644 --- a/server/api/controllers/admin.js +++ b/server/api/controllers/admin.js @@ -111,7 +111,7 @@ const putAdminKit = (req, res) => { const getUsersAdmin = (req, res) => { loggerAdmin.verbose(req.uuid, 'controllers/admin/getUsers/auth', req.auth); - const { id, search, pending, limit, page, order_by, order, start_date, end_date, format } = req.swagger.params; + const { id, search, pending, pending_type, limit, page, order_by, order, start_date, end_date, format } = req.swagger.params; if (order_by.value && typeof order_by.value !== 'string') { loggerAdmin.error( @@ -126,6 +126,7 @@ const getUsersAdmin = (req, res) => { id: id.value, search: search.value, pending: pending.value, + pending_type: pending_type.value, limit: limit.value, page: page.value, order_by: order_by.value, diff --git a/server/api/controllers/user.js b/server/api/controllers/user.js index 13e63238b6..08be7bc92a 100644 --- a/server/api/controllers/user.js +++ b/server/api/controllers/user.js @@ -27,7 +27,7 @@ const { USER_EMAIL_IS_VERIFIED, INVALID_VERIFICATION_CODE } = require('../../messages'); -const { DEFAULT_ORDER_RISK_PERCENTAGE, EVENTS_CHANNEL, API_HOST, DOMAIN } = require('../../constants'); +const { DEFAULT_ORDER_RISK_PERCENTAGE, EVENTS_CHANNEL, API_HOST, DOMAIN, TOKEN_TIME_NORMAL, TOKEN_TIME_LONG } = require('../../constants'); const { all } = require('bluebird'); const { each } = require('lodash'); const { publisher } = require('../../db/pubsub'); @@ -296,9 +296,13 @@ const loginPost = (req, res) => { password, otp_code, captcha, - service + service, + long_term } = req.swagger.params.authentication.value; - let { email } = req.swagger.params.authentication.value; + let { + email + } = req.swagger.params.authentication.value; + const ip = req.headers['x-real-ip']; const device = req.headers['user-agent']; const domain = req.headers['x-real-origin']; @@ -306,6 +310,32 @@ const loginPost = (req, res) => { const referer = req.headers.referer; const time = new Date(); + loggerUser.verbose( + req.uuid, + 'controllers/user/loginPost', + 'email', + email, + 'otp_code', + otp_code, + 'captcha', + captcha, + 'service', + service, + 'long_term', + long_term, + 'ip', + ip, + 'device', + device, + 'domain', + domain, + 'origin', + origin, + 'referer', + referer + ); + + if (!email || typeof email !== 'string' || !isEmail(email)) { loggerUser.error( req.uuid, @@ -394,7 +424,8 @@ const loginPost = (req, res) => { user.is_support, user.is_supervisor, user.is_kyc, - user.is_communicator + user.is_communicator, + long_term ? TOKEN_TIME_LONG : TOKEN_TIME_NORMAL ) }); }) @@ -505,9 +536,9 @@ const resetPassword = (req, res) => { const getUser = (req, res) => { loggerUser.debug(req.uuid, 'controllers/user/getUser', req.auth.sub); - const email = req.auth.sub.email; + const id = req.auth.sub.id; - toolsLib.user.getUserByEmail(email, true, true, { + toolsLib.user.getUserByKitId(id, true, true, { additionalHeaders: { 'x-forwarded-for': req.headers['x-forwarded-for'] } diff --git a/server/api/controllers/withdrawal.js b/server/api/controllers/withdrawal.js index 2a184dd53f..021739c0cd 100644 --- a/server/api/controllers/withdrawal.js +++ b/server/api/controllers/withdrawal.js @@ -121,7 +121,24 @@ const performWithdrawal = (req, res) => { }), withdrawal ]); + } else if (toolsLib.getKitCoin(withdrawal.currency).type === 'fiat') { + // burn the asset + return all([ + toolsLib.wallet.burnAssetByKitId( + withdrawal.user_id, + withdrawal.currency, + withdrawal.amount, + { + transactionId: withdrawal.transaction_id, + address: withdrawal.address, + status: false, + fee: withdrawal.fee + } + ), + withdrawal + ]); } else { + // blockchain type to sent to the network return all([ toolsLib.wallet.performWithdrawal( withdrawal.user_id, diff --git a/server/api/swagger/swagger.yaml b/server/api/swagger/swagger.yaml index f157b0eeed..67513dbda9 100644 --- a/server/api/swagger/swagger.yaml +++ b/server/api/swagger/swagger.yaml @@ -1,6 +1,6 @@ swagger: "2.0" info: - version: "2.4.1" + version: "2.4.4" title: HollaEx Kit host: api.hollaex.com basePath: /v2 @@ -1613,7 +1613,7 @@ paths: in: query required: true type: string - minLength: 3 + minLength: 2 maxLength: 15 - name: network in: query @@ -3061,6 +3061,11 @@ paths: in: query required: false type: boolean + - name: pending_type + in: query + required: false + type: string + enum: ['id', 'bank'] - in: query name: limit description: "Number of elements to return. Default: 50. Maximun: 100" @@ -4681,6 +4686,8 @@ definitions: type: string service: type: string + long_term: + type: boolean ResetPassword: type: object required: diff --git a/server/constants.js b/server/constants.js index b9c7965805..8a3460fe88 100644 --- a/server/constants.js +++ b/server/constants.js @@ -302,7 +302,8 @@ exports.SETTING_KEYS = [ 'interface', 'audio', 'risk', - 'chat' + 'chat', + 'app' ]; exports.OMITTED_USER_FIELDS = [ @@ -349,6 +350,9 @@ exports.DEFAULT_ORDER_RISK_PERCENTAGE = 90; // used in settings in percentage to // SECURITY CONSTANTS START -------------------------------------------------- +exports.TOKEN_TIME_NORMAL = '24h'; +exports.TOKEN_TIME_LONG = '30d'; + exports.TOKEN_TYPES = { HMAC: 'hmac' }; diff --git a/server/db/migrations/20221012043710-add-affiliation-code.js b/server/db/migrations/20221012043710-add-affiliation-code.js new file mode 100644 index 0000000000..a6f6b74063 --- /dev/null +++ b/server/db/migrations/20221012043710-add-affiliation-code.js @@ -0,0 +1,14 @@ +'use strict'; + +const TABLE = 'Affiliations'; +const COLUMN = 'code'; + +module.exports = { + up: (queryInterface, Sequelize) => + queryInterface.addColumn(TABLE, COLUMN, { + type: Sequelize.STRING, + allowNull: true + }), + down: (queryInterface) => + queryInterface.removeColumn(TABLE, COLUMN) +}; \ No newline at end of file diff --git a/server/db/migrations/20221019035508-add-mongolian-mail.js b/server/db/migrations/20221019035508-add-mongolian-mail.js new file mode 100644 index 0000000000..f4f817be6e --- /dev/null +++ b/server/db/migrations/20221019035508-add-mongolian-mail.js @@ -0,0 +1,20 @@ +'use strict'; +const TABLE = 'Statuses'; +const COLUMN = 'email'; + +const mongolian = JSON.stringify(require('../../mail/strings/mn.json')); + +module.exports = { + async up(queryInterface) { + await queryInterface.sequelize.query( + `UPDATE public."${TABLE}" + SET ${COLUMN} = ${COLUMN} || '${mongolian}' + `); + }, + + down: () => { + return new Promise((resolve) => { + resolve(); + }); + } +}; diff --git a/server/db/models/affiliation.js b/server/db/models/affiliation.js index 40f59d197e..b9c69b0f00 100644 --- a/server/db/models/affiliation.js +++ b/server/db/models/affiliation.js @@ -25,6 +25,10 @@ module.exports = function(sequelize, DataTypes) { model: 'Users', key: 'id' } + }, + code: { + type: DataTypes.STRING, + allowNull: true } }, { diff --git a/server/mail/strings/ar.json b/server/mail/strings/ar.json index 4b82bb5e96..8f04464b64 100644 --- a/server/mail/strings/ar.json +++ b/server/mail/strings/ar.json @@ -95,6 +95,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p> ${name}العزيز </p><p>تمت معالجة طلب سحبك بمبلغ ${amount} ${currency} و نقله إلى عنوان.${address}. </p><p>المبلغ: ${amount} ${currency}<br />الرسوم: ${fee} ${currency}<br />الحالة: ${status}<br />العنوان: ${address}<br />معرّف المعاملة: ${transaction_id}<br /><span id='network'>شبكة الاتصال: ${network}</span><br /><ul>${explorers}</ul><p> تحية<br> فريق${api_name} </p></div>", "title": "${currency} سحب completed" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } } } \ No newline at end of file diff --git a/server/mail/strings/de.json b/server/mail/strings/de.json index 3aaaeacd05..e477371866 100644 --- a/server/mail/strings/de.json +++ b/server/mail/strings/de.json @@ -95,6 +95,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p> Sehr geehrte/r ${name} </p><p>Ihr Auszahlungsantrag für ${amount} ${currency} wurde bearbeitet.</p><p>Betrag: ${amount} ${currency}<br />Gebühr: ${fee} ${currency}<br />Status: ${status}<br />Adresse: ${address}<br />Transaktionsnummer: ${transaction_id}<br /><span id='network'>Netzwerk: ${network}</span><br /><ul>${explorers}</ul><p> Mit freundlichen Grüßen<br> ${api_name} team </p></div>", "title": "${currency} Abbuchung completed" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } } } \ No newline at end of file diff --git a/server/mail/strings/en.json b/server/mail/strings/en.json index d05bb68f92..42c307b902 100644 --- a/server/mail/strings/en.json +++ b/server/mail/strings/en.json @@ -1,113 +1,112 @@ - - { - "en": { - "DOC_REJECTED": { - "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", - "title": "KYC Documents Rejected" - }, - "DOC_VERIFIED": { - "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", - "title": "KYC Documents Approved" - }, - "CONFIRM_EMAIL": { - "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immidiately and proceed to change your crendetials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", - "title": "Security Verification" - }, - "LOGIN": { - "html": "<div> <p> Dear ${name} </p> <p> We have recorded a login to your account with the following details </p> <div> <div>Time: ${time}</div> <div>Country: ${country}</div> <div>IP Address: ${ip}</div> </div> <p> If this was not you, please change your password, set up two-factor authentication, and contact us immediately. </p> <p> Regards<br> ${api_name} team </p> </div>", - "title": "Login" - }, - "SIGNUP": { - "html": "<div> <p> Dear ${name} </p> <p> You need to confirm your email account by clicking the button below.<br> If you have any questions feel free to contact us simply by replying to this email.</p><p>Please click on the button below to proceed with your registration.</p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Confirm</Button></a></div><p> Regards<br> ${api_name} team </p></div>", - "title": "Sign Up" - }, - "WELCOME": { - "html": "<div><p> Dear ${name} </p><p>Thank you for signing up to ${api_name}.</p><p>To begin trading, you must first deposit cryptocurrency or fund money to your account.Please go to your <a href=\"${link_account}\" target=\"_blank\">account</a> and visit the <a href=\"${link_deposit}\" target=\"_blank\">deposit</a> page.,</p><p>If you have any questions or concerns, please contact us simply by replying to this email.</p><p> Regards<br> ${api_name} team </p></div>", - "title": "Welcome" - }, - "RESET_PASSWORD": { - "html": "<div><p> Dear ${name} </p><p>You have made a request to reset the password for your account.<br />To update your password, click on the link below.<br /></p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Reset My Password</Button></a></div><p>If this request was made in error, it is safe to ignore it; no changes will be made to your account.</p><p>Request initiated from: ${ip}</p><p> Regards<br> ${api_name} team </p></div>", - "title": "Reset Password Request" - }, - "ACCOUNT_VERIFY": { - "html": "<div><p> Dear ${name} </p><p>Congratulations. Your account is verified successfully.</p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Trade Now</Button></a></div><p> Regards<br> ${api_name} team </p></div>", - "title": "Account Verified" - }, - "ACCOUNT_UPGRADE": { - "html": "<div><p> Dear ${name} </p><p>Congratulations. Your account access level is upgraded to ${tier} tier. You will benefit from lower fees, higher withdrawal limits and other premium features.</p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Trade Now</Button></a></div><p> Regards<br> ${api_name} team </p></div>", - "title": "Account Upgraded" - }, - "DEPOSIT_CANCEL": { - "html": "<div><p> Dear ${name} </p><p>We were not able to find or process your ${currency} deposit made on ${date} for ${amount}. Thus, the transaction is rejected by our system.</p><p>If you have any further inquiries, you can reply to this email</p><p>Transaction ID: ${txid}<br />Amount: ${amount}<br />Status: Rejected</p><p> Regards<br> ${api_name} team </p></div>", - "title": "${currency} Deposit rejected" - }, - "DEPOSIT_PENDING": { - "html": "<div><div><p> Dear ${name} </p><p> You have a new deposit for ${amount} ${currency} pending in your ${api_name} wallet. Please wait until the transaction is confirmed and your funds will be available in your wallet.</p><p>Amount: ${amount} ${currency}<br />Status: ${status}<br />Address: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Network: ${network}</span><br />Fee: ${fee} ${fee_coin}<br /><ul>${explorers}</ul></div><p> Regards<br> ${api_name} team </p></div>", - "title": "${currency} Deposit pending" - }, - "DEPOSIT_COMPLETED": { - "html": "<div><div><p> Dear ${name} </p><p> Your ${currency} deposit for ${amount} ${currency} is confirmed and completed and it is available in your ${currency} wallet.</p><p>Amount: ${amount} ${currency}<br />Status: ${status}<br />Address: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Network: ${network}</span><br />Fee: ${fee} ${fee_coin}<br /><ul>${explorers}</ul></div><p> Regards<br> ${api_name} team </p></div>", - "title": "${currency} Deposit completed" - }, - "WITHDRAWAL_PENDING": { - "html": "<div><p> Dear ${name} </p><p>You made a withdrawal request for ${amount} ${currency}. Your withdrawal status is pending and will be processed shortly.</p><p>Amount: ${amount} ${currency}<br />Fee: ${fee} ${fee_coin}<br />Status: ${status}<br />Address: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Network: ${network}</span><br /><ul>${explorers}</ul><p> Regards<br> ${api_name} team </p></div>", - "title": "${currency} withdrawal pending" - }, - "WITHDRAWAL_COMPLETED": { - "html": "<div><p> Dear ${name} </p><p>Your withdrawal request for ${amount} ${currency} is processed.</p><p>Amount: ${amount} ${currency}<br />Fee: ${fee} ${fee_coin}<br />Status: ${status}<br />Address: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Network: ${network}</span><br /><ul>${explorers}</ul><p> Regards<br> ${api_name} team </p></div>", - "title": "${currency} withdrawal completed" - }, - "WITHDRAWAL_CANCEL": { - "html": "<div><p> Dear ${name} </p><p>We were not able to find or process your ${currency} withdrawal made on ${date} for ${amount}. Thus the transaction is rejected by our system and your pending withdrawal amount is credited back to your ${api_name} wallet.</p><p>If you have any further inquiries, you can reply to this email</p><p>Transaction ID: ${txid}<br />Amount: ${amount}<br />Status: Rejected</p><p> Regards<br> ${api_name} team </p></div>", - "title": "${currency} Withdrawal rejected" - }, - "WITHDRAWAL_REQUEST": { - "html": "<div><p> Dear ${name} </p><p>You have made a ${currency} withdrawal request of ${amount} to ${address}<br /><br />Amount: ${amount} ${currency}<br />Fee: ${fee} ${fee_coin}<br />Address: ${address}<br /><span id=\"network\">Network: ${network}</span><br /><br />In order to confirm this withdrawal, please click the button below.<br /></p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Confirm</Button></a></div><p>If this request was made in error, it is safe to ignore it; no changes will be made to your account.</p><p>Request initiated from: ${ip}</p><p> Regards<br> ${api_name} team </p></div>", - "title": "${currency} Withdrawal Request" - }, - "USER_VERIFICATION": { - "html": "<div><h3>User Verification Required</h3><div>User \"${email}\" uploaded his documents for verification. Please verify his documents.</div></div>", - "title": "User Verification" - }, - "SUSPICIOUS_DEPOSIT": { - "html": "<div><h3>Suspicious Deposit</h3><div>The client with email ${email} has received a ${currency} deposit that is suspicious.<br />Transaction ID: ${txid}<h4>Transaction data:</h4><div>${data}</div></div></div>", - "title": "Suspicious Deposit" - }, - "INVALID_ADDRESS": { - "html": "<div><p> Dear ${name} </p><p>Your ${currency} withdrawal for ${amount} was being sent to an invalid address and is rejected.</p><p>Address: ${address}</p><p> Regards<br> ${api_name} team </p></div>", - "title": "Invalid Withdrawal Address" - }, - "USER_DEACTIVATED": { - "html": "<div><p>Your account ${email} has been deactivated. You will not be able to use your account until it is activated by the exchange admin.</p><p> Regards<br> ${api_name} team </p></div>", - "title": "Account ${type}" - }, - "USER_ACTIVATED": { - "html": "<div><p>Your account ${email} has been activated. You are now able to use your account.</p><p> Regards<br> ${api_name} team </p></div>", - "title": "Account ${type}" - }, - "DISCOUNT_UPDATE": { - "html": "<div><p> Dear ${name} </p><p>Your discount rate has been changed to ${rate}%. This rate will be applied to your order fees.</p><p> Regards<br> ${api_name} team </p></div>", - "title": "Discount Rate Change" - }, - "BANK_VERIFIED": { - "html": "<div><p> Dear ${name} </p><p>A pending bank account has been verified. Your valid account can now be used for exchange operations requiring a bank account.</p><div><strong>Verified Bank Accounts:</strong>${list_detail_bank_account}</div><p><a href=\"${link_verification}\">To view your current bank accounts, please visit the exchange verification Tab</a></p><p> Regards<br> ${api_name} team </p></div>", - "title": "Bank Verified" - }, - "USER_ID_VERIFICATION_REJECT": { - "html": "<div><p> Dear ${name} </p><p>Your recent ID verification is processed and is unfortunately rejected. For further actions read the message from our expert below:</p><p>Message: ${message}</p><p> Regards<br> ${api_name} team </p></div>", - "title": "ID Verification Rejected" - }, - "USER_BANK_VERIFICATION_REJECT": { - "html": "<div><p> Dear ${name} </p><p>Your new bank registration is processed and is unfortunately rejected. For further actions read the message from our expert below:</p><p>Message: ${message}</p><p> Regards<br> ${api_name} team </p></div>", - "title": "New Bank Application Rejected" - }, - "PASSWORD_CHANGED": { - "html": "<div><p> Dear ${name} </p><p>This email confirms that you recently changed the password for your account. No further action is required.<br />If you did not authorize this change please contact us immediately.<br /></p><p> Regards<br> ${api_name} team </p></div>", - "title": "Password Changed" - }, - "CHANGE_PASSWORD": { - "html": "<div><p> Dear ${name} </p><p>You have made a request to change the password for your account.<br />To confirm your password changed, click on the link below.<br /></p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Confirm Change My Password</Button></a></div><p>If this request was made in error, it is safe to ignore it; no changes will be made to your account.</p><p>Request initiated from: ${ip}</p><p> Regards<br> ${api_name} team </p></div>", - "title": "Change Password Confirmation" - } +{ + "en": { + "LOGIN": { + "html": "<div> <p> Dear ${name} </p> <p> We have recorded a login to your account with the following details </p> <div> <div>Time: ${time}</div> <div>Country: ${country}</div> <div>IP Address: ${ip}</div> </div> <p> If this was not you, please change your password, set up two-factor authentication, and contact us immediately. </p> <p> Regards<br> ${api_name} team </p> </div>", + "title": "Login" + }, + "SIGNUP": { + "html": "<div> <p> Dear ${name} </p> <p> You need to confirm your email account by clicking the button below.<br> If you have any questions feel free to contact us simply by replying to this email.</p><p>Please click on the button below to proceed with your registration.</p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Confirm</Button></a></div><p> Regards<br> ${api_name} team </p></div>", + "title": "Sign Up" + }, + "WELCOME": { + "html": "<div><p> Dear ${name} </p><p>Thank you for signing up to ${api_name}.</p><p>To begin trading, you must first deposit cryptocurrency or fund money to your account.Please go to your <a href=\"${link_account}\" target=\"_blank\">account</a> and visit the <a href=\"${link_deposit}\" target=\"_blank\">deposit</a> page.,</p><p>If you have any questions or concerns, please contact us simply by replying to this email.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Welcome" + }, + "RESET_PASSWORD": { + "html": "<div><p> Dear ${name} </p><p>You have made a request to reset the password for your account.<br />To update your password, click on the link below.<br /></p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Reset My Password</Button></a></div><p>If this request was made in error, it is safe to ignore it; no changes will be made to your account.</p><p>Request initiated from: ${ip}</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Reset Password Request" + }, + "ACCOUNT_VERIFY": { + "html": "<div><p> Dear ${name} </p><p>Congratulations. Your account is verified successfully.</p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Trade Now</Button></a></div><p> Regards<br> ${api_name} team </p></div>", + "title": "Account Verified" + }, + "ACCOUNT_UPGRADE": { + "html": "<div><p> Dear ${name} </p><p>Congratulations. Your account access level is upgraded to ${tier} tier. You will benefit from lower fees, higher withdrawal limits and other premium features.</p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Trade Now</Button></a></div><p> Regards<br> ${api_name} team </p></div>", + "title": "Account Upgraded" + }, + "DEPOSIT_CANCEL": { + "html": "<div><p> Dear ${name} </p><p>We were not able to find or process your ${currency} deposit made on ${date} for ${amount}. Thus, the transaction is rejected by our system.</p><p>If you have any further inquiries, you can reply to this email</p><p>Transaction ID: ${txid}<br />Amount: ${amount}<br />Status: Rejected</p><p> Regards<br> ${api_name} team </p></div>", + "title": "${currency} Deposit rejected" + }, + "DEPOSIT_PENDING": { + "html": "<div><div><p> Dear ${name} </p><p> You have a new deposit for ${amount} ${currency} pending in your ${api_name} wallet. Please wait until the transaction is confirmed and your funds will be available in your wallet.</p><p>Amount: ${amount} ${currency}<br />Status: ${status}<br />Address: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Network: ${network}</span><br />Fee: ${fee} ${fee_coin}<br /><ul>${explorers}</ul></div><p> Regards<br> ${api_name} team </p></div>", + "title": "${currency} Deposit pending" + }, + "DEPOSIT_COMPLETED": { + "html": "<div><div><p> Dear ${name} </p><p> Your ${currency} deposit for ${amount} ${currency} is confirmed and completed and it is available in your ${currency} wallet.</p><p>Amount: ${amount} ${currency}<br />Status: ${status}<br />Address: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Network: ${network}</span><br />Fee: ${fee} ${fee_coin}<br /><ul>${explorers}</ul></div><p> Regards<br> ${api_name} team </p></div>", + "title": "${currency} Deposit completed" + }, + "WITHDRAWAL_PENDING": { + "html": "<div><p> Dear ${name} </p><p>You made a withdrawal request for ${amount} ${currency}. Your withdrawal status is pending and will be processed shortly.</p><p>Amount: ${amount} ${currency}<br />Fee: ${fee} ${fee_coin}<br />Status: ${status}<br />Address: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Network: ${network}</span><br /><ul>${explorers}</ul><p> Regards<br> ${api_name} team </p></div>", + "title": "${currency} withdrawal pending" + }, + "WITHDRAWAL_COMPLETED": { + "html": "<div><p> Dear ${name} </p><p>Your withdrawal request for ${amount} ${currency} is processed.</p><p>Amount: ${amount} ${currency}<br />Fee: ${fee} ${fee_coin}<br />Status: ${status}<br />Address: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Network: ${network}</span><br /><ul>${explorers}</ul><p> Regards<br> ${api_name} team </p></div>", + "title": "${currency} withdrawal completed" + }, + "WITHDRAWAL_CANCEL": { + "html": "<div><p> Dear ${name} </p><p>We were not able to find or process your ${currency} withdrawal made on ${date} for ${amount}. Thus the transaction is rejected by our system and your pending withdrawal amount is credited back to your ${api_name} wallet.</p><p>If you have any further inquiries, you can reply to this email</p><p>Transaction ID: ${txid}<br />Amount: ${amount}<br />Status: Rejected</p><p> Regards<br> ${api_name} team </p></div>", + "title": "${currency} Withdrawal rejected" + }, + "WITHDRAWAL_REQUEST": { + "html": "<div><p> Dear ${name} </p><p>You have made a ${currency} withdrawal request of ${amount} to ${address}<br /><br />Amount: ${amount} ${currency}<br />Fee: ${fee} ${fee_coin}<br />Address: ${address}<br /><span id=\"network\">Network: ${network}</span><br /><br />In order to confirm this withdrawal, please click the button below.<br /></p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Confirm</Button></a></div><p>If this request was made in error, it is safe to ignore it; no changes will be made to your account.</p><p>Request initiated from: ${ip}</p><p> Regards<br> ${api_name} team </p></div>", + "title": "${currency} Withdrawal Request" + }, + "USER_VERIFICATION": { + "html": "<div><h3>User Verification Required</h3><div>User \"${email}\" uploaded his documents for verification. Please verify his documents.</div></div>", + "title": "User Verification" + }, + "SUSPICIOUS_DEPOSIT": { + "html": "<div><h3>Suspicious Deposit</h3><div>The client with email ${email} has received a ${currency} deposit that is suspicious.<br />Transaction ID: ${txid}<h4>Transaction data:</h4><div>${data}</div></div></div>", + "title": "Suspicious Deposit" + }, + "INVALID_ADDRESS": { + "html": "<div><p> Dear ${name} </p><p>Your ${currency} withdrawal for ${amount} was being sent to an invalid address and is rejected.</p><p>Address: ${address}</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Invalid Withdrawal Address" + }, + "USER_DEACTIVATED": { + "html": "<div><p>Your account ${email} has been deactivated. You will not be able to use your account until it is activated by the exchange admin.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Account ${type}" + }, + "USER_ACTIVATED": { + "html": "<div><p>Your account ${email} has been activated. You are now able to use your account.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Account ${type}" + }, + "DISCOUNT_UPDATE": { + "html": "<div><p> Dear ${name} </p><p>Your discount rate has been changed to ${rate}%. This rate will be applied to your order fees.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Discount Rate Change" + }, + "BANK_VERIFIED": { + "html": "<div><p> Dear ${name} </p><p>A pending bank account has been verified. Your valid account can now be used for exchange operations requiring a bank account.</p><div><strong>Verified Bank Accounts:</strong>${list_detail_bank_account}</div><p><a href=\"${link_verification}\">To view your current bank accounts, please visit the exchange verification Tab</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "Bank Verified" + }, + "USER_ID_VERIFICATION_REJECT": { + "html": "<div><p> Dear ${name} </p><p>Your recent ID verification is processed and is unfortunately rejected. For further actions read the message from our expert below:</p><p>Message: ${message}</p><p> Regards<br> ${api_name} team </p></div>", + "title": "ID Verification Rejected" + }, + "USER_BANK_VERIFICATION_REJECT": { + "html": "<div><p> Dear ${name} </p><p>Your new bank registration is processed and is unfortunately rejected. For further actions read the message from our expert below:</p><p>Message: ${message}</p><p> Regards<br> ${api_name} team </p></div>", + "title": "New Bank Application Rejected" + }, + "PASSWORD_CHANGED": { + "html": "<div><p> Dear ${name} </p><p>This email confirms that you recently changed the password for your account. No further action is required.<br />If you did not authorize this change please contact us immediately.<br /></p><p> Regards<br> ${api_name} team </p></div>", + "title": "Password Changed" + }, + "CHANGE_PASSWORD": { + "html": "<div><p> Dear ${name} </p><p>You have made a request to change the password for your account.<br />To confirm your password changed, click on the link below.<br /></p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Confirm Change My Password</Button></a></div><p>If this request was made in error, it is safe to ignore it; no changes will be made to your account.</p><p>Request initiated from: ${ip}</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Change Password Confirmation" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } + } } \ No newline at end of file diff --git a/server/mail/strings/es.json b/server/mail/strings/es.json index d80e13fd79..6dd257b19e 100644 --- a/server/mail/strings/es.json +++ b/server/mail/strings/es.json @@ -95,6 +95,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p> Estimado/ Estimada ${name} </p><p>Su solicitud de retirada de ${amount} ${currency} se está procesando.</p><p>Cantidad: ${amount} ${currency}<br />Tarifa: ${fee} ${currency}<br />Estado: ${status}<br />Dirección: ${address}<br />ID de transacciónID: ${transaction_id}<br /><span id='network'>La red: ${network}</span><br /><ul>${explorers}</ul><p> Saludos<br>Equipo de ${api_name} </p></div>", "title": "${currency} Retirada completed" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } } } \ No newline at end of file diff --git a/server/mail/strings/fa.json b/server/mail/strings/fa.json index 7ce434530e..94fd088207 100644 --- a/server/mail/strings/fa.json +++ b/server/mail/strings/fa.json @@ -95,6 +95,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p> کاربر عزیز${name} </p><p>درخواست برداشت شما به مبلغ ${amount} ${currency} درحال انجام و ارسال به آدرس ${address} می باشد.<br />کارمزد: ${fee} ${currency}<br />Status: ${status}<br />آدرس: ${address}<br />شماره پیگیری تراکنش: ${transaction_id}<br /><span id='network'>شبکه: ${network}</span><br /><ul>${explorers}</ul><p> Regards<br> ${api_name} team </p></div>", "title": "${currency} برداشت completed" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } } } \ No newline at end of file diff --git a/server/mail/strings/fr.json b/server/mail/strings/fr.json index 7ed1a05621..8c74e4876a 100644 --- a/server/mail/strings/fr.json +++ b/server/mail/strings/fr.json @@ -95,6 +95,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p> Bonjour ${name} </p><p>Votre demande de retrait de ${amount} ${currency} est traité.</p><p>Montant: ${amount} ${currency}<br />Frais: ${fee} ${currency}<br />Status: ${status}<br />Addresse: ${address}<br />Identité de la transaction: ${transaction_id}<br /><span id='network'>Réseau: ${network}</span><br /><ul>${explorers}</ul><p> Bien cordialement<br> ${api_name} team </p></div>", "title": "${currency} withdrawal completed" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } } } \ No newline at end of file diff --git a/server/mail/strings/id.json b/server/mail/strings/id.json index e2524f2c6d..de1b791832 100644 --- a/server/mail/strings/id.json +++ b/server/mail/strings/id.json @@ -95,6 +95,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p>Kepada ${name} </p><p>Permintaan penarikan Anda untuk ${amount} ${currency} telah diproses dan ditransfer ke alamat ${address}.</p><p>Jumlah: ${amount} ${currency}<br />Biaya: ${fee} ${currency}<br />Status: ${status}<br />Alamat: ${address}<br />ID Transaksi: ${transaction_id}<br /><span id='network'>Jaringan: ${network}</span><br /><ul>${explorers}</ul><p> Salam<br> ${api_name} tim </p></div>", "title": "${currency} Penarikan completed" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } } } \ No newline at end of file diff --git a/server/mail/strings/ja.json b/server/mail/strings/ja.json index bbaf021f02..3b8f16f39d 100644 --- a/server/mail/strings/ja.json +++ b/server/mail/strings/ja.json @@ -95,6 +95,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p> ${name}様 </p><p>お客様の${amount} ${currency}出金が完了し、アドレス${address}に振り込みされました。</p><p>金額: ${amount} ${currency}<br />手数料: ${fee} ${currency}<br />取引状態: ${status}<br />アドレス: ${address}<br />取引ID: ${transaction_id}<br /><span id='network'>ネットワーク: ${network}</span><br /><ul>${explorers}</ul><p> 敬具<br> ${api_name} チーム </p></div>", "title": "${currency}の引き出しが完了しました" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } } } \ No newline at end of file diff --git a/server/mail/strings/ko.json b/server/mail/strings/ko.json index 19cf001bc7..85dc719087 100644 --- a/server/mail/strings/ko.json +++ b/server/mail/strings/ko.json @@ -95,6 +95,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p> ${name}님 </p><p>회원님의 ${amount} ${currency}를 출금이 완료되어 회원님의 계좌로 이체되었습니다.</p><p>금액: ${amount} ${currency}<br />수수료: ${fee} ${currency}<br />입금 상태: ${status}<br />주소: ${address}<br />거래 ID 확인: ${transaction_id}<br /><span id='network'>회로망: ${network}</span>>br /><ul>${explorers}</ul><p> 이용해 주셔서 감사합니다.<br> ${api_name} 팀 </p></div>", "title": "${currency} 출금 완료" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } } } \ No newline at end of file diff --git a/server/mail/strings/mn.json b/server/mail/strings/mn.json new file mode 100644 index 0000000000..874a1ef5bf --- /dev/null +++ b/server/mail/strings/mn.json @@ -0,0 +1,112 @@ +{ + "mn": { + "LOGIN": { + "html": "<div> <p> Эрхэм хүндэт ${name} </p> <p> Та дараах хаягнаас нэвтэрч орсон байна </p> <div> <div>Цаг: ${time}</div> <div>Улс: ${country}</div> <div>IP Хаяг: ${ip}</div> </div> <p> Хэрэв энэ нь та биш байсан бол нууц үгээ сольж, давхар баталгаажуулалтыг тохируулаад бидэнтэй шууд холбогдоно уу. </p> <p> Хүндэтгэсэн<br> ${api_name} team </p> </div>", + "title": "Нэвтрэх" + }, + "SIGNUP": { + "html": "<div> <p> Эрхэм хүндэт ${name} </p> <p> Та доорх товчийг дарж имэйл хаягаа баталгаажуулах шаардлагатай.<br> Хэрэв танд асуух зүйл байвал энэ имэйлд хариу бичих замаар бидэнтэй холбоо барина уу.</p><p>Доорх товчийг дарж бүртгэлээ үргэлжлүүлнэ үү.</p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Баталгаажуулах</Button></a></div><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Бүртгүүлэх" + }, + "WELCOME": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>${api_name} бүртгүүлсэнд баярлалаа.</p><p>Арилжааэд оролцохын тулд та эхлээд криптовалютын орлого хийх эсвэл дансандаа мөнгө байршуулах ёстой. Та өөрийн <a href=${link_account} target=_blank>account</a> руу нэвтэрч<a href=${link_deposit} target=_blank>deposit</a> хуудас руу орно уу.,</p><p>Хэрэв танд асуулт, тусламж хэрэгтэй байвал энэ имэйлд хариу бичих замаар бидэнтэй холбоо барина уу.</p><p> Хүндэтгэсэн<br> ${api_name} </p></div>", + "title": "Welcome" + }, + "RESET_PASSWORD": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Та нууц үгээ өөрчлөх хүсэлт явуулсан байна.<br />Нууц үгээ өөрчлөхийн тулд доорх линк дээр дарна уу.<br /></p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Нууц үг шинэчлэх</Button></a></div><p>Хэрэв та энэ хүсэлтийг санамсаргүйгээр хийсэн бол ямар ч үйлдэл хийх шаардлагагүй; таны бүртгэлд ямар нэг өөрчлөлт орохгүй болно.</p><p>Request initiated from: ${ip}</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Нууц үг өөрчлөх хүсэлт" + }, + "ACCOUNT_VERIFY": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Баяр хүргэе. Таны бүртгэл ажилттай баталгаажлаа.</p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Арилжаа хийх</Button></a></div><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Бүртгэл баталгаажлаа" + }, + "ACCOUNT_UPGRADE": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Баяр хүргэе. Таны бүртгэлийн ${tier} түвшин болж дээшиллээ. Таны шимтгэл багасч, зарлага гаргах хэмжээ ихэслээ.</p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Арилжаанд оролцох</Button></a></div><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Бүртгэлийн түвшин дээшиллээ" + }, + "DEPOSIT_CANCEL": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Бид таны ${date} өдөр ${amount} дүнтэй ${currency} -р хийсэн орлогын гүйлгээг батлах боломжгүй байна. Тиймээс гүйлгээс систем автоматаар цуцалсан болно.</p><p>Танд асуух зүйл байвал, энэ и-мэйлд хариу бичнэ үү</p><p>Гүйлгээний №: ${txid}<br />Дүн: ${amount}<br />Төлөв: Татгалзсан</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "${currency} орлого цуцлагдлаа" + }, + "DEPOSIT_PENDING": { + "html": "<div><div><p> Эрхэм хүндэт ${name} </p><p> Таны ${amount} ${currency} орлого, таны ${api_name} хэтэвчинд орохоор хүлээгдэж байна. Гүйлгээ баталгаажиж таны хэтэвчинд ортол түр хүлээнэ үү.</p><p>Дүн: ${amount} ${currency}<br />Төлөв: ${status}<br />Хаяг: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Сүлжээ: ${network}</span><br />Шимтгэл: ${fee} ${fee_coin}<br /><ul>${explorers}</ul></div><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "${currency} орлого хүлээгдэж байна" + }, + "DEPOSIT_COMPLETED": { + "html": "<div><div><p> Эрхэм хүндэт ${name} </p><p> Таны ${amount} ${currency} орлого амжилттай хийгдэж, таны ${currency} хэтэвчинд орлоо.</p><p>Дүн: ${amount} ${currency}<br />Төлөв: ${status}<br />Хаяг: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Сүлжээ: ${network}</span><br />Шимтгэл: ${fee} ${fee_coin}<br /><ul>${explorers}</ul></div><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "${currency} Орлого амжилттай" + }, + "WITHDRAWAL_PENDING": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Та ${amount} ${currency} зарлагын хүсэлт илгээсэн байна. Таны зарлагын хүсэлт тун удахгүй шийдэгдэх болно.</p><p>Дүн: ${amount} ${currency}<br />Шимтгэл: ${fee} ${fee_coin}<br />Төлөв: ${status}<br />Хаяг: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Сүлжээ: ${network}</span><br /><ul>${explorers}</ul><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "${currency} зарлага хүлээгдэж байна" + }, + "WITHDRAWAL_COMPLETED": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Таны ${amount} ${currency} зарлагын хүсэлт амжилттай биеллээ.</p><p>Дүн: ${amount} ${currency}<br />Шимтгэл: ${fee} ${fee_coin}<br />Төлөв: ${status}<br />Хаяг: ${address}<br />Transaction ID: ${transaction_id}<br /><span id=\"network\">Сүлжээ: ${network}</span><br /><ul>${explorers}</ul><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "${currency} зарлага амжилттай" + }, + "WITHDRAWAL_CANCEL": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Бид таны ${date} өдөр хийсэн ${amount} ${currency} хийсэн зарлагын хүсэлтийг баталгаажуулах боломжгүй байна. Таны зарлага цуцлагдаж, зарлагын дүн ${api_name} хэтэвч рүү буцаж орсон болно.</p><p>Танд тусламж хэрэгтэй байвал бидэнд и-мэйл илгээнэ үү</p><p>Гүйлгээ №: ${txid}<br />Дүн: ${amount}<br />Төлөв: Татгалзсан</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "${currency} зарлага татгалзлаа" + }, + "WITHDRAWAL_REQUEST": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Та ${amount} ${currency} -г ${address} хаяг руу зарлагадахаар хүсэлт илгээсэн байна<br /><br />Дүн: ${amount} ${currency}<br />Шимтгэл: ${fee} ${fee_coin}<br />Хаяг: ${address}<br /><span id=\"network\">Сүлжээ: ${network}</span><br /><br />Энэ зарлагыг баталгаажуулахын тулд доорх линк дээр дарна уу.<br /></p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Баталгаажуулах</Button></a></div><p>Хэрэв та энэ хүсэлтийг санамсаргүйгээр хийсэн бол ямар ч үйлдэл хийх шаардлагагүй; таны бүртгэлд ямар нэг өөрчлөлт орохгүй болно.</p><p>Хүсэлт гаргасан хаяг: ${ip}</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "${currency} Зарлагын хүсэлт" + }, + "USER_VERIFICATION": { + "html": "<div><h3>Баталгаажуулалт шаардлагатай байна</h3><div> \"${email}\" хаягтай хэрэглэгч бичиг баримтаа баталгаажуулахаар илгээсэн байна. Бичиг баримтыг нь шалгана уу.</div></div>", + "title": "Хэрэглэгч баталгаажуулалт" + }, + "SUSPICIOUS_DEPOSIT": { + "html": "<div><h3>Сэжигтэй гүйлгээ</h3><div> ${email} и-мэйл хаягтай хэрэглэгч ${currency} сэжигтэй орлого хүлээн авлаа.<br />Transaction ID: ${txid}<h4>Transaction data:</h4><div>${data}</div></div></div>", + "title": "Сэжигтэй гүйлгээ" + }, + "INVALID_ADDRESS": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Таны ${amount} ${currency} зарлага буруу хаяг руу илгээгдсэн байсан тул цуцлагдлаа.</p><p>Хаяг: ${address}</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Зарлагын хаяг буруу байна" + }, + "USER_DEACTIVATED": { + "html": "<div><p>Таны ${email} идэвхигүй боллоо. Таны и-мэйл дахин хүсэлт гаргах хүртэл ашиглах боломжгүй болно.</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "${type} аккаунт" + }, + "USER_ACTIVATED": { + "html": "<div><p>Таны ${email} баталгаажлаа. Та нэвтэрч орон бүртгэлээ үргэлжлүүлнэ үү.</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "${type} аккаунт" + }, + "DISCOUNT_UPDATE": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Таны хөнгөлөлтийн дүн ${rate}% боллоо. Энэ хөнгөлөлт нь таны захиалгын хураамжид хамаарна.</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Хөнгөлөлтийн дүн өөрчлөгдлөө" + }, + "BANK_VERIFIED": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Таны банкны дансыг баталгаажууллаа. Та одоо орлого, зарлага гаргах боломжтой боллоо</p><div><strong>Баталгаажсан банкны данс:</strong>${list_detail_bank_account}</div><p><a href=\"${link_verification}\">Баталгаажсан банкны дансаа харахын тулд баталгаажуулалтын хэсэг рүү очно уу</a></p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Банк баталгаажлаа" + }, + "USER_ID_VERIFICATION_REJECT": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Таны бичиг баримтыг шалгаж үзээд баталгаажуулах боломжгүй байна. Та доорх мессежийн дагуу дахин илгээнэ үү:</p><p>Шалтгаан: ${message}</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Үнэмлэх баталгаажуулалт амжилтгүй" + }, + "USER_BANK_VERIFICATION_REJECT": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Таны банкны данс бүртгүүлэх хүсэлтийг шалгаж үзээд баталгаажуулах боломжгүй байна. Шалгааныг дор бичив:</p><p>Шалтгаан: ${message}</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Банкны мэдээлэл баталгаажуулалт амжилтгүй" + }, + "PASSWORD_CHANGED": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Энэ имэйл таныг саяхан өөрийн акаунтын нууц үгээ өөрчилсөн болохыг баталгаажуулж байна. Цаашид арга хэмжээ авах шаардлагагүй.<br />Хэрэв та энэ өөрчлөлтийг хийгээгүй бол бидэнтэй шууд холбогдоно уу.<br /></p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Нууц үг өөрчлөгдлөө" + }, + "CHANGE_PASSWORD": { + "html": "<div><p> Эрхэм хүндэт ${name} </p><p>Та нууц үг солих хүсэлт гаргасан байна.<br />Нууц үгээ өөрчилсныг баталгаажуулахын тулд доор линк дээр дарна уу.<br /></p><div style=\"padding-top: 10px; margin-bottom: 10px;\"><a href=\"${link}\" target=\"_blank\"><Button style=\"cursor: pointer; background-color: #333333; color: white; border: none; padding: 1rem; text-transform: uppercase; cursor: pointer !important; font-size: 14px; min-width: 11rem;\">Нууц үг өөрчилснийг батлах</Button></a></div><p>Хэрэв энэ хүсэлтийг алдаатай хийсэн бол та энэ и-мэйлийг тоохгүй байж болно. Таны бүртгэлд ямар нэг өөрчлөлт орохгүй</p><p>Request initiated from: ${ip}</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Нууц үг өөрчлөх баталгаажуулалт" + }, + "DOC_REJECTED": { + "html": "<div><p>Эрхэм хүндэт ${email} </p><p>Харамсалтай нь таны илгээсэн KYC баримт бичгүүдийг баталгаажуулах боломжгүй байна.<br>Таны баримт бичгүүдээс татгалзсан шалтгааныг доор жагсаав.<br></p><div><ul>${doc_information}</ul></div><p>Хэрэв та эдгээр шалтгааныг буруу гэж үзвэл энэ имэйлд хариу илгээнэ үү.<br>Эсвэл, бичиг баримтаа шаардлагын дагуу дахин илгээнэ үү.</p><p> Хүндэтгэсэн<br> ${api_name} team </p</div>", + "title": "KYC бичиг баримт татаглзлаа" + }, + "DOC_VERIFIED": { + "html": "<div><p>Эрхэм хүндэт ${email} </p><p>Таны бичиг баримт баталгаажсан байна.<br>Та одоо баталгаажуулалт шаардсан бүх хэсэгт хандах боломжтой.</p><ul>${doc_information}</ul><p>Та баталгаажуулсан бичиг баримтаа шалгахыг хүсвэл <a href=\"${link}\" target=\"_blank\">Баталгаажуулах хуудас</a> руу орно уу.</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "KYC бичиг баримт баталгаажлаа" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Эрхэм хүндэт ${name} </p></p><p>Та өөрийн бүртгэлийн аюулгүй байдалтай холбоотой хүсэлт гаргасан байна. Үйлдлийг баталгаажуулахын тулд та доорх кодыг оруулаарай.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>Хэрэв та энэ хүсэлтийг гаргаагүй бол энэ тухай нэн даруй мэдэгдэж, нэвтрэх мэдээллээ аль болох хурдан солино уу.</p><p> Хүндэтгэсэн<br> ${api_name} team </p></div>", + "title": "Аюулгүй байдлын баталгаажуулалт" + } + } +} \ No newline at end of file diff --git a/server/mail/strings/pt.json b/server/mail/strings/pt.json index dcd7510e5d..cf5975dd6e 100644 --- a/server/mail/strings/pt.json +++ b/server/mail/strings/pt.json @@ -95,6 +95,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p> Dear ${name} </p><p>Sua solicitação de saque de ${amount} ${currency} foi processada e transferida para o endereço ${address}.</p><p>Quantia: ${amount} ${currency}<br />Taxa: ${fee} ${currency}<br />Status: ${status}<br />Endereço: ${address}<br />ID da transação: ${transaction_id}<br /><span id='network'>Rede: ${network}</span><br /><ul>${explorers}</ul><p> Saudações<br> ${api_name} equipe </p></div>", "title": "${currency} Saque concluído" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } } } \ No newline at end of file diff --git a/server/mail/strings/tr.json b/server/mail/strings/tr.json index f873aa7cd4..86f5af4026 100644 --- a/server/mail/strings/tr.json +++ b/server/mail/strings/tr.json @@ -107,6 +107,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p> Sayın ${name} </p><p> ${amount} ${currency} için çekiminiz tamamlanmıştır.</p><p>Miktar: ${amount} ${currency}<br />Ücret: ${fee} ${fee_coin}<br />Durum: ${status}<br />Adres: ${address}<br />İşlem ID: ${transaction_id}<br /><span id=\"network\">Ağ: ${network}</span><br /><ul>${explorers}</ul><p> İyi dileklerimizle<br> ${api_name} takımı </p></div>", "title": "${currency} Çekimi Tamamlandı" - } + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" + } } } diff --git a/server/mail/strings/vi.json b/server/mail/strings/vi.json index 5a35b2f9fa..86746cbe90 100644 --- a/server/mail/strings/vi.json +++ b/server/mail/strings/vi.json @@ -95,6 +95,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p> ${name} thân mến </p><p>Yêu cầu rút ${amount} ${currency} của quý khách đã được thực hiện và số tiền tương ứng đã được chuyển thành công tới địa chỉ ${address}.</p><p>Số lượng: ${amount} ${currency}<br />Phí: ${fee} ${currency}<br />Trạng thái: ${status}<br />Địa chỉ: ${address}<br />ID giao dịch: ${transaction_id}<br /><span id='network'>Mạng: ${network}</span><br /><ul>${explorers}</ul><p> Cảm ơn quý khách vì đã sử dụng dịch vụ của chúng tôi. <br> Đội ngũ ${api_name} </p></div>", "title": "${currency} Rút tiền hoàn thành" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } } } \ No newline at end of file diff --git a/server/mail/strings/zh.json b/server/mail/strings/zh.json index 446c1a3684..beb23d7ce8 100644 --- a/server/mail/strings/zh.json +++ b/server/mail/strings/zh.json @@ -91,6 +91,18 @@ "WITHDRAWAL_COMPLETED": { "html": "<div><p> ${name} </p><p>你的${amount} ${currency}已向该地址${address}提款完毕。</p><p>金额: ${amount} ${currency}<br />手续费: ${fee} ${currency}<br />状态: ${status}<br />地址: ${address}<br />交易 ID: ${transaction_id}<br /><span id='network'>网络: ${network}</span><br /><ul>${explorers}</ul><p> 感谢你的使用<br> ${api_name} 团队 </p></div>", "title": "${currency} 提款完成" + }, + "DOC_REJECTED": { + "html": "<div><p>Dear ${email} </p><p>Unfortunately, your uploaded KYC documents have been rejected.<br>The reasons for your documents being rejected are listed below.<br></p><div><ul>${doc_information}</ul></div><p>If you feel these reasons are invalid, please feel free to reply to this email.<br>Otherwise, please reupload valid documents in order to verify your identity.</p><p> Regards<br> ${api_name} team </p</div>", + "title": "KYC Documents Rejected" + }, + "DOC_VERIFIED": { + "html": "<div><p>Dear ${email} </p><p>Your uploaded KYC documents have been approved.<br>You now have access to all exchange features that require identity verification.</p><ul>${doc_information}</ul><p>To view your approved documents, visit your <a href=\"${link}\" target=\"_blank\">Verification page</a></p><p> Regards<br> ${api_name} team </p></div>", + "title": "KYC Documents Approved" + }, + "CONFIRM_EMAIL": { + "html": "<div><p><p>Dear ${name} </p></p><p>You have made sensitive request related to your accounts security. To verify the operation you would require to use to code below to authorize this operation.<br /><p style=\"font-size: 1.2rem; text-align: center;\">${code}</p>If you did not make this request, report this immediately and proceed to change your credentials as soon as possible.</p><p> Regards<br> ${api_name} team </p></div>", + "title": "Security Verification" } } } \ No newline at end of file diff --git a/server/package.json b/server/package.json index 5ced19e23f..66ca3f3647 100644 --- a/server/package.json +++ b/server/package.json @@ -1,5 +1,5 @@ { - "version": "2.4.1", + "version": "2.4.4", "private": false, "description": "HollaEx Kit", "keywords": [ @@ -10,15 +10,12 @@ "cryptocurrency", "hollaex" ], - "author": "bitHolla Inc.", - "license": "bitHolla Inc.", "main": "app.js", "dependencies": { - "JSONStream": "1.3.5", "bcryptjs": "2.4.3", "bluebird": "3.5.3", "body-parser": "1.19.0", - "ccxt": "^1.77.49", + "ccxt": "1.77.49", "chai": "4.2.0", "cors": "2.8.5", "elastic-apm-node": "3.15.0", @@ -34,9 +31,11 @@ "hollaex-network-lib": "file:utils/hollaex-network-lib", "hollaex-tools-lib": "file:utils/hollaex-tools-lib", "http": "0.0.0", + "http-proxy-middleware": "2.0.6", "install": "0.10.4", "ip-range-check": "0.2.0", "json2csv": "4.5.4", + "JSONStream": "1.3.5", "jsonwebtoken": "7.4.3", "latest-version": "5.1.0", "lodash": "4.17.20", @@ -48,7 +47,7 @@ "multicoin-address-validator": "0.5.5", "node-cron": "2.0.3", "nodemailer": "6.4.6", - "npm": "5.7.1", + "npm": "8.19.1", "npm-programmatic": "0.0.12", "otp": "0.1.3", "pg": "6.4.2", @@ -89,7 +88,8 @@ "undomigrate": "sequelize db:migrate:undo:all", "migrate": "sequelize db:migrate", "start": "node app.js", - "test": "NODE_ENV=test nyc --reporter=html --reporter=text mocha --recursive --timeout 5000" + "test": "NODE_ENV=test nyc --reporter=html --reporter=text mocha --recursive --timeout 5000", + "dev:plugin": "docker exec -it server_hollaex-kit-server_1 node plugins/dev.js" }, "nyc": { "exclude": [ diff --git a/server/plugins/controllers.js b/server/plugins/controllers.js index c4c5fd572d..ff671204b9 100644 --- a/server/plugins/controllers.js +++ b/server/plugins/controllers.js @@ -38,7 +38,7 @@ const getPlugins = async (req, res) => { 'postscript' ] }, - order: [[ 'id', 'asc' ]] + order: [['id', 'asc']] }; if (name) { @@ -59,7 +59,7 @@ const getPlugins = async (req, res) => { count: data.count, data: data.rows.map((plugin) => { plugin.enabled_admin_view = !!plugin.admin_view; - return lodash.omit(plugin, [ 'admin_view' ]); + return lodash.omit(plugin, ['admin_view']); }) }; @@ -225,7 +225,7 @@ const postPlugin = async (req, res) => { throw new Error(`Error while minifying script: ${minifiedScript.error.message}`); } - pluginConfig[field] = minifiedScript.code; + pluginConfig[field] = minifiedScript.code; } break; case 'description': @@ -411,7 +411,7 @@ const putPlugin = async (req, res) => { if ( lodash.isPlainObject(plugin[field]) && plugin[field][key].overwrite === false - && (!value[key] || value[key].overwrite === false) + && (!value[key] || value[key].overwrite === false) ) { value[key] = plugin[field][key]; } @@ -787,4 +787,4 @@ module.exports = { getPluginScript, disablePlugin, enablePlugin -}; +}; \ No newline at end of file diff --git a/server/plugins/dev.js b/server/plugins/dev.js index b2b0655854..38a966f22f 100644 --- a/server/plugins/dev.js +++ b/server/plugins/dev.js @@ -1,152 +1,120 @@ - -/** - * Add your mock publicMeta and meta values in the object below - * In production, these values are stored in the configuration JSON file - - * Example mock configurations are included below -**/ - -this.configValues = { - // // ------------ CONFIG VALUES EXAMPLE START ------------ - - // publicMeta: { - // public_value: { - // type: 'string', - // description: 'Public meta value', - // required: false, - // value: 'i am public' - // } - // }, - // meta: { - // private_value: { - // type: 'string', - // description: 'Private meta value', - // required: true, - // value: 'i am private' - // } - // } - - // // ------------ CONFIG VALUES EXAMPLE END ------------ -}; - -const pluginScript = () => { - /** - * Add the plugin script here - * The script within this function should be in the script.js file for a plugin - - * An example of a plugin script is included below - **/ - - // // ------------ PLUGIN EXAMPLE START ------------ - - // const { app, loggerPlugin, toolsLib } = this.pluginLibraries; // this.pluginLibraries holds app, loggerPlugin, and toolsLib in the plugin script - // const { publicMeta, meta } = this.configValues; // this.configValues holds publicMeta and meta in the plugin script - - // const lodash = require('lodash'); - // const moment = require('moment'); - // const { public_value: { value: PUBLIC_VALUE } } = publicMeta; - // const { private_value: { value: PRIVATE_VALUE } } = meta; - - // // All endpoints for a plugin should follow the format: '/plugins/<PLUGIN_NAME>/...'. For this example, the plugin name is 'test' - // const HEALTH_ENDPOINT = '/plugins/test/health'; - // const CONFIG_VALUES_ENDPOINT = '/plugins/test/config-values'; - - // // We recommend creating an init function that checks for all required configuration values and all other requirements for this plugin to run - // const init = async () => { - // loggerPlugin.verbose( - // 'DEV PLUGIN initializing...' - // ); - - // if (!lodash.isString(PRIVATE_VALUE)) { - // throw new Error('Private Value must be configured for this plugin to run'); - // } - - // loggerPlugin.verbose( - // 'DEV PLUGIN initialized' - // ); - // }; - - // init() - // .then(() => { - // app.get(HEALTH_ENDPOINT, async (req, res) => { - // loggerPlugin.info( - // req.uuid, - // HEALTH_ENDPOINT - // ); - - // return res.json({ - // status: 'running', - // current_time: moment().toISOString(), - // exchange_name: toolsLib.getKitConfig().info.name - // }); - // }); - - // app.get(CONFIG_VALUES_ENDPOINT, async (req, res) => { - // loggerPlugin.info( - // req.uuid, - // CONFIG_VALUES_ENDPOINT - // ); - - // return res.json({ - // public_value: PUBLIC_VALUE, - // private_value: PRIVATE_VALUE - // }); - // }); - // }) - // .catch((err) => { - // // It's important to catch all errors in a script. If a thrown error is not caught, the plugin process will exit and continuously try to restart - // loggerPlugin.error( - // 'DEV PLUGIN initialization error', - // err.message - // ); - // }); - - // // ------------ PLUGIN EXAMPLE END ------------ -}; - - - - - - - - -// BELOW IS THE SCRIPT FOR RUNNING THE PLUGIN DEV ENVIRONMENT THAT IS NOT NECESSARY IN THE PLUGIN ITSELF +'use strict'; const { checkStatus } = require('../init'); +const express = require('express'); +const morgan = require('morgan'); +const PORT = process.env.PLUGIN_PORT || 10012; +const { logEntryRequest, stream, loggerPlugin } = require('../config/logger'); +const morganType = process.env.NODE_ENV === 'development' ? 'dev' : 'combined'; +const { domainMiddleware, helmetMiddleware } = require('../config/middleware'); +const cors = require('cors'); +const fs = require('fs'); +const path = require('path'); +const toolsLib = require('hollaex-tools-lib'); +const expressValidator = require('express-validator'); +const lodash = require('lodash'); +const npm = require('npm-programmatic'); +const _eval = require('eval'); +const rp = require('request-promise'); + +const getPluginConfig = () => { + return rp('http://host.docker.internal:8080/config.json'); +}; -const initializeDevPlugin = async () => { - await checkStatus(); - - const morgan = require('morgan'); - const { logEntryRequest, stream, loggerPlugin } = require('../config/logger'); - const { domainMiddleware, helmetMiddleware } = require('../config/middleware'); - const morganType = process.env.NODE_ENV === 'development' ? 'dev' : 'combined'; - const PORT = 10012; - const cors = require('cors'); - const toolsLib = require('hollaex-tools-lib'); - const express = require('express'); +let config, script; - const app = express(); - app.use(morgan(morganType, { stream })); - app.listen(PORT); - app.use(cors()); - app.use(express.urlencoded({ extended: true })); - app.use(express.json()); - app.use(logEntryRequest); - app.use(domainMiddleware); - helmetMiddleware(app); +const installLibrary = async (library) => { + const [name, version = 'latest'] = library.split('@'); + await npm.install([`${name}@${version}`], { + cwd: path.resolve(__dirname, '../'), + save: true, + output: true + }); - const pluginLibraries = { - app, - loggerPlugin, - toolsLib - }; + loggerPlugin.verbose( + 'plugins/index/installLibrary', + `${name} version ${version} installed` + ); - this.pluginLibraries = pluginLibraries; + const lib = require(name); + return lib; + }; -(async () => { - await initializeDevPlugin(); - pluginScript(); -})(); \ No newline at end of file +getPluginConfig() + .then((data) => { + data = JSON.parse(data); + config = data; + script = data.script; + return checkStatus(); + }) + .then(async () => { + const app = express(); + + app.use(morgan(morganType, { stream })); + app.listen(PORT); + app.use(cors()); + app.use(express.urlencoded({ extended: true })); + app.use(express.json()); + app.use(logEntryRequest); + app.use(domainMiddleware); + helmetMiddleware(app); + + const context = { + exports: exports, + require: require, + module: module, + toolsLib, + app, + loggerPlugin, + expressValidator, + pluginLibraries: { + app, + toolsLib, + loggerPlugin + }, + publicMeta: config.public_meta, + meta: config.meta, + configValues: { + publicMeta: config.public_meta, + meta: config.meta + }, + installedLibraries: {} + }; + + if (config.prescript && lodash.isArray(config.prescript.install) && !lodash.isEmpty(config.prescript.install)) { + loggerPlugin.verbose( + 'plugins/index/initialization', + `Installing packages for plugin ${config.name}` + ); + + for (const library of config.prescript.install) { + context.installedLibraries[library] = await installLibrary(library); + } + + loggerPlugin.verbose( + 'plugins/index/initialization', + `Plugin ${config.name} packages installed` + ); + } + + _eval(script, 'dev', context, true); + }) + .catch((err) => { + let message = 'Plugin Initialization failed'; + + if (err.message) { + message = err.message; + } + + if (err.statusCode && err.statusCode === 402) { + message = err.error.message; + } + + loggerPlugin.error( + '/plugins/index/initialization err', + message + ); + + setTimeout(() => { process.exit(1); }, 5000); + }); \ No newline at end of file diff --git a/server/tools/dbs/setEmail.js b/server/tools/dbs/setEmail.js new file mode 100644 index 0000000000..2b3890c2b6 --- /dev/null +++ b/server/tools/dbs/setEmail.js @@ -0,0 +1,44 @@ +const { Status } = require('../../db/models'); +const { CONFIGURATION_CHANNEL } = require('../../constants'); +const { + SMTP_SERVER, + SMTP_PORT, + SMTP_USER, + SMTP_PASSWORD, + SMTP_SENDER +} = process.env; +const { publisher } = require('../../db/pubsub'); + +Status.findOne({}) + .then((status) => { + const secrets = { + ...status.secrets, + smtp: { + server: SMTP_SERVER, + port: SMTP_PORT, + user: SMTP_USER, + password: SMTP_PASSWORD + }, + emails: { + ...status.secrets.emails, + sender: SMTP_SENDER + } + }; + + return status.update({ secrets }, { fields: ['secrets'], returning: true }); + }) + .then((data) => { + publisher.publish( + CONFIGURATION_CHANNEL, + JSON.stringify({ + type: 'update', + data: { secrets: data.secrets } + }) + ); + console.log('Emails values are reset'); + process.exit(0); + }) + .catch((err) => { + console.error('Error', err); + process.exit(1); + }); \ No newline at end of file diff --git a/server/utils/hollaex-tools-lib/tools/order.js b/server/utils/hollaex-tools-lib/tools/order.js index 170bc7020e..c51f9870a2 100644 --- a/server/utils/hollaex-tools-lib/tools/order.js +++ b/server/utils/hollaex-tools-lib/tools/order.js @@ -283,7 +283,7 @@ const cancelAllUserOrdersByKitId = async (userKitId, symbol, opts = { } else if (!idDictionary[userKitId]) { throw new Error(USER_NOT_REGISTERED_ON_NETWORK); } - return getNodeLib().cancelAllOrders(idDictionary[userKitId], {symbol, ...opts}); + return getNodeLib().cancelAllOrders(idDictionary[userKitId], { symbol, ...opts }); }; const cancelAllUserOrdersByEmail = (email, symbol, opts = { @@ -339,22 +339,28 @@ const getAllTradesNetwork = (symbol, limit, page, orderBy, order, startDate, end .then(async (trades) => { if (trades.data.length > 0) { const networkIds = []; - for (const trade of trades.data) { - networkIds.push(trade.maker_id, trade.taker_id); + if (trade.maker_id) { + networkIds.push(trade.maker_id); + } + if (trade.taker_id) { + networkIds.push(trade.taker_id); + } } const idDictionary = await mapNetworkIdToKitId(networkIds); for (let trade of trades.data) { - const maker_kit_id = idDictionary[trade.maker_id] || 0; - const taker_kit_id = idDictionary[trade.taker_id] || 0; - - trade.maker_network_id = trade.maker_id; - trade.maker_id = maker_kit_id; - - trade.taker_network_id = trade.taker_id; - trade.taker_id = taker_kit_id; + if (trade.maker_id) { + const maker_kit_id = idDictionary[trade.maker_id] || 0; + trade.maker_network_id = trade.maker_id; + trade.maker_id = maker_kit_id; + } + if (trade.taker_id) { + const taker_kit_id = idDictionary[trade.taker_id] || 0; + trade.taker_network_id = trade.taker_id; + trade.taker_id = taker_kit_id; + } } } diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index 528e0843db..10ea913467 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -448,6 +448,7 @@ const getAllUsersAdmin = (opts = { id: null, search: null, pending: null, + pending_type: null, limit: null, page: null, order_by: null, @@ -499,19 +500,30 @@ const getAllUsersAdmin = (opts = { }; } } else if (isBoolean(opts.pending) && opts.pending) { + + let pendingQuery = []; + // users that have a pending id waiting for admin to confirm + const pendingId = { + id_data: { + status: 1 + } + }; + // users that have a pending bank waiting for admin to confirm + const pendingBank = getModel('sequelize').literal('bank_account @> \'[{"status":1}]\''); + + if (opts.pending_type) { + if (opts.pending_type === 'id') { + pendingQuery.push(pendingId); + } else if (opts.pending_type === 'bank') { + pendingQuery.push(pendingBank); + } + } else { + pendingQuery = [pendingId, pendingBank]; + } + query = { where: { - $or: [ - getModel('sequelize').literal('bank_account @> \'[{"status":1}]\''), - { - id_data: { - status: 1 - } - }, - { - activated: false - } - ] + [Op.or]: pendingQuery }, attributes: [ 'id', diff --git a/server/utils/hollaex-tools-lib/tools/wallet.js b/server/utils/hollaex-tools-lib/tools/wallet.js index a250c50b7e..05154dfe09 100644 --- a/server/utils/hollaex-tools-lib/tools/wallet.js +++ b/server/utils/hollaex-tools-lib/tools/wallet.js @@ -195,9 +195,15 @@ async function validateWithdrawal(user, address, amount, currency, network = nul const sendRequestWithdrawalEmail = (user_id, address, amount, currency, opts = { network: null, otpCode: null, + fee: null, + fee_coin: null, + skipValidate: false, // should be used with care if set to true ip: null, domain: null }) => { + let fee = opts.fee; + let fee_coin = opts.fee_coin; + return verifyOtpBeforeAction(user_id, opts.otpCode) .then((validOtp) => { if (!validOtp) { @@ -206,7 +212,12 @@ const sendRequestWithdrawalEmail = (user_id, address, amount, currency, opts = { return getUserByKitId(user_id); }) .then(async (user) => { - const { fee, fee_coin } = await validateWithdrawal(user, address, amount, currency, opts.network); + if (!opts.skipValidate) { + const withdrawal = await validateWithdrawal(user, address, amount, currency, opts.network); + fee = withdrawal.fee; + fee_coin = withdrawal.fee_coin; + } + return withdrawalRequestEmail( user, @@ -230,7 +241,7 @@ const sendRequestWithdrawalEmail = (user_id, address, amount, currency, opts = { const withdrawalRequestEmail = (user, data, domain, ip) => { data.timestamp = Date.now(); let stringData = JSON.stringify(data); - const token = crypto.randomBytes(60).toString('hex'); + const token = data.transaction_id || crypto.randomBytes(60).toString('hex'); return client.hsetAsync(WITHDRAWALS_REQUEST_KEY, token, stringData) .then(() => { diff --git a/test/Cypress/cypress/integration/Gherkin/pre/pre.js b/test/Cypress/cypress/integration/Gherkin/pre/pre.js index b3ba2d222e..b17df16b67 100644 --- a/test/Cypress/cypress/integration/Gherkin/pre/pre.js +++ b/test/Cypress/cypress/integration/Gherkin/pre/pre.js @@ -69,7 +69,7 @@ And ('Show pop up when order has partially filled is off',()=>{ And ('All Audio cues is off',()=>{ cy.get('.tab_controller-tabs > :nth-child(2) > div').as('Interface').click() - cy.contains('Play Audio Cue').click() + cy.contains('Audio Cues').click() cy.get('.toggle-wrapper-all > :nth-child(1) > :nth-child(1) > .field-content > .field-children > .justify-content-between > .toggle_button-wrapper > .toggle-content > .toggle-action_button') .invoke('text') .then(text => { @@ -124,8 +124,8 @@ And ('chatbox is off',()=>{ And ('XHTT spread in market is less than 0.001',()=>{ cy.get('.top-box-menu').click() cy.contains('Pro trade').click() - cy.contains('XHTT/USDT').click() - cy.get('.app_bar-currency-txt').should('have.text', 'XHTT/USDT:') + cy.contains('XHT/USDT').click() + cy.get('.app_bar-currency-txt').should('have.text', 'XHT/USDT:') cy.get('.trade_orderbook-asks > :nth-child(1) > .d-flex > .trade_orderbook-cell-price') .should('be.visible') cy.log('check lowest aks exist and click on the price will send the price') diff --git a/version b/version index 58073ef8d7..ab6d27898c 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.4.1 \ No newline at end of file +2.4.4 \ No newline at end of file diff --git a/web/package-lock.json b/web/package-lock.json index 2d25043409..03152894bb 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,6 +1,6 @@ { "name": "hollaex-kit", - "version": "2.4.0", + "version": "2.4.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/web/package.json b/web/package.json index 4dca3cf51c..8ff54d7b66 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "hollaex-kit", - "version": "2.4.1", + "version": "2.4.4", "private": true, "dependencies": { "@ant-design/compatible": "1.0.5", diff --git a/web/public/assets/icons/coin-graphic-not-detected.svg b/web/public/assets/icons/coin-graphic-not-detected.svg new file mode 100644 index 0000000000..52c6f6e251 --- /dev/null +++ b/web/public/assets/icons/coin-graphic-not-detected.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 26.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 125 125" style="enable-background:new 0 0 100 100;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#8C8C8C;} + .st1{fill:#FFFFFF;} +</style> +<circle class="st0" cx="50" cy="50" r="50"/> +<g> + <path class="st1" d="M45.5,60l-0.1-1.8c-0.4-3.7,0.8-7.7,4.2-11.9c3.1-3.6,4.8-6.3,4.8-9.4c0-3.5-2.2-5.8-6.5-5.9 + c-2.5,0-5.2,0.8-6.9,2.1l-1.6-4.3c2.3-1.6,6.2-2.7,9.8-2.7c7.9,0,11.4,4.9,11.4,10.1c0,4.7-2.6,8-5.9,11.9c-3,3.6-4.1,6.6-3.9,10.1 + l0.1,1.8H45.5z M44,69.6c0-2.5,1.7-4.3,4.1-4.3c2.4,0,4,1.8,4,4.3c0,2.4-1.6,4.3-4.1,4.3C45.7,73.9,44,72,44,69.6z"/> +</g> +</svg> diff --git a/web/public/assets/icons/metamask-fox-stake-not-detected.svg b/web/public/assets/icons/metamask-fox-stake-not-detected.svg new file mode 100644 index 0000000000..c37e3b5f92 --- /dev/null +++ b/web/public/assets/icons/metamask-fox-stake-not-detected.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="65.251" height="64.134" viewBox="0 0 65.251 64.134"> + <path id="Path_11" data-name="Path 11" d="M146.077,121.228,113.45,96.75l8.192-12.283V57.094l17.839,22.3h13.2l17.827-22.3V84.467L178.7,96.75ZM118.6,95.87l27.476,20.616L173.562,95.87l-6.833-10.255V67.906L154.5,83.174H137.657L125.434,67.906v17.71Z" transform="translate(-113.45 -57.094)" fill="gray"/> +</svg> diff --git a/web/public/assets/icons/refresh-icon.svg b/web/public/assets/icons/refresh-icon.svg new file mode 100644 index 0000000000..1502e06685 --- /dev/null +++ b/web/public/assets/icons/refresh-icon.svg @@ -0,0 +1 @@ +<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" width="30px" height="30px"><path d="M 15 3 C 12.031398 3 9.3028202 4.0834384 7.2070312 5.875 A 1.0001 1.0001 0 1 0 8.5058594 7.3945312 C 10.25407 5.9000929 12.516602 5 15 5 C 20.19656 5 24.450989 8.9379267 24.951172 14 L 22 14 L 26 20 L 30 14 L 26.949219 14 C 26.437925 7.8516588 21.277839 3 15 3 z M 4 10 L 0 16 L 3.0507812 16 C 3.562075 22.148341 8.7221607 27 15 27 C 17.968602 27 20.69718 25.916562 22.792969 24.125 A 1.0001 1.0001 0 1 0 21.494141 22.605469 C 19.74593 24.099907 17.483398 25 15 25 C 9.80344 25 5.5490109 21.062074 5.0488281 16 L 8 16 L 4 10 z"/></svg> \ No newline at end of file diff --git a/web/public/assets/images/all-apps.svg b/web/public/assets/images/all-apps.svg new file mode 100644 index 0000000000..7626228965 --- /dev/null +++ b/web/public/assets/images/all-apps.svg @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 26.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.2" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" + x="0px" y="0px" viewBox="0 0 26.3 26.3" overflow="visible" xml:space="preserve"> +<g class="all-apps" id="Group_5258" transform="translate(-569.286 -408.426)"> + <path id="Path_4762" d="M575.6,425h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C576.1,424.8,575.9,425,575.6,425z"/> + <path id="Path_4762-2" d="M575.6,434.7h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C576.1,434.5,575.9,434.7,575.6,434.7z"/> + <path id="Path_4762-3" d="M585.3,415.3h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C585.8,415.1,585.6,415.3,585.3,415.3z"/> + <path id="Path_4762-4" d="M595.1,415.3h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C595.5,415.1,595.3,415.3,595.1,415.3z"/> + <path id="Path_4762-5" d="M585.3,425h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C585.8,424.8,585.6,425,585.3,425z"/> + <path id="Path_4762-6" d="M585.3,434.7h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C585.8,434.5,585.6,434.7,585.3,434.7z"/> + <path id="Path_4762-7" d="M595.1,425h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C595.5,424.8,595.3,425,595.1,425z"/> + <path id="Path_4762-8" d="M595.1,434.7h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C595.5,434.5,595.3,434.7,595.1,434.7z"/> + <path id="Path_4762-9" d="M575.6,415.3h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C576.1,415.1,575.9,415.3,575.6,415.3z"/> +</g> +</svg> diff --git a/web/public/assets/images/apps.svg b/web/public/assets/images/apps.svg new file mode 100644 index 0000000000..ea2feaba05 --- /dev/null +++ b/web/public/assets/images/apps.svg @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 26.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.2" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" + x="0px" y="0px" viewBox="0 0 39.3 39.4" overflow="visible" xml:space="preserve"> +<g class="apps" id="Group_5256" transform="translate(8676.22 -1331)"> + <g id="Group_5253" transform="translate(-8676.22 1331)"> + <path id="Path_4762" d="M16,17.2H1.2C0.6,17.2,0,16.7,0,16V1.2C0,0.6,0.6,0,1.2,0H16c0.7,0,1.2,0.6,1.2,1.2l0,0V16 + C17.2,16.7,16.6,17.2,16,17.2z"/> + <path id="Path_4762-2" d="M16,39.4H1.2c-0.7,0-1.2-0.6-1.2-1.2V23.4c0-0.7,0.5-1.2,1.2-1.2H16 + c0.7,0,1.2,0.6,1.2,1.2l0,0v14.8C17.2,38.8,16.6,39.4,16,39.4z"/> + <path id="Path_4762-3" d="M38.1,17.2H23.4c-0.7,0-1.2-0.6-1.2-1.2V1.2c0-0.7,0.5-1.2,1.2-1.2h14.7 + c0.7,0,1.2,0.6,1.2,1.2l0,0V16C39.3,16.7,38.8,17.2,38.1,17.2z"/> + <path id="Path_4762-4" d="M38.1,39.4H23.4c-0.7,0-1.2-0.6-1.2-1.2V23.4c0-0.7,0.5-1.2,1.2-1.2h14.7 + c0.7,0,1.2,0.6,1.2,1.2l0,0v14.8C39.3,38.8,38.8,39.4,38.1,39.4z"/> + </g> +</g> +</svg> diff --git a/web/public/assets/images/blue-deposit-icon.svg b/web/public/assets/images/blue-deposit-icon.svg new file mode 100644 index 0000000000..669efbec69 --- /dev/null +++ b/web/public/assets/images/blue-deposit-icon.svg @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 26.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve"> +<style type="text/css"> + .icon-plus-1{fill:#0000FF;} + .st0{fill:#002BFF;} + .st1{fill:#FFFFFF;} +</style> +<circle id="XMLID_134_" class="icon-plus-1" cx="25" cy="25" r="25"/> +<path id="Path_3_00000016764327731827108580000010424901856094027934_" class="st1" d="M14.7,38.7c-0.9,0.9-2.3,0.9-3.2,0 + c-0.4-0.4-0.6-1-0.6-1.6l0-19.8c0-1.3,1-2.3,2.3-2.2s2.3,1,2.2,2.3l0,19.8C15.4,37.7,15.2,38.2,14.7,38.7L14.7,38.7z"/> +<path id="Path_3_00000047778029988004519910000017533062724939776692_" class="st1" d="M11.5,38.6c-0.9-0.9-0.9-2.3,0-3.2 + c0.4-0.4,1-0.6,1.6-0.6l19.8,0c1.3,0,2.3,1,2.2,2.3s-1,2.3-2.3,2.2l-19.8,0C12.5,39.3,11.9,39,11.5,38.6L11.5,38.6z"/> +<path id="Path_3_00000010272100705195573310000003847338887338401679_" class="st1" d="M13.1,39.3c-1.3,0-2.3-1.1-2.2-2.3 + c0-0.6,0.3-1.2,0.7-1.6l23.7-23.8c0.9-0.9,2.3-0.9,3.2,0c0.9,0.9,0.9,2.3,0,3.2L14.7,38.6C14.3,39.1,13.7,39.3,13.1,39.3L13.1,39.3z + "/> +</svg> diff --git a/web/public/assets/images/blue_withrow_icon.svg b/web/public/assets/images/blue_withrow_icon.svg new file mode 100644 index 0000000000..a7171332e5 --- /dev/null +++ b/web/public/assets/images/blue_withrow_icon.svg @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 26.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve"> + <style type="text/css"> + .icon-plus-1{fill:#0000FF;} + .st0{fill:#002BFF;} + .st1{fill:#FFFFFF;} +</style> + <circle id="XMLID_134_" class="icon-plus-1" cx="25" cy="25" r="25" /> + <path id="Path_3_00000016764327731827108580000010424901856094027934_" class="st1" d="M35.3,11.6c0.9-0.9,2.3-0.9,3.2,0 + c0.4,0.4,0.6,1,0.6,1.6l0,19.8c0,1.3-1,2.3-2.3,2.2s-2.3-1-2.2-2.3l0-19.8C34.6,12.6,34.8,12.1,35.3,11.6L35.3,11.6z" /> + <path id="Path_3_00000047778029988004519910000017533062724939776692_" class="st1" d="M38.5,11.7c0.9,0.9,0.9,2.3,0,3.2 + c-0.4,0.4-1,0.6-1.6,0.6l-19.8,0c-1.3,0-2.3-1-2.2-2.3c0-1.3,1-2.3,2.3-2.2l19.8,0C37.5,11,38.1,11.2,38.5,11.7L38.5,11.7z" /> + <path id="Path_3_00000010272100705195573310000003847338887338401679_" class="st1" d="M36.9,11c1.3,0,2.3,1.1,2.2,2.3 + c0,0.6-0.3,1.2-0.7,1.6L14.7,38.7c-0.9,0.9-2.3,0.9-3.2,0c-0.9-0.9-0.9-2.3,0-3.2l23.7-23.7C35.7,11.2,36.3,11,36.9,11L36.9,11z" /> +</svg> \ No newline at end of file diff --git a/web/public/assets/images/clock.svg b/web/public/assets/images/clock.svg new file mode 100644 index 0000000000..ed49f1a34a --- /dev/null +++ b/web/public/assets/images/clock.svg @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 26.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#FFFFFF;} +</style> +<path id="Path_3_00000049195749705309616170000002146436606352155561_" class="st0" d="M23.2,26.8c-0.9-0.9-0.9-2.3,0-3.2 + c0.4-0.4,1-0.7,1.6-0.7l18.5-0.1c1.3,0,2.3,1,2.3,2.3c0,1.3-1,2.3-2.3,2.3l-18.5,0.1C24.2,27.5,23.6,27.2,23.2,26.8L23.2,26.8z"/> +<path id="Path_3_00000141440866148849312550000016656160126446402465_" class="st0" d="M26.3,26.8c-0.9,0.9-2.3,0.9-3.2,0 + c-0.4-0.4-0.7-1-0.7-1.6l-0.2-13.8c0-1.3,1-2.3,2.3-2.3s2.3,1,2.3,2.3L27,25.1C27,25.7,26.7,26.3,26.3,26.8L26.3,26.8z"/> +</svg> diff --git a/web/public/assets/images/earn.svg b/web/public/assets/images/earn.svg new file mode 100644 index 0000000000..2b4bdf18b6 --- /dev/null +++ b/web/public/assets/images/earn.svg @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 26.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#FFFFFF;} + .icon-plus-1{fill:#0000FF;} +</style> +<circle id="XMLID_134_" class="icon-plus-1" cx="25" cy="25" r="25"/> +<g id="Group_1" transform="translate(-1288.505 -307.413)"> + <path id="Path_3" class="st0" d="M1296.1,352.1c-1.3,0-2.3-1-2.3-2.3c0-0.6,0.2-1.2,0.7-1.6l35-35c0.9-0.9,2.3-0.9,3.2,0 + c0.9,0.9,0.9,2.3,0,3.2l-35,35C1297.3,351.9,1296.7,352.1,1296.1,352.1L1296.1,352.1z"/> + <path id="Path_4" class="st0" d="M1301.4,328.7c-4.8,0-8.6-3.9-8.6-8.6c0-4.8,3.9-8.6,8.6-8.6c4.8,0,8.6,3.9,8.6,8.6 + c0,2.3-0.9,4.5-2.5,6.1C1305.9,327.8,1303.7,328.7,1301.4,328.7z M1301.4,316c-2.2,0-4.1,1.8-4.1,4.1c0,2.2,1.8,4.1,4.1,4.1 + c2.2,0,4.1-1.8,4.1-4.1c0-1.1-0.4-2.1-1.2-2.9C1303.5,316.4,1302.5,316,1301.4,316z"/> + <path id="Path_5" class="st0" d="M1325.9,353.2c-2.3,0-4.5-0.9-6.1-2.5l0,0c-3.4-3.4-3.4-8.8,0-12.2c3.4-3.4,8.8-3.4,12.2,0 + c3.4,3.4,3.4,8.8,0,12.2C1330.4,352.3,1328.2,353.2,1325.9,353.2z M1323,347.5c1.6,1.6,4.2,1.6,5.7,0c1.6-1.6,1.6-4.2,0-5.7 + c-1.6-1.6-4.2-1.6-5.7,0c-1.7,1.5-1.9,3.9-0.4,5.6C1322.7,347.4,1322.8,347.5,1323,347.5L1323,347.5z"/> +</g> +</svg> diff --git a/web/public/assets/images/my-apps.svg b/web/public/assets/images/my-apps.svg new file mode 100644 index 0000000000..0546dc9262 --- /dev/null +++ b/web/public/assets/images/my-apps.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 26.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.2" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" + x="0px" y="0px" viewBox="0 0 26.3 26.3" overflow="visible" xml:space="preserve"> +<g class="my-apps" id="Group_5258" transform="translate(-569.286 -408.426)"> + <path id="Path_4762" d="M575.6,425h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C576.1,424.8,575.9,425,575.6,425z"/> + <path id="Path_4762-2" d="M575.6,434.7h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C576.1,434.5,575.9,434.7,575.6,434.7z"/> + <path id="Path_4762-3" d="M575.6,415.3h-5.9c-0.3,0-0.5-0.2-0.5-0.5v-5.9c0-0.3,0.2-0.5,0.5-0.5h5.9 + c0.3,0,0.5,0.2,0.5,0.5v5.9C576.1,415.1,575.9,415.3,575.6,415.3z"/> + <path id="Path_4762-4" d="M594.4,434.7h-14.2c-0.7,0-1.2-0.8-1.2-1.9v-22.5c0-1,0.5-1.9,1.2-1.9h14.2 + c0.7,0,1.2,0.8,1.2,1.9v22.5C595.5,433.9,595,434.7,594.4,434.7z"/> +</g> +</svg> diff --git a/web/public/assets/images/no-active-orders-01.svg b/web/public/assets/images/no-active-orders-01.svg new file mode 100644 index 0000000000..a9b6cac8dc --- /dev/null +++ b/web/public/assets/images/no-active-orders-01.svg @@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="42.439" height="42.446" viewBox="0 0 42.439 42.446"> + <g id="no-active-orders-01" opacity="0.55"> + <path id="Path_42" data-name="Path 42" d="M354.107,229.122h7.214a4.088,4.088,0,0,0,4.082-4.082V211.51a2.285,2.285,0,0,0-3.24-2.072l-.394.186-.178-.394a2.283,2.283,0,0,0-3.039-1.144l-.394.186-.178-.394a2.27,2.27,0,0,0-2.837-1.222l-.564.2v-7.074a2.294,2.294,0,0,0-.665-1.616,2.262,2.262,0,0,0-1.616-.665,2.3,2.3,0,0,0-1.616.665,2.262,2.262,0,0,0-.665,1.616v15.687l-2.42-2.42a2.262,2.262,0,0,0-1.616-.665,2.294,2.294,0,0,0-1.616.665,2.262,2.262,0,0,0-.665,1.616,2.3,2.3,0,0,0,.665,1.616l5.257,5.257a1.329,1.329,0,0,1,.387.936v2.567A4.112,4.112,0,0,0,354.107,229.122ZM345.053,215.6a1.323,1.323,0,0,1,1.871-1.871l3.232,3.232a.463.463,0,0,0,.518.1.48.48,0,0,0,.294-.441V199.781a1.316,1.316,0,0,1,.387-.936,1.329,1.329,0,0,1,.936-.387,1.316,1.316,0,0,1,.936.387,1.329,1.329,0,0,1,.387.936v14.435a.479.479,0,0,0,.959,0V208.8a1.33,1.33,0,1,1,2.66,0v5.412a.479.479,0,0,0,.959.015v-4.075a1.33,1.33,0,1,1,2.66,0v4.075a.479.479,0,0,0,.959-.015V211.51a1.33,1.33,0,1,1,2.66,0v13.53a3.138,3.138,0,0,1-3.131,3.131h-7.214a3.138,3.138,0,0,1-3.131-3.131v-2.567a2.3,2.3,0,0,0-.665-1.616Z" transform="translate(-322.964 -186.676)" fill="#fff" fill-rule="evenodd"/> + <path id="Path_43" data-name="Path 43" d="M97.628,57.5H77.781A2.28,2.28,0,0,0,75.5,59.781v13.53a2.28,2.28,0,0,0,2.281,2.281H97.628a2.28,2.28,0,0,0,2.281-2.281V59.781A2.285,2.285,0,0,0,97.628,57.5ZM98.95,73.311a1.33,1.33,0,0,1-1.33,1.33H77.781a1.33,1.33,0,0,1-1.33-1.33V59.781a1.33,1.33,0,0,1,1.33-1.33H97.628a1.33,1.33,0,0,1,1.33,1.33v13.53Z" transform="translate(-75.5 -57.5)" fill="#fff" fill-rule="evenodd"/> + <path id="Path_44" data-name="Path 44" d="M320.979,127.5a.482.482,0,0,0-.479.479V134.3a.479.479,0,1,0,.959,0v-6.317A.487.487,0,0,0,320.979,127.5Z" transform="translate(-301.558 -122.088)" fill="#fff" fill-rule="evenodd"/> + <path id="Path_45" data-name="Path 45" d="M274.279,104.6a.482.482,0,0,0-.479.479V111.4a.479.479,0,1,0,.959,0v-6.317A.477.477,0,0,0,274.279,104.6Z" transform="translate(-258.468 -100.958)" fill="#fff" fill-rule="evenodd"/> + <path id="Path_46" data-name="Path 46" d="M227.579,151.6a.482.482,0,0,0-.479.479V158.4a.479.479,0,1,0,.959,0v-6.317A.477.477,0,0,0,227.579,151.6Z" transform="translate(-215.379 -144.325)" fill="#fff" fill-rule="evenodd"/> + <path id="Path_47" data-name="Path 47" d="M180.979,104.6a.482.482,0,0,0-.479.479V111.4a.479.479,0,0,0,.959,0v-6.317A.482.482,0,0,0,180.979,104.6Z" transform="translate(-172.382 -100.958)" fill="#fff" fill-rule="evenodd"/> + <path id="Path_48" data-name="Path 48" d="M134.779,127.5a.482.482,0,0,0-.479.479V134.3a.479.479,0,0,0,.959,0v-6.317A.482.482,0,0,0,134.779,127.5Z" transform="translate(-129.754 -122.088)" fill="#fff" fill-rule="evenodd"/> + </g> +</svg> diff --git a/web/public/assets/images/no-recent-deposits.svg b/web/public/assets/images/no-recent-deposits.svg new file mode 100644 index 0000000000..9eba8e665f --- /dev/null +++ b/web/public/assets/images/no-recent-deposits.svg @@ -0,0 +1,9 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="31.263" height="40.277" viewBox="0 0 31.263 40.277"> + <g id="Group_7" data-name="Group 7" transform="translate(-1098 -418)"> + <g id="no-recent-trades-01" transform="translate(313.475 90.003)" opacity="0.55"> + <path id="Path_49" data-name="Path 49" d="M795.493,361.953h6.966a4.044,4.044,0,0,0,2.327-.727l8.922-6.177a4.829,4.829,0,0,0,2.08-3.974,2.019,2.019,0,0,0-1.129-1.809h0a2.02,2.02,0,0,0-2.118.209l-7.492,5.76-.155-.626a2.284,2.284,0,0,0-2.219-1.724h-7.94a4.075,4.075,0,0,0-3.44,1.879l-6.409,10a2.3,2.3,0,0,0-.085,2.327,2.274,2.274,0,0,0,2,1.183h2.319a2.273,2.273,0,0,0,1.856-.959l3.433-4.8A1.327,1.327,0,0,1,795.493,361.953Zm-1.856,0-3.433,4.809a1.329,1.329,0,0,1-1.082.557H786.8a1.326,1.326,0,0,1-1.121-2.042l6.409-9.989a3.107,3.107,0,0,1,2.636-1.438h7.948a1.315,1.315,0,0,1,1.307,1.137l.031.263-.07.294.008.008-.008-.008v.015a1.334,1.334,0,0,1-1.268.943h-5.412a.479.479,0,1,0,0,.959h5.7a2.3,2.3,0,0,0,1.392-.472l8.76-6.742a1.064,1.064,0,0,1,1.709.843h0a3.893,3.893,0,0,1-1.67,3.193l-8.922,6.177a3.133,3.133,0,0,1-1.786.557h-6.964A2.22,2.22,0,0,0,793.637,361.953Z" fill="#fff" fill-rule="evenodd"/> + </g> + <path id="Path_54" data-name="Path 54" d="M806.161,349H791.023a2.934,2.934,0,0,1-2.93-2.932V330.928a2.934,2.934,0,0,1,2.93-2.931h15.138a2.935,2.935,0,0,1,2.932,2.931v15.137A2.936,2.936,0,0,1,806.161,349Zm-15.138-20a1.933,1.933,0,0,0-1.93,1.931v15.137a1.933,1.933,0,0,0,1.93,1.932h15.138a1.934,1.934,0,0,0,1.932-1.932V330.928A1.933,1.933,0,0,0,806.161,329Z" transform="translate(313.475 90.003)" fill="#fff" opacity="0.55"/> + <path id="Path_55" data-name="Path 55" d="M803.113,333.976a.5.5,0,0,0-.707,0l-7.481,7.481v-5.363a.5.5,0,0,0-1,0v6.571a.5.5,0,0,0,.309.461.505.505,0,0,0,.191.039h6.57a.5.5,0,0,0,0-1h-5.363l7.481-7.482A.5.5,0,0,0,803.113,333.976Z" transform="translate(313.475 90.003)" fill="#fff" opacity="0.55"/> + </g> +</svg> diff --git a/web/public/assets/images/no-recent-trades-01.svg b/web/public/assets/images/no-recent-trades-01.svg new file mode 100644 index 0000000000..7fa67e65d9 --- /dev/null +++ b/web/public/assets/images/no-recent-trades-01.svg @@ -0,0 +1,9 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="33.423" height="42.445" viewBox="0 0 33.423 42.445"> + <g id="no-recent-trades-01" opacity="0.55"> + <path id="Path_49" data-name="Path 49" d="M172.811,368.915h6.966a4.046,4.046,0,0,0,2.327-.727l8.922-6.177a4.828,4.828,0,0,0,2.08-3.974,2.017,2.017,0,0,0-1.129-1.809h0a2.021,2.021,0,0,0-2.118.209l-7.492,5.76-.155-.626a2.283,2.283,0,0,0-2.219-1.724h-7.94a4.077,4.077,0,0,0-3.44,1.879l-6.409,10a2.3,2.3,0,0,0-.085,2.327,2.275,2.275,0,0,0,2,1.183h2.319a2.273,2.273,0,0,0,1.856-.959l3.433-4.8A1.326,1.326,0,0,1,172.811,368.915Zm-1.856,0-3.433,4.809a1.327,1.327,0,0,1-1.082.557h-2.319A1.326,1.326,0,0,1,163,372.239l6.409-9.989a3.109,3.109,0,0,1,2.636-1.438h7.948a1.314,1.314,0,0,1,1.307,1.137l.031.263-.07.294.008.008-.008-.008v.015a1.332,1.332,0,0,1-1.268.943h-5.412a.479.479,0,1,0,0,.959h5.7a2.307,2.307,0,0,0,1.392-.472l8.76-6.742a1.064,1.064,0,0,1,1.709.843h0a3.891,3.891,0,0,1-1.67,3.193l-8.922,6.177a3.13,3.13,0,0,1-1.786.557H172.8A2.223,2.223,0,0,0,170.955,368.915Z" transform="translate(-159.683 -332.786)" fill="#fff" fill-rule="evenodd"/> + <path id="Path_50" data-name="Path 50" d="M147.268,76.862a11.182,11.182,0,0,0,5.141,1.237,11.3,11.3,0,1,0-11.3-11.3,11.182,11.182,0,0,0,1.237,5.141l.139.278-7.917,7.925a2.262,2.262,0,0,0-.665,1.616,2.294,2.294,0,0,0,.665,1.616l1.276,1.276a2.262,2.262,0,0,0,1.616.665,2.294,2.294,0,0,0,1.616-.665h0l7.917-7.932Zm-8.876,7.113a1.316,1.316,0,0,1-.936.387h0a1.316,1.316,0,0,1-.935-.387L135.245,82.7a1.334,1.334,0,0,1-.387-.943,1.316,1.316,0,0,1,.387-.936L143,73.066l.294.4c.008.008.015.023.023.031a.169.169,0,0,0,.031.039c.031.046.07.093.1.139l.008.008c.062.077.124.162.193.24l.1.124c.054.07.116.139.17.2s.1.108.147.162a1.189,1.189,0,0,1,.131.147c.039.046.085.085.124.131l.2.2c.046.046.093.085.139.131s.093.085.139.131l.216.193c.039.039.085.07.124.108l.015.015.139.116c.07.054.131.108.2.162.054.046.116.085.17.131a.168.168,0,0,1,.039.031c.008.008.023.015.031.023l.4.294Zm8.474-8.443c-.085-.054-.17-.108-.255-.17l-.031-.023c-.07-.046-.139-.1-.209-.147l-.07-.046c-.062-.046-.124-.093-.178-.139l-.062-.046-.232-.186-.031-.031c-.062-.054-.131-.108-.193-.162-.023-.015-.039-.039-.062-.054l-.008-.008c-.054-.046-.1-.093-.155-.139l-.015-.015a.357.357,0,0,1-.054-.054c-.062-.062-.131-.124-.193-.186l-.031-.031c-.062-.062-.124-.124-.186-.193-.015-.023-.039-.039-.054-.062l-.015-.015c-.046-.046-.093-.1-.131-.147a.7.7,0,0,0-.07-.077l-.155-.178-.039-.046a2.515,2.515,0,0,1-.178-.224.235.235,0,0,1-.039-.054l-.015-.023c-.039-.054-.085-.108-.124-.17-.015-.023-.039-.054-.054-.077-.046-.062-.093-.131-.139-.193l-.031-.046c-.054-.085-.108-.162-.162-.247l-.039-.062c-.039-.07-.085-.131-.124-.2a10.359,10.359,0,1,1,3.6,3.6c-.077-.046-.147-.093-.224-.139Z" transform="translate(-133.9 -55.5)" fill="#fff" fill-rule="evenodd"/> + <path id="Path_51" data-name="Path 51" d="M277.465,202.288v-5.165l1.894,1.894a.476.476,0,0,0,.673,0,.467.467,0,0,0,.139-.34.48.48,0,0,0-.139-.34l-2.706-2.706a.241.241,0,0,0-.07-.054l-.015-.008a.481.481,0,0,0-.2-.07h-.108a.416.416,0,0,0-.2.07c-.008.008-.015.008-.023.015a.431.431,0,0,0-.062.046l-2.706,2.706a.476.476,0,1,0,.673.673l1.894-1.894v5.165a.482.482,0,0,0,.479.479A.475.475,0,0,0,277.465,202.288Z" transform="translate(-262.984 -184.676)" fill="#fff" fill-rule="evenodd"/> + <path id="Path_52" data-name="Path 52" d="M337.9,105.949a.475.475,0,0,0,.34-.812l-2.706-2.706a.447.447,0,0,0-.193-.116h-.008a.336.336,0,0,0-.039-.008h-.015a.666.666,0,0,0-.124-.008h-.015a.07.07,0,0,0-.039.008l-.015.008c-.008,0-.015.008-.031.008l-.015.008c-.008,0-.015.008-.031.008l-.015.008c-.008.008-.015.008-.031.015l-.015.008c-.008.008-.015.008-.023.015l-.015.008c-.008.008-.015.015-.023.015l-.039.039-2.706,2.706a.467.467,0,0,0-.139.34.48.48,0,0,0,.139.34.467.467,0,0,0,.34.139h0a.48.48,0,0,0,.34-.139h0l1.894-1.894v5.141a.479.479,0,1,0,.959,0v-5.165l1.894,1.894A.45.45,0,0,0,337.9,105.949Z" transform="translate(-316.684 -98.682)" fill="#fff" fill-rule="evenodd"/> + <path id="Path_53" data-name="Path 53" d="M396.632,198.926a.467.467,0,0,0,.139-.34.48.48,0,0,0-.139-.34l-2.706-2.706a.136.136,0,0,0-.039-.031.507.507,0,0,0-.294-.108h-.016a.463.463,0,0,0-.325.139l-.015.015-2.7,2.7a.476.476,0,0,0,.673.673l1.894-1.894V202.2a.479.479,0,0,0,.959,0v-5.165l1.894,1.894A.476.476,0,0,0,396.632,198.926Z" transform="translate(-370.569 -184.584)" fill="#fff" fill-rule="evenodd"/> + </g> +</svg> diff --git a/web/public/assets/images/no-recent-withdrawals.svg b/web/public/assets/images/no-recent-withdrawals.svg new file mode 100644 index 0000000000..20dd61cc5a --- /dev/null +++ b/web/public/assets/images/no-recent-withdrawals.svg @@ -0,0 +1,9 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="31.262" height="40.277" viewBox="0 0 31.262 40.277"> + <g id="Group_5" data-name="Group 5" transform="translate(-884.428 -327.997)"> + <g id="no-recent-trades-01" opacity="0.55"> + <path id="Path_49" data-name="Path 49" d="M895.4,361.953h6.966a4.044,4.044,0,0,0,2.327-.727l8.922-6.177a4.829,4.829,0,0,0,2.08-3.974,2.018,2.018,0,0,0-1.129-1.809h0a2.02,2.02,0,0,0-2.118.209l-7.492,5.76-.155-.626a2.284,2.284,0,0,0-2.219-1.724h-7.94a4.075,4.075,0,0,0-3.44,1.879l-6.409,10a2.3,2.3,0,0,0-.085,2.327,2.273,2.273,0,0,0,2,1.183h2.319a2.273,2.273,0,0,0,1.856-.959l3.433-4.8A1.326,1.326,0,0,1,895.4,361.953Zm-1.856,0-3.433,4.809a1.329,1.329,0,0,1-1.082.557h-2.319a1.326,1.326,0,0,1-1.121-2.042l6.409-9.989a3.107,3.107,0,0,1,2.636-1.438h7.948a1.315,1.315,0,0,1,1.307,1.137l.031.263-.07.294.008.008-.008-.008v.015a1.334,1.334,0,0,1-1.268.943h-5.412a.479.479,0,1,0,0,.959h5.7a2.3,2.3,0,0,0,1.392-.472l8.76-6.742a1.064,1.064,0,0,1,1.709.843h0a3.893,3.893,0,0,1-1.67,3.193l-8.922,6.177a3.133,3.133,0,0,1-1.786.557h-6.964A2.22,2.22,0,0,0,893.54,361.953Z" fill="#fff" fill-rule="evenodd"/> + </g> + <path id="Path_56" data-name="Path 56" d="M906.064,349H890.927a2.936,2.936,0,0,1-2.932-2.932V330.928A2.935,2.935,0,0,1,890.927,328h15.137a2.934,2.934,0,0,1,2.931,2.931v15.137A2.934,2.934,0,0,1,906.064,349Zm-15.137-20a1.933,1.933,0,0,0-1.932,1.931v15.137A1.934,1.934,0,0,0,890.927,348h15.137a1.934,1.934,0,0,0,1.931-1.932V330.928A1.933,1.933,0,0,0,906.064,329Z" fill="#fff" opacity="0.55"/> + <path id="Path_57" data-name="Path 57" d="M903.125,334.138a.5.5,0,0,0-.271-.27.487.487,0,0,0-.191-.039h-6.57a.5.5,0,0,0,0,1h5.363l-7.481,7.482a.5.5,0,1,0,.707.707l7.481-7.482V340.9a.5.5,0,0,0,1,0v-6.571A.5.5,0,0,0,903.125,334.138Z" fill="#fff" opacity="0.55"/> + </g> +</svg> diff --git a/web/public/assets/images/search-blockchain.svg b/web/public/assets/images/search-blockchain.svg new file mode 100644 index 0000000000..6d9ebb1001 --- /dev/null +++ b/web/public/assets/images/search-blockchain.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 26.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 480 480" style="enable-background:new 0 0 480 480;" xml:space="preserve"> + <g> + <path d="M460.7,460.1l-55.6-64.9c18.8-21.9,26.6-51.2,21.1-79.5c-5.5-28.3-23.8-52.5-49.5-65.7c-25.7-13.2-56-13.8-82.2-1.7 + c-26.2,12.1-45.5,35.5-52.2,63.6c-6.7,28.1-0.2,57.7,17.7,80.3c17.9,22.6,45.2,35.8,74.1,35.7c21.2,0,41.8-7.2,58.4-20.5l55,64.1h0 + c1.4,2.1,3.6,3.5,6.1,3.8s5-0.4,6.9-2.1s3-4,3-6.5c0-2.5-1-4.9-2.9-6.6L460.7,460.1z M257.2,332.4c0.3-20.3,8.6-39.7,23.1-53.9 + s34.1-22.1,54.4-21.9c20.3,0.2,39.8,8.4,54,22.9c14.3,14.5,22.2,34,22.1,54.3c-0.1,20.3-8.2,39.8-22.6,54.1 + c-14.4,14.3-33.9,22.4-54.2,22.4c-20.5-0.2-40.1-8.5-54.5-23.1C265.1,372.7,257.1,352.9,257.2,332.4L257.2,332.4z" /> + <path d="M213.4,348.9L191.6,362V203.9l140-80.8v88.2c0,4.8,3.9,8.8,8.8,8.8s8.8-3.9,8.8-8.8v-107c0-3.1-1.7-6-4.4-7.6L187.2,5.9 + c-2.7-1.6-6-1.6-8.8,0L20.9,96.8c-2.7,1.6-4.4,4.5-4.4,7.6v182c0,3.1,1.7,6,4.4,7.6l157.5,90.7c2.7,1.6,6,1.6,8.8,0l35-20.8 + c3.6-2.6,4.7-7.6,2.4-11.5C222.4,348.6,217.5,347.1,213.4,348.9L213.4,348.9z M182.8,23.5l143.1,82.6l-143.1,82.6L39.7,106.1 + L182.8,23.5z M34.1,123.1l140,80.8V362l-140-80.9V123.1z" /> + </g> +</svg> \ No newline at end of file diff --git a/web/public/assets/images/trade.svg b/web/public/assets/images/trade.svg new file mode 100644 index 0000000000..a3dfa468a1 --- /dev/null +++ b/web/public/assets/images/trade.svg @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 26.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#FFFFFF;} + .icon-plus-1{fill:#0000FF;} +</style> +<circle id="XMLID_134_" class="icon-plus-1" cx="25" cy="25" r="25"/> +<path id="Union_1" class="st0" d="M4.9,36.6c-0.8-1.1-0.8-2.5,0-3.6l11.1-14.3c0.3-0.5,0.9-0.8,1.5-0.7c0.6-0.1,1.2,0.2,1.6,0.6 + l9.4,10.2l13.4-16.2c0.7-1,2.1-1.2,3-0.4c0.2,0.1,0.3,0.3,0.4,0.4c1,1.2,1,3,0,4.2l-14,16.9c-0.4,0.5-1.1,0.9-1.7,0.9 + c-0.1,0-0.2,0-0.3,0c-0.1,0-0.2,0-0.3,0c-0.5,0-1.1-0.2-1.4-0.6l-9.8-10.6L7.6,36.6c-0.3,0.4-0.8,0.7-1.4,0.7 + C5.7,37.3,5.2,37,4.9,36.6z"/> +</svg> diff --git a/web/public/index.html b/web/public/index.html index 5d96bb2788..31484cf341 100644 --- a/web/public/index.html +++ b/web/public/index.html @@ -8,12 +8,42 @@ <link rel="shortcut icon" href="/favicon.ico"> <link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="/css/bootstrap-grid.min.css"> - <script src="%PUBLIC_URL%/datafeeds/udf/dist/bundle.js"></script> + <style> + .app-booting { + display: none; + height: 100vh; + width: 100vw; + align-items: center; + justify-content: center; + } + .booting-container { + width: 5rem; + height: 5rem; + max-width: 100%; + max-height: 100%; + position: absolute; + pointer-events: none; + + background-size: contain; + background-repeat: no-repeat; + background-position: center; + } + #app-booting-image { + width: 100%; + height: 100%; + } + </style> + <script src="%PUBLIC_URL%/datafeeds/udf/dist/bundle.js"></script> </head> <body> <noscript> You need to enable JavaScript to run this app. </noscript> <div id="root"></div> + <div class="app-booting"> + <div class="booting-container"> + <img id="app-booting-image" alt="Loading ..."> + </div> + </div> </body> </html> \ No newline at end of file diff --git a/web/src/_common.scss b/web/src/_common.scss index 6ec3dd9783..09c709dee4 100644 --- a/web/src/_common.scss +++ b/web/src/_common.scss @@ -96,6 +96,10 @@ table th { color: $link !important; } +.blue-link:hover { + opacity: 0.5; +} + .arrow { border: solid grey; border-width: 0 3px 3px 0; @@ -216,6 +220,24 @@ table th { } } +.filter-option { + gap: 1rem; + + .coin-icons { + width: 13px !important; + height: 13px !important; + } + + .currency-ball-image-wrapper { + width: 13px; + height: 13px; + } +} + +.filter-dropdown { + width: 150px !important; +} + .custom-select-input-style { &.no-border { .ant-select-selector { @@ -223,6 +245,17 @@ table th { } } + .coin-icons { + width: 16px; + height: 16px; + } + + .currency-ball-image-wrapper { + width: 16px; + height: 16px; + margin-right: 15px; + } + .ant-select-selector { border-radius: 0.35rem !important; border-color: $colors-main-border !important; @@ -337,3 +370,7 @@ table th { .inline-flex { display: inline-flex !important; } + +.no-wrap { + white-space: nowrap !important; +} diff --git a/web/src/actions/appActions.js b/web/src/actions/appActions.js index ff05682d16..46ea2f12ff 100644 --- a/web/src/actions/appActions.js +++ b/web/src/actions/appActions.js @@ -38,6 +38,7 @@ export const NOTIFICATIONS = { UNSTAKE: 'UNSTAKE', MOVE_XHT: 'MOVE_XHT', METAMASK_ERROR: 'METAMASK_ERROR', + CONFIGURE_APPS: 'CONFIGURE_APPS', }; export const CONTACT_FORM = 'CONTACT_FORM'; export const HELPFUL_RESOURCES_FORM = 'HELPFUL_RESOURCES_FORM'; @@ -376,6 +377,9 @@ export const openConnectViaDesktop = (data = {}) => export const openMetamaskError = (data = {}) => setNotification(NOTIFICATIONS.METAMASK_ERROR, data, true); +export const openConfigureApps = (onRemove) => + setNotification(NOTIFICATIONS.CONFIGURE_APPS, { onRemove }, true); + export const openRiskPortfolioOrderWarning = (data = {}) => setNotification(RISK_PORTFOLIO_ORDER_WARING, data, true); diff --git a/web/src/actions/chartAction.js b/web/src/actions/chartAction.js index 204412996b..a87ccb56e7 100644 --- a/web/src/actions/chartAction.js +++ b/web/src/actions/chartAction.js @@ -28,6 +28,7 @@ export const getChartSymbol = (symbol, tickSize, api_name = '') => { let count = getDecimals(tickSize); pricescale = math.pow(10, count); } + if (pricescale === 0) pricescale = 1; // return axios({ // url: `/udf/symbols?symbol=${symbol}`, // method: 'GET' diff --git a/web/src/actions/orderAction.js b/web/src/actions/orderAction.js index aa73069055..a0dd3e3c6b 100644 --- a/web/src/actions/orderAction.js +++ b/web/src/actions/orderAction.js @@ -1,8 +1,8 @@ import axios from 'axios'; import ICONS from 'config/icons'; import { requestAuthenticated } from 'utils'; -import STRINGS from '../config/localizedStrings'; -import { playBackgroundAudioNotification } from '../utils/utils'; +import STRINGS from 'config/localizedStrings'; +import { playBackgroundAudioNotification } from 'utils/utils'; // Set orders from websocket export function setUserOrders(orders) { diff --git a/web/src/actions/walletActions.js b/web/src/actions/walletActions.js index 3fbae0b81d..042a7b5451 100644 --- a/web/src/actions/walletActions.js +++ b/web/src/actions/walletActions.js @@ -221,7 +221,6 @@ export const getOrdersHistory = ({ dataParams.open = open; } const query = querystring.stringify(dataParams); - return (dispatch) => { dispatch({ type: ACTION_KEYS.ORDER_HISTORY_PENDING, payload: { page } }); axios diff --git a/web/src/components/AdminForm/hoc.js b/web/src/components/AdminForm/hoc.js index d82451e089..b31de35f46 100644 --- a/web/src/components/AdminForm/hoc.js +++ b/web/src/components/AdminForm/hoc.js @@ -3,6 +3,7 @@ import renderFields from './utils'; import { reduxForm, reset, getFormValues } from 'redux-form'; import { Button } from 'antd'; import { connect } from 'react-redux'; +import FormButton from 'components/FormButton/Button'; const Form = (name, className = '', allowPristine = false) => { const HocForm = ({ @@ -49,9 +50,9 @@ const Form = (name, className = '', allowPristine = false) => { {secondaryBtnTxt} </Button> ) : null} - <Button + <FormButton type={buttonType ? buttonType : 'primary'} - onClick={handleSubmit(onSubmit)} + handleSubmit={handleSubmit(onSubmit)} disabled={ disableAllFields || (allowPristine ? false : fields && pristine) || @@ -63,9 +64,8 @@ const Form = (name, className = '', allowPristine = false) => { size={small ? 'small' : 'large'} className={small ? `${buttonClass}` : `w-100 ${buttonClass}`} style={small ? { float: 'right' } : null} - > - {buttonText} - </Button> + buttonText={buttonText} + /> </form> ); }; @@ -78,7 +78,7 @@ const Form = (name, className = '', allowPristine = false) => { })(HocForm); const mapStateToProps = (state) => ({ - formValues: getFormValues(name)(state) + formValues: getFormValues(name)(state), }); return connect(mapStateToProps)(CommonHocForm); }; diff --git a/web/src/components/AppBar/AnnouncementList.js b/web/src/components/AppBar/AnnouncementList.js index 5185f9c8a4..860faaee27 100644 --- a/web/src/components/AppBar/AnnouncementList.js +++ b/web/src/components/AppBar/AnnouncementList.js @@ -4,10 +4,10 @@ import { bindActionCreators } from 'redux'; import Scrollbars from 'react-custom-scrollbars'; import { EditWrapper, NotificationsList, Image } from 'components'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import { getAnnouncement } from 'actions/appActions'; -import { LAST_UPDATED_NOTIFICATION_KEY } from '../../config/constants'; +import { LAST_UPDATED_NOTIFICATION_KEY } from 'config/constants'; const AnnouncementList = ({ icons: ICONS, diff --git a/web/src/components/AppBar/HamburgerMenu.js b/web/src/components/AppBar/HamburgerMenu.js index 9e1d58e52a..87fb2eda3d 100644 --- a/web/src/components/AppBar/HamburgerMenu.js +++ b/web/src/components/AppBar/HamburgerMenu.js @@ -1,6 +1,6 @@ import React from 'react'; import classnames from 'classnames'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; class HamburgerMenu extends React.Component { constructor(props) { diff --git a/web/src/components/AppBar/LanguageSwitcher.js b/web/src/components/AppBar/LanguageSwitcher.js new file mode 100644 index 0000000000..e9c6f18579 --- /dev/null +++ b/web/src/components/AppBar/LanguageSwitcher.js @@ -0,0 +1,68 @@ +import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons'; +import { updateUserSettings } from 'actions/userAction'; +import { Select } from 'antd'; +import { generateLanguageFormValues } from 'containers/UserSettings/LanguageForm'; +import React, { useEffect, useState } from 'react'; +import { SubmissionError } from 'redux-form'; +const { Option } = Select; + +const LanguageSwitcher = ({ selected, valid_languages, toggle }) => { + const [isOpen, setIsOpen] = useState(false); + const [_selected, setSelected] = useState(selected); + const languageFormValue = generateLanguageFormValues(valid_languages).language + .options; + const onSwitch = (val) => { + updateUserSettings({ language: val }) + .then(({ data }) => { + if (data.settings) { + if (data.settings.language) { + toggle(data.settings.language); + } + } + }) + .catch((err) => { + const _error = + err.response && err.response.data + ? err.response.data.message + : err.message; + throw new SubmissionError({ _error }); + }); + }; + + useEffect(() => { + if (setSelected && _selected !== selected) setSelected(selected); + }, [setSelected, _selected, selected]); + + useEffect(() => { + if (toggle) toggle(_selected); + }, [_selected, toggle]); + return ( + <Select + value={_selected} + size="small" + onSelect={onSwitch} + bordered={false} + onClick={() => setIsOpen((prev) => !prev)} + suffixIcon={isOpen ? <CaretUpOutlined /> : <CaretDownOutlined />} + className="custom-select-input-style appbar elevated" + dropdownClassName="custom-select-style select-option-wrapper" + > + {languageFormValue.map(({ value, icon, label }) => ( + <Option value={value} key={value} className="capitalize"> + <div className="language_option"> + <img + width="10px" + height="10px" + src={icon} + alt={label} + className="mr-2" + /> + {label} + </div> + </Option> + ))} + </Select> + ); +}; + +export default LanguageSwitcher; diff --git a/web/src/components/AppBar/LinkButton.js b/web/src/components/AppBar/LinkButton.js index 2ccaf1154d..7a3c32acbe 100644 --- a/web/src/components/AppBar/LinkButton.js +++ b/web/src/components/AppBar/LinkButton.js @@ -1,7 +1,7 @@ import React from 'react'; import classnames from 'classnames'; import { Link } from 'react-router'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; const COMMON_CLASSES = [ 'text-uppercase', diff --git a/web/src/components/AppBar/MenuList.js b/web/src/components/AppBar/MenuList.js index 08aa6ed00a..3026544f1b 100644 --- a/web/src/components/AppBar/MenuList.js +++ b/web/src/components/AppBar/MenuList.js @@ -8,6 +8,7 @@ import MenuListItem from './MenuListItem'; class MenuList extends Component { state = { isOpen: false, + startTransition: false, }; element = null; @@ -29,7 +30,19 @@ class MenuList extends Component { event.target !== this.element && this.element.contains(event.target) ) { - this.setState({ isOpen: !this.state.isOpen }); + this.setState({ isOpen: !this.state.isOpen }, () => { + if (this.state.isOpen) { + setTimeout(() => { + this.setState({ + startTransition: true, + }); + }, 50); + } else { + this.setState({ + startTransition: false, + }); + } + }); } }; @@ -70,7 +83,7 @@ class MenuList extends Component { activePath, onMenuChange, } = this.props; - const { isOpen } = this.state; + const { isOpen, startTransition } = this.state; const totalPending = securityPending + verificationPending; return ( <div @@ -92,7 +105,12 @@ class MenuList extends Component { </div> <div>{user.email}</div> {isOpen && ( - <div id="tab-account-menu" className="app-bar-account-menu apply_rtl"> + <div + id="tab-account-menu" + className={`${ + startTransition ? 'opacity-1 ' : ' ' + } app-bar-account-menu apply_rtl`} + > {menuItems.map( ( { path, icon_id, string_id, hide_from_menulist, activePaths }, diff --git a/web/src/components/AppBar/PairTabs.js b/web/src/components/AppBar/PairTabs.js index 415246085c..db97ba2475 100644 --- a/web/src/components/AppBar/PairTabs.js +++ b/web/src/components/AppBar/PairTabs.js @@ -105,7 +105,6 @@ class PairTabs extends Component { 'app_bar-pair-content', 'd-flex', 'justify-content-between', - 'px-2', 'market-trigger', { 'active-tab-pair': location.pathname === '/markets', diff --git a/web/src/components/AppBar/ThemeSwitcher.js b/web/src/components/AppBar/ThemeSwitcher.js index 8b14cef97a..46e76dba25 100644 --- a/web/src/components/AppBar/ThemeSwitcher.js +++ b/web/src/components/AppBar/ThemeSwitcher.js @@ -1,14 +1,15 @@ -import React from 'react'; +import React, { useState } from 'react'; import classnames from 'classnames'; import Image from 'components/Image'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; import withConfig from 'components/ConfigProvider/withConfig'; import { Select } from 'antd'; -import { CaretDownOutlined } from '@ant-design/icons'; +import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons'; const { Option } = Select; const ThemeSwitcher = ({ selected, options = [], toggle, icons: ICONS }) => { + const [isOpen, setIsOpen] = useState(false); const handleClick = () => { const theme = options[0].value === selected ? options[1].value : options[0].value; @@ -72,12 +73,13 @@ const ThemeSwitcher = ({ selected, options = [], toggle, icons: ICONS }) => { size="small" onSelect={toggle} bordered={false} - suffixIcon={<CaretDownOutlined />} + onClick={() => setIsOpen((prev) => !prev)} + suffixIcon={isOpen ? <CaretUpOutlined /> : <CaretDownOutlined />} className="custom-select-input-style appbar elevated" dropdownClassName="custom-select-style select-option-wrapper" > {options.map(({ value }) => ( - <Option value={value} key={value}> + <Option value={value} key={value} className="capitalize"> {value} </Option> ))} diff --git a/web/src/components/AppBar/_AppBar.scss b/web/src/components/AppBar/_AppBar.scss index a1571f7815..883a16dd2b 100644 --- a/web/src/components/AppBar/_AppBar.scss +++ b/web/src/components/AppBar/_AppBar.scss @@ -332,7 +332,13 @@ $app-menu-width: calc(100vw - 40rem); font-weight: bold; } + .opacity-1 { + opacity: 1 !important; + } + .app-bar-account-menu { + transition: 0.9s; + opacity: 0; display: block; position: absolute; // right: 0; @@ -371,7 +377,8 @@ $app-menu-width: calc(100vw - 40rem); .tab-history-st, .help-question, .tab-signout, - .tab-api0 { + .tab-api0, + .apps { fill: $colors-black; } } @@ -506,6 +513,9 @@ $app-menu-width: calc(100vw - 40rem); font-size: 11px; } } +.capitalize { + text-transform: capitalize; +} .home_app_bar { position: relative; @@ -613,6 +623,7 @@ $app-menu-width: calc(100vw - 40rem); max-width: $app-menu-width; .app-menu-bar-content { + transition: 0.3s; color: $base_top-bar-navigation_text-inactive; cursor: pointer; margin: 0 15px; @@ -627,6 +638,9 @@ $app-menu-width: calc(100vw - 40rem); .app-menu-bar-content-item { margin: auto; position: relative; + &:hover { + opacity: 0.5; + } } .app-menu-bar-icon { @@ -1361,6 +1375,7 @@ $app-menu-width: calc(100vw - 40rem); left: unset; } } + .app_bar { .app-bar-account-menu { .app-bar-account-list-icon { @@ -1375,6 +1390,7 @@ $app-menu-width: calc(100vw - 40rem); &.ant-dropdown-trigger { height: 100% !important; width: 100% !important; + box-sizing: content-box; } } diff --git a/web/src/components/AppBar/index.js b/web/src/components/AppBar/index.js index c837dddb4c..f9d0a0250b 100644 --- a/web/src/components/AppBar/index.js +++ b/web/src/components/AppBar/index.js @@ -8,7 +8,7 @@ import { DEFAULT_URL } from 'config/constants'; import MenuList from './MenuList'; import { MobileBarWrapper } from '../'; import { isLoggedIn } from '../../utils/token'; -import { getTickers, changeTheme } from '../../actions/appActions'; +import { getTickers, changeTheme, setLanguage } from '../../actions/appActions'; import { updateUserSettings, setUserData } from '../../actions/userAction'; import ThemeSwitcher from './ThemeSwitcher'; import { EditWrapper, ButtonLink, Image } from 'components'; @@ -16,6 +16,7 @@ import withEdit from 'components/EditProvider/withEdit'; import withConfig from 'components/ConfigProvider/withConfig'; import AnnouncementList from './AnnouncementList'; import STRINGS from 'config/localizedStrings'; +import LanguageSwitcher from './LanguageSwitcher'; class AppBar extends Component { state = { @@ -304,6 +305,13 @@ class AppBar extends Component { id="trade-nav-container" className="d-flex app-bar-account justify-content-end" > + <div className="d-flex app_bar-quicktrade-container"> + <LanguageSwitcher + selected={this.props.activeLanguage} + valid_languages={this.props.constants.valid_languages} + toggle={this.props.changeLanguage} + /> + </div> <div className="d-flex app_bar-quicktrade-container"> <ThemeSwitcher selected={selected} @@ -344,6 +352,7 @@ const mapDispatchToProps = (dispatch) => ({ getTickers: bindActionCreators(getTickers, dispatch), changeTheme: bindActionCreators(changeTheme, dispatch), setUserData: bindActionCreators(setUserData, dispatch), + changeLanguage: bindActionCreators(setLanguage, dispatch), }); export default connect( diff --git a/web/src/components/AppFooter/index.js b/web/src/components/AppFooter/index.js index d5c9068509..8076e5d728 100644 --- a/web/src/components/AppFooter/index.js +++ b/web/src/components/AppFooter/index.js @@ -1,9 +1,8 @@ import React from 'react'; import classnames from 'classnames'; import { isMobile } from 'react-device-detect'; -// import { PUBLIC_URL } from '../../config/constants'; import withConfig from 'components/ConfigProvider/withConfig'; -import Image from 'components/Image'; +import { Image } from 'components'; import withEdit from 'components/EditProvider/withEdit'; import STRINGS from 'config/localizedStrings'; diff --git a/web/src/components/AppMenuSidebar/_AppMenuSidebar.scss b/web/src/components/AppMenuSidebar/_AppMenuSidebar.scss index 7f7f1fbfe8..d18ac60bd7 100644 --- a/web/src/components/AppMenuSidebar/_AppMenuSidebar.scss +++ b/web/src/components/AppMenuSidebar/_AppMenuSidebar.scss @@ -23,6 +23,7 @@ } } .app-menu-bar-side_list { + transition: 0.3s; height: 60px; padding: 18px 17px; cursor: pointer; @@ -50,7 +51,8 @@ .help-question, .tab-signout, .tab-history-st, - .stake-page-icon { + .stake-page-icon, + .apps { fill: $base_top-bar-navigation_text !important; } } diff --git a/web/src/components/Button/CheckboxButton.js b/web/src/components/Button/CheckboxButton.js index 336cf8d42a..d8fc3a5e41 100644 --- a/web/src/components/Button/CheckboxButton.js +++ b/web/src/components/Button/CheckboxButton.js @@ -3,10 +3,16 @@ import classnames from 'classnames'; import { EditWrapper } from 'components'; import Image from 'components/Image'; -const renderCheckboxImage = (checked, ICONS = {}) => ( +const renderCheckboxImage = (checked, ICONS = {}, customCheckIcon) => ( <Image iconId={checked ? 'SUCCESS_BLACK' : 'SECURE'} - icon={checked ? ICONS['SUCCESS_BLACK'] : ICONS['SECURE']} + icon={ + checked + ? customCheckIcon + ? ICONS[customCheckIcon] + : ICONS['SUCCESS_BLACK'] + : ICONS['SECURE'] + } wrapperClassName="checkbutton-input-wrapper--image" /> ); @@ -27,6 +33,7 @@ const CheckboxButton = ({ loading = false, children, icons, + customCheckIcon = '', }) => ( <div className="checkbutton-wrapper"> <div @@ -43,7 +50,7 @@ const CheckboxButton = ({ {loading ? ( <div className="checkbutton-input-wrapper--loader" /> ) : ( - renderCheckboxImage(checked, icons) + renderCheckboxImage(checked, icons, customCheckIcon) )} <span className="checkbutton-input-wrapper--label"> <EditWrapper stringId={stringId}>{label}</EditWrapper> diff --git a/web/src/components/Chat/ChatFooter.js b/web/src/components/Chat/ChatFooter.js index bb85196ca4..24a3a2b4c6 100644 --- a/web/src/components/Chat/ChatFooter.js +++ b/web/src/components/Chat/ChatFooter.js @@ -1,10 +1,10 @@ import React from 'react'; import classnames from 'classnames'; -import { ChatMessageBox, ButtonLink } from '../'; +import { ChatMessageBox, ButtonLink } from 'components'; import ChatEmoji from './ChatEmoji'; -import STRINGS from '../../config/localizedStrings'; -import { isLoggedIn } from '../../utils/token'; +import STRINGS from 'config/localizedStrings'; +import { isLoggedIn } from 'utils/token'; const ChatFooter = ({ sendMessage, diff --git a/web/src/components/Chat/ChatHeader.js b/web/src/components/Chat/ChatHeader.js index 6b756fd52a..229f498d6e 100644 --- a/web/src/components/Chat/ChatHeader.js +++ b/web/src/components/Chat/ChatHeader.js @@ -1,6 +1,6 @@ import React from 'react'; import classnames from 'classnames'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; export const MinimalizeChat = ({ minimized, onClick }) => ( <div className={classnames('d-flex', 'minimize-button')} onClick={onClick}> diff --git a/web/src/components/Chat/ChatMessage.js b/web/src/components/Chat/ChatMessage.js index ce9b7b6eca..57b54a8e27 100644 --- a/web/src/components/Chat/ChatMessage.js +++ b/web/src/components/Chat/ChatMessage.js @@ -1,10 +1,10 @@ import React, { Component } from 'react'; import classnames from 'classnames'; import moment from 'moment'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import TruncateMarkup from 'react-truncate-markup'; -import { ICONS } from '../../config/constants'; -import { USER_TYPES } from '../../actions/appActions'; +import { ICONS } from 'config/constants'; +import { USER_TYPES } from 'actions/appActions'; import { ReactSVG } from 'react-svg'; moment.updateLocale('en', { diff --git a/web/src/components/CheckDeposit/index.js b/web/src/components/CheckDeposit/index.js index 58e17831ff..11e048b2f8 100644 --- a/web/src/components/CheckDeposit/index.js +++ b/web/src/components/CheckDeposit/index.js @@ -2,7 +2,7 @@ import React from 'react'; import { connect } from 'react-redux'; import { reduxForm, getFormValues } from 'redux-form'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import { Button } from '../../components'; import { STATIC_ICONS } from 'config/icons'; import renderFields from '../../components/Form/factoryFields'; @@ -94,17 +94,15 @@ const CheckDeposit = ({ <form className="check-deposit-modal-wrapper" onSubmit={handleSubmit}> <div className="d-flex justify-content-center align-items-center flex-column"> <img - src={STATIC_ICONS.SEARCH} + src={STATIC_ICONS.SEARCH_BLOCKCHAIN} alt="search" - className="search-icon mb-4" + className="search-icon mb-4 blockchain-search" /> <h2>{STRINGS['DEPOSIT_STATUS.CHECK_DEPOSIT_STATUS']}</h2> </div> <div className="inner-content"> - <span className="field-header"> - {STRINGS['DEPOSIT_STATUS.CHECK_DEPOSIT_STATUS']} - </span> - <div className="mb-5"> + <span>{STRINGS['DEPOSIT_STATUS.SEARCH_BLOCKCHAIN_FOR_DEPOSIT']}</span> + <div className="mb-5 field-header"> {STRINGS['DEPOSIT_STATUS.STATUS_DESCRIPTION']} </div> {renderFields(formFields)} diff --git a/web/src/components/CheckTitle/HeaderSection.js b/web/src/components/CheckTitle/HeaderSection.js index aab6e2d1c8..d4bd5c787f 100644 --- a/web/src/components/CheckTitle/HeaderSection.js +++ b/web/src/components/CheckTitle/HeaderSection.js @@ -1,10 +1,9 @@ import React from 'react'; import Image from 'components/Image'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; -import { ActionNotification } from '../../components'; -import { EditWrapper } from 'components'; +import { ActionNotification, EditWrapper } from 'components'; const HeaderSection = ({ title, diff --git a/web/src/components/CheckTitle/_CheckTitle.scss b/web/src/components/CheckTitle/_CheckTitle.scss index 2579c49488..5f09395f30 100644 --- a/web/src/components/CheckTitle/_CheckTitle.scss +++ b/web/src/components/CheckTitle/_CheckTitle.scss @@ -3,6 +3,7 @@ $custom-title-img-size: 6rem; $notification-size: 1.5rem; .check_title-container { + transition: 0.3s; display: flex; flex-direction: column; justify-content: center; @@ -17,7 +18,7 @@ $notification-size: 1.5rem; .custom_title-label { font-size: $font-size-subhead3; line-height: $font-size-subhead3; - padding: 0.25rem 0 1.5rem 0; + padding: 0.25rem 0 1.5rem 0; text-align: center; } @@ -216,6 +217,11 @@ $notification-size: 1.5rem; } } } +.tab_item-deactive { + &:hover { + opacity: 0.5; + } +} .custom-tab-wrapper { .tab_item { @@ -227,6 +233,7 @@ $notification-size: 1.5rem; } .tab_item-active { + transition: 0.3s; border: 1px solid $colors-main-border; color: $tab-active !important; font-weight: bold; diff --git a/web/src/components/CheckTitle/index.js b/web/src/components/CheckTitle/index.js index 840081c52b..ca57d35856 100644 --- a/web/src/components/CheckTitle/index.js +++ b/web/src/components/CheckTitle/index.js @@ -4,7 +4,7 @@ import { ReactSVG } from 'react-svg'; import Image from 'components/Image'; import { EditWrapper } from 'components'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; import { STATIC_ICONS as ICONS } from 'config/icons'; export const renderStatusIcon = (statusCode = -1, className = '') => { diff --git a/web/src/components/Countdown/index.js b/web/src/components/Countdown/index.js index f322370247..e6a4c3e50c 100644 --- a/web/src/components/Countdown/index.js +++ b/web/src/components/Countdown/index.js @@ -2,8 +2,8 @@ import React, { Component } from 'react'; import classnames from 'classnames'; import moment from 'moment'; -import { playBackgroundAudioNotification } from '../../utils/utils'; -import STRINGS from '../../config/localizedStrings'; +import { playBackgroundAudioNotification } from 'utils/utils'; +import STRINGS from 'config/localizedStrings'; import { Button, Loader } from '../'; diff --git a/web/src/components/CurrencyBall/index.js b/web/src/components/CurrencyBall/index.js index 36698ad52e..52c71b701a 100644 --- a/web/src/components/CurrencyBall/index.js +++ b/web/src/components/CurrencyBall/index.js @@ -1,6 +1,6 @@ import React from 'react'; import classnames from 'classnames'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; const getSizeClass = (size) => { switch (size) { diff --git a/web/src/components/CurrencyBall/withPrice.js b/web/src/components/CurrencyBall/withPrice.js index e8f78e9da5..33949a283d 100644 --- a/web/src/components/CurrencyBall/withPrice.js +++ b/web/src/components/CurrencyBall/withPrice.js @@ -1,8 +1,8 @@ import React from 'react'; import { connect } from 'react-redux'; -import { CurrencyBall } from '../'; -import { formatToCurrency } from '../../utils/currency'; -import { DEFAULT_COIN_DATA } from '../../config/constants'; +import { CurrencyBall } from 'components'; +import { formatToCurrency } from 'utils/currency'; +import { DEFAULT_COIN_DATA } from 'config/constants'; const CurrencyBallWithPrice = ({ symbol, diff --git a/web/src/components/Dialog/DesktopDialog.js b/web/src/components/Dialog/DesktopDialog.js index 4df97e636b..057d68b41c 100644 --- a/web/src/components/Dialog/DesktopDialog.js +++ b/web/src/components/Dialog/DesktopDialog.js @@ -3,10 +3,10 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import Modal from 'react-modal'; import Ionicon from 'react-ionicons'; -import { Button, ActionNotification } from '../'; -import STRINGS from '../../config/localizedStrings'; -import { getClasesForLanguage, getLanguage } from '../../utils/string'; -import { getThemeClass } from '../../utils/theme'; +import { Button, ActionNotification } from 'components'; +import STRINGS from 'config/localizedStrings'; +import { getClasesForLanguage, getLanguage } from 'utils/string'; +import { getThemeClass } from 'utils/theme'; import withEdit from 'components/EditProvider/withEdit'; class Dialog extends PureComponent { diff --git a/web/src/components/Dialog/MessageDisplay.js b/web/src/components/Dialog/MessageDisplay.js index 93957b59c1..36a3677814 100644 --- a/web/src/components/Dialog/MessageDisplay.js +++ b/web/src/components/Dialog/MessageDisplay.js @@ -1,8 +1,6 @@ import React from 'react'; -import { Button } from '../'; -import STRINGS from '../../config/localizedStrings'; -import Image from 'components/Image'; -import { EditWrapper } from 'components'; +import { Image, Button, EditWrapper } from 'components'; +import STRINGS from 'config/localizedStrings'; const MessageDisplay = ({ stringId, diff --git a/web/src/components/Dialog/MobileDialog.js b/web/src/components/Dialog/MobileDialog.js index 3c93673b9f..1572a52104 100644 --- a/web/src/components/Dialog/MobileDialog.js +++ b/web/src/components/Dialog/MobileDialog.js @@ -2,11 +2,11 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import Modal from 'react-modal'; -import { isLoggedIn } from '../../utils/token'; -import { MobileBarBack } from '../'; -import { getClasesForLanguage, getLanguage } from '../../utils/string'; -import { getThemeClass } from '../../utils/theme'; -import { ICONS } from '../../config/constants'; +import { isLoggedIn } from 'utils/token'; +import { MobileBarBack } from 'components'; +import { getClasesForLanguage, getLanguage } from 'utils/string'; +import { getThemeClass } from 'utils/theme'; +import { ICONS } from 'config/constants'; import { ReactSVG } from 'react-svg'; const CompressedContent = ({ children, onClose }) => { diff --git a/web/src/components/ElapsedTimer/index.js b/web/src/components/ElapsedTimer/index.js index c89065d5b1..9ed512b684 100644 --- a/web/src/components/ElapsedTimer/index.js +++ b/web/src/components/ElapsedTimer/index.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import Image from 'components/Image'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; let timerInterval = ''; diff --git a/web/src/components/Form/FormFields/DropdownField.js b/web/src/components/Form/FormFields/DropdownField.js index ce020c3f0c..381152686e 100644 --- a/web/src/components/Form/FormFields/DropdownField.js +++ b/web/src/components/Form/FormFields/DropdownField.js @@ -102,6 +102,20 @@ class DropdownField extends Component { </div> ); + renderOptionWhenOpen = (option, index) => ( + <div + id={`${this.props.input.name}-${option.value}-${index}`} + key={`${this.props.input.name}-${option.value}-${index}`} + onClick={this.onSelectOption(option)} + className={classnames('dropdown-option-open', { + pointer: !this.props.disabled, + })} + > + {this.renderIcon(option)} + {option.label} + </div> + ); + renderOptions = (options) => ( <div className={classnames('dropdown-options-wrapper')}> {options.length > 0 @@ -195,6 +209,10 @@ class DropdownField extends Component { </div> )} </div> + {isOpen && + selectedItem && + !autocomplete && + this.renderOptionWhenOpen(selectedItem)} {isOpen && this.renderOptions(filteredOptions)} </FieldWrapper> ); diff --git a/web/src/components/Form/FormFields/DumbField.js b/web/src/components/Form/FormFields/DumbField.js index a56a59cfbe..638c179590 100644 --- a/web/src/components/Form/FormFields/DumbField.js +++ b/web/src/components/Form/FormFields/DumbField.js @@ -2,9 +2,9 @@ import React from 'react'; import classnames from 'classnames'; import { CopyToClipboard } from 'react-copy-to-clipboard'; import FieldWrapper, { FieldContent } from './FieldWrapper'; -import { ActionNotification } from '../../'; -import { ICONS } from '../../../config/constants'; -import STRINGS from '../../../config/localizedStrings'; +import { ActionNotification } from 'components'; +import { ICONS } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; export const renderCopy = (text, onCopy, component) => { return ( diff --git a/web/src/components/Form/FormFields/FieldWrapper.js b/web/src/components/Form/FormFields/FieldWrapper.js index ef1b972884..7dd46ecd8a 100644 --- a/web/src/components/Form/FormFields/FieldWrapper.js +++ b/web/src/components/Form/FormFields/FieldWrapper.js @@ -162,7 +162,7 @@ class FieldWrapper extends Component { preview, isEmail = false, emailMsg = '', - showCross = showCross, + showCross, onCrossClick = () => {}, } = this.props; diff --git a/web/src/components/Form/FormFields/PinInput.js b/web/src/components/Form/FormFields/PinInput.js new file mode 100644 index 0000000000..4f13d6a046 --- /dev/null +++ b/web/src/components/Form/FormFields/PinInput.js @@ -0,0 +1,90 @@ +import React, { useEffect, useRef, useState } from 'react'; +import classnames from 'classnames'; + +const PinInput = ({ + input: { value = '', onChange }, + callback: { handleSubmit, error, isSubmitting }, +}) => { + const [isFocused, setIsFocused] = useState(true); + const [isError, setIsError] = useState(undefined); + const masterRef = useRef(); + + useEffect(() => { + if (value.length === 6) { + handleSubmit(); + } + }, [value, handleSubmit]); + + useEffect(() => { + if (error && masterRef?.current) { + const inputEvent = new Event('input', { bubbles: true }); + const nativeInputValueSetter = Object.getOwnPropertyDescriptor( + window.HTMLInputElement.prototype, + 'value' + ).set; + nativeInputValueSetter.call(masterRef.current, ''); + masterRef.current.dispatchEvent(inputEvent); + setIsError(error); + } + }, [error, onChange, masterRef]); + + const handleOnMasterFocus = (e) => { + var temp_value = e.target.value; + e.target.value = ''; + e.target.value = temp_value; + setIsError(false); + setIsFocused(true); + }; + + const handleOnMasterBlur = () => { + setIsFocused(false); + }; + + const handleMasterValueChange = (e) => { + if (e.target.value.length > 0) { + setIsError(undefined); + } + if (e.target.value.length <= 6 && onChange && !isSubmitting) { + onChange(e); + } + }; + + const getClassname = (index) => { + if (isError) return classnames('error'); + if (isFocused && index === value.length) return classnames('active'); + return ''; + }; + + return ( + <React.Fragment> + <div className={classnames('mainContainer')}> + <input + autoFocus + inputMode={'numeric'} + ref={masterRef} + className={classnames('masterInput')} + disabled={isSubmitting} + type="text" + value={value} + onClick={handleOnMasterFocus} + onChange={handleMasterValueChange} + onBlur={handleOnMasterBlur} + /> + <div className="group"> + <input value={value[0] || ''} className={getClassname(0)} /> + <input value={value[1] || ''} className={getClassname(1)} /> + <input value={value[2] || ''} className={getClassname(2)} /> + </div> + <div className="seperator"></div> + <div className="group"> + <input value={value[3] || ''} className={getClassname(3)} /> + <input value={value[4] || ''} className={getClassname(4)} /> + <input value={value[5] || ''} className={getClassname(5)} /> + </div> + </div> + {isError && <div className="warning_text">{isError}</div>} + </React.Fragment> + ); +}; + +export default PinInput; diff --git a/web/src/components/Form/FormFields/ToggleField.js b/web/src/components/Form/FormFields/ToggleField.js index ac435ec14c..843c43eb3b 100644 --- a/web/src/components/Form/FormFields/ToggleField.js +++ b/web/src/components/Form/FormFields/ToggleField.js @@ -79,7 +79,7 @@ class ToggleField extends Component { {...rest} > <div className="d-flex justify-content-between"> - <div>{label}</div> + <div className={selected ? '' : 'half-opacity'}>{label}</div> <Toggle selected={selected} options={options} diff --git a/web/src/components/Form/FormFields/_DropdownField.scss b/web/src/components/Form/FormFields/_DropdownField.scss index a7aa1e391d..511115ff0f 100644 --- a/web/src/components/Form/FormFields/_DropdownField.scss +++ b/web/src/components/Form/FormFields/_DropdownField.scss @@ -15,6 +15,15 @@ $dropdown-option--padding: 0.25rem; } } +.dropdown-option-open { + margin: 0px !important; + & img { + height: 1rem; + margin-right: 0.25rem; + margin-bottom: 0.25rem; + } +} + .disabled { .field-children { color: $colors-deactivate; diff --git a/web/src/components/Form/FormFields/_FieldWrapper.scss b/web/src/components/Form/FormFields/_FieldWrapper.scss index a95fb9c42f..67b9aa599a 100644 --- a/web/src/components/Form/FormFields/_FieldWrapper.scss +++ b/web/src/components/Form/FormFields/_FieldWrapper.scss @@ -77,6 +77,8 @@ $outline-height: 1.5px; } .clear-field { + width: 1.25rem !important; + height: 1.25rem !important; @include size($valid-icon-size); svg { @include size($valid-icon-size); diff --git a/web/src/components/Form/FormFields/_FormFields.scss b/web/src/components/Form/FormFields/_FormFields.scss index 7da02f0e1f..1580c5c8b1 100644 --- a/web/src/components/Form/FormFields/_FormFields.scss +++ b/web/src/components/Form/FormFields/_FormFields.scss @@ -1,5 +1,6 @@ @import './DropdownField.scss'; @import './FieldWrapper.scss'; +@import './PinInput.scss'; $toggle-size: 14px; $toggle-border: 2px; @@ -61,10 +62,6 @@ $placeholder--font-weight: bold; } } - .datefield-input { - // visibility: hidden; - } - .datefield-values-wrapper { display: flex; > * { @@ -107,7 +104,7 @@ $placeholder--font-weight: bold; } } .dropdown-triangle::after { - bottom: 0 !important; + bottom: 0 !important; } } } @@ -127,9 +124,6 @@ $placeholder--font-weight: bold; } } -.input_file { -} - .placeholder { font-size: $placeholder--font-size; font-weight: $placeholder--font-weight; @@ -150,14 +144,14 @@ $placeholder--font-weight: bold; position: relative; top: 0 !important; } - .paper-clip-icon{ + .paper-clip-icon { .action_notification-svg { background-color: $link; width: 1.2rem; height: 1.2rem; border-radius: 50%; display: flex; - margin-left: 5px; + margin-left: 5px; svg { width: 0.8rem !important; height: 0.8rem !important; @@ -215,7 +209,7 @@ $placeholder--font-weight: bold; cursor: pointer; &.left { - opacity: 0.3; + opacity: 0.3; .option-text { position: relative; left: 23px; @@ -309,9 +303,9 @@ $placeholder--font-weight: bold; .toggle-action_button { width: $toggle-size * 3; &.left .option-text { - left: 20px; + left: 20px; } } } } -} \ No newline at end of file +} diff --git a/web/src/components/Form/FormFields/_PinInput.scss b/web/src/components/Form/FormFields/_PinInput.scss new file mode 100644 index 0000000000..f337c23da3 --- /dev/null +++ b/web/src/components/Form/FormFields/_PinInput.scss @@ -0,0 +1,48 @@ +.mainContainer { + display: flex; + width: fit-content; + margin: auto; + position: relative; + justify-content: center; + align-items: center; + input { + width: 30px; + height: 30px; + border-radius: 0.5rem; + border: 1px solid $colors-border; + background: $app-background-color; + text-align: center; + font-size: large; + } + .masterInput { + position: absolute; + width: 100%; + top: 8px; + opacity: 0 !important; + } + + .seperator { + width: 2rem; + border: 1px solid $colors-black; + background: $colors-black; + } +} + +.active { + border: 1px solid $colors-black !important; +} + +.error { + border: 1px solid red !important; +} + +.warning_text { + text-align: center; +} + +.group { + padding: 1rem; + & input { + margin: 0rem 0.25rem; + } +} diff --git a/web/src/components/Form/TradeFormFields/ChoiceSelector.js b/web/src/components/Form/TradeFormFields/ChoiceSelector.js index f998a129f2..1a1444c199 100644 --- a/web/src/components/Form/TradeFormFields/ChoiceSelector.js +++ b/web/src/components/Form/TradeFormFields/ChoiceSelector.js @@ -15,6 +15,7 @@ const ChoiceSelector = (props) => { 'justify-content-center', 'align-items-center', 'pointer', + option.value !== input.value ? option.className : '', 'holla-button-font', { active: option.value === input.value } )} diff --git a/web/src/components/Form/TradeFormFields/DropDown.js b/web/src/components/Form/TradeFormFields/DropDown.js index 579971265f..f90021cf57 100644 --- a/web/src/components/Form/TradeFormFields/DropDown.js +++ b/web/src/components/Form/TradeFormFields/DropDown.js @@ -1,6 +1,6 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Select } from 'antd'; -import { CaretDownOutlined } from '@ant-design/icons'; +import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons'; import STRINGS from 'config/localizedStrings'; const { Option } = Select; @@ -8,6 +8,7 @@ const { Option } = Select; // todo: add antd component to redux form const DropDown = (props) => { + const [isOpen, setIsOpen] = useState(false); const { input: { onChange, value }, options, @@ -22,7 +23,10 @@ const DropDown = (props) => { bordered={false} size="small" onChange={onChange} - suffixIcon={<CaretDownOutlined />} + onClick={() => { + setIsOpen((prev) => !prev); + }} + suffixIcon={isOpen ? <CaretUpOutlined /> : <CaretDownOutlined />} className="custom-select-input-style w-100 elevated" dropdownClassName="custom-select-style select-option-wrapper" > diff --git a/web/src/components/Form/TradeFormFields/InputField.js b/web/src/components/Form/TradeFormFields/InputField.js index f577e73ce1..b291b32207 100644 --- a/web/src/components/Form/TradeFormFields/InputField.js +++ b/web/src/components/Form/TradeFormFields/InputField.js @@ -21,7 +21,7 @@ const InputField = (props) => { > <input ref={setRef} {...input} {...rest} /> {currency && ( - <div className="trade_input-input-currency d-flex justify-content-center align-items-center"> + <div className="trade_input-input-currency d-flex justify-content-center align-items-center mr-2"> {currency} </div> )} diff --git a/web/src/components/Form/TradeFormFields/Slider.js b/web/src/components/Form/TradeFormFields/Slider.js index 29c0deeb25..082d239ce6 100644 --- a/web/src/components/Form/TradeFormFields/Slider.js +++ b/web/src/components/Form/TradeFormFields/Slider.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { Slider } from 'antd'; // todo: connect antd slider to redux form @@ -31,8 +31,18 @@ const marks = { }, }; -const SizeSlider = (props) => { - const { onClick } = props; +const SizeSlider = ({ onClick, value, setRef }) => { + const [val, setVal] = useState(0); + + useEffect(() => { + if (setRef) { + setRef({ + reset: () => { + setVal(0); + }, + }); + } + }, [setRef]); return ( <div className="size-slider px-1 pb-2"> @@ -42,6 +52,8 @@ const SizeSlider = (props) => { defaultValue={0} tooltipVisible={false} onAfterChange={onClick} + value={val} + onChange={setVal} /> </div> ); diff --git a/web/src/components/Form/TradeFormFields/TabSelector.js b/web/src/components/Form/TradeFormFields/TabSelector.js index 61bfb88286..d5dd1a7a98 100644 --- a/web/src/components/Form/TradeFormFields/TabSelector.js +++ b/web/src/components/Form/TradeFormFields/TabSelector.js @@ -9,9 +9,15 @@ const TabSelector = (props) => { {options.map((option, index) => ( <div key={`type-${index}`} - className={classnames('text-uppercase', 'text-center', 'pointer', { - active: input.value === option.value, - })} + className={classnames( + 'text-uppercase', + 'text-center', + 'pointer', + input.value !== option.value ? option.className : '', + { + active: input.value === option.value, + } + )} onClick={() => input.onChange(option.value)} > {option.label} diff --git a/web/src/components/Form/TradeFormFields/_TradeFormFields.scss b/web/src/components/Form/TradeFormFields/_TradeFormFields.scss index f795c12dff..1fbaf70a85 100644 --- a/web/src/components/Form/TradeFormFields/_TradeFormFields.scss +++ b/web/src/components/Form/TradeFormFields/_TradeFormFields.scss @@ -97,6 +97,11 @@ $padding: 0.25rem; } .size-slider { + .ant-slider { + * { + transition: 0.1s; + } + } .ant-slider-with-marks { margin-bottom: 10px; } diff --git a/web/src/components/Form/factoryFields.js b/web/src/components/Form/factoryFields.js index 396566e7ea..ff935fd017 100644 --- a/web/src/components/Form/factoryFields.js +++ b/web/src/components/Form/factoryFields.js @@ -11,6 +11,7 @@ import EditableInputField from './FormFields/EditableInputField'; import CaptchaField from './FormFields/Captcha'; import ToggleField from './FormFields/ToggleField'; import DumbField from './FormFields/DumbFieldForm'; +import PinInput from './FormFields/PinInput'; const renderFields = (fields = {}, callback) => { return ( @@ -62,6 +63,8 @@ const renderFields = (fields = {}, callback) => { return <Field component={TextAreaField} {...commonProps} />; case 'toggle': return <Field component={ToggleField} {...commonProps} />; + case 'pin': + return <Field component={PinInput} {...commonProps} />; case 'text': case 'password': case 'email': diff --git a/web/src/components/FormButton/Button.js b/web/src/components/FormButton/Button.js new file mode 100644 index 0000000000..871e9988e1 --- /dev/null +++ b/web/src/components/FormButton/Button.js @@ -0,0 +1,31 @@ +import React from 'react'; +import { Button } from 'antd'; + +const FormButton = ({ + type = 'primary', + handleSubmit = () => {}, + disabled = true, + size, + className = '', + style = null, + buttonText = '', + htmlType = '', +}) => { + return ( + <div> + <Button + type={type} + onClick={handleSubmit} + disabled={disabled} + size={size} + className={className} + style={style} + htmlType={htmlType} + > + {buttonText} + </Button> + </div> + ); +}; + +export default FormButton; diff --git a/web/src/components/Notification/ContactForm.js b/web/src/components/Notification/ContactForm.js index 81fc09318f..572ae93b90 100644 --- a/web/src/components/Notification/ContactForm.js +++ b/web/src/components/Notification/ContactForm.js @@ -1,9 +1,7 @@ import React from 'react'; -import { Button } from '../'; +import { Button, EditWrapper } from 'components'; import { NotificationWraper, NotificationContent } from './Notification'; -import { EditWrapper } from 'components'; - -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; const ContactFormNotification = ({ onClose, icons: ICONS }) => { return ( diff --git a/web/src/components/Notification/GenerateAddress.js b/web/src/components/Notification/GenerateAddress.js index baec91e4ec..01974d5ca6 100644 --- a/web/src/components/Notification/GenerateAddress.js +++ b/web/src/components/Notification/GenerateAddress.js @@ -1,10 +1,8 @@ import React from 'react'; import { DEFAULT_COIN_DATA } from 'config/constants'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import { NotificationWraper, NotificationContent } from './Notification'; -import { Button, Loader } from '../'; -import { EditWrapper } from 'components'; -import Image from 'components/Image'; +import { Button, Loader, EditWrapper, Image } from 'components'; const GenerateAddressNotification = ({ type, diff --git a/web/src/components/Notification/GenerateApiKey.js b/web/src/components/Notification/GenerateApiKey.js index 230e211d2f..2d5e7b5d94 100644 --- a/web/src/components/Notification/GenerateApiKey.js +++ b/web/src/components/Notification/GenerateApiKey.js @@ -1,9 +1,8 @@ import React from 'react'; -import STRINGS from '../../config/localizedStrings'; -import { EditWrapper } from 'components'; +import STRINGS from 'config/localizedStrings'; +import { Button, EditWrapper } from 'components'; import { NotificationWraper, NotificationContent } from './Notification'; -import { Button } from '../'; export const GenerateApiKey = (props) => { const { diff --git a/web/src/components/Notification/InviteFriends.js b/web/src/components/Notification/InviteFriends.js index daa162dc21..f328995221 100644 --- a/web/src/components/Notification/InviteFriends.js +++ b/web/src/components/Notification/InviteFriends.js @@ -2,13 +2,11 @@ import React, { Component } from 'react'; import { CopyToClipboard } from 'react-copy-to-clipboard'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; - -import IconTitle from '../IconTitle'; -import DumbField from '../Form/FormFields/DumbField'; -import Button from '../Button'; -import STRINGS from '../../config/localizedStrings'; -import { getUserReferralCount } from '../../actions/userAction'; -import { setSnackNotification } from '../../actions/appActions'; +import DumbField from 'components/Form/FormFields/DumbField'; +import { Button, IconTitle } from 'components'; +import STRINGS from 'config/localizedStrings'; +import { getUserReferralCount } from 'actions/userAction'; +import { setSnackNotification } from 'actions/appActions'; import { EditWrapper } from 'components'; const RenderDumbField = (props) => <DumbField {...props} />; diff --git a/web/src/components/Notification/Logout.js b/web/src/components/Notification/Logout.js index 5d98f01b67..f0cec3377b 100644 --- a/web/src/components/Notification/Logout.js +++ b/web/src/components/Notification/Logout.js @@ -1,8 +1,7 @@ import React from 'react'; -import { Button } from '../'; +import { Button } from 'components'; import { NotificationWraper, NotificationContent } from './Notification'; - -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; const ERROR_DENIED = 'Error Denied: '; const ERROR_INVALID_TOKEN = 'Invalid token'; diff --git a/web/src/components/Notification/Notification.js b/web/src/components/Notification/Notification.js index ed361a2338..61e4af4c63 100644 --- a/web/src/components/Notification/Notification.js +++ b/web/src/components/Notification/Notification.js @@ -1,10 +1,8 @@ import React from 'react'; import classnames from 'classnames'; import { isMobile } from 'react-device-detect'; -import { Button } from '../'; -import STRINGS from '../../config/localizedStrings'; -import Image from 'components/Image'; -import { EditWrapper } from 'components'; +import STRINGS from 'config/localizedStrings'; +import { EditWrapper, Button, Image } from 'components'; export const NotificationWraperDesktop = ({ icon, diff --git a/web/src/components/Notification/Order.js b/web/src/components/Notification/Order.js index 00301b107c..31e230b9b8 100644 --- a/web/src/components/Notification/Order.js +++ b/web/src/components/Notification/Order.js @@ -1,12 +1,9 @@ import React from 'react'; import math from 'mathjs'; import { connect } from 'react-redux'; -import { - CURRENCY_PRICE_FORMAT, - DEFAULT_COIN_DATA, -} from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; -import { formatBtcAmount, formatToCurrency } from '../../utils/currency'; +import { CURRENCY_PRICE_FORMAT, DEFAULT_COIN_DATA } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; +import { formatBtcAmount, formatToCurrency } from 'utils/currency'; import { NotificationWraper, NotificationContent, diff --git a/web/src/components/Notification/Trade.js b/web/src/components/Notification/Trade.js index ea42702a20..7926b2f53c 100644 --- a/web/src/components/Notification/Trade.js +++ b/web/src/components/Notification/Trade.js @@ -1,17 +1,14 @@ import React from 'react'; import math from 'mathjs'; import { connect } from 'react-redux'; -import { - CURRENCY_PRICE_FORMAT, - DEFAULT_COIN_DATA, -} from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; +import { CURRENCY_PRICE_FORMAT, DEFAULT_COIN_DATA } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; import { NotificationWraper, NotificationContent, InformationRow, } from './Notification'; -import { formatToCurrency } from '../../utils/currency'; +import { formatToCurrency } from 'utils/currency'; const SIDE_BUY = 'buy'; const SIDE_SELL = 'sell'; diff --git a/web/src/components/Notification/Verification.js b/web/src/components/Notification/Verification.js index 555cfaa982..b8084aa91a 100644 --- a/web/src/components/Notification/Verification.js +++ b/web/src/components/Notification/Verification.js @@ -1,9 +1,8 @@ import React from 'react'; -import { Button } from '../'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import { NotificationWraper, NotificationContent } from './Notification'; -import { EditWrapper } from 'components'; +import { EditWrapper, Button } from 'components'; const getTitleAndIcon = (type, ICONS) => { const data = { diff --git a/web/src/components/Notification/VerificationWarning.js b/web/src/components/Notification/VerificationWarning.js index 87c708a182..cdae4fb5ce 100644 --- a/web/src/components/Notification/VerificationWarning.js +++ b/web/src/components/Notification/VerificationWarning.js @@ -1,9 +1,7 @@ import React from 'react'; -import { CurrencyBallWithPrice, ActionNotification } from '../'; -import { ICONS } from '../../config/constants'; -import { NotificationWraper, NotificationContent } from './Notification'; - -import STRINGS from '../../config/localizedStrings'; +import { ICONS } from 'config/constants'; +import { NotificationWraper } from './Notification'; +import STRINGS from 'config/localizedStrings'; const VerificationWarningNotification = ({}) => { return ( diff --git a/web/src/components/Notification/Withdraw.js b/web/src/components/Notification/Withdraw.js index 7677063c1c..2293652642 100644 --- a/web/src/components/Notification/Withdraw.js +++ b/web/src/components/Notification/Withdraw.js @@ -1,10 +1,8 @@ import React from 'react'; import { NotificationWraper, NotificationContent } from './Notification'; -import { EXPLORERS_ENDPOINT } from '../../config/constants'; -import { Button } from '../'; - -import STRINGS from '../../config/localizedStrings'; -import { EditWrapper } from 'components'; +import { EXPLORERS_ENDPOINT } from 'config/constants'; +import { Button, EditWrapper } from 'components'; +import STRINGS from 'config/localizedStrings'; const WithdrawNotification = ({ data, onClose, icons: ICONS }) => { const notificationProps = { diff --git a/web/src/components/Notification/constants.js b/web/src/components/Notification/constants.js index 960740968e..69fdbc4030 100644 --- a/web/src/components/Notification/constants.js +++ b/web/src/components/Notification/constants.js @@ -1,6 +1,6 @@ -// import { BASE_CURRENCY } from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; -import { DEFAULT_COIN_DATA } from '../../config/constants'; +// import { BASE_CURRENCY } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; +import { DEFAULT_COIN_DATA } from 'config/constants'; // const generateBaseDepositTexts = (strings) => ({ // TITLE: strings.formatString( diff --git a/web/src/components/OtpForm/_OtpForm.scss b/web/src/components/OtpForm/_OtpForm.scss index 222612a461..967c5158d4 100644 --- a/web/src/components/OtpForm/_OtpForm.scss +++ b/web/src/components/OtpForm/_OtpForm.scss @@ -6,11 +6,22 @@ border-top: 1px solid $colors-border; margin: 1rem 0; position: relative; +} - .otp_form-title-text { - font-weight: bold; - font-size: $font-size-main; - } +.otp_form-info-text { + font-weight: bold; + font-size: $font-size-main; + width: 100%; + text-align: center !important; +} + +.otp_form-subnote-text { + font-weight: 400; + font-size: $font-size-main; + opacity: 0.7; + width: 100%; + margin-top: 5rem; + text-align: center !important; } .otp_form-fields { diff --git a/web/src/components/OtpForm/index.js b/web/src/components/OtpForm/index.js index 529f6bb6e4..a1b316e327 100644 --- a/web/src/components/OtpForm/index.js +++ b/web/src/components/OtpForm/index.js @@ -1,11 +1,8 @@ import React, { Component } from 'react'; import { reduxForm } from 'redux-form'; -import { required, validateOtp } from '../../components/Form/validations'; -import renderFields from '../../components/Form/factoryFields'; -import { Button, IconTitle, ActionNotification } from '../'; - -import STRINGS from '../../config/localizedStrings'; -import { EditWrapper } from 'components'; +import renderFields from 'components/Form/factoryFields'; +import { IconTitle, ActionNotification } from 'components'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; class Form extends Component { @@ -31,12 +28,8 @@ class Form extends Component { setFormValues = () => { const formValues = { otp_code: { - type: 'number', - stringId: - 'OTP_FORM.OTP_LABEL,OTP_FORM.OTP_PLACEHOLDER,OTP_FORM.ERROR_INVALID', + type: 'pin', label: STRINGS['OTP_FORM.OTP_LABEL'], - placeholder: STRINGS['OTP_FORM.OTP_PLACEHOLDER'], - validate: [required, validateOtp(STRINGS['OTP_FORM.ERROR_INVALID'])], fullWidth: true, }, }; @@ -53,11 +46,9 @@ class Form extends Component { render() { const { - handleSubmit, submitting, - pristine, + handleSubmit, error, - valid, onClickHelp, icons: ICONS, } = this.props; @@ -68,15 +59,10 @@ class Form extends Component { <IconTitle stringId="OTP_FORM.OTP_TITLE" text={STRINGS['OTP_FORM.OTP_TITLE']} - iconId="OTP_CODE" - iconPath={ICONS['OTP_CODE']} + iconId="SET_NEW_PASSWORD" + iconPath={ICONS['SET_NEW_PASSWORD']} /> <div className="otp_form-title-wrapper"> - <span className="otp_form-title-text"> - <EditWrapper stringId="OTP_FORM.OTP_FORM_TITLE"> - {STRINGS['OTP_FORM.OTP_FORM_TITLE']} - </EditWrapper> - </span> {onClickHelp && ( <ActionNotification stringId="NEED_HELP_TEXT" @@ -90,14 +76,19 @@ class Form extends Component { </div> <form onSubmit={handleSubmit} className="w-100" ref={this.setFormRef}> <div className="w-100 otp_form-fields"> - {renderFields(formValues)} - {error && <div className="warning_text">{error}</div>} + {renderFields(formValues, { + isSubmitting: submitting, + error, + handleSubmit, + })} + </div> + <div className="otp_form-info-text"> + {STRINGS['OTP_FORM.OTP_FORM_INFO']} + </div> + <div className="otp_form-subnote-text"> + {STRINGS['OTP_FORM.OTP_FORM_SUBNOTE_LINE_1']} + {STRINGS['OTP_FORM.OTP_FORM_SUBNOTE_LINE_2']} </div> - <EditWrapper stringId="OTP_FORM.OTP_BUTTON" /> - <Button - label={STRINGS['OTP_FORM.OTP_BUTTON']} - disabled={pristine || submitting || !valid} - /> </form> </div> ); diff --git a/web/src/components/QuickTrade/InputBlock.js b/web/src/components/QuickTrade/InputBlock.js index d269136475..e83a09e20a 100644 --- a/web/src/components/QuickTrade/InputBlock.js +++ b/web/src/components/QuickTrade/InputBlock.js @@ -2,12 +2,10 @@ import React, { Component } from 'react'; import classnames from 'classnames'; import math from 'mathjs'; import { isNumeric, isFloat } from 'validator'; - -import { CurrencyBall } from '../../components'; - -import { minValue, maxValue } from '../../components/Form/validations'; -import { FieldError } from '../../components/Form/FormFields/FieldWrapper'; -import { FLEX_CENTER_CLASSES, DEFAULT_COIN_DATA } from '../../config/constants'; +import { CurrencyBall } from 'components'; +import { minValue, maxValue } from 'components/Form/validations'; +import { FieldError } from 'components/Form/FormFields/FieldWrapper'; +import { FLEX_CENTER_CLASSES, DEFAULT_COIN_DATA } from 'config/constants'; import { translateError } from './utils'; const PLACEHOLDER = '0.00'; diff --git a/web/src/components/QuickTrade/InputGroup.js b/web/src/components/QuickTrade/InputGroup.js index a1ab564f06..b7b27d37a0 100644 --- a/web/src/components/QuickTrade/InputGroup.js +++ b/web/src/components/QuickTrade/InputGroup.js @@ -64,7 +64,7 @@ class InputGroup extends React.PureComponent { } = this.props; const keydata = pair.split('-'); let error = ''; - if (!value) { + if (!value || (value && !parseFloat(value))) { error = ''; } else if ( keydata[0] === selectValue && @@ -159,7 +159,7 @@ class InputGroup extends React.PureComponent { placeholder={STRINGS['AMOUNT']} style={isOpen ? { display: 'none' } : { width: '67%' }} className="input-group__input" - value={`${inputValue}`} + value={inputValue || ''} onChange={this.onChangeEvent} bordered={false} step={limits.MIN} diff --git a/web/src/components/QuickTrade/ToogleButton.js b/web/src/components/QuickTrade/ToogleButton.js index dc6e6006bd..84b62c9364 100644 --- a/web/src/components/QuickTrade/ToogleButton.js +++ b/web/src/components/QuickTrade/ToogleButton.js @@ -1,7 +1,7 @@ import React from 'react'; import classnames from 'classnames'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; const ToogleButton = ({ onToogle, values, selected }) => ( <div className={classnames('toogle_button-wrapper', 'd-flex')}> diff --git a/web/src/components/QuickTrade/index.js b/web/src/components/QuickTrade/index.js index dd4ddfd694..76efadace1 100644 --- a/web/src/components/QuickTrade/index.js +++ b/web/src/components/QuickTrade/index.js @@ -193,6 +193,23 @@ class QuickTrade extends Component { isUseBroker = false; } const increment_unit = isUseBroker ? SIZE && SIZE.STEP : increment_size; + + const getClassnameForPriceDifferences = (priceDifferences) => { + if (priceDifference === 0) + return 'price-diff-none trade-tab-price_diff_none'; + if (priceDifference < 0) + return 'price-diff-down trade-tab-price_diff_down'; + return 'price-diff-up trade-tab-price_diff_up'; + }; + + const getClassnameForTickDifferences = (tickDifferences, state) => { + if (tickDifferences === 0) + return `glance-price-diff-none glance-trade-tab-price_diff_none ${state}`; + if (tickDifferences < 0) + return `glance-price-diff-down glance-trade-tab-price_diff_down ${state}`; + return `glance-price-diff-up glance-trade-tab-price_diff_up ${state}`; + }; + return ( <div className="quick_trade-container"> <div @@ -279,12 +296,8 @@ class QuickTrade extends Component { <div className={classnames( 'title-font', - priceDifference < 0 - ? 'price-diff-down trade-tab-price_diff_down' - : 'price-diff-up trade-tab-price_diff_up', - tickerDiff < 0 - ? `glance-price-diff-down glance-trade-tab-price_diff_down ${state}` - : `glance-price-diff-up glance-trade-tab-price_diff_up ${state}` + getClassnameForPriceDifferences(priceDifference), + getClassnameForTickDifferences(tickerDiff, state) )} > {priceDifferencePercent} @@ -301,6 +314,7 @@ class QuickTrade extends Component { containerProps={{ style: { height: '100%', width: '100%' }, }} + renderDefaultLine /> </div> <div className="d-flex pb-35"> diff --git a/web/src/components/QuickTrade/utils.js b/web/src/components/QuickTrade/utils.js index 2d9205c74e..f3650adc46 100644 --- a/web/src/components/QuickTrade/utils.js +++ b/web/src/components/QuickTrade/utils.js @@ -1,4 +1,4 @@ -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; const QUICK_TRADE_OUT_OF_LIMITS = 'Order size is out of the limits'; const QUICK_TRADE_TOKEN_USED = 'Token has been used'; diff --git a/web/src/components/SidebarHub/CurrencySelector.js b/web/src/components/SidebarHub/CurrencySelector.js index a1ffc6f0d9..b40a5591e0 100644 --- a/web/src/components/SidebarHub/CurrencySelector.js +++ b/web/src/components/SidebarHub/CurrencySelector.js @@ -1,7 +1,6 @@ import React from 'react'; import classnames from 'classnames'; import { connect } from 'react-redux'; -import STRINGS from '../../config/localizedStrings'; const CurrencySelector = ({ activeCurrency, changeCurrency, coins }) => { return ( diff --git a/web/src/components/SidebarHub/index.js b/web/src/components/SidebarHub/index.js index 4e1ee18f22..50cb4b380c 100644 --- a/web/src/components/SidebarHub/index.js +++ b/web/src/components/SidebarHub/index.js @@ -1,10 +1,8 @@ import React, { Component } from 'react'; import classnames from 'classnames'; import withConfig from 'components/ConfigProvider/withConfig'; -import STRINGS from '../../config/localizedStrings'; -import { IconTitle } from '../../components'; - -import { ButtonLink, Wallet } from '../'; +import STRINGS from 'config/localizedStrings'; +import { ButtonLink, Wallet, IconTitle } from 'components'; class SidebarHub extends Component { render() { diff --git a/web/src/components/SmartTarget/index.js b/web/src/components/SmartTarget/index.js index eab4197f83..984b8c16b8 100644 --- a/web/src/components/SmartTarget/index.js +++ b/web/src/components/SmartTarget/index.js @@ -12,25 +12,33 @@ import renderFields from 'components/Form/factoryFields'; import { getErrorLocalized } from 'utils/errors'; import { IconTitle, ErrorBoundary } from 'components'; -const DefaultChildren = ({ strings: STRINGS, icons: ICONS }) => { +const DefaultChildren = ({ + strings: STRINGS, + icons: ICONS, + extra: { top, bottom } = {}, +}) => { return ( - <div - style={{ - height: '28rem', - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - }} - > - <IconTitle - stringId="PAGE_UNDER_CONSTRUCTION" - text={STRINGS['PAGE_UNDER_CONSTRUCTION']} - iconId="FIAT_UNDER_CONSTRUCTION" - iconPath={ICONS['FIAT_UNDER_CONSTRUCTION']} - className="flex-direction-column" - /> - </div> + <Fragment> + {top} + <div + style={{ + height: '28rem', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + }} + > + <IconTitle + stringId="PAGE_UNDER_CONSTRUCTION" + text={STRINGS['PAGE_UNDER_CONSTRUCTION']} + iconId="FIAT_UNDER_CONSTRUCTION" + iconPath={ICONS['FIAT_UNDER_CONSTRUCTION']} + className="flex-direction-column" + /> + </div> + {bottom} + </Fragment> ); }; @@ -44,6 +52,7 @@ const SmartTarget = (props) => { loaderClassName = 'default-remote-component-loader', errorClassName = 'default-remote-component-error', icons: ICONS, + extra, } = props; return targets.includes(id) ? ( @@ -68,7 +77,7 @@ const SmartTarget = (props) => { ) : children ? ( <Fragment>{children}</Fragment> ) : ( - <DefaultChildren strings={STRINGS} icons={ICONS} /> + <DefaultChildren strings={STRINGS} icons={ICONS} extra={extra} /> ); }; diff --git a/web/src/components/SnackNotification/_SnackNotification.scss b/web/src/components/SnackNotification/_SnackNotification.scss index a16cc69593..29eedbadba 100644 --- a/web/src/components/SnackNotification/_SnackNotification.scss +++ b/web/src/components/SnackNotification/_SnackNotification.scss @@ -7,9 +7,10 @@ height: 3.5rem; left: calc(50vw - 10rem); padding: 0.3rem 0.5rem !important; - position: absolute; + position: fixed; + min-width: 20rem; + max-width: 30rem; // top: 1rem; - width: 20rem; z-index: 9999; -webkit-box-shadow: 2px 2px 3px 2px rgba(0, 0, 0, 0.4); -moz-box-shadow: 2px 2px 3px 2px rgba(0, 0, 0, 0.4); diff --git a/web/src/components/TabController/_TabController.scss b/web/src/components/TabController/_TabController.scss index 98829e6b22..737ef0a1af 100644 --- a/web/src/components/TabController/_TabController.scss +++ b/web/src/components/TabController/_TabController.scss @@ -20,6 +20,7 @@ $tab_controller-item-min-width: 8rem; .layout-mobile { .tab_controller-tabs, .tab_item { + transition: 0.3s; font-size: $extra-thick--font-size !important; } } diff --git a/web/src/components/Table/TableBody.js b/web/src/components/Table/TableBody.js index 45572d8247..443d49b457 100644 --- a/web/src/components/Table/TableBody.js +++ b/web/src/components/Table/TableBody.js @@ -82,6 +82,7 @@ const TableBody = ({ cancelDelayData, expandable, cssTransitionClassName, + rowKey, }) => ( <tbody className={classnames('table_body-wrapper', { @@ -113,6 +114,7 @@ const TableBody = ({ <Fragment> {data.map((row, rowIndex) => ( <TableRow + key={rowKey(row)} headers={headers} cancelDelayData={cancelDelayData} expandable={expandable} diff --git a/web/src/components/Table/index.js b/web/src/components/Table/index.js index 44c7dfcaed..2c59fa7e1f 100644 --- a/web/src/components/Table/index.js +++ b/web/src/components/Table/index.js @@ -6,7 +6,7 @@ import TableBody from './TableBody'; // import TableFooter from './TableFooter'; import Paginator from './paginator'; import { EditWrapper } from 'components'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; class Table extends Component { state = { @@ -105,6 +105,7 @@ class Table extends Component { className, expandable, cssTransitionClassName, + rowKey, } = this.props; const count = this.props.count || this.props.data.length; @@ -153,6 +154,7 @@ class Table extends Component { withIcon={withIcon} expandable={expandable} cssTransitionClassName={cssTransitionClassName} + rowKey={rowKey} /> </table> </div> @@ -190,6 +192,7 @@ Table.defaultProps = { rowExpandable: () => false, }, cssTransitionClassName: '', + rowKey: ({ id }) => id, }; export default Table; diff --git a/web/src/components/Table/paginator.js b/web/src/components/Table/paginator.js index 9a9fbe40f2..43d1fbb6ab 100644 --- a/web/src/components/Table/paginator.js +++ b/web/src/components/Table/paginator.js @@ -1,8 +1,8 @@ import React from 'react'; import classnames from 'classnames'; -import { ActionNotification } from '../'; +import { ActionNotification } from 'components'; import withConfig from 'components/ConfigProvider/withConfig'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; const renderPageCount = (currentPage, totalPages) => { if (totalPages > 0) { diff --git a/web/src/components/Wallet/Section.js b/web/src/components/Wallet/Section.js index 67a38777af..6bf9f774c4 100644 --- a/web/src/components/Wallet/Section.js +++ b/web/src/components/Wallet/Section.js @@ -1,12 +1,12 @@ import React from 'react'; import math from 'mathjs'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import { BASE_CURRENCY, CURRENCY_PRICE_FORMAT, DEFAULT_COIN_DATA, -} from '../../config/constants'; -import { formatToCurrency } from '../../utils/currency'; +} from 'config/constants'; +import { formatToCurrency } from 'utils/currency'; const TextHolders = ({ ordersOfSymbol, currencySymbol, hold, name }) => { const ordersText = diff --git a/web/src/components/Wallet/index.js b/web/src/components/Wallet/index.js index 8cddf8815a..420cc5ba6c 100644 --- a/web/src/components/Wallet/index.js +++ b/web/src/components/Wallet/index.js @@ -3,12 +3,11 @@ import { connect } from 'react-redux'; import { Link } from 'react-router'; import classnames from 'classnames'; -import { Accordion, ControlledScrollbar } from 'components'; -import { BASE_CURRENCY, DEFAULT_COIN_DATA } from '../../config/constants'; -import { formatToCurrency } from '../../utils/currency'; +import { Accordion, ControlledScrollbar, DonutChart } from 'components'; +import { BASE_CURRENCY, DEFAULT_COIN_DATA } from 'config/constants'; +import { formatToCurrency } from 'utils/currency'; import WalletSection from './Section'; -import { DonutChart } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; class Wallet extends Component { state = { diff --git a/web/src/components/WarningVerification/index.js b/web/src/components/WarningVerification/index.js index be5367bb99..c4527081f6 100644 --- a/web/src/components/WarningVerification/index.js +++ b/web/src/components/WarningVerification/index.js @@ -1,5 +1,5 @@ import React from 'react'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; const generateTexts = (level = 0) => { if (level === 1) { diff --git a/web/src/config/icons/dark.js b/web/src/config/icons/dark.js index 5084dfecd8..7a7773ea77 100644 --- a/web/src/config/icons/dark.js +++ b/web/src/config/icons/dark.js @@ -39,6 +39,7 @@ const nestedIcons = { SECURITY: '/assets/images/tab-security.svg', VERIFY: '/assets/images/tab-verify.svg', SETTING: '/assets/images/tab-setting.svg', + APPS: '/assets/images/apps.svg', API: '/assets/images/tab-api.svg', STAKE: '/assets/images/stake-page-icon.svg', }, @@ -76,6 +77,13 @@ const nestedIcons = { RISK_MANAGE_WARNING_ICON: '/assets/images/risk-manage-pop-warning.svg', }, + APPS: { + ALL: '/assets/images/all-apps.svg', + USER: '/assets/images/my-apps.svg', + CONFIGURE: '/assets/images/interface-settings-icon.svg', + REMOVE: '/assets/images/cancel-cross-active.svg', + }, + SECURITY: { OTP_ICON: '/assets/images/2fa-security-icon.svg', CHANGE_PASSWORD_ICON: '/assets/images/password-security-icon.svg', @@ -181,7 +189,11 @@ const nestedIcons = { BLUE_ARROW_RIGHT: '/assets/images/blue-arrow-right.svg', SESSION_TIMED_OUT: '/assets/images/session-timed-out.svg', BLUE_EDIT: '/assets/images/blue-edit-exir-icon.svg', + BLUE_TRADE_ICON: '/assets/images/trade.svg', + BLUE_EARN_ICON: '/assets/images/earn.svg', BLUE_PLUS: '/assets/images/max-plus-blue-icon.svg', + BLUE_DEPOSIT_ICON: '/assets/images/blue-deposit-icon.svg', + BLUE_WITHROW_ICON: '/assets/images/blue_withrow_icon.svg', BLUE_TIMER: '/assets/images/timer-icon.svg', NOTIFICATION_VERIFICATION_WARNING: '/assets/images/verification.svg', @@ -222,7 +234,7 @@ const nestedIcons = { REFER_ICON: '/assets/images/refer-icon.svg', STAKETOKEN_ICON: '/assets/images/stake.svg', - DEFAULT_ICON: '/assets/icons/missing-coin-light.svg', + DEFAULT_ICON: '/assets/icons/coin-graphic-not-detected.svg', EXPIRED_ICON: '/assets/images/expired.svg', HAP_ACCOUNT_ICON: '/assets/icons/hap-account-icon.svg', @@ -248,6 +260,7 @@ const nestedIcons = { STAKING_VARIABLE: '/assets/stake/variable_icon.svg', STAKING_UNLOCK: '/assets/stake/unlock-unstake-icon.svg', STAKING_BACKGROUND: '/assets/stake/stake-background.jpg', + META_MASK_NOT_FOUND: '/assets/icons/metamask-fox-stake-not-detected.svg', STAKING_ACCOUNT: '', METAMASK: '', MOVE_XHT: '/assets/stake/xht-move.svg', diff --git a/web/src/config/icons/light.js b/web/src/config/icons/light.js index c5bc219413..b039713a45 100644 --- a/web/src/config/icons/light.js +++ b/web/src/config/icons/light.js @@ -167,6 +167,10 @@ const nestedIcons = { SESSION_TIMED_OUT: '/assets/images/session-timed-out.svg', BLUE_EDIT: '/assets/images/blue-edit-exir-icon.svg', BLUE_PLUS: '/assets/images/max-plus-blue-icon.svg', + BLUE_DEPOSIT_ICON: '/assets/images/blue-deposit-icon.svg', + BLUE_TRADE_ICON: '/assets/images/trade.svg', + BLUE_EARN_ICON: '/assets/images/earn.svg', + BLUE_WITHROW_ICON: '/assets/images/blue_withrow_icon.svg', BLUE_TIMER: '/assets/images/timer-icon.svg', NOTIFICATION_VERIFICATION_WARNING: '/assets/images/verification.svg', @@ -205,7 +209,7 @@ const nestedIcons = { REFER_ICON: '/assets/images/refer-icon.svg', STAKETOKEN_ICON: '/assets/images/stake.svg', - DEFAULT_ICON: '/assets/icons/missing-coin-light.svg', + DEFAULT_ICON: '/assets/icons/coin-graphic-not-detected.svg', EXPIRED_ICON: '/assets/images/expired.svg', HAP_ACCOUNT_ICON: '/assets/icons/hap-account-icon.svg', @@ -228,6 +232,7 @@ const nestedIcons = { STAKING_SUCCESSFUL_MESSAGE: '/assets/stake/stake-unstake-light.png', STAKING_PANEL_BACKGROUND: '/assets/stake/stake-unstake-light.png', STAKING_BACKGROUND: '/assets/stake/stake-background-light.png', + META_MASK_NOT_FOUND: '/assets/icons/metamask-fox-stake-not-detected.svg', }; const icons = flatten(nestedIcons, options); diff --git a/web/src/config/icons/static.js b/web/src/config/icons/static.js index 9f50ac8efd..e43376d6b9 100644 --- a/web/src/config/icons/static.js +++ b/web/src/config/icons/static.js @@ -42,15 +42,22 @@ const icons = { ADMIN_PLUGINS: '/assets/images/plugins.svg', ADMIN_TIERS: '/assets/images/tiers.svg', ADMIN_ROLES: '/assets/images/roles.svg', + META_MASK_NOT_FOUND: '/assets/icons/metamask-fox-stake-not-detected.svg', ADMIN_CUSTOMIZE: '/assets/images/customize.svg', ADMIN_MISSING_GO_BACK: '/assets/images/missing-page-go-back-to-dash.svg', HELP_DESCRIPTION_POPUP: '/assets/images/help-popup-description.png', HELP_FOOTER_POPUP: '/assets/images/terms_of_service_and_privacy_policy-tooltip.png', HELP_REFERRAL_BADGE_POPUP: '/assets/images/help-popup-footer.png', + REFRESH: '/assets/icons/refresh-icon.svg', DEPOSIT_TIERS_SECTION: '/assets/images/deposit-tier-section.svg', WITHDRAW_TIERS_SECTION: '/assets/images/withdraw-tier-section.svg', TAKER_TIERS_SECTION: '/assets/images/taker-tier-section.svg', + SEARCH_BLOCKCHAIN: '/assets/images/search-blockchain.svg', + NO_ACTIVE_ORDERS: '/assets/images/no-active-orders-01.svg', + NO_ACTIVE_TRADES: '/assets/images/no-recent-trades-01.svg', + NO_ACTIVE_DEPOSITS: '/assets/images/no-recent-deposits.svg', + NO_ACTIVE_WITHDRAWALS: '/assets/images/no-recent-withdrawals.svg', MAKER_TIERS_SECTION: '/assets/images/maker-tier-section.svg', LIMITS_SECTION_ICON: '/assets/images/limits-coin-tiers.svg', FEES_SECTION_ICON: '/assets/images/limits-pairs-tiers.svg', @@ -71,6 +78,7 @@ const icons = { CANCEL_CROSS_ACTIVE: '/assets/images/cancel-cross-active.svg', VERIFICATION_ICON: '/assets/images/verification-green-tick.svg', CHAT_FEATURE_ICON: '/assets/images/chat-feature-icon.svg', + APPS_FEATURE_ICON: '/assets/images/apps.svg', HOME_PAGE_FEATURE_ICON: '/assets/images/home-page.svg', USER_EMAIL: '/assets/images/user-email.svg', USER_EMAIL_VERIFIED: '/assets/images/user-email-verified.svg', @@ -101,7 +109,7 @@ const icons = { xmr: '/assets/images/xmr-icon.svg', xrp: '/assets/images/xrp-icon.svg', }, - MISSING_ICON: '/assets/images/missing-coin.svg', + MISSING_ICON: '/assets/images/coin-graphic-not-detected.svg', SETTINGS: '/assets/images/noun_settings.svg', CURRENCY_SYMBOL: '/assets/images/noun_currency.svg', BLOCKCHAIN_BACKGROUND: '/assets/images/blockchain-background.svg', @@ -144,6 +152,7 @@ const icons = { FIAT_PLUGIN: '/assets/images/fiat-plugin.svg', DOLLAR_GEAR: '/assets/images/single-dollar-gear.svg', SWITCH_ASSET_FOR_FEES: '/assets/images/switch-asset-for-fees.svg', + CLOCK: '/assets/images/clock.svg', }; export default icons; diff --git a/web/src/config/lang/ar.json b/web/src/config/lang/ar.json index ce82aa6e23..491673b07f 100644 --- a/web/src/config/lang/ar.json +++ b/web/src/config/lang/ar.json @@ -23,6 +23,7 @@ "HELPFUL_RESOURCES_TEXT": "مصادر مفيدة", "HELP_TELEGRAM_TEXT": "تحقق من وثائق API المفتوحة:", "HELP_TELEGRAM_LINK": "https://apidocs.hollaex.com", + "NO_ACTIVE_ORDERS": "No orders detected. Place your orders on the Pro or Quick trade page", "NEED_HELP_TEXT": "تحتاج لمساعدة؟", "HELP_TEXT": "مساعدة", "SUCCESS_TEXT": "نجاح", @@ -1022,6 +1023,7 @@ "SEARCH": "بحث", "SEARCHING": "جاري البحث", "CHECK_DEPOSIT_STATUS": "تحقق من حالة الايداع", + "SEARCH_BLOCKCHAIN_FOR_DEPOSIT": "ابحث في blockchain عن الإيداع الخاص بك", "STATUS_DESCRIPTION": "يمكنك التحقق من حالة الإيداع الخاص بك عن طريق إضافة معرف المعاملة أدناه.", "TRANSACTION_ID": "معرف المعاملة ", "SEARCH_SUCCESS": "تم العثور على المعاملة!", diff --git a/web/src/config/lang/de.json b/web/src/config/lang/de.json index 85cb51fe53..e0e4adc0e9 100644 --- a/web/src/config/lang/de.json +++ b/web/src/config/lang/de.json @@ -7,6 +7,7 @@ "CANCEL_WITHDRAWAL": "Auszahlung abbrechen", "CANCEL_WITHDRAWAL_POPUP_CONFIRM": "Möchten Sie Ihre ausstehende Auszahlung stornieren?:", "TIMESTAMP_FORMAT": "YYYY/MM/DD HH:mm:ss", + "NO_ACTIVE_ORDERS": "No orders detected. Place your orders on the Pro or Quick trade page", "HOUR_FORMAT": "HH:mm:ss", "LOGIN_TEXT": "Login", "SIGN_IN": "Anmelden", diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index 297a45964e..2a84c369e9 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -7,6 +7,10 @@ "CANCEL_WITHDRAWAL": "Cancel Withdrawal", "CANCEL_WITHDRAWAL_POPUP_CONFIRM": "Do you want to cancel your pending withdrawal of:", "TIMESTAMP_FORMAT": "YYYY/MM/DD HH:mm:ss", + "NO_ACTIVE_ORDERS": "No orders detected. Place your orders on the Pro or Quick trade page", + "NO_ACTIVE_TRADES": "Looks like there aren't any trades yet", + "NO_ACTIVE_DEPOSITS": "Looks like there aren't any deposits yet.", + "NO_ACTIVE_WITHDRAWALS": "Looks like there aren't any withdrawals yet", "HOUR_FORMAT": "HH:mm:ss", "LOGIN_TEXT": "Login", "SIGN_IN": "Sign In", @@ -60,6 +64,7 @@ "TAB_VERIFICATION": "Verification", "TAB_SECURITY": "Security", "TAB_SETTINGS": "Settings", + "TAB_APPS": "Apps", "TAB_WALLET": "Wallet", "TAB_SUMMARY": "Summary", "TAB_HISTORY": "History", @@ -154,6 +159,9 @@ "REFERRAL_SUCCESS": { "TITLE": "Request Sent", "BUTTON_TEXT": "Okay" }, "OTP_FORM": { "OTP_FORM_TITLE": "Enter your authentication code to continue", + "OTP_FORM_INFO": "Enter your 6-digit code to continue", + "OTP_FORM_SUBNOTE_LINE_1": "Your code is also known as a two-factor authenticator (2FA) or OTP code.", + "OTP_FORM_SUBNOTE_LINE_2": "If you've lost your code, please reach out to support.", "OTP_LABEL": "OTP Code", "OTP_PLACEHOLDER": "Enter the authentication code", "OTP_TITLE": "Authenticator Code", @@ -234,7 +242,9 @@ }, "VERIFICATION_EMAIL_REQUEST": { "TITLE": "Resend Email Request", - "BUTTON": "Request Email" + "BUTTON": "Request Email", + "SUBTITLE": "Make another email verification request below", + "SUPPORT": "Contact Support" }, "VERIFICATION_EMAIL_REQUEST_SUCCESS": { "TITLE": "Resent Email", @@ -471,6 +481,55 @@ "WARNING_POP_UP": "Warning pop ups" } }, + "USER_APPS": { + "TITLE": "Your exchange apps", + "SUBTITLE": "Your exchange account applications information and extra functionality below.", + "ALL_APPS": { + "TAB_TITLE": "All apps", + "TITLE": "Exchange apps", + "SUBTITLE": "Get more functionality from your exchange account by simply selecting an app below and clicking Add button.", + "SEARCH_PLACEHOLDER": "Search apps...", + "ADD": { + "SUCCESSFUL": "You've successfully added a new app!", + "FAILED": "Something went wrong" + } + }, + "MY_APPS": { + "TAB_TITLE": "My apps", + "TITLE": "My exchange apps", + "SUBTITLE": "Below are your active exchange applications. You can click to see expand on each applications information, functions and add/remove them. Apps are designed to provide more your functionality to your exchange experience." + }, + "TABLE": { + "APP_NAME": "App name", + "DESCRIPTION": "Description", + "ACTION": "Action", + "CONFIGURE": "Configure", + "VIEW_APP": "View app", + "ADD": "Add", + "NOT_FOUND": "Can't find this app...", + "RETRY": "Try another search term" + }, + "APP_DETAILS": { + "BACK_PLACEHOLDER": "{0} {1}", + "BACK_TO_APPS": "to my apps", + "BACK": "Back" + }, + "CONFIGURE": { + "TITLE": "Configure app", + "SUBTITLE": "Configure your app below:", + "REMOVE": "Remove app", + "TEXT": "If you are having issues with your app please contact us by clicking help below.", + "BACK": "BACK", + "HELP": "HELP" + }, + "REMOVE": { + "TITLE": "Remove app", + "SUBTITLE": "This will remove the app from your 'My apps' list.", + "TEXT": "Are you sure you want to remove this app?", + "BACK": "BACK", + "CONFIRM": "CONFIRM" + } + }, "TRANSACTION_HISTORY": { "TITLE": "History", "TITLE_TRADES": "Trades History", @@ -631,6 +690,7 @@ "COMPLETED_TOOLTIP": "Stake is mature. Continue staking to earn more rewards or unstake to claim rewards.", "CONNECT_ERROR": "Please check your wallet", "INSTALL_METAMASK": "You must install Metamask into your browser: https://metamask.io/download.html", + "INSTALL_METAMASK_TITLE": "MetaMask not detected", "REWARDS": { "0": { "CARD": "Earn rewards (no bonuses)", "TEXT": "regular rewards." }, "1": { @@ -1116,6 +1176,7 @@ "NEW": "New", "SEARCH_FIELD_LABEL": "Paste your transaction ID", "CHECK_DEPOSIT_STATUS": "Check deposit status", + "SEARCH_BLOCKCHAIN_FOR_DEPOSIT": "Search blockchain for your deposit", "STATUS_DESCRIPTION": "You can check the status of your deposit by passing the transaction ID (hash) below.", "TRANSACTION_ID": "Transaction ID (hash)", "SEARCH_SUCCESS": "Search complete", diff --git a/web/src/config/lang/es.json b/web/src/config/lang/es.json index ef62aa021d..9f3a2db1aa 100644 --- a/web/src/config/lang/es.json +++ b/web/src/config/lang/es.json @@ -6,6 +6,7 @@ "CANCEL_BASE_WITHDRAWAL": "Cancelar {0} Retiro", "CANCEL_WITHDRAWAL": "Cancelar Retiro", "CANCEL_WITHDRAWAL_POPUP_CONFIRM": "Quiere cancelar su retiro pendiente de:", + "NO_ACTIVE_ORDERS": "No orders detected. Place your orders on the Pro or Quick trade page", "TIMESTAMP_FORMAT": "YYYY/MM/DD HH:mm:ss", "HOUR_FORMAT": "HH:mm:ss", "LOGIN_TEXT": "Iniciar Sesión", diff --git a/web/src/config/lang/fa.json b/web/src/config/lang/fa.json index bed5d40011..980cf62fc3 100644 --- a/web/src/config/lang/fa.json +++ b/web/src/config/lang/fa.json @@ -36,6 +36,7 @@ "GO_TRADE": "معامله رو شروع کن", "VIEW_INFO": "مشاهده صفحه اطلاعات", "APPLY_HERE": "اعمال تغییرات", + "NO_ACTIVE_ORDERS": "No orders detected. Place your orders on the Pro or Quick trade page", "HOME": { "SECTION_1_TITLE": "به HollaEx kit خوش آمدید", "SECTION_1_TEXT_1": "با خیالی آسوده اکسچنج تبادل دارایی های دیجیتال خود را بسازید و جزو آینده بازارهای مالی جهان شوید.", @@ -1294,6 +1295,7 @@ "NEW": "New", "SEARCH_FIELD_LABEL": "Paste your transaction ID", "CHECK_DEPOSIT_STATUS": "Check deposit status", + "SEARCH_BLOCKCHAIN_FOR_DEPOSIT": "Search blockchain for your deposit", "STATUS_DESCRIPTION": "You can check the status of your deposit by passing the transaction ID (hash) below.", "TRANSACTION_ID": "Transaction ID (hash)", "SEARCH_SUCCESS": "Search complete", diff --git a/web/src/config/lang/fr.json b/web/src/config/lang/fr.json index fac0aa8ea3..93d8d6e2f3 100644 --- a/web/src/config/lang/fr.json +++ b/web/src/config/lang/fr.json @@ -11,6 +11,7 @@ "LOGIN_TEXT": "Connexion", "SIGN_IN": "S'identifier", "SIGNUP_TEXT": "S'enregistrer", + "NO_ACTIVE_ORDERS": "No orders detected. Place your orders on the Pro or Quick trade page", "REGISTER_TEXT": "S'inscrire", "ACCOUNT_TEXT": "Compte", "CLOSE_TEXT": "Fermer", diff --git a/web/src/config/lang/index.js b/web/src/config/lang/index.js index 25ed0aaba3..3a5a2999da 100644 --- a/web/src/config/lang/index.js +++ b/web/src/config/lang/index.js @@ -11,6 +11,7 @@ import id from './id.json'; import zh from './zh.json'; import pt from './pt.json'; import tr from './tr.json'; +import mn from './mn.json'; export default { en, @@ -25,5 +26,6 @@ export default { id, zh, pt, - tr + tr, + mn }; diff --git a/web/src/config/lang/mn.json b/web/src/config/lang/mn.json new file mode 100644 index 0000000000..52fa658bde --- /dev/null +++ b/web/src/config/lang/mn.json @@ -0,0 +1,1300 @@ +{ + "APP_TITLE": "HollaEx", + "APP_SUB_TITLE": "Нээлттэй Крипто Эксченж", + "LOGOUT_CONFIRM_TEXT": "Та гарахдаа итгэлтэй байна уу", + "ADD_TRADING_PAIR": "Макет сонгох", + "CANCEL_BASE_WITHDRAWAL": "{0} зарлага цуцлах", + "CANCEL_WITHDRAWAL": "Зарлага цуцлах", + "CANCEL_WITHDRAWAL_POPUP_CONFIRM": "Та дараах хүлээгдэж буй зарлагыг цуцлахдаа итгэлтэй байна уу:", + "TIMESTAMP_FORMAT": "YYYY/MM/DD HH:mm:ss", + "NO_ACTIVE_ORDERS": "Захиалга байхгүй байна. Pro эсвэл Quick trade хуудсан дээр захиалгаа өгөөрэй", + "NO_ACTIVE_TRADES": "Арилжаа одоогоор хийгдээгүй байна", + "NO_ACTIVE_DEPOSITS": "Орлого одоогоор байхгүй байна.", + "NO_ACTIVE_WITHDRAWALS": "Зарлага одоогоор байхгүй байна", + "HOUR_FORMAT": "HH:mm:ss", + "LOGIN_TEXT": "Нэвтрэх хэсэг", + "SIGN_IN": "Нэвтрэх", + "SIGNUP_TEXT": "Бүртгүүлэх", + "REGISTER_TEXT": "Бүртгүүлэх", + "ACCOUNT_TEXT": "Бүртгэл", + "CLOSE_TEXT": "Хаах", + "COPY_TEXT": "Хуулбарлах", + "COPY_SUCCESS_TEXT": "Амжилттай хуулбарлалаа", + "CANCEL_SUCCESS_TEXT": "Амжилттай цуцаллаа!", + "ADD_FILES": "ФАЙЛ НЭМЭХ", + "OR_TEXT": "Эсвэл", + "CONTACT_US_TEXT": "Холбоо барих", + "HELPFUL_RESOURCES_TEXT": "Хэрэгтэй мэдээллүүд", + "HELP_RESOURCE_GUIDE": { + "CONTACT_US": "холбоо барих", + "TEXT": "Танд тусламж хэрэгтэй болон асуух асуулт байвал {0} хандах, эсвэл и-мэйл илгээнэ үү." + }, + "HELP_TELEGRAM_TEXT": "API зааврыг нээж үзнэ үү:", + "HELP_TELEGRAM_LINK": "https://apidocs.hollaex.com", + "NEED_HELP_TEXT": "Тусламж хэрэгтэй юу?", + "HELP_TEXT": "тусламж", + "SUCCESS_TEXT": "Амжилттай", + "ERROR_TEXT": "Алдаа", + "PROCEED": "ҮРГЭЛЖЛҮҮЛЭХ", + "EDIT_TEXT": "Засварлах", + "BACK_TEXT": "Буцах", + "NO_OPTIONS": "Сонголт байхгүй байна", + "SECONDS": "хором", + "VIEW_MARKET": "маркет харах", + "GO_TRADE": "Арилжаанд оролцох", + "VIEW_INFO": "Мэдээллийн хуудас зочлох", + "APPLY_HERE": "Энд дарна уу", + "CONVERT": "Хөрвүүлэх", + "TO": "Юунд", + "HOME": { + "MAIN_TITLE": "Крипто арилжааны бирж", + "MAIN_TEXT": "Та өөрийн и-мэйл хаягаар бүртгүүлээд 24 цагийн турш крипто хөрөнө хялбархан худалдан авах, арилжаалах боломжтой", + "TRADE_CRYPTO": "Арилжаанд оролцох", + "VIEW_EXCHANGE": "Трэйдинг платформ" + }, + "FOOTER": { + "FOOTER_LANGUAGE_TEXT": "ХЭЛ", + "TERMS_OF_SERVICE": "Үйлчилгээний нөхцөл", + "PRIVACY_POLICY": "Нууцлалын бодлого", + "CLICK_HERE": "энд дарж", + "VISIT_HERE": "энд дарж зочилно уу" + }, + "ACCOUNTS": { + "TITLE": "Бүртгэл", + "TAB_VERIFICATION": "Баталгаажуулалт", + "TAB_SECURITY": "Аюулгүй байдал", + "TAB_SETTINGS": "Тохиргоо", + "TAB_APPS": "Аппликэйшн", + "TAB_WALLET": "Хэтэвч", + "TAB_SUMMARY": "Ерөнхий", + "TAB_HISTORY": "Түүх", + "TAB_SIGNOUT": "Гарах", + "TAB_STAKE": "Стэйкинг", + "TAB_FIAT": "Бэлэн мөнгөний удирдлага" + }, + "CONTACT_FORM": { + "CATEGORY_LABEL": "Ангилал", + "CATEGORY_PLACEHOLDER": "Таны асуудалд тохирох ангиллыг сонгоно уу", + "CATEGORY_OPTIONS": { + "OPTION_VERIFY": "Хэрэглэгч баталгаажуулалт", + "OPTION_LEVEL": "Түвшин ахиулах", + "OPTION_DEPOSIT": "Орлого ба зарлага", + "OPTION_BUG": "Алдааг мэдээлэх", + "OPTION_PERSONAL_INFO": "Хувийн мэдээлэл өөрчлөх", + "OPTION_BANK_TRANSFER": "Банкны шилжүүлэг", + "OPTION_REQUEST": "HollaEx бирж дээр урилга илгээх" + }, + "SUBJECT_LABEL": "Гарчиг", + "SUBJECT_PLACEHOLDER": "Асуудлын тухай гарчиг оруулах", + "DESCRIPTION_LABEL": "Тайлбар", + "DESCRIPTION_PLACEHOLDER": "Асуудлын дэлгэрэнгүй тайлбар", + "ATTACHMENT_LABEL": "Хасвралт оруулах (хамгийн ихдээ 3)", + "ATTACHMENT_PLACEHOLDER": "Асуудалд холбоотой файлууд. PDF, JPG, PNG ба GIF файл оруулах боломжтой", + "SUCCESS_TITLE": "Зурвас илгээлээ", + "SUCCESS_MESSAGE_1": "Таны асуудлыг хэрэглэгчийн тусламжийн төвд илгээлээ.", + "SUCCESS_MESSAGE_2": "Та 1-3 өдрийн дараа хариу авах болно." + }, + "DEPOSIT": { + "CRYPTO_LABELS": { + "ADDRESS": "Таны {0} хүлээн авах хаяг", + "DESTINATION_TAG": "Таны {0} хүлээн авах tag", + "MEMO": "Таны {0} memo" + }, + "QR_CODE": "Энэ QR кодыг танд мөнгө илгээхийг хүссэн хүн сканнердаж болно", + "NO_DATA": "Мэдээлэл байхгүй байна" + }, + "LOGIN": { + "LOGIN_TO": "{0} нэвтрэх", + "CANT_LOGIN": "Нэвтэрч чадахгүй байна уу?", + "NO_ACCOUNT": "Бүртгэлгүй юу?", + "CREATE_ACCOUNT": "Энд дарж бүртгүүлээрэй", + "HELP": "Тусламж" + }, + "FORM_FIELDS": { + "EMAIL_LABEL": "И-мэйл", + "EMAIL_PLACEHOLDER": "И-мэйл хаягаа энд оруулна", + "PASSWORD_LABEL": "Нууц үг", + "PASSWORD_PLACEHOLDER": "Нууц үгээ оруулна уу", + "PASSWORD_REPEAT_LABEL": "Retype your password", + "PASSWORD_REPEAT_PLACEHOLDER": "Retype your password" + }, + "VALIDATIONS": { + "OTP_LOGIN": "OTP код оруулна уу", + "CAPTCHA": "Идэвхитэй байх хугацаа дууссан. Хуудсыг дахин уншуулна уу", + "FROZEN_ACCOUNT": "Таны бүртгэл түгжигдсэн байна", + "INVALID_EMAIL": "И-мэйл хаяг буруу байна", + "TYPE_EMAIL": "И-мэйл хаяг оруулна уу", + "REQUIRED": "Бөглөх шаардлагатай", + "INVALID_DATE": "Огноо буруу байна", + "INVALID_PASSWORD": "Iууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", + "INVALID_PASSWORD_2": "Нууц үг буруу байна. Доод тал нь 8 тэмдэгттэй, тоо болон тусгай тэмдэгт орно.", + "INVALID_CURRENCY": "Дараах {0} хаяг буруу байна ({1})", + "INVALID_BALANCE": "Таны баланс ({0}) хүрэлцэхгүй байна: ({1}).", + "MIN_VALUE": "Боломжит доод дүн {0}.", + "MAX_VALUE": "Боломжит дээд дүн {0}.", + "MIN_VALUE_NE": "Боломжит доод дүн {0}.", + "MAX_VALUE_NE": "Боломжит дээд дүн {0}.", + "INSUFFICIENT_BALANCE": "Үлдэгдэл хүрэлцэхгүй байна", + "PASSWORDS_DONT_MATCH": "Нууц үг буруу байна.", + "USER_EXIST": "И-мэйл хаяг бүртгэлтэй байна", + "ACCEPT_TERMS": "Үйлчилгээний нөхцөл, нууцлалын бодлогыг зөвшөөрөөгүй байна", + "STEP": "Буруу утга: {0}", + "ONLY_NUMBERS": "Зөвхөн тоо оруулна уу" + }, + "NOTIFICATIONS": { + "BUTTONS": { + "OKAY": "Okay", + "START_TRADING": "арилжаа хийж эхлэх", + "SEE_HISTORY": "түүх харах" + }, + "DEPOSITS": { + "TITLE_RECEIVED": "{0} орлого хүлээн авлаа", + "TITLE_INCOMING": "{0} орлого ирж байна", + "SUBTITLE_RECEIVED": "Та {0} орлого хүлээн авлаа", + "SUBTITLE_INCOMING": "Танд {0} ирж байна", + "INFORMATION_PENDING_1": "Таны {0} арилжаанд орохын тулд ядаж 1 баталгаажуулалт хэрэгтэй.", + "INFORMATION_PENDING_2": "Энэ гүйлгээ нь 10-30 минут болох бөгөөд, амжилттай болонгуут бид танд мэдэгдэх болно." + } + }, + "REFERRAL_SUCCESS": { "TITLE": "Хүсэлт илгээсэн", "BUTTON_TEXT": "Okay" }, + "OTP_FORM": { + "OTP_FORM_TITLE": "Баталгаажуулах код оруулна уу", + "OTP_FORM_INFO": "Үргэлжлүүлэхийн тулд 6 оронтой кодоо оруулна уу", + "OTP_FORM_SUBNOTE_LINE_1": "Your code is also known as a two-factor authenticator (2FA) or OTP code.", + "OTP_FORM_SUBNOTE_LINE_2": "Хэрэв та кодоо алдсан бол оператортой холбогдоно уу.", + "OTP_LABEL": "OTP Code", + "OTP_PLACEHOLDER": "Баталгаажуулах код оруулна уу", + "OTP_TITLE": "Баталгаажуулах код", + "OTP_BUTTON": "илгээх", + "ERROR_INVALID": "OTP Code буруу байна" + }, + "EMAIL_CODE_FORM": { + "TITLE": "Аюулгүй байдлын кодыг оруулна уу", + "LABEL": "Код оруулах (имэйлээ шалгана уу)", + "PLACEHOLDER": "Имэйлд илгээсэн кодыг оруулна уу", + "FORM_TITLE": "Таны имэйл рүү илгээсэн кодыг OTP кодын хамт оруулна уу.", + "BUTTON": "Илгээх", + "ERROR_INVALID": "Таны оруулсан код буруу байна. Дахин оролдоно уу", + "OTP_LABEL": "2FA код (OTP)", + "OTP_PLACEHOLDER": "2FA кодоо оруулна уу" + }, + "QUICK_TRADE_COMPONENT": { + "TITLE": "Хялбар арилжаа", + "BUTTON": "Захиалга батлах", + "INFO": "Крипто арилжаа хийх хурдан бөгөөд хямд", + "CHANGE_TEXT": "өөрчлөлт", + "HIGH_24H": "24Ц ДЭЭД", + "LOW_24H": "24Ц ДООД", + "BEST_BID": "BEST BID", + "BEST_ASK": "BEST ASK", + "FOOTER_TEXT": "Хялбар арилжаанд taker fee бодогдоно", + "FOOTER_TEXT_1": "Эх сурвалж", + "GO_TO_TEXT": "Очих", + "SOURCE_TEXT": "Брокер OTC гэрээ" + }, + "PREVIOUS_PAGE": "өмнөх хуудас", + "NEXT_PAGE": "дараагийн хуудас", + "WALLET": { + "LOADING_ASSETS": "Уншиж байна...", + "TOTAL_ASSETS": "Нийт хөрөнгө", + "AVAILABLE_WITHDRAWAL": "Арилжаалах боломжтой", + "ORDERS_PLURAL": "захиалга", + "ORDERS_SINGULAR": "захиалга", + "HOLD_ORDERS": "Танд {0} нээлттэй {1} байгаа тул таны {4} үлдэгдэл дээр {2} {3} хадгалагдах болно" + }, + "REQUEST_RESET_PASSWORD": { + "TITLE": "Бүртгэл сэргээх", + "SUBTITLE": "Доорх мэдээллээр сэргээнэ үү", + "SUPPORT": "Холбоо барих", + "BUTTON": "Сэргээх линк илгээх" + }, + "REQUEST_RESET_PASSWORD_SUCCESS": { + "TITLE": "Нууц үг сэргээх линк илгээлээ", + "TEXT": "Таны бүртгэлтэй и-мэйл хаяг руу нууц үг сэргээх заавар явууллаа." + }, + "RESET_PASSWORD": { + "TITLE": "Шинэ нууц үг", + "SUBTITLE": "Шинэ нууц үг", + "BUTTON": "Шинэ нууц үг" + }, + "RESET_PASSWORD_SUCCESS": { + "TEXT_1": "Та нууц үгээ амжилттай шинэчиллээ", + "TEXT_2": "Доорх хэсгийг ашиглан нэвтэрч орно уу." + }, + "SIGN_UP": { + "SIGNUP_TO": "{0} -д бүртгүүлэх", + "NO_EMAIL": "И-мэйл хүлээн аваагүй юу?", + "REQUEST_EMAIL": "Энд дарж и-мэйл дахин авна уу", + "HAVE_ACCOUNT": "Бүртгэлтэй юу?", + "GOTO_LOGIN": "Энд дарж нэвтрэх хэсэгт очно уу", + "AFFILIATION_CODE": "Найзын код (заавал биш)", + "AFFILIATION_CODE_PLACEHOLDER": "Найзын кодоо оруулна уу", + "TERMS": { + "terms": "Үйлчилгээний нөхцөл", + "policy": "Нууцлалын бодлого", + "text": "Би {0} болон {1} -г уншсан бөгөөд, хүлээн зөвшөөрч байна" + } + }, + "VERIFICATION_TEXTS": { + "TITLE": "И-мэйл илгээлээ", + "TEXT_1": "Таны и-мэйл хаяг руу баталгаажуулах линк илгээлээ. Та и-мэйлээ шалгана уу", + "TEXT_2": "Хэрэв танд и-мэйл очоогүй бол доорх линк дээр дарж дахин илгээнэ үү." + }, + "VERIFICATION_EMAIL_REQUEST": { + "TITLE": "И-мэйл дахин илгээх хүсэлт", + "BUTTON": "И-мэйл илгээх", + "SUBTITLE": "Доорх имэйлээр баталгаажуулах өөр хүсэлт гаргана уу", + "SUPPORT": "Холбоо барих" + }, + "VERIFICATION_EMAIL_REQUEST_SUCCESS": { + "TITLE": "И-мэйл дахин илгээлээ", + "TEXT_1": "Танд удахгүй баталгаажуулах и-мэйл очно. Хэрэв ирээгүй бол тусламжын оператортой холбогдоно уу" + }, + "VERIFICATION_EMAIL": { + "INVALID_UUID": "Код буруу байна", + "TEXT_1": "Та и-мэйл хаягаа амжилттай баталгаажууллаа.", + "TEXT_2": "Та одоо системд нэвтрэх боломжтой" + }, + "USER_VERIFICATION": { + "INFO_TXT": "Энэ хэсэгт та баталгаажуулалт болон бүртгэл шинэчлэх хэсгийг харж болно.", + "INFO_TXT_1": "Доорх хэсэг тус бүрд шаардлагатай холбогдох мэдээллийг оруулна уу. Зөвхөн бүх хэсгүүдийг бөглөж дууссаны дараа таны мэдээллийг хянаж, бүртгэл шинэчлэлтийг зөвшөөрөх болно..", + "COMPLETED": "Дууссан", + "PENDING_VERIFICATION": "Баталгаажуулалт хүлээгдэж байна", + "TITLE_EMAIL": "И-мэйл", + "MY_EMAIL": "И-мэйл", + "TITLE_USER_DOCUMENTATION": "Бүртгэл", + "TITLE_ID_DOCUMENTS": "Файл оруулах", + "TITLE_BANK_ACCOUNT": "Банкны мэдээлэл", + "TITLE_MOBILE_PHONE": "Утас", + "TITLE_PERSONAL_INFORMATION": "Хувийн мэдээлэл", + "VERIFY_EMAIL": "И-мэйл баталгаажуулах", + "VERIFY_MOBILE_PHONE": "Утас баталгаажуулах", + "VERIFY_USER_DOCUMENTATION": "Бичиг баримт баталгаажуулах", + "VERIFY_ID_DOCUMENTS": "Иргэний үнэмлэх баталгаажуулах", + "TITLE_IDENTITY": "Бүртгэл", + "TITLE_MOBILE": "Гар утас", + "TITLE_BANK": "Банк", + "CHANGE_VALUE": "Мэдээлэл өөрчлөх", + "PENDING_VERIFICATION_PERSONAL_INFORMATION": "Таны мэдээллийг шалгаж байна", + "PENDING_VERIFICATION_DOCUMENTS": "Таны бичиг баримтыг шалгаж байна", + "GOTO_VERIFICATION": "Баталгаажуулалт руу очих", + "GOTO_WALLET": "Хэтэвч рүү очих", + "INCOMPLETED": "Дутуу", + "BANK_VERIFICATION": "Банк баталгаажуулалт", + "IDENTITY_VERIFICATION": "Бүртгэл баталгаажуулалт", + "PHONE_VERIFICATION": "Утас баталгаажуулалт", + "DOCUMENT_VERIFICATION": "Бичиг баримт баталгаажуулалт", + "START_BANK_VERIFICATION": "Банк баталгаажуулалт эхлэх", + "START_IDENTITY_VERIFICATION": "Бүртгэл баталгаажуулалт эхлэх", + "START_PHONE_VERIFICATION": "Утас баталгаажуулалт эхлэх", + "START_DOCUMENTATION_SUBMISSION": "Бичиг баримт баталгаажуулалт эхлэх", + "GO_BACK": "Буцах", + "BANK_VERIFICATION_TEXT_1": "Та энэ хэсэгт өөрийн дансны дугаараа оруулж баталгаажуулна уу.", + "BANK_VERIFICATION_TEXT_2": "Банкаа баталгаажуулснаар та дараах үйлдлүүдийг хийх боломжтой болно:", + "BASE_WITHDRAWAL": "Мөнгөн зарлага", + "BASE_DEPOSITS": "Мөнгөн орлого", + "ADD_ANOTHER_BANK_ACCOUNT": "Данс нэмэх", + "BANK_NAME": "Банкны нэр", + "ACCOUNT_NUMBER": "Дансны дугаар", + "BANK_VERIFICATION_HELP_TEXT": "Энэ хэсгийг баталгаажуулахын тулд та {0} хэсгийг дуусгасан байх ёстой.", + "DOCUMENT_SUBMISSION": "Бичиг баримт илгээх", + "REVIEW_IDENTITY_VERIFICATION": "Бүртгэл баталгаажуулалт хянах", + "PHONE_DETAILS": "Утасны мэдээлэл", + "PHONE_COUNTRY_ORIGIN": "Улс", + "MOBILE_NUMBER": "Утас", + "DOCUMENT_PROOF_SUBMISSION": "Бичиг баримт илгээх", + "START_DOCUMENTATION_RESUBMISSION": "Бичиг баримт дахин илгээх", + "SUBMISSION_PENDING_TXT": "*Энэ хэсгийг та өмнө нь илгээсэн байна. Өөрчлөлт хийж, дахин илгээх нь таны өмнөх мэдээллийг дарж бичих болно.", + "CUSTOMER_SUPPORT_MESSAGE": "Операторын хариу", + "DOCUMENT_PENDING_NOTE": "Таны бичиг баримтыг илгээсэн бөгөөд шалгахаар хүлээгдэж байна.", + "DOCUMENT_VERIFIED_NOTE": "Таны бичиг баримт баталгаажсан байна.", + "NOTE_FROM_VERIFICATION_DEPARTMENT": "Баталгаажуулалтын хариу", + "CODE_EXPIRES_IN": "Код дуусах хугацаа", + "EMAIL_VERIFICATION": "Баталгаажуулах и-мэйл илгээх", + "VERIFICATION_SENT": "Баталгаажуулалт илгээсэн", + "VERIFICATION_SENT_INFO": "И-мэйл хаягаа шалгаад та баталгаажуулалтаа хийнэ үү.", + "OKAY": "Ok", + "USER_DOCUMENTATION_FORM": { + "FORM_FIELDS": { + "FULL_NAME_LABEL": "Таны нэр", + "FULL_NAME_PLACEHOLDER": "Иргэний үнэмлэх дээрх өөрийн нэрээ бичнэ үү", + "GENDER_LABEL": "Хүйс", + "GENDER_PLACEHOLDER": "Өөрийн хүйсээ оруулна уу", + "GENDER_OPTIONS": { "MAN": "Эрэгтэй", "WOMAN": "Эмэгтэй" }, + "NATIONALITY_LABEL": "Иргэншил", + "NATIONALITY_PLACEHOLDER": "Та өөрийн иргэншилээ бичнэ үү", + "DOB_LABEL": "Төрсөн огноо", + "COUNTRY_LABEL": "Оршин суугаа улс", + "COUNTRY_PLACEHOLDER": "Одоогийн оршин суугаа улсаа оруулна уу", + "CITY_LABEL": "Хот", + "CITY_PLACEHOLDER": "Амьдарч буй хотоо бичнэ үү", + "ADDRESS_LABEL": "Хаяг", + "ADDRESS_PLACEHOLDER": "Хаяг", + "POSTAL_CODE_LABEL": "Зип код", + "POSTAL_CODE_PLACEHOLDER": "Зип кодоо оруулна уу", + "PHONE_CODE_LABEL": "Улс", + "PHONE_CODE_PLACEHOLDER": "Утасны дугаар байршиж буй улсаа бичнэ үү", + "PHONE_CODE_DISPLAY": "({0}) {1}", + "PHONE_NUMBER_LABEL": "Утасны дугаар", + "PHONE_NUMBER_PLACEHOLDER": "Утасны дугаараа оруулна уу", + "CONNECTING_LOADING": "Холбогдож байна", + "SMS_SEND": "SМS илгээх", + "SMS_CODE_LABEL": "SМS код", + "SMS_CODE_PLACEHOLDER": "SМS кодоо оруулна уу" + }, + "INFORMATION": { + "TEXT": "АНХААРУУЛГА: Иргэний үнэмлэх дээрхтэй яг ижлээр нэрээ оруулна уу (овог нэр, өөрийн нэр). Та бизнес эрхэлдэг бол байгууллагын дансны хэрэглэгчийн дэмжлэгтэй холбогдоно уу.", + "TITLE_PERSONAL_INFORMATION": "Хувийн мэдээлэл", + "TITLE_PHONE": "Утас", + "PHONE_VERIFICATION_TXT": "Та утасны мэдээллээ баталгаажуулснаар аливаа эрсдлээс сэргийлэгдэх болно.", + "PHONE_VERIFICATION_TXT_1": "Таны орлого зарлагын мэдээлэл таны гар утсанд очно.", + "PHONE_VERIFICATION_TXT_2": "Цаашид LAN утасны дугаараа оруулах, өөрийн мэдээлэл, хаягаа баталгаажуулна уу (заавал биш)." + } + }, + "ID_DOCUMENTS_FORM": { + "VALIDATIONS": { + "ID_NUMBER": "Иргэний үнэмлэхний төрөл сонгоно уу", + "ISSUED_DATE": "Олгосон огноо бичнэ үү", + "EXPIRATION_DATE": "Дуусах огноо бичнэ үү", + "FRONT": "Иргэний үнэмлэхний урд талын зургийг оруулна уу", + "PROOF_OF_RESIDENCY": "Иргэний үнэмлэхний ард тал эсвэл оршин суугаа хаягийн тодорхойлолт оруулна уу", + "SELFIE_PHOTO_ID": "Иргэний үнэмлэхээ гартаа барьсан сельфи зураг авч оруулна уу" + }, + "FORM_FIELDS": { + "ID_NUMBER_LABEL": "Регистрийн дугаар", + "ID_NUMBER_PLACEHOLDER": "Регистрийн дугаараа оруулна уу", + "ISSUED_DATE_LABEL": "Олгосон огноо", + "EXPIRATION_DATE_LABEL": "Дуусах огноо", + "FRONT_LABEL": "Иргэний үнэмлэх эсвэл пасспорт", + "FRONT_PLACEHOLDER": "Хуулбараа энд оруулна уу", + "POR_LABEL": "Хаягийн баталгаажуулалт", + "POR_PLACEHOLDER": "Иргэний үнэмлэхний ард тал эсвэл Хаягийн тодорхойлолт", + "SELFIE_PHOTO_ID_LABEL": "Иргэний үнэмлэхтэй сельфи зураг", + "SELFIE_PHOTO_ID_PLACEHOLDER": "Иргэний үнэмлэхтэй сельфи зургаа оруулна уу" + }, + "INFORMATION": { + "PROOF_OF_RESIDENCY": "Хаягийн тодорхойлолт", + "ID_SECTION": { + "TITLE": "Дараах шаардлагыг хангасан зураг оруулна уу:", + "LIST_ITEM_0": "Бүх документын нийт хэмжээ {0}mb-аас хэтрэхгүй байх ёстой", + "LIST_ITEM_1": "ӨНДӨР ЧАНАР (өнгөт зураг, 300dpi ба түүнээс дээш нягтаршилтай, Зураг тус бүр 2MB буюу түүнээс бага хэмжээтэй байх ёстой) Хэмжээг өөрчлөхийн тулд Webtool ашиглана уу.", + "LIST_ITEM_2": "ТОД ХАРАГДАХУЙЦ БАЙХ.", + "LIST_ITEM_3": "ХҮЧИНТЭЙ БАЙХ", + "WARNING_1": "Зөвхөн хүчинтэй бичиг баримтыг хүлээн авна; Эдгээр баримт бичгийн өндөр чанартай зураг эсвэл сканнердсан зургийг хүлээн авах боломжтой:", + "WARNING_3": "Энэ хэсэгт та иргэний үнэмлэхнйи ар талыг оруулж болно.", + "VIOLATION_ERROR": "Таны байршуулсан бүх баримт бичгийн нийт хэмжээ {0}mb-ын байршуулах хязгаараас хэтэрсэн байна. Үргэлжлүүлэхийн тулд жижиг файлуудыг байршуулна уу." + }, + "POR": { + "SECTION_1_TEXT_1": "Бүртгэл баталгаажуулалтаа удаашруулахгүйн тулд дараах зүйлсийг анхаарна уу:", + "SECTION_1_TEXT_2": "НЭР, ХАЯГ, ОЛГОСОН ОГНОО, ДУУСАХ ОГНОО харагдахуйц байх.", + "SECTION_1_TEXT_3": "Оршин суугаа хаягийн тодорхойлолт 3 САРЫН ДОТОР авсан байх.", + "SECTION_1_TEXT_4": "ӨНДӨР ЧАНАРТАЙ байх (хамгийн багадаа 300 DPI)", + "SECTION_2_TITLE": "ЗӨВШӨӨРӨГДӨХ ХАЯГИЙН ТОДОРХОЙЛОЛТ:", + "SECTION_2_LIST_ITEM_1": "Банкны тодорхойлолт.", + "SECTION_2_LIST_ITEM_2": "E-Mongolia тодорхойлолт.", + "SECTION_2_LIST_ITEM_3": "Цахилгаан, Орон сууцны төлбөрийн баримт.", + "WARNING": "Иргэний үнэмлэхний ард тал, өөрчлөлтийн хуудсын хамт." + }, + "SELFIE": { + "TITLE": "Сельфи зураг оруулах заавар", + "INFO_TEXT": "Паспортоо барьж байгаа зургаа оруулна уу. Ижил зурган дээр солилцооны url-ийн лавлагаа, өнөөдрийн огноо болон таны гарын үсгийг харуулна. Таны царай тодорхой харагдаж, таны ID-ны дэлгэрэнгүй унших боломжтой эсэхийг шалгаарай.", + "REQUIRED": "Анхаарах зүйлс:", + "INSTRUCTION_1": "Царай бүтэн харагдах", + "INSTRUCTION_2": "Бичиг баримт тод харагдах", + "INSTRUCTION_3": "Ncx.mn гэж бичих", + "INSTRUCTION_4": "Өнөөдрийн огноо бичих", + "INSTRUCTION_5": "Гарын үсэг зурах", + "WARNING": "Өөр паспорттой сельфиг татгалзах болно" + } + } + }, + "BANK_ACCOUNT_FORM": { + "VALIDATIONS": { + "ACCOUNT_NUMBER_MAX_LENGTH": "Дансны дугаар 50 тэмдэгтээс бага байх ёстой" + }, + "FORM_FIELDS": { + "BANK_NAME_LABEL": "Банкны нэр", + "BANK_NAME_PLACEHOLDER": "Банкны нэрээ бичнэ үү", + "ACCOUNT_NUMBER_LABEL": "Дансны дугаар", + "ACCOUNT_NUMBER_PLACEHOLDER": "Дансны дугаараа бичнэ үү", + "ACCOUNT_OWNER_LABEL": "Дансны нэр", + "CARD_NUMBER_PLACEHOLDER": "16 оронтой картын дугаараа оруулна уу" + } + }, + "WARNING": { + "TEXT_1": "Та баталгаажуулалтаа хийснээр дараах эрхтэй болно:", + "LIST_ITEM_1": "Өдрийн зарлагын хэмжээ нэмэгдэнэ", + "LIST_ITEM_2": "Өдрийн орлогын хэмжээ нэмэгдэнэ", + "LIST_ITEM_3": "Шимтгэл буурна" + }, + "TITLE_PAYMENT": "Төлбөрийн хэлбэр", + "PAYMENT_VERIFICATION": "Төлбөрийн баталгаажуулалт", + "START_PAYMENT_VERIFICATION": "Баталгаажуулалтыг эхлүүлэх", + "PAYMENT_VERIFICATION_TEXT_1": "Төлбөрийн дансны дэлгэрэнгүй мэдээллийг доор нэмнэ үү.", + "PAYMENT_VERIFICATION_TEXT_2": "Тэдгээрийг баталгаажуулсны дараа таны дансанд янз бүрийн мөнгөн тэмдэгтээр мөнгө авах, байршуулах илүү олон арга бий болно.", + "ADD_ANOTHER_PAYMENT_METHOD": "ӨӨР ТӨЛБӨРИЙН АРГА НЭМЭХ", + "PAYMENT_VERIFICATION_HELP_TEXT": "Энэ хэсгийг баталгаажуулахын тулд та {0} хэсгийг бөглөх ёстой." + }, + "USER_SETTINGS": { + "TITLE_TEXT_1": "Энэ хэсэгт та ерөнхий тохиргоог өөрчлөх боломжтой.", + "TITLE_TEXT_2": "Өөрчлөлтөө хадгалахын тулд Хадгалах товчлуурыг дарна уу.", + "TITLE_NOTIFICATION": "Мэдэгдэл", + "TITLE_INTERFACE": "Интерфэйс", + "TITLE_LANGUAGE": "Хэл", + "TITLE_CHAT": "Чат", + "TITLE_AUDIO_CUE": "Аудио ", + "TITLE_MANAGE_RISK": "Эрсдлийн удирдлага", + "ORDERBOOK_LEVEL": "Захиалгын түвшин (Ихдээ 20)", + "SET_TXT": "ТОХИРУУЛАХ", + "CREATE_ORDER_WARING": "Захиалгын анхааруулга үүсгэх", + "RISKY_TRADE_DETECTED": "Эрсдэлтэй арилжаа мэдрэгдлээ", + "RISKY_WARNING_TEXT_1": "Энэ захиалга нь таны тохируулсан {0} хэмжээнээс хэтэрч байна.", + "RISKY_WARNING_TEXT_2": "(Нийт хөрөнгийн {0} хувь)", + "RISKY_WARNING_TEXT_3": " Та энэ арилжааг хийхийг үнэхээр хүсч байгаагаа шалгаж, баталгаажуулна уу.", + "GO_TO_RISK_MANAGMENT": "ЭРСДЛИЙН УДИРДЛАГА", + "CREATE_ORDER_WARING_TEXT": "Таны арилжааны захиалга таны багцын {0}-ээс илүү гарах үед сэрэмжлүүлэг гарна", + "ORDER_PORTFOLIO_LABEL": "Хэтэвчний хувь хэмжээ:", + "NOTIFICATION_FORM": { + "POPUP_ORDER_CONFIRMATION": "Захиалга өгөхөөс өмнө баталгаажуулна уу.", + "POPUP_ORDER_COMPLETED": "Захиалга дууссаны дараа гарч ирэх цонхыг харуул", + "POPUP_ORDER_PARTIALLY_FILLED": "Захиалга хэсэгчлэн дүүрсэн үед гарч ирэх цонхыг харуулах" + }, + "AUDIO_CUE_FORM": { + "ALL_AUDIO": "Бүх дуун сануулга", + "PUBLIC_TRADE_AUDIO": "Арилжаа хийгдсэн үед", + "ORDERS_PARTIAL_AUDIO": "Захиалга хагас дүүрсэн үед", + "ORDERS_PLACED_AUDIO": "Захиалга тавигдсан үед", + "ORDERS_CANCELED_AUDIO": "Захиалга цуцлагдсан үед", + "ORDERS_COMPLETED_AUDIO": "'Захиалга бүрэн биелсэн үед", + "CLICK_AMOUNTS_AUDIO": "Захиалгын үнэ, хэмжээ дарагдах үед", + "GET_QUICK_TRADE_AUDIO": "Хялбар арилжаа хийх үнийн санал авах үе", + "SUCCESS_QUICK_TRADE_AUDIO": "Амжилттай хялбар арилжаа хийгдэх үед", + "QUICK_TRADE_TIMEOUT_AUDIO": "Хялбар арилжаа цуцлагдах үед" + }, + "RISK_MANAGEMENT": { + "INFO_TEXT": "Худалдааны захиалгын үнэ таны багцын тогтоосон хувиас хэтэрсэн тохиолдолд анхааруулах цонх гарч ирнэ", + "INFO_TEXT_1": "Нийт хөрөнгө {0}: {1}", + "PORTFOLIO": "Хөрөнгийн хувь", + "VALUE_ASSET": "Багцаа үнэ", + "ADJUST": "(ХУВЬ ӨӨРЧЛӨХ)", + "ACTIVATE_RISK_MANAGEMENT": "Эрсдлийн удирдлага идэвхижүүлэх", + "WARNING_POP_UP": "Анхааруулах цонх" + } + }, + "USER_APPS": { + "TITLE": "Таны биржийн апп", + "SUBTITLE": "Таны биржийн дансны хэрэглээний мэдээлэл болон нэмэлт функцуудыг доороос үзнэ үү.", + "ALL_APPS": { + "TAB_TITLE": "Бүх аппууд", + "TITLE": "Биржийн аппууд", + "SUBTITLE": "Таны биржийн дансны хэрэглээний мэдээлэл болон нэмэлт функцуудыг доороос үзнэ үү..", + "SEARCH_PLACEHOLDER": "Хайлт...", + "ADD": { + "SUCCESSFUL": "Таны апп амжилттай нэмлээ!", + "FAILED": "Something went wrong" + } + }, + "MY_APPS": { + "TAB_TITLE": "Миний аппууд", + "TITLE": "Миний арилжааны аппууд", + "SUBTITLE": "Таны идэвхтэй арилжааны аппуудыг доор харуулав. Та товшиж аппын мэдээлэл, функц тус бүрийг өргөжүүлж, нэмэх/хасах боломжтой. Аппликейшн нь таны солилцооны туршлагад илүү их боломжоор хангах зорилготой юм." + }, + "TABLE": { + "APP_NAME": "Аппын нэр", + "DESCRIPTION": "Тодорхойлолт", + "ACTION": "Үйлдэл", + "CONFIGURE": "Тохируулах", + "VIEW_APP": "Аппыг үзэх", + "ADD": "Нэмэх", + "NOT_FOUND": "Ийм апп байхгүй байна...", + "RETRY": "Өөр нэр томъёогоор хайж үзнэ үү" + }, + "APP_DETAILS": { + "BACK_PLACEHOLDER": "{0} {1}", + "BACK_TO_APPS": "Миний аппууд руу", + "BACK": "Буцах" + }, + "CONFIGURE": { + "TITLE": "Аппыг тохируулах", + "SUBTITLE": "Өөрийн аппыг доороос тохируулна уу:", + "REMOVE": "Аппыг устгана уу", + "TEXT": "Хэрэв танд апп холбоотой асуудал байгаа бол доорх 'тусламж' дээр дарж бидэнтэй холбогдоно уу.", + "BACK": "БУЦАХ", + "HELP": "ТУСЛАМЖ" + }, + "REMOVE": { + "TITLE": "Аппыг устгах", + "SUBTITLE": "Энэ нь таны 'Миний аппууд' жагсаалтаас уг аппыг устгах болно.", + "TEXT": "Энэ аппыг устгахдаа итгэлтэй байна уу?", + "BACK": "БУЦАХ", + "CONFIRM": "БАТАЛГААЖУУЛАХ" + } + }, + "TRANSACTION_HISTORY": { + "TITLE": "Түүх", + "TITLE_TRADES": "Арилжааны түүх", + "TITLE_DEPOSITS": "Хадгаламжийн түүх", + "TITLE_WITHDRAWALS": "Татан авалтын түүх", + "TEXT_DOWNLOAD": "ТҮҮХИЙГ ТАТАЖ АВАХ", + "TRADES": "Арилжаанууд", + "DEPOSITS": "Хадгаламжууд", + "WITHDRAWALS": "Татан авалтууд" + }, + "ACCOUNT_SECURITY": { + "TITLE_TEXT": "2FA баталгаажуулалт, нууц үг, API түлхүүрүүд болон бусад аюулгүй байдалтай холбоотой функцуудаас бүртгэлийнхээ аюулгүй байдлын тохиргоог тохируулна уу.", + "OTP": { + "TITLE": "2FA", + "OTP_ENABLED": "otp идэвхитэй", + "OTP_DISABLED": "2FA ИДЭВХИЖҮҮЛЭХ", + "ENABLED_TEXTS": { + "TEXT_1": "Нэвтэрч орох үед OTP шаардах", + "TEXT_2": "Зарлага гаргах үед OTP шаардах" + }, + "DIALOG": { + "SUCCESS": "Та амжилттай 2FA идэвхижүүллээ", + "REVOKE": "ТА 2FA идэвхигүй болголоо" + }, + "CONTENT": { + "TITLE": "Давхар баталгаажуулалт идэвхижүүлэх", + "MESSAGE_1": "Скан", + "MESSAGE_2": "2FA баталгаажуулалтыг төхөөрөмждөө автоматаар тохируулахын тулд Google Authenticator эсвэл Authy ашиглан доорх qrcode-г уншина уу.", + "MESSAGE_3": "Хэрэв танд үүнийг скан хийхэд асуудал гарвал доорх кодыг гараар оруулж болно", + "MESSAGE_4": "Та ирээдүйд гар утсаа солих эсвэл алдах тохиолдолд 2FA-аа сэргээхийн тулд энэ кодыг найдвартай хадгалах ёстой.", + "MESSAGE_5": "Гарын авлага", + "WARNING": "Бид танд 2FA тохируулахыг зөвлөж байна. Ингэх нь таны хөрөнгийн аюулгүй байдлыг ихээхэн нэмэгдүүлэх болно.", + "ENABLE": "2FA баталгаажуулалтыг идэвхжүүлнэ үү", + "DISABLE": "2FA баталгаажуулалтыг идэвхгүй болгох", + "INPUT": "OTP-ээ оруулна уу" + }, + "FORM": { + "PLACEHOLDER": "Google Authenticator-с өгсөн OTP-ээ оруулна уу.", + "BUTTON": "2FA-г идэвхжүүлнэ үү" + } + }, + "CHANGE_PASSWORD": { + "TITLE": "Нууц үг", + "ACTIVE": "ИДЭВХИТЭЙ", + "DIALOG": { + "EMAIL_CONFIRMATION": "Нууц үг солихыг зөвшөөрөхийн тулд танд имэйл илгээгдэх болно." + }, + "FORM": { + "BUTTON": "Нууц үг", + "CURRENT_PASSWORD": { + "label": "Одоогийн нууц үг", + "placeholder": "Шинэ нууц үгээ оруулна уу" + }, + "NEW_PASSWORD": { + "label": "Шинэ нууц үг", + "placeholder": "Шинэ нууц үгээ оруулна уу" + }, + "NEW_PASSWORD_REPEAT": { + "label": "Нууц үг батлах", + "placeholder": "Шинэ нууц үгээ дахин оруулна уу" + } + } + }, + "LOGIN": { + "TITLE": "Нэвтрэлтийн түүх", + "IP_ADDRESS": "IP хаяг", + "TIME": "Огноо", + "CONTENT": { "TITLE": "Нэвтрэлтийн түүх" } + }, + "FREEZE": { + "TITLE": "Аккаунт түгжих", + "CONTENT": { + "MESSAGE_1": "Та дансаа түгжснээр зарлага болон бүх арилжаа зогсоно.", + "WARNING_1": "Хэрэв та халдлагад өртсөн гэж үзсэн тохиолдолд л энэ хэсгийг ашиглана уу", + "TITLE_1": "Аккаунтаа түгжих", + "TITLE_2": "Бүртгэл царцаах", + "MESSAGE_2": "Бүртгэлээ царцаах нь таны бүртгэлийг кибер халдлагаас хамгаалахад тусална.", + "MESSAGE_3": "Та бүртгэлээ царцааснаар дараах үйлдлүүд явагдана:", + "MESSAGE_4": "1. Хүлээгдэж буй зарлагууд цуцлагдана.", + "MESSAGE_5": "2. Бүх арилжаа зогсож, дутуу биелсэн захиалгууд цуцлагдана.", + "MESSAGE_6": "3. Бүртгэлээ дахин идэвхижүүлэхийн тулд оператортой холбогдох шаардлагатай.", + "WARNING_2": "Та бүртгэлээ царцаахдаа итгэлтэй байна уу?" + } + } + }, + "STAKE": { + "NETWORK_WARNING": "Тохиромжгүй сүлжээ. Сүлжээгээ {0} болгож өөрчилнө үү", + "EARN": "Олж авах", + "TITLE": "Стэйк", + "MODAL_TITLE": "Стэйклэж, {0}-г олоорой", + "REVIEW_MODAL_TITLE": "Стэйкийг шалгаж баталгаажуулна уу", + "AVAILABLE_TOKEN": "{0} ({1}) Стэйклэх боломжтой: {2}", + "DEFI_TITLE": "DeFi хөрөнгийн үнэлгээ", + "DEFI_TEXT": "Стэйкинг DeFi стиль нь биржээс гадуур өөрийн хэтэвчийг ашиглах болно. Эхлэхийн тулд та холболт үүсгэх шаардлагатай бөгөөд холбогдсоны дараа та түрийвчнээсээ шууд бооцоо тавьж, орлого олж эхлэх боломжтой.", + "GET_STAKES": "Стэйк авах", + "CURRENT_ETH_BLOCK": "Одоогийн ETH блок: {0}", + "ON_EXCHANGE_XHT": "Биржийн {0} үлдэгдэл: {1} {2}", + "LOGIN_HERE": "Энд нэвтэрнэ үү", + "MOVE_XHT": "{0}-г зөөх", + "ESTIMATED_STAKED": "Нийт Стэйкийн үнэ цэнэ", + "ESTIMATED_EARNINGS": "Орлогын тооцоолсон үнэ цэнэ", + "CONNECT_WALLET": "Хэтэвчээ холбоно уу", + "BACK": "Буцах", + "NEXT": "Дараачийн", + "REVIEW": "Шүүмж", + "ESTIMATED": "EST.", + "BLOCK": "Блок", + "CANCEL": "Цуцлах", + "PROCEED": "Үргэлжлүүлэх", + "GO_TO_WALLET": "Хэтэвч рүү очих", + "AMOUNT_LABEL": "Стэйкийн хэмжээ", + "PERIOD_SUBTITLE": "Удаан стэйклэх тусам илүү их шагнал авах болно. Стэйклэх хугацааг доороос сонгоно уу.", + "STAKE_AND_EARN_DETAILS": "~{0}-р Стэйклэж, {1}-г олоорой", + "PREDICTED_EARNINGS": "Урьдчилан таамагласан орлого", + "VARIABLE_TITLE": "Хувьсагч*", + "VARIABLE_TEXT": "*{0} хувьсагчийн ханш хэрхэн ажилладаг талаар.", + "READ_MORE": "Цааш унших", + "CURRENT_BLOCK": "Одоогийн блок: {0}", + "END_BLOCK": "Төгсгөлийн блок: {0}", + "DURATION": "Үргэлжлэх хугацаа", + "END_ON_BLOCK": "Блок дээр дуусах: {0}", + "SLASHING_TITLE": "Таслах", + "SLASHING_TEXT_1": "Таны Стэйкийн зарчмын {0}%", + "SLASHING_TEXT_2": "Бүх орлогыг хураана", + "REVIEW_NOTE": "Үргэлжлэх хугацааг Ethereum блокуудын цаг хугацаагаар хэмждэг. Эрт стэйклэх нь таны бооцооны зарчмын тодорхой хувийг хасч, ашиг орлогоо хураах тул бооцоо тавихаасаа өмнө дээрх дэлгэрэнгүй мэдээллийг шалгаж баталгаажуулна уу.", + "WAITING_TITLE": "Баталгаажуулахыг хүлээж байна", + "WAITING_TEXT": "Энэ гүйлгээг түрийвчэндээ баталгаажуулна уу", + "PENDING_TEXT": "Гүйлгээ хүлээгдэж байна...", + "CHECKING_ALLOWANCE": "{0} тэтгэмжийг шалгаж байна...", + "WAITING_PROMPT": "{0} {1} {2}", + "WAITING_STAKE": "Стэйкийн хэмжээг баталгаажуулна уу", + "WAITING_WITHDRAW": "Зарцуулахыг зөвшөөрч байна", + "WAITING_UNSTAKE": "Стэйклэхээ болих", + "WAITING_STAKE_ING": "Стэйкинг хүлээгдэж байна", + "WAITING_WITHDRAW_ING": "Зарцуулалтын зөвшөөрлийг боловсруулах", + "WAITING_UNSTAKE_ING": "Стэйклэхээ болих", + "SUCCESSFUL_STAKE_TITLE": "Та {0}-г амжилттай стэйклэлээ", + "SUCCESSFUL_STAKE_AMOUNT": "Стэйклэсэн дүн", + "SUCCESSFUL_STAKE_DURATION_KEY": "Үргэлжлэх хугацаа", + "SUCCESSFUL_STAKE_DURATION_DEF": "{0} ({1}) блок дээр дуусна", + "SUCCESSFUL_STAKE_DESTINATION": "Очих газар", + "SUCCESSFUL_UNSTAKE_ADDRESS": "Миний хаяг", + "OKAY": "Ok", + "ERROR_TITLE": "Алдаа: {0} татгалзсан", + "ERROR_SUBTITLE": "Хэрэв энэ алдаа байсан бол та буцаж очоод дахин оролдож болно", + "SUCCESSFUL_UNSTAKE_TITLE": "Та {0}-г амжилттай арилгалаа", + "SUCCESSFUL_UNSTAKE_AMOUNT": "Нийт хүлээн авах нь", + "EARNINGS": "Орлого", + "ORIGINAL_AMOUNT": "Стэйклэсэн анхны дүн", + "CONNECT_A_WALLET": "Хэтэвчтэй холбогдоно уу", + "CONNECT_WALLET_TABLE": "Стэйкийн үйл явдлуудын түүхийг харахын тулд {0}", + "ZERO_STAKES": "0 стэйк", + "PENDING_TRANSACTIONS": "Хүлээгдэж буй {0} {1}", + "VIEW_ON": "{0} дээрээс харах", + "BLOCKCHAIN": "блокчейн", + "VIEW_POT": "Түгээлтийн POT-г харах", + "COMPLETED": "Ханасан", + "COMPLETED_TOOLTIP": "Стейк нь гүйцсэн. Илүү их шагнал авахын тулд үргэлжлүүлэх эсвэл орлогоо авахын тулд зогсооно уу.", + "CONNECT_ERROR": "Хэтэвчээ шалгана уу", + "INSTALL_METAMASK": "Та өөрийн хөтөч дээрээ Metamask суулгах ёстой: https://metamask.io/download.html", + "INSTALL_METAMASK_TITLE": "MetaMask илэрсэнгүй", + "REWARDS": { + "0": { "CARD": "Шагнал авах (бонус байхгүй)", "TEXT": "тогтмол шагналууд." }, + "1": { + "CARD": "Шагнал + урамшуулал аваарай", + "TEXT": "орлогоосоо урамшуулах урамшуулал" + }, + "2": { + "CARD": "Хамгийн өндөр шагнал, хамгийн өндөр урамшуулал", + "TEXT": "таны орлогын хамгийн өндөр урамшуулал" + }, + "3": { "CARD": "", "TEXT": "" }, + "4": { "CARD": "", "TEXT": "" } + } + }, + "UNSTAKE": { + "TITLE": "Unstake", + "EARLY_TITLE": "Unstake early", + "EARLY_WARNING_TITLE": "Looks like you are trying to unstake early", + "EARLY_WARNING_TEXT_1": "This could lead to a percentage of your initial principle stake being deducted and all earnings being forfeited.", + "EARLY_WARNING_TEXT_2": "Are you sure you want to proceed?", + "BACK": "GO BACK", + "REVIEW": "REMOVE STAKE", + "DURATION": "EST. maturation duration", + "CANCEL": "Cancel", + "PROCEED": "Proceed", + "EARNINGS_FORFEITED": "Earnings forfeited", + "PRICE_FORMAT": "{0} {1}", + "EST_PENDING": "EST. pending: {0}", + "AMOUNT_SLASHED": "Amount slashed*", + "AMOUNT_TO_RECEIVE": "Amount to receive", + "SLASH_FOOTNOTE": "*All amounts slashed are distributed to remaining stakers. Please consider the slashed amount from initial principle, the earnings forfeited and duration remaining and determine if the value lost in unstaking early is worth the cost.", + "AMOUNT_NOTE": "Amounts will be distributed to your wallet address", + "TOTAL_EARNT": "Total earnt", + "PENDING_EARNINGS": "Pending earnings*", + "PENDING_EARNINGS_FOOTNOTE": "*Pending earnings are amounts that have not cleared and require a blockchain transaction in order to be added to your total receiving amount." + }, + "STAKE_TABLE": { + "CURRENCY": "Currency", + "AVAILABLE": "Available to stake", + "TOTAL": "Total staked", + "REWARD_RATE": "Reward rate", + "EARNINGS": "Earnings", + "STAKE": "Stake", + "VARIABLE": "Variable" + }, + "STAKE_LIST": { + "AMOUNT": "Стэйкинг хэмжээ", + "DURATION": "EST. MATURATION DURATION", + "START": "Стейкинг эхэлсэн", + "END": "Стэйк дуусах", + "EARNINGS": "ОРЛОГО", + "STAKE": "Стэйк" + }, + "STAKE_DETAILS": { + "BACK_SUBTITLE": "stake хуудас руу {0}", + "GO_BACK": "Буцах", + "CONTRACT_SUBTITLE": "Token гэрээ: {0}", + "VIEW_MORE": "ИЛҮҮ ИХИЙГ ҮЗЭХ", + "VIEW": "Дэлгэрэнгүй", + "TOKEN": "{0} Token", + "TABS": { + "PUBLIC_INFO": "Олон нийтийн мэдээлэл", + "DISTRIBUTIONS": "Хуваарилалт", + "MY_STAKING": "Миний стэйкинг" + }, + "PUBLIC_INFO": { + "TITLE": "Стэйкингийн мэдээлэл", + "SUBTITLE": "Below is a staking tokenomics for {0} ({1}).", + "TOTAL_DISTRIBUTED_REWARDS": "Total distributed rewards ({0})", + "POT_BALANCE": "POT balance", + "UNCLAIMED_REWARDS": "Unclaimed rewards", + "TOTAL_STAKED": "Нийт стэйк", + "REWARD_RATE": "Хувь хэмжээ", + "MY_STAKE": "Миний стэйк ({0}%)", + "MY_STAKE_PERCENTLESS": "Миний стэйк", + "OTHER_STAKE": "Бусад стэйк ({0}%)", + "EVENTS_TITLE": "Саяхан тараасан урамшуулал" + }, + "DISTRIBUTIONS": { + "TITLE": "{0} шагналыг тараасан", + "SUBTITLE": "Доорх нь {0}-н стэйкинг эзэмшигчдэд хийсэн түгээлтийн түүхэн жагсаалт юм..", + "TIME": "Хуваарилсан огноо", + "TRANSACTION_ID": "Гүйлгээний ID", + "AMOUNT": "Хуваарилсан дүн" + }, + "MY_STAKING": { + "TITLE": "Миний стэйкинг", + "SUBTITLE": "Below displays information and some historical events related to your {0} staking.", + "EVENTS_TITLE": "Historical stake events", + "TIME": "Цаг", + "EVENT": "Event", + "TRANSACTION_ID": "Гүйлгээний ID", + "AMOUNT": "Дүн" + } + }, + "MOVE_XHT": { + "TITLE": "XHT-г зөөх", + "TEXT_1": "XHT-г бооцоо болгохын тулд та эхлээд өөрийн XHT-ээ өөрийн хэтэвч рүү шилжүүлэх ёстой.", + "TEXT_2": "Таны одоо холбогдсон хэтэвчний хаяг байна:", + "LABEL": "Хэтэвчний хаяг", + "TEXT_3": "Хэтэвчний хаяг найдвартай эсэхийг шалгах нь чухал. XHT нь дээрх хэтэвчний хаяг руу шилжих болно." + }, + "MOVE_AMOUNT": { + "TITLE": "Оруулсан хэмжээ", + "PROMPT": "Зөөхийг хүссэн дүнгээ оруулна уу.", + "BALANCE": "{0} баланс: {1}", + "LABEL": "Хөдөлгөөн хийх хэмжээ", + "FEE": "Гүйлгээний хураамж: {0} {1}" + }, + "CURRENCY": "Крипто", + "TYPE": "Төрөл", + "TYPES_VALUES": { "market": "market", "limit": "limit" }, + "TYPES": { "MARKET": "market", "LIMIT": "limit" }, + "SIDE": "Side", + "SIDES_VALUES": { "buy": "авах", "sell": "зарах" }, + "SIDES_VERBS": { "buy": "авсан", "sell": "зарсан" }, + "SIDES": { "BUY": "авах", "SELL": "зарах" }, + "DEFAULT_TOGGLE_OPTIONS": { "ON": "асаалттай", "OFF": "унтарсан" }, + "SIZE": "Хэмжээ", + "PRICE": "Үнэ", + "FEE": "Шимтгэл", + "FEES": "Шимтгэл", + "TIME": "Цаг", + "MORE": "Илүүг", + "VIEW": "Харах", + "STATUS": "Төлөв", + "AMOUNT": "Хэмжээ", + "COMPLETE": "Дууссан", + "PENDING": "Хүлээгдэж буй", + "REJECTED": "Татгалзсан", + "ORDERBOOK": "Захиалгын дэвтэр", + "CANCEL": "Цуцлах", + "CANCEL_ALL": "Бүгдийг цуцлах", + "ORDER_ENTRY": "Захиалга оруулах", + "TRADE_HISTORY": "Түүх", + "CHART": "Үнийн график", + "ORDERS": "Миний идэвхитэй захиалгууд", + "RECENT_TRADES": "Миний гүйлгээнүүд", + "ORDER_HISTORY": "Захиалгын түүх", + "PUBLIC_SALES": "Олон нийтийн борлуулалт", + "REMAINING": "үлдэгдэл", + "FULLFILLED": "{0} % Дүүрсэн", + "FILLED": "Дүүрсэн", + "LOWEST_PRICE": "Доод үнэ ({0})", + "PHASE": "Үе шат", + "INCOMING": "Орлого", + "PRICE_CURRENCY": "Үнэ", + "AMOUNT_SYMBOL": "Хэмжээ", + "ESTIMATED_PRICE": "Багцаа үнэ", + "ORDER_PRICE": "Захиалгын үнэ", + "NO_DATA": "Мэдээлэл байхгүй", + "CHART_TEXTS": { + "d": "Огноо", + "o": "Нээлттэй", + "h": "Дээд", + "l": "Доод", + "c": "Хаах", + "v": "Хэмжээ" + }, + "QUICK_TRADE": "Хялбар ажиллагаа", + "PRO_TRADE": "Арилжаа", + "WALLET_TITLE": "Хэтэвч", + "LOGOUT": "Гарах", + "WITHDRAWALS_MIN_VALUE_ERROR": "Гүйлгээний дүн хэт бага байна. Дүнгээ өөрчилнө үү.", + "WITHDRAWALS_MAX_VALUE_ERROR": "Гүйлгээний дүн хэт өндөр байна. Дүнгээ өөрчилнө үү.", + "WITHDRAWALS_LOWER_BALANCE": "Үлдэгдэл хүрэлцэхгүй байна. Хамгийн багадаа {0} байх шаардлагатай.", + "WITHDRAWALS_BTC_INVALID_ADDRESS": "Bitcoin хаяг буруу байна. Хаягаа дахин шалгана уу", + "WITHDRAWALS_ETH_INVALID_ADDRESS": "Ethereum хаяг буруу байна. Хаягаа дахин шалгана уу", + "WITHDRAWALS_BUTTON_TEXT": "Зарлага хянах", + "WITHDRAWALS_FORM_NETWORK_LABEL": "Сүлжээ", + "DEPOSIT_FORM_NETWORK_WARNING": "Сонгосон сүлжээ нь илгээгчийн сүлжээтэй тохирч байгаа эсэхийг нягтлана уу", + "DEPOSIT_FORM_TITLE_WARNING_DESTINATION_TAG": "Хаяг болон таг заавал оруулна уу.", + "WITHDRAW_PAGE_DESTINATION_TAG_NONE": "Байхгүй", + "WITHDRAW_PAGE_DESTINATION_TAG_MESSAGE": "Хүргэх tag: {0}", + "WITHDRAW_PAGE_NETWORK_TYPE_MESSAGE": "{0} хаягийн сүлжээний төрөл: {1}", + "WITHDRAWALS_FORM_NETWORK_WARNING": "Сонгосон сүлжээ нь очих газрын хэтэвчтэй нийцэж байгаа эсэхийг шалгаарай", + "WITHDRAWALS_FORM_FEE_WARNING": "{0} ({1}) нь энэ хөрөнгийг эргүүлэн татахад тавигдах шаардлага юм", + "WITHDRAWALS_FORM_DESTINATION_TAG_WARNING": "Хүлээн авах хаяг нь шошго шаардлагатай эсэхийг шалгана уу. Мөн Memo, дижитал ID, шошго, тэмдэглэл гэж нэрлэдэг.", + "WITHDRAWALS_FORM_NETWORK_PLACEHOLDER": "Сүлжээ сонгох", + "WITHDRAWALS_FORM_ADDRESS_LABEL": "Хүлээн авах хаяг", + "WITHDRAWALS_FORM_ADDRESS_PLACEHOLDER": "Хаягаа бичнэ үү", + "WITHDRAWALS_FORM_DESTINATION_TAG_LABEL": "Хүлээн авах tag оруулна уу", + "WITHDRAWALS_FORM_MEMO_LABEL": "Memo (заавал биш)", + "WITHDRAWALS_FORM_DESTINATION_TAG_PLACEHOLDER": "Хүлээн авах tag (заавал биш)", + "WITHDRAWALS_FORM_AMOUNT_LABEL": "{0} зарлага хийх дүн", + "WITHDRAWALS_FORM_AMOUNT_PLACEHOLDER": "{0} зарлага хийх дүнгээ оруулна уу", + "WITHDRAWALS_FORM_FEE_COMMON_LABEL": "Гүйлгээний шимтгэл", + "WITHDRAWALS_FORM_FEE_COMMON_LABEL_COIN": "Гүйлгээний шимтгэл ({0})", + "WITHDRAWALS_FORM_FEE_PLACEHOLDER": "Гүйлгээний шимтгэлд ашиглах {0} сонгоно уу", + "DEPOSIT_BANK_REFERENCE": "Энэ '{0}' кодыг гүйлгээний утган дээрээ заавал бичээрэй", + "QUOTE_SUCCESS_REVIEW_MESSAGE": "Та {0} {1} {2} - амжилттай худалдан авлаа", + "COUNTDOWN_ERROR_MESSAGE": "Каунтдаун дууслаа", + "WITHDRAW_PAGE": { + "BANK_TO_WITHDRAW": "Банкны зарлага гаргах", + "MESSAGE_ABOUT_SEND": "Та илгээх гэж байна", + "MESSAGE_BTC_WARNING": "{0} шилжүүлгийг буцаах боломжгүй тул энэ хаягийн үнэн зөвийг баталгаажуулна уу", + "MESSAGE_FEE": "Гүйлгээний шимтлэг {0} ({1}) багтсан", + "MESSAGE_FEE_COIN": "{0} гүйлгээний шимтгэл", + "BASE_MESSAGE_1": "Та өөрийн бүртгүүлсэн нэртэй ижил данс руу гүйлгээ хийх боломжтой.", + "BASE_MESSAGE_2": "Зарлагын доод дүн", + "BASE_MESSAGE_3": "Өдрийн зарлагын дээд хэмжээ", + "CONFIRM_VIA_EMAIL": "И-мэйлээр баталгаажуулах", + "CONFIRM_VIA_EMAIL_1": "Бид тань руу зарлага баталгаажуулах и-мэйл илгээнэ.", + "CONFIRM_VIA_EMAIL_2": "Зарлагын гүйлгээг баталгаажуулахын тулд та", + "CONFIRM_VIA_EMAIL_3": "И-мэйлийг 5 минутын дотор баталгаажуулах шаардлагатай.", + "WITHDRAW_CONFIRM_SUCCESS_1": "Таны зарлагын хүсэлтийг хүлээн авлаа. Зарлага удахгүй баталгаажих болно", + "WITHDRAW_CONFIRM_SUCCESS_2": "Зарлагын төлвөө Зарлагын түүх хэсгээс харна уу.", + "GO_WITHDRAWAL_HISTORY": "Зарлагын түүх", + "WITHDRAWALS_FORM_ERROR_TITLE": "Шилжүүлгийн мэдээлэл буруу байна", + "WITHDRAWALS_FORM_ERROR": "Таны сангийн шилжүүлэг амжилтгүй боллоо. Имэйл рүү мөнгө илгээхдээ хэрэглэгч энэ бирж дотор данстай байхыг шаарддаг. Имэйл зөв эсэхийг шалгаад дахин оролдоно уу." + }, + "WALLET_BUTTON_BASE_DEPOSIT": "орлого", + "WALLET_BUTTON_BASE_WITHDRAW": "зарлага", + "WALLET_BUTTON_CRYPTOCURRENCY_DEPOSIT": "хүлээн авах", + "WALLET_BUTTON_CRYPTOCURRENCY_WITHDRAW": "илгээх", + "AVAILABLE_BALANCE_TEXT": "Боломжит {0} Баланс: {1} {2}", + "BALANCE_TEXT": "Баланс", + "CURRENCY_BALANCE_TEXT": "{0} Баланс", + "WALLET_ALL_ASSETS": "Бүх хөрөнгө", + "WALLET_HIDE_ZERO_BALANCE": "0 дүнтэйг нуух", + "WALLET_ESTIMATED_TOTAL_BALANCE": "Нийт баланс (багцаа)", + "WALLET_ASSETS_SEARCH_TXT": "Хайх", + "PAGINATOR_FORMAT": "{0} / {1}", + "ORDERBOOK_SELLERS": "Худалдагч", + "ORDERBOOK_BUYERS": "Худалдан авагч", + "ORDERBOOK_SPREAD": "зөрүү {0}", + "CALCULATE_MAX": "Дээд хэмжээ", + "VERIFICATION_WARNING_TITLE": "Банкны баталгаажуулалт", + "VERIFICATION_WARNING_MESSAGE": "Та зарлага гаргахын өмнө банкаа баталгаажуулах шаардлагатай.", + "ORDER_SPENT": "Зарцуулсан", + "ORDER_RECEIVED": "Хүлээн авсан", + "ORDER_SOLD": "Зарсан", + "ORDER_BOUGHT": "Худалдаж авсан", + "ORDER_AVERAGE_PRICE": "Дундаж үнэ", + "ORDER_TITLE_CREATED": "Лимит {0} захиалга үүсгэлээ", + "ORDER_TITLE_FULLY_FILLED": "{0} захиалга дүүрлээ", + "ORDER_TITLE_PARTIALLY_FILLED": "{0} захиалга хэсэгчлэн дүүрлээ", + "ORDER_TITLE_TRADE_COMPLETE": "{0} {1} захиалга дууслаа", + "LOGOUT_TITLE": "Та системээс гарсан байна", + "LOGOUT_ERROR_TOKEN_EXPIRED": "Таны системийн хугацаа дууслаа. Дахин нэвтэрч орно уу", + "LOGOUT_ERROR_LOGIN_AGAIN": "Дахин нэвтэрч орно уу", + "LOGOUT_ERROR_INVALID_TOKEN": "Tокен буруу байна", + "LOGOUT_ERROR_INACTIVE": "Та идэвхигүй байсан тул системээс гарсан байна", + "ORDER_ENTRY_BUTTON": "{0} {1}", + "ORDER_ENTRY_ADVANCED": "Нарийвчилсан", + "QUICK_TRADE_OUT_OF_LIMITS": "Захиалгын хэмжээ лимитээс хэтэрсэн байна", + "QUICK_TRADE_TOKEN_USED": "Token хэрэглэгдсэн байна", + "QUICK_TRADE_QUOTE_EXPIRED": "Саналын хугацаа дууссан байна", + "QUICK_TRADE_QUOTE_INVALID": "Санал буруу байна", + "QUICK_TRADE_QUOTE_CALCULATING_ERROR": "Саналыг тооцоолоход алдаа гарлаа", + "QUICK_TRADE_ORDER_CAN_NOT_BE_FILLED": "Ийм хэмжээтэй захиалга дүүрэх боломжгүй", + "QUICK_TRADE_ORDER_NOT_FILLED": "Захиалга дүүрсэнгүй", + "QUICK_TRADE_NO_BALANCE": "Баланс хүрэлцэхгүй байна", + "QUICK_TRADE_SUCCESS": "Амжилттай!", + "QUICK_TRADE_INSUFFICIENT_FUND": "Үлдэгдэл хүрэлцэхгүй байна", + "QUICK_TRADE_INSUFFICIENT_FUND_MESSAGE": "Энэ гүйлгээг хийхэд таны үлдэгдэл хүрэлцэхгүй байна.", + "QUICK_TRADE_BROKER_NOT_AVAILABLE_MESSAGE": "Брокерын OTC хэлэлцээр одоогоор боломжгүй байна.", + "SUBMIT": "илгээх", + "RESUBMIT": "Дахин илгээх", + "VERIFICATION_NOTIFICATION_SKIP_TITLE": "Бичиг баримт дутуу байна!", + "VERIFICATION_NOTIFICATION_SKIP_TEXT": "Мөнгөн орлого зарлагыг идэвхжүүлэхийн тулд та KYC баталгаажуулалтаа хийх ёстой.", + "VERIFICATION_NOTIFICATION_SUCCESS_TITLE": "Амжилттай!", + "VERIFICATION_NOTIFICATION_SUCCESS_TEXT": "Таны мэдээлэл баталгаажсаны дараа та и-мэйл хүлээн авна. Баталгаажуулалт 1-3 хоног үргэлжилнэ", + "VERIFICATION_NOTIFICATION_BUTTON": "ЭКСЧЭЙНЖ РҮҮ ОЧИХ", + "ERROR_USER_ALREADY_VERIFIED": "Хэрэглэгч баталгаажсан байна", + "ERROR_INVALID_CARD_USER": "Банкны мэдээлэл буруу байна", + "ERROR_INVALID_CARD_NUMBER": "Картын дугаар буруу байна", + "ERROR_LOGIN_USER_NOT_VERIFIED": "Хэрэглэгч баталгаажаагүй байна", + "ERROR_LOGIN_USER_NOT_ACTIVATED": "Хэрэглэгч идэвхигүй байна", + "ERROR_LOGIN_INVALID_CREDENTIALS": "Нэвтрэх мэдээлэл буруу", + "SMS_SENT_TO": "{0} SMS илгээх", + "SMS_ERROR_SENT_TO": "{0} руу SMS илгээхэд алдаа гарлаа. Хуудсыг дахин сэргээгээд дахин оролдоно уу.", + "WITHDRAW_NOTIFICATION_TRANSACTION_ID": "Гүйлгээний №:", + "CHECK_ORDER": "Захиалгаа шалгаад баталгаажуулна уу", + "CHECK_ORDER_TYPE": "{0} {1}", + "CONFIRM_TEXT": "Баталгаажуулах", + "INVALID_CAPTCHA": "Captcha буруу байна", + "NO_FEE": "N/A", + "SETTINGS_LANGUAGE_LABEL": "Хэлний сонголт (И-мэйл орно)", + "SETTINGS_THEME_LABEL": "Хэрэглэгчийн интерфэйс", + "SETTING_BUTTON": "хадгалах", + "VERIFICATION_NO_WITHDRAW_TITLE": "Зарлага гаргах боломжгүй", + "VERIFICATION_NO_WITHDRAW_MESSAGE": "Таны бүртгэл зарлага гаргах боломжгүй", + "UP_TO_MARKET": "Up to market", + "VIEW_MY_FEES": "Миний Шимтгэл", + "DEVELOPER_SECTION": { + "TITLE": "API Key", + "INFORMATION_TEXT": "API нь хэтэвчний үлдэгдэл авах, худалдан авах/худалдах захиалгыг удирдах, мөнгө авах хүсэлт гаргах, түүнчлэн сүүлийн арилжаа, захиалгын дэвтэр, ticker зэрэг зах зээлийн мэдээллийг авах боломж олгодог.", + "ERROR_INACTIVE_OTP": "API түлхүүр үүсгэхийн тулд та 2FA баталгаажуулалтыг идэвхжүүлэх хэрэгтэй.", + "ENABLE_2FA": "2FA Идэвхижүүлэх", + "WARNING_TEXT": "DAPI түлхүүрийг бусадтай битгий хуваалцаарай.", + "GENERATE_KEY": "API Түлхүүр үүсгэх", + "ACTIVE": "Идэвхитэй", + "INACTIVE": "Идэвхигүй", + "INVALID_LEVEL": "Та энэ хэсэгт хандахын тулд өөрийн баталгаажуулалтын түвшингээ ахиулах хэрэгтэй" + }, + "DEVELOPERS_TOKEN": { + "API_KEY": "API түлхүүр", + "SECRET_KEY": "Нууц түлхүүр", + "ACCESS": "Хандалт", + "BASIC_ACCESS": "үндсэн хандалт", + "BASIC_ACCESS_PROMPT": "үндсэн хандалт", + "READING_ACCESS": "Унших (Хэтэвчний үлдэгдэл гэх мэт)", + "TRADING_ACCESS": "Арилжаа", + "IP_ACCESS": "IP хандалт", + "IP_ACCESS_PROMPT": "Энэ API түлхүүрээр ямар IP хаяг ажиллахыг тохируулна уу.", + "ANY_IP_ADDRESS": "Аливаа IP хаяг", + "ONLY_TRUSTED_IPS": "Зөвхөн итгэмжлэгдсэн IP", + "ADD_IP_PH": "IP хаягаа оруулна уу. Та олон IP нэмж болно", + "ADD_IP": "Нэмэх", + "ADVANCED_ACCESS": "Нарийвчилсан хандалт", + "ADVANCED_ACCESS_PROMPT": "Итгэмжлэгдсэн IP-г идэвхжүүлэх шаардлагатай.", + "WITHDRAWAL_ACCESS": "Татан авалт", + "SAVE": "Хадгалах", + "BEWARE": "Татан авалтыг зөвшөөрөх нь тодорхой эрсдэлтэй тул болгоомжтой байгаарай!" + }, + "DEVELOPERS_TOKENS_POPUP": { + "GENERATE_TITLE": "API Түлхүүр үүсгэх", + "GENERATE_TEXT": "API түлхүүрээ нэрлээд үүсгэсний дараа нууцална уу. Та дараа нь дахин сэргээх боломжгүй.", + "GENERATE": "Үүсгэх", + "DELETE_TITLE": "API Түлхүүр устгах", + "DELETE_TEXT": "API түлхүүрээ устгах нь буцаах боломжгүй бөгөөд та хүссэн үедээ шинэ API түлхүүр үүсгэж болно. Та API түлхүүрээ устгахыг хүсэж байна уу?", + "DELETE": "УСТГАХ", + "FORM_NAME_LABEL": "Нэр", + "FORM_LABLE_PLACEHOLDER": "Api түлхүүрийн нэр", + "API_KEY_LABEL": "API түлхүүр", + "SECRET_KEY_LABEL": "Нууц үг", + "CREATED_TITLE": "API түлхүүрийг хуулбарлах", + "CREATED_TEXT_1": "API түлхүүрийг яг одоо хуулбарлаж авна уу.", + "CREATED_TEXT_2": "Та түлхүүрийн нууцлалыг өөрөө хариуцах болно." + }, + "DEVELOPERS_TOKENS_TABLE": { + "NAME": "Нэр", + "API_KEY": "API түлхүүр", + "SECRET": "Нууцлал", + "CREATED": "Үүсгэсэн огноо", + "REVOKE": "Хүчингүй болгох", + "REVOKED": "Хүчингүй болгосон", + "REVOKE_TOOLTIP": "Та идэвхигүй болгохын тулд 2FA идэвхижүүлэх шаардлагатай" + }, + "CHAT": { + "READ_MORE": "Дэлгэрэнгүй", + "SHOW_IMAGE": "Зураг харуулах", + "HIDE_IMAGE": "Зураг нуух", + "CHAT_MESSAGE_BOX_PLACEHOLDER": "Мессеж", + "TROLLBOX": "Trollbox ({0})", + "SET_USERNAME": "ХЭРЭГЛЭГЧИЙН НЭРИЙГ ЧАТАНД ТОХИРУУЛАХ" + }, + "INVALID_USERNAME": "Хэрэглэгчийн нэр 3-15 тэмдэгтийн урттай байх ёстой. Зөвхөн жижиг үсэг, тоо, доогуур зураасыг агуулна", + "USERNAME_TAKEN": "Энэ нэр бүртгэлтэй байна.", + "USERNAME_LABEL": "Ник нэр (чатанд ашиглах)", + "USERNAME_PLACEHOLDER": "Ник нэр", + "TAB_USERNAME": "Ник нэр", + "USERNAME_WARNING": "Таны хэрэглэгчийн нэрийг зөвхөн нэг удаа өөрчлөх боломжтой. Хэрэглэгчийн нэрээ авах нь зүйтэй гэдэгт итгэлтэй байна уу.", + "USERNAME_CANNOT_BE_CHANGED": "Хэрэглэгчийн нэрийг өөрчлөх боломжгүй", + "UPGRADE_LEVEL": "Түвшин ахиулах", + "LEVELS": { + "LABEL_LEVEL": "Түвшин", + "LABEL_LEVEL_1": "Нэг", + "LABEL_LEVEL_2": "Хоёр", + "LABEL_LEVEL_3": "Гурав", + "LABEL_BASE_DEPOSIT": "Maker шимтгэл", + "LABEL_BASE_WITHDRAWAL": "Өдрийн зарлагын лимит", + "LABEL_BTC_DEPOSIT": "Өдрийн биткойн орлогын лимит", + "LABEL_BTC_WITHDRAWAL": "Өдрийн биткойн зарлагын лимит", + "LABEL_ETH_DEPOSIT": "Өдрийн Этериум орлого", + "LABEL_ETH_WITHDRAWAL": "Өдрийн Этериум зарлага", + "LABEL_PAIR_MAKER_FEE": "{0} Maker шимтгэл", + "LABEL_PAIR_TAKER_FEE": "{0} Taker шимтгэл", + "UNLIMITED": "Хязгааргүй", + "BLOCKED": "Идэвхигүй" + }, + "WALLET_ADDRESS_TITLE": "{0} Хэтэвч үүсгэх", + "WALLET_ADDRESS_GENERATE": "Үүсгэх", + "WALLET_ADDRESS_MESSAGE": "Та хэтэвчээ үүсгэснээр орлого хийх боломжтой болно.", + "WALLET_ADDRESS_ERROR": "Хаяг үүсгэхэд алдаа гарлаа. Дахин оролдоно уу", + "DEPOSIT_WITHDRAW": "Орлого/Зарлага", + "GENERATE_WALLET": "Хэтэвч үүсгэх", + "TRADE_TAB_CHART": "График", + "TRADE_TAB_TRADE": "Арилжаа", + "TRADE_TAB_ORDERS": "Захиалга", + "TRADE_TAB_POSTS": "Зарлал", + "WALLET_TAB_WALLET": "Хэтэвч", + "WALLET_TAB_TRANSACTIONS": "Гүйлгээ", + "RECEIVE_CURRENCY": "{0} Хүлээн авах", + "SEND_CURRENCY": "{0} Илгээх", + "COPY_ADDRESS": "Хаяг хуулах", + "SUCCESFUL_COPY": "Амжилттай хууллаа!", + "QUICK_TRADE_MODE": "Хялбар арилжаа", + "JUST_NOW": "яг одоо", + "PAIR": "Хослол", + "ZERO_ASSET": "Танд хөрөнгө байхгүй байна", + "DEPOSIT_ASSETS": "Хөрөнгө орлогодох", + "SEARCH_TXT": "Хайх", + "SEARCH_ASSETS": "Хөрөнгө хайх", + "TOTAL_ASSETS_VALUE": "Таны хөрөнгийн багцаа {0}: {1}", + "SUMMARY": { + "TITLE": "Хураангуй", + "URGENT_REQUIREMENTS": "Яаралтай шаардлага", + "TRADING_VOLUME": "Арилжааны хэмжээ", + "ACCOUNT_ASSETS": "Хэрэглэгчийн хөрөнгүүд", + "ACCOUNT_DETAILS": "Хэрэглэгчийн мэдээлэл", + "VIEW_FEE_STRUCTURE": "Шимтгэлийн шатлал, хэмжээ", + "UPGRADE_ACCOUNT": "Түвшин ахиулах", + "ACTIVE_2FA_SECURITY": "2FA Хамгаалалт идэвхижүүлэх", + "ACCOUNT_ASSETS_TXT_1": "Энэ хэсэгт таны бүх хөрөнгийн хураангуй байна.", + "ACCOUNT_ASSETS_TXT_2": "Их хэмжээний хөрөнгөтэй байх нь танд өвөрмөц тэмдэг, арилжааны хураамж бага зэрэг дансны шинэчлэлт хийх эрх олгоно.", + "ACCOUNT_DETAILS_TXT_1": "Таны дансны төрөл нь таны дансны тэмдэг, арилжааны хураамж, хадгаламж, мөнгө авах хязгаарыг тодорхойлдог.", + "ACCOUNT_DETAILS_TXT_2": "Таны арилжааны дансны нас, үйл ажиллагааны түвшин болон дансны нийт хөрөнгийн хэмжээ таны дансыг шинэчлэх боломжтой эсэхийг тодорхойлно.", + "ACCOUNT_DETAILS_TXT_3": "Дансны түвшингээ хадгалахын тулд тогтмол арилжаа хийх, тодорхой хэмжээний хадгалуулсан хөрөнгийг хадгалах шаардлагатай.", + "ACCOUNT_DETAILS_TXT_4": "Үйл ажиллагаа болон хөрөнгийг хадгалахгүй бол дансны зэрэглэлийг үе үе бууруулна.", + "REQUIREMENTS": "Шаардлага", + "ONE_REQUIREMENT": "Аль нэгийг хангасан:", + "REQUEST_ACCOUNT_UPGRADE": "Түвшин ахиулах хүсэлт илгээх", + "FEES_AND_LIMIT": "{0} Шимтгэл & Лимит", + "FEES_AND_LIMIT_TXT_1": "Крипто арилжаачин болох нь шинэ эхлэлийг илтгэнэ. Оюун ухаан, хүсэл зориг, хурдаараа зэвсэглэсэн, эрсдэлд орж, арилжаа хийснээр та дансаа шинэчлэх боломжтой болно.", + "FEES_AND_LIMIT_TXT_2": "Данс бүр өөрийн гэсэн шимтгэлтэй, мөнгө байршуулах, авах хязгаартай.", + "TRADING_FEE_STRUCTURE": "Орлого зарлагын хэмжээ", + "DEPOSIT_AND_WITHDRAWAL_FEES": "Орлого, зарлагын шимтгэлүүд", + "WITHDRAWAL": "Зарлага", + "DEPOSIT": "Орлого", + "TAKER": "Taker", + "MAKER": "Maker", + "DEPOSITS": "Орлогууд", + "WITHDRAWALS": "Зарлагууд", + "NOMINAL_TRADING_WITH_MONTH": "{0} сарын арилжааны хэмжээ", + "LEVEL_OF_ACCOUNT": "{0} дүгээр түвшний бүртгэл", + "TITLE_OF_ACCOUNT": "{0} Бүртгэл", + "LEVEL_TXT_DEFAULT": "Өөрийн түвшний тайлбарыг энд нэмнэ үү", + "CURRENT_TXT": "Одоогийн", + "EMAIL_VERIFICATION": "Имэйл баталгаажуулалт", + "DOCUMENTS": "Баримт бичиг", + "HAP_TEXT": "NCX түншлэлийн хөтөлбөр (HAP) {0}", + "LOCK_AN_EXCHANGE": "Exchange-г түгжих {0}", + "WALLET_SUBSCRIPTION_USERS": "Vault захиалгын хэрэглэгчид {0}", + "TRADE_OVER_XHT": "{0} USDT-с дээш үнээр худалдаа хийнэ", + "XHT_IN_WALLET": "Хэтэвчинд {0} XHT", + "TASKS": "Даалгаврууд", + "INVITE_USER": "Хэрэглэгчдийг урьж, тэдний арилжаанаас шимтгэл аваарай", + "DISCOUNT": "({0}% хөнгөлөлт)", + "MY_FEES_LIMITS": "Миний хураамж ба хязгаарлалт", + "MARKETS": "Арилжаа", + "CHANGE_24H": "24 цагийн өөрчлөлт", + "VOLUME_24H": "24 цагийн хэмжээ", + "VIEW_MORE_MARKETS": "Бүх хослол" + }, + "REFERRAL_LINK": { + "TITLE": "Найзаа урих", + "INFO_TEXT": "Та найзаа урьснаар танд олон төрлийн урамшуулал очих болно.", + "COPY_FIELD_LABEL": "Доорх холбоосыг найзуудтайгаа хуваалцаж, урамшуулал аваарай:", + "REFERRED_USER_COUT": "Та {0} найз урьсан байна", + "COPY_LINK_BUTTON": "ЛИНК ХУУЛАХ" + }, + "NOT_LOGGEDIN": { + "TXT_1": "Арилжаа эхлүүлэхийн тулд та нэвтрэх ёстой", + "TXT_2": "{0} эсвэл {1}", + "LOGIN_HERE": "энд нэвтэрнэ үү" + }, + "USER_LEVEL": "Хэрэглэгчийн түвшин", + "LIMIT_AMOUNT": "Лимит", + "FEE_AMOUNT": "Шимтгэл", + "COINS": "Койн", + "PAIRS": "Хослол", + "NOTE_FOR_EDIT_COIN": "Жич: {0}-г нэмэх, хасахын тулд {1}-г үзнэ үү.", + "REFER_DOCS_LINK": "баримт бичиг", + "EXPIRED_INFO_1": "Таны trial дууслаа. ", + "EXPIRED_INFO_2": "Биржийг дахин идэвхжүүлэхийн тулд барьцаа хөрөнгөө тавина уу.", + "EXPIRED_BUTTON_TXT": "EXCHANGE-г ИДЭВХЖҮҮЛЭХ", + "TRADE_POSTS": { "LEARN_MORE": "Илүү их судла" }, + "OPEN_WALLET": "Хэтэвч", + "CUMULATIVE_AMOUNT_SYMBOL": "Нийт", + "POST_ONLY": "Post only", + "CLEAR": "Арилгах", + "ORDER_TYPE": "Төрөл", + "ORDER_MODE": "Хэлбэр", + "TRIGGER_CONDITIONS": "Хэрэгжих нөхцөл", + "TRANSACTION_STATUS": { + "PENDING": "Хүлээгдэж буй", + "REJECTED": "Татгалзсан", + "COMPLETED": "Дууссан" + }, + "DEPOSIT_STATUS": { + "NEW": "Шинэ", + "SEARCH_FIELD_LABEL": "Гүйлгээний ID хуулж тавина уу", + "CHECK_DEPOSIT_STATUS": "Орлого шалгах", + "SEARCH_BLOCKCHAIN_FOR_DEPOSIT": "Хадгаламжиндаа блокчейн хайх", + "STATUS_DESCRIPTION": "Та гүйлгээний ID (hash) доорх нүдэнд тавьж орлогын явцыг шалгах боломжтой.", + "TRANSACTION_ID": "Гүйлгээний ID (hash)", + "SEARCH_SUCCESS": "Хайлт дууслаа", + "ADDRESS_FIELD_LABEL": "Хаяг хуулж тавина уу", + "CURRENCY_FIELD_LABEL": "Валют сонгоно уy" + }, + "CANCEL_ORDERS": { + "HEADING": "Захиалга цуцлах", + "SUB_HEADING": "Бүх захиалгыг цуцлах", + "INFO_1": "Энэ үйлдэл хийгдсэн бүх хослол дээрх бүх захиалга цуцлагдана.", + "INFO_2": "Та бүх захиалгаа цуцлахдаа итгэлтэй байна уу?" + }, + "AMOUNT_IN": "Оруулсан дүн", + "LIMITS_BLOCK": { + "HEADER_ROW_DESCRIPTION": "24ц дотор хийх орлого зарлагын хэмжээ ({0})", + "HEADER_ROW_TYPE": "Төрөл (Бүх хөрөнгө)", + "HEADER_ROW_AMOUNT": "24ц Хэмжээ ({0})" + }, + "MARKETS_TABLE": { + "TITLE": "Арилжааны хослолууд", + "MARKETS": "Арилжаа", + "LAST_PRICE": "Сүүлийн үнэ", + "CHANGE_24H": "Өөрчлөлт (24 цаг)", + "VOLUME_24h": "Хэмжээ (24 цаг)", + "CHART_24H": "График (24 фаг)", + "VIEW_MARKETS": "Арилжаанд оролцох" + }, + "PAGE_UNDER_CONSTRUCTION": "Энэ хуудас засвартай байгаа тул та дараа зочилж үзнэ үү.", + "UNDEFINED_ERROR_TITLE": "Тодорхойгүй алдаа гарлаа", + "UNDEFINED_ERROR": "Wow! Тодорхойгүй алдаа гарлаа. Та дараа дахин оролдох эсвэл хуудсыг дахин ачааллуулж үзнэ үү.", + "POST_ONLY_TOOLTIP": "Post only захиалга нь лимит захиалгаар явагдана.", + "REFRESH": "Шинэчлэх", + "FEE_REDUCTION": "Шимтгэл бууралт", + "FEE_REDUCTION_DESCRIPTION": "*таны дансанд шимтгэлийн хөнгөлөлт үзүүлсэн байна. Хөнгөлөлт нь таны хийж буй арилжааны Шимтгэлид хамаарна.", + "CHANGE_PASSWORD_FAILED": "Нууц үг солиход алдаа гарлаа", + "MARKET_OPTIONS": { "LIST": "Жагсаалт", "CARD": "Card" }, + "ALL": "Бүгд", + "ASSET_TXT": "Хөрөнгө", + "ONE_DAY": "1 өдөр", + "ONE_WEEK": "7 хоног", + "MONTH": "{0} сар", + "START_DATE": "Эхлэх огноо", + "END_DATE": "Дуусах огноо", + "REGULAR": "Энгийн", + "STOPS": "Зогсох хязгаар", + "VIEW_ALL": "бүгд", + "TRIGGER_PRICE": "Триггер үнэ", + "SPEND_AMOUNT": "Зарцуулсан хэмжээ", + "ESTIMATE_RECEIVE_AMOUNT": "Хүлээн авах дүнгийн хэмжээ", + "TOOLS": { + "ORDERBOOK": "Захиалгын дэлгэрэнгүй", + "CHART": "Үнийн график", + "PUBLIC_SALES": "Олон нийтийн борлуулалт", + "ORDER_ENTRY": "захиалга оруулах", + "RECENT_TRADES": "Миний сүүлд хийсэн арилжаа", + "OPEN_ORDERS": "Нээлттэй захиалга", + "WALLET": "Хэтэвч", + "DEPTH_CHART": "График", + "COMING_SOON": "тун удахгүй" + }, + "WALLET_BALANCE_LOADING": "Үлдэгдэл ачаалж байна...", + "LOADING": "Ачаалж байна...", + "CONNECT_VIA_DESKTOP": { + "TITLE": "Суурин компьютерээр холбогдоно уу", + "SUBTITLE": "Таны мобайл төхөөрөмжөөр дамжуулан DeFi stake хийхийг одоогоор дэмжихгүй байна.", + "TEXT": "Хэтэвчээ холбохын тулд сууран/зөөврийн компьютер ашиглана уу." + }, + "ORDER_HISTORY_CLOSED": "Хаалттай", + "FIAT": { + "UNVERIFIED": { + "TITLE": "Бүрэн баталгаажуулалт", + "TEXT": "{0}-г хийхийн тулд та өөрийн банкны дэлгэрэнгүй мэдээллийг баталгаажуулалтаа дуусгах шаардлагатай. Доорх үргэлжлүүлэх товчийг дарна уу.", + "DEPOSIT": "хадгаламж", + "WITHDRAWAL": "татах" + }, + "REVIEW_DEPOSIT": { + "TITLE": "Орлогын дэлгэрэнгүй мэдээллийг шалгаж баталгаажуулна уу", + "SUBTITLE": "Бүх зүйл зөв эсэхийг шалгахын тулд доорх орлогын дэлгэрэнгүй мэдээллийг шалгана уу.", + "FORMAT": "{0} {1}", + "AMOUNT": "Орлогын хэмжээ", + "FEE": "Орлогын хураамж", + "TRANSACTION_ID": "Гүйлгээний ID", + "NOTE": "Саатал гарахаас зайлсхийхийн тулд орлогын дүн, тэмдэглэл болон гүйлгээний ID нь дээрх дэлгэрэнгүй мэдээлэлтэй тохирч байгаа эсэхийг шалгаарай. Хэрэв асуудал гарвал холбоо барина уу.", + "BACK": "Буцах", + "PROCEED": "Үргэлжлүүлэх" + } + }, + "DEPOSIT_FEE_NOTE": "Таны дансанд байршуулсан нийт дүн нь орлогын хураамжийг хассан дүн байх болно гэдгийг анхаарна уу", + "AMOUNT_LABEL": "Орлогын дүнг оруулна уу (бодит дүнтэй ижил байх ёстой)", + "TRANSACTION_ID_LABEL": "Орлогын гүйлгээний ID-г оруулна уу", + "FEE_LABEL": "Орлогын хураамж", + "AMOUNT_FORMAT": "{0} {1}", + "PENDING_DEPOSIT_TITLE": "Орлого хүлээгдэж байна", + "PENDING_DEPOSIT_TEXT_1": "Таны орлого хүсэлт баталгаажуулах хийхийг хүлээж байна.", + "PENDING_DEPOSIT_TEXT_2": "Орлого 24 цагийн дотор арилдаг боловч 48 цаг хүртэл хугацаа шаардагдах бөгөөд таны хадгаламжийн дүнг хассаны дараа шимтгэл таны үлдэгдэлд орно.", + "DEPOSIT_HOME_NOTE": "Орлогоо хийхдээ өөрийн данснаас мөнгө байршуулах мөнгөө оруулна уу. Саатал гарахаас зайлсхийхийн тулд доор оруулсан дүн таны данснаас илгээх эсвэл илгээсэн бодит дүнтэй тохирч байгаа эсэхийг шалгаарай.", + "DEPOSIT_TXID_NOTE": "Орлогоо хойшлуулахаас зайлсхийхийн тулд гүйлгээний тэмдэглэл эсвэл мессежийн дотор банкны мөнгө хийхдээ дээр харуулсан өвөрмөц тэмдэглэлээ оруулна уу. Доорх дүн нь таны банкнаас байршуулсантай тохирч байгаа эсэх, мөн гүйлгээ хийсний дараа банкнаас өгсөн гүйлгээний ID-г оруулсан эсэхээ шалгаарай.", + "DEPOSIT_BANK_TEXT": "Доорх банкны дэлгэрэнгүй мэдээллийг ашиглан мөнгө байршуулна уу.", + "MIN_DEPOSIT": "Орлогын доод хэмжээ", + "MAX_DEPOSIT": "Орлогын дээд хэмжээ", + "BACK": "буцах", + "DONE": "Дууслаа", + "PENDING_WITHDRAWAL_TITLE": "Зарлагын хүсэлт хүлээгдэж байна", + "PENDING_WITHDRAWAL_TEXT_1": "Таны зарлагын хүсэлтийг баталгаажуулах шаардлагатай тул та түр хүлээнэ үү.", + "DEPOSIT_AMOUNT_MIN_VALIDATION": "Гүйлгээ илгээх хэмжээ бага байна. Илүү их хэмжээгээр туршиж үзээрэй.", + "DEPOSIT_AMOUNT_MAX_VALIDATION": "Гүйлгээ илгээх хэмжээ их байна. Бага хэмжээгээр туршиж үзээрэй.", + "ACCOUNT_NAME": "дансны нэр", + "ACCOUNT_NUMBER": "дансны дугаар", + "BANK_NAME": "банкны нэр", + "VERIFY_BANK_WITHDRAW": "Зардага гаргахын тулд та өөрийн банкны дэлгэрэнгүй мэдээллийн баталгаажуулалтаа дуусгах шаардлагатай. Доорх үргэлжлүүлэх товчийг дарна уу.", + "VERIFICATION_TITLE": "Баталгаажуулалт", + "WITHDRAW_NOTE": "Анхаарна уу: Та зөвхөн өөрийн нэр дээрх дансруу мөнгө татах боломжтой.", + "USER_PAYMENT": { "TITLE": "Төлбөр" }, + "QUOTE_CONFIRMATION_MSG_TEXT_1": "Доорх захиалгаа шалгаад баталгаажуулна уу.", + "QUOTE_CONFIRMATION_MSG_TEXT_2": "Хүлээн авах дүн нь урьдчилсан тооцоо бөгөөд арилжааны хураамжийг оруулаагүй болно", + "ORDER_EXPIRED_MSG": "Захиалгын хугацаа дууссан. Дахин ачааллуулна уу?", + "WITHDRAWALS_FORM_METHOD": "Арга", + "WITHDRAWALS_FORM_ADDRESS_EXCHANGE": "Имэйл солилцох", + "WITHDRAWALS_FORM_EXCHANGE_PLACEHOLDER": "Хэрэглэгчийн имэйлийг оруулна уу", + "WITHDRAWALS_FORM_MAIL_INFO": "Бирж дээрх хэрэглэгчийн имэйлийг оруулаад үнэгүй шилжүүлээрэй." +} \ No newline at end of file diff --git a/web/src/config/lang/pt.json b/web/src/config/lang/pt.json index 32f2fef6c6..bb3b5d5c44 100644 --- a/web/src/config/lang/pt.json +++ b/web/src/config/lang/pt.json @@ -1012,6 +1012,7 @@ "SEARCH": "PESQUISAR", "SEARCHING": "PESQUISANDO", "CHECK_DEPOSIT_STATUS": "Verificar o status do depósito", + "SEARCH_BLOCKCHAIN_FOR_DEPOSIT": "Pesquise blockchain para seu depósito", "STATUS_DESCRIPTION": "Você pode verificar o status do seu depósito passando o ID da transação (hash) abaixo.", "TRANSACTION_ID": "ID de transação (hash)", "SEARCH_SUCCESS": "Pesquisa finalizada", diff --git a/web/src/config/lang/tr.json b/web/src/config/lang/tr.json index 82e8f2705f..c802b69781 100644 --- a/web/src/config/lang/tr.json +++ b/web/src/config/lang/tr.json @@ -1180,6 +1180,7 @@ "NEW": "Yeni", "SEARCH_FIELD_LABEL": "İşlem ID'sini yapıştırın", "CHECK_DEPOSIT_STATUS": "Yatırım durumunu kontrol et", + "SEARCH_BLOCKCHAIN_FOR_DEPOSIT": "Depozitonuz için blockchain arayın", "STATUS_DESCRIPTION": "Aşağıya İşlem ID'nizi (hash) yapıştırarak, yatırım durumunuzu kontrol edebilirsiniz.", "TRANSACTION_ID": "İşlem ID (hash)", "SEARCH_SUCCESS": "Arama tamamlandı", diff --git a/web/src/config/menu.js b/web/src/config/menu.js index f2b2125d5b..5c773a9d45 100644 --- a/web/src/config/menu.js +++ b/web/src/config/menu.js @@ -47,6 +47,13 @@ export const MENU_ITEMS = { hide_from_appbar: true, hide_from_bottom_nav: true, }, + { + id: 'apps', + path: '/apps', + icon_id: 'TAB_APPS', + string_id: 'ACCOUNTS.TAB_APPS', + hide_from_bottom_nav: true, + }, { id: 'chat', path: '/chat', diff --git a/web/src/config/options.js b/web/src/config/options.js index 2f8a20783d..a76c00f3c2 100644 --- a/web/src/config/options.js +++ b/web/src/config/options.js @@ -1,13 +1,21 @@ import STRINGS from 'config/localizedStrings'; export const SIDES = [ - { value: 'buy', label: STRINGS['SIDES.BUY'] }, - { value: 'sell', label: STRINGS['SIDES.SELL'] }, + { value: 'buy', label: STRINGS['SIDES.BUY'], className: 'onHoverOpacity' }, + { value: 'sell', label: STRINGS['SIDES.SELL'], className: 'onHoverOpacity' }, ]; export const TYPES = [ - { value: 'market', label: STRINGS['TYPES.MARKET'] }, - { value: 'limit', label: STRINGS['TYPES.LIMIT'] }, + { + value: 'market', + label: STRINGS['TYPES.MARKET'], + className: 'onHoverOpacity', + }, + { + value: 'limit', + label: STRINGS['TYPES.LIMIT'], + className: 'onHoverOpacity', + }, ]; export const DEFAULT_TOGGLE_OPTIONS = [ diff --git a/web/src/containers/Admin/AppWrapper/index.js b/web/src/containers/Admin/AppWrapper/index.js index 82a11fb2d7..d2504b1700 100644 --- a/web/src/containers/Admin/AppWrapper/index.js +++ b/web/src/containers/Admin/AppWrapper/index.js @@ -426,6 +426,8 @@ class AppWrapper extends React.Component { return 'Markets'; } else if (location.pathname.includes('/admin/plugins')) { return 'Plugins'; + } else if (location.pathname.includes('/admin/apps')) { + return 'Apps'; } else if (location.pathname.includes('/admin/tiers')) { return 'Tiers'; } else if (location.pathname.includes('/admin/roles')) { @@ -549,7 +551,12 @@ class AppWrapper extends React.Component { }; render() { - const { children, router, user } = this.props; + const { + children, + router, + user, + constants: { features }, + } = this.props; const logout = () => { removeToken(); router.replace('/login'); @@ -563,6 +570,18 @@ class AppWrapper extends React.Component { isConfigure, } = this.state; let pathNames = PATHS; + + if (features.apps) { + pathNames = [ + ...pathNames, + { + path: '/admin/apps', + label: 'Apps', + routeKey: 'apps', + }, + ]; + } + myPlugins.forEach((data) => { if (data.enabled && data.enabled_admin_view) { pathNames = [ diff --git a/web/src/containers/Admin/Apps/index.css b/web/src/containers/Admin/Apps/index.css new file mode 100644 index 0000000000..6ec015a74f --- /dev/null +++ b/web/src/containers/Admin/Apps/index.css @@ -0,0 +1,43 @@ +.apps-list-container { + color: #ffffff; + margin: 0rem auto; + padding: 2rem 0rem; +} + +.apps-list-container .apps-icon { + height: 5rem; + margin: 0rem 1rem 0rem 0.5rem; + width: 4rem; +} + +.apps-list-container .apps-icon .apps { + fill: transparent !important; + stroke: #ffffff !important; +} + +.apps-list-container .small-font { + font-size: 9px; + font-weight: bold; +} + +.apps-list-container .apps-text { + width: 45rem; +} + +.apps-list-container .apps-title { + font-size: 18px; + font-weight: bold; +} + +.apps-list-container .anchor { + text-decoration: underline; + cursor: pointer; +} + +.apps-list-container .ant-breadcrumb-link { + cursor: pointer; +} + +.apps-list-container .ant-breadcrumb-link span:hover { + color: var(--admin_panel_main_font); +} diff --git a/web/src/containers/Admin/Apps/index.js b/web/src/containers/Admin/Apps/index.js new file mode 100644 index 0000000000..f77704ebf3 --- /dev/null +++ b/web/src/containers/Admin/Apps/index.js @@ -0,0 +1,142 @@ +import React, { useState, useEffect, Fragment } from 'react'; +import { connect } from 'react-redux'; +import { ReactSVG } from 'react-svg'; +import { STATIC_ICONS } from 'config/icons'; +import { Table, Breadcrumb, Button } from 'antd'; +import { appsSelector } from './utils'; +import { SmartTarget } from 'components'; +import { generateDynamicTarget } from 'utils/id'; + +import './index.css'; + +const { Item } = Breadcrumb; + +const generateHeaders = (configure, viewApp) => { + return [ + { + title: 'App name', + key: 'name', + dataIndex: 'name', + }, + { + title: 'Description', + key: 'description', + dataIndex: 'description', + }, + { + title: 'Config', + key: '', + dataIndex: '', + render: (_, { name }, key) => ( + <td key={`${key}-${name}-configure`}> + <span + className="underline-text pointer no-wrap" + onClick={() => configure(name)} + > + Config + </span> + </td> + ), + }, + { + title: 'App details', + key: '', + dataIndex: '', + render: (_, { name }, key) => ( + <td key={`${key}-${name}-view`}> + <span + className="underline-text pointer no-wrap" + onClick={() => viewApp(name)} + > + View App + </span> + </td> + ), + }, + ]; +}; + +const Index = ({ router, apps }) => { + const [app, setApp] = useState(); + const [id, setId] = useState(); + + const back = () => setApp(); + const configure = (app) => router.push(`/admin/plugins?plugin=${app}`); + const goToPlugins = () => router.push('/admin/plugins'); + + const renderBreadcrumb = () => { + return ( + <Breadcrumb> + <Item> + <span onClick={back}>Apps</span> + </Item> + <Item>{app}</Item> + </Breadcrumb> + ); + }; + + useEffect(() => { + setId(generateDynamicTarget(app, 'app', 'admin')); + }, [app]); + + return ( + <div className="app_container-content admin-user-container admin-user-content apps-list-container"> + {app ? ( + <SmartTarget + id={id} + onBack={back} + extra={{ top: renderBreadcrumb() }} + /> + ) : ( + <Fragment> + <div className="d-flex align-items-center"> + <div> + <ReactSVG + src={STATIC_ICONS.APPS_FEATURE_ICON} + className="apps-icon" + /> + </div> + <div className="apps-text"> + <div className="apps-title">Active apps</div> + <div> + <span> + Below is a list of exchange applications that were activated + from the{' '} + </span> + <span className="anchor" onClick={goToPlugins}> + plugins page. + </span> + <span> + {' '} + These apps are active and visible to your users and provide + extra functionality. + </span> + </div> + </div> + </div> + + <div className="pt-3 pb-5 text-align-right"> + <Button type="primary" className="green-btn" onClick={goToPlugins}> + Add plugin app + </Button> + </div> + + <Table + className="blue-admin-table" + dataSource={apps} + columns={generateHeaders(configure, setApp)} + pagination={false} + /> + </Fragment> + )} + </div> + ); +}; + +const mapStateToProps = (state) => { + return { + apps: appsSelector(state), + }; +}; + +export default connect(mapStateToProps)(Index); diff --git a/web/src/containers/Admin/Apps/utils.js b/web/src/containers/Admin/Apps/utils.js new file mode 100644 index 0000000000..5038c8ba02 --- /dev/null +++ b/web/src/containers/Admin/Apps/utils.js @@ -0,0 +1,11 @@ +import { createSelector } from 'reselect'; + +const getPlugins = (state) => state.app.plugins; + +export const appsSelector = createSelector([getPlugins], (plugins) => + plugins.filter( + ({ web_view }) => + web_view && + web_view.some(({ meta: { is_app, type } }) => is_app && type === 'admin') + ) +); diff --git a/web/src/containers/Admin/Fiat/Summarycontent.js b/web/src/containers/Admin/Fiat/Summarycontent.js index 9f564b861b..c8420e255a 100644 --- a/web/src/containers/Admin/Fiat/Summarycontent.js +++ b/web/src/containers/Admin/Fiat/Summarycontent.js @@ -1,7 +1,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import { STATIC_ICONS } from 'config/icons'; import { Link } from 'react-router'; -import { Button, Select, Spin, Table } from 'antd'; +import { Alert, Button, Modal, Select, Spin, Table } from 'antd'; // import { Icon as LegacyIcon } from '@ant-design/compatible'; // import { RightOutlined } from '@ant-design/icons'; // import moment from 'moment'; @@ -9,7 +9,7 @@ import { Button, Select, Spin, Table } from 'antd'; import { Image } from 'components'; // import IconToolTip from '../IconToolTip'; import Coins from '../Coins'; -import { requestDeposits } from '../Deposits/actions'; +import { requestDeposits, requestBurn, requestMint } from '../Deposits/actions'; import { renderContent, renderRowContent, @@ -18,6 +18,7 @@ import { } from '../Deposits/utils'; import './index.css'; +import ValidateDismiss from '../Deposits/ValidateDismiss'; const Summarycontent = ({ handleTabChange, @@ -39,7 +40,11 @@ const Summarycontent = ({ const [fiatCoins, setFiatCoins] = useState([]); const [selectedDepositAsset, setSelectedDepositAsset] = useState(''); const [selectedWithdrawalAsset, setSelectedWithdrawalAsset] = useState(''); - + const [isOpen, setIsOpen] = useState(false); + const [statusType, setStatusType] = useState(''); + const [validateData, setValidateData] = useState({}); + const [queryType, setQueryType] = useState(''); + const [error, setError] = useState(''); let onRampData = Object.values(onramp).filter((d) => Object.keys(d).length); let offRampData = Object.values(offramp).filter((d) => Object.keys(d).length); @@ -70,7 +75,7 @@ const Summarycontent = ({ if (Object.keys(queryParams).length === 0) { setQueryParams({}); } - + setQueryType(queryParams.type); requestDeposits({ ...values, ...queryParams, @@ -169,6 +174,78 @@ const Summarycontent = ({ // </Button> // ); + const onOpenModal = (validateData, statusType) => { + setIsOpen(true); + setStatusType(statusType); + setValidateData(validateData); + }; + + const onCancelModal = () => { + setIsOpen(false); + setStatusType(''); + }; + + const handleConfirm = (formValues) => { + let body = { + transaction_id: formValues.transaction_id, + updated_transaction_id: formValues.updated_transaction_id, + rejected: false, + processing: false, + waiting: false, + }; + if (formValues.description) { + body = { + ...body, + description: formValues.description, + }; + } + if (statusType === 'validate') { + body = { + ...body, + status: true, + dismissed: false, + }; + } else { + body = { + ...body, + dismissed: true, + status: false, + }; + } + if (queryType === 'deposit') { + requestMint(body) + .then((data) => { + onSuccess(queryParams, queryType); + }) + .catch((error) => { + onFailure(error); + }); + } else { + requestBurn(body) + .then((data) => { + onSuccess(queryParams, queryType); + }) + .catch((error) => { + onFailure(error); + }); + } + }; + + const onFailure = (errObj) => { + const message = errObj.data ? errObj.data.message : errObj.message; + setError(message); + onCancelModal(); + }; + + const onSuccess = (queryParams, queryType) => { + requestDeposits(queryParams, { type: queryType }); + onCancelModal(); + }; + + const onCloseErrorAlert = () => { + setError(''); + }; + const renderSelect = (type) => { return ( <Select @@ -216,7 +293,7 @@ const Summarycontent = ({ { title: 'Amount', dataIndex: 'amount', key: 'amount' }, { title: 'Validate/dismiss', - render: (renderData) => renderContent(renderData, () => {}), + render: (renderData) => renderContent(renderData, onOpenModal), }, ]; @@ -619,6 +696,16 @@ const Summarycontent = ({ : 'fiattable1 mb-5' } > + {error && ( + <Alert + message={error} + type="error" + showIcon + onClose={onCloseErrorAlert} + closable={true} + closeText="Close" + /> + )} <Table columns={columns} dataSource={withdrawal.map((item) => { @@ -670,6 +757,21 @@ const Summarycontent = ({ </div> </div> */} </div> + <Modal + visible={isOpen} + footer={null} + onCancel={onCancelModal} + width="37rem" + > + {isOpen ? ( + <ValidateDismiss + validateData={validateData} + statusType={statusType} + onCancel={onCancelModal} + handleConfirm={handleConfirm} + /> + ) : null} + </Modal> </div> ); }; diff --git a/web/src/containers/Admin/General/EmailVerificationForm.js b/web/src/containers/Admin/General/EmailVerificationForm.js index c7be2202ec..ceddd9960e 100644 --- a/web/src/containers/Admin/General/EmailVerificationForm.js +++ b/web/src/containers/Admin/General/EmailVerificationForm.js @@ -1,7 +1,9 @@ import React, { useEffect, useState } from 'react'; -import { Button, Checkbox, Form } from 'antd'; +import { Checkbox, Form } from 'antd'; import { InfoCircleFilled } from '@ant-design/icons'; +import FormButton from 'components/FormButton/Button'; + const { Item } = Form; const EmailVerificationForm = ({ @@ -71,14 +73,13 @@ const EmailVerificationForm = ({ </div> </div> <div> - <Button + <FormButton type="primary" htmlType="submit" - className="green-btn minimal-btn" disabled={isDisable || buttonSubmitting} - > - Save - </Button> + className="green-btn minimal-btn" + buttonText="Save" + /> </div> </Form> </div> diff --git a/web/src/containers/Admin/General/FooterForm.js b/web/src/containers/Admin/General/FooterForm.js index a5ad37b2b3..9bafde762a 100644 --- a/web/src/containers/Admin/General/FooterForm.js +++ b/web/src/containers/Admin/General/FooterForm.js @@ -5,9 +5,10 @@ import { Button } from 'antd'; import _findLast from 'lodash/findLast'; import _findLastKey from 'lodash/findLastKey'; import isEqual from 'lodash.isequal'; +import debounce from 'lodash.debounce'; import renderFields from '../../../components/AdminForm/utils'; -import debounce from 'lodash.debounce'; +import FormButton from 'components/FormButton/Button'; class FormWrapper extends Component { componentDidMount() { @@ -114,16 +115,14 @@ class FormWrapper extends Component { {customFields ? this.renderCustomFields(fields) : renderFields(fields, getFieldDecorator, initialValues)} - <Button - block + <FormButton type="primary" + handleSubmit={handleSubmit(this.onSubmit)} htmlType="submit" - className="green-btn minimal-btn" - onClick={handleSubmit(this.onSubmit)} disabled={buttonSubmitting} - > - {buttonTxt} - </Button> + className="green-btn minimal-btn" + buttonText={buttonTxt} + /> </form> </div> ); diff --git a/web/src/containers/Admin/General/InterfaceForm.js b/web/src/containers/Admin/General/InterfaceForm.js index 46832cad84..ad6192217d 100644 --- a/web/src/containers/Admin/General/InterfaceForm.js +++ b/web/src/containers/Admin/General/InterfaceForm.js @@ -5,6 +5,7 @@ import classnames from 'classnames'; import _isEqual from 'lodash/isEqual'; import { STATIC_ICONS } from 'config/icons'; +import FormButton from 'components/FormButton/Button'; const { Item } = Form; @@ -28,6 +29,7 @@ const InterfaceForm = ({ stake_page: !!values.stake_page, home_page: isUpgrade ? false : !!values.home_page, ultimate_fiat: !!values.ultimate_fiat, + apps: !!values.apps, }; handleSaveInterface(formValues); } @@ -50,6 +52,7 @@ const InterfaceForm = ({ if (isUpgrade) { initialValue.home_page = false; initialValue.chat = false; + initialValue.apps = false; } return ( <div className="general-wrapper"> @@ -128,145 +131,222 @@ const InterfaceForm = ({ </Checkbox> </Item> - <div className={classnames({ 'disabled-area': isFiatUpgrade })}> - <Item name="ultimate_fiat" valuePropName="checked"> - <Checkbox className="mt-3"> - <div className="d-flex align-items-center"> - <div className="feature-trade-box mr-1"> - <ReactSVG - src={STATIC_ICONS.MPESA_ICON} - className="d-flex feature-icon justify-content-center mr-2 mt-3 ml-1 pl-1" - beforeInjection={(svg) => { - svg.setAttribute('style', 'width: 60px'); - }} - /> + <div className="d-flex"> + <div + className={classnames('interface-item', { + 'disabled-area': isFiatUpgrade, + })} + > + <Item name="ultimate_fiat" valuePropName="checked"> + <Checkbox className="mt-3"> + <div className="d-flex align-items-center"> + <div className="feature-trade-box mr-1"> + <ReactSVG + src={STATIC_ICONS.MPESA_ICON} + className="d-flex feature-icon justify-content-center mr-2 mt-3 ml-1 pl-1" + beforeInjection={(svg) => { + svg.setAttribute('style', 'width: 60px'); + }} + /> + </div> + <div className="ml-2 checkbox-txt"> + Fiat Controls + <div className="small-text"> + (On & off ramping and tracking for fiat assets) + </div> + </div> </div> - <div className="ml-2 checkbox-txt"> - Ultimate fiat - <div className="small-text">(Ultimate fiat ...)</div> + </Checkbox> + </Item> + </div> + {isFiatUpgrade && ( + <div className="d-flex"> + <div className="d-flex align-items-center justify-content-between upgrade-section mt-2 mb-5"> + <div> + <div className="font-weight-bold"> + Powerful fiat ramping + </div> + <div>Cash in and out with fiat ramps</div> </div> - </div> - </Checkbox> - </Item> - </div> - {isFiatUpgrade ? ( - <div className="d-flex"> - <div className="d-flex align-items-center justify-content-between upgrade-section mt-2 mb-5"> - <div> - <div className="font-weight-bold"> - Make a good first impression + <div className="ml-5 button-wrapper"> + <a + href="https://dash.bitholla.com/billing" + target="_blank" + rel="noopener noreferrer" + > + <Button type="primary" className="w-100"> + Upgrade Now + </Button> + </a> </div> - <div>Add a customizable landing page</div> - </div> - <div className="ml-5 button-wrapper"> - <a - href="https://dash.bitholla.com/billing" - target="_blank" - rel="noopener noreferrer" - > - <Button type="primary" className="w-100"> - Upgrade Now - </Button> - </a> </div> </div> - </div> - ) : null} - <div className={classnames({ 'disabled-area': isUpgrade })}> - <Item name="chat" valuePropName="checked"> - <Checkbox className="mt-3"> - <div className="d-flex align-items-center"> - <div className="feature-trade-box mr-1"> - <ReactSVG - src={STATIC_ICONS.CHAT_FEATURE_ICON} - className="feature-chat-icon" - /> - </div> - <div className="ml-2 checkbox-txt"> - Chat system - <div className="d-flex justify-content-between"> - <div className="small-text"> - (Usernames, text and emoji communication) + )} + </div> + + <div className="d-flex"> + <div + className={classnames('interface-item', { + 'disabled-area': isUpgrade, + })} + > + <Item name="chat" valuePropName="checked"> + <Checkbox className="mt-3"> + <div className="d-flex align-items-center"> + <div className="feature-trade-box mr-1"> + <ReactSVG + src={STATIC_ICONS.CHAT_FEATURE_ICON} + className="feature-chat-icon" + /> + </div> + <div className="ml-2 checkbox-txt"> + Chat system + <div className="d-flex justify-content-between"> + <div className="small-text"> + (Usernames, text and emoji communication) + </div> </div> </div> </div> - </div> - </Checkbox> - </Item> - </div> - {isUpgrade ? ( - <div className="d-flex"> - <div className="d-flex align-items-center justify-content-between upgrade-section mt-2 mb-5"> - <div> - <div className="font-weight-bold"> - Start your crypto culture + </Checkbox> + </Item> + </div> + {isUpgrade && ( + <div className="d-flex"> + <div className="d-flex align-items-center justify-content-between upgrade-section mt-2 mb-5"> + <div> + <div className="font-weight-bold"> + Start your crypto culture + </div> + <div>Allow your users to socialize through chat</div> + </div> + <div className="ml-5 button-wrapper"> + <a + href="https://dash.bitholla.com/billing" + target="_blank" + rel="noopener noreferrer" + > + <Button type="primary" className="w-100"> + Upgrade Now + </Button> + </a> </div> - <div>Allow your users to socialize through chat</div> - </div> - <div className="ml-5 button-wrapper"> - <a - href="https://dash.bitholla.com/billing" - target="_blank" - rel="noopener noreferrer" - > - <Button type="primary" className="w-100"> - Upgrade Now - </Button> - </a> </div> </div> - </div> - ) : null} - <div className={classnames({ 'disabled-area': isUpgrade })}> - <Item name="home_page" valuePropName="checked"> - <Checkbox className="mt-3"> - <div className="d-flex align-items-center"> - <div className="feature-trade-box mr-1"> - <ReactSVG - src={STATIC_ICONS.HOME_PAGE_FEATURE_ICON} - className="feature-chat-icon" - /> - </div> - <div className="ml-2 checkbox-txt"> - Homepage - <div className="d-flex justify-content-between"> - <div className="small-text"> - (This will be the first page seen on your domain) + )} + </div> + + <div className="d-flex"> + <div + className={classnames('interface-item', { + 'disabled-area': isUpgrade, + })} + > + <Item name="home_page" valuePropName="checked"> + <Checkbox className="mt-3"> + <div className="d-flex align-items-center"> + <div className="feature-trade-box mr-1"> + <ReactSVG + src={STATIC_ICONS.HOME_PAGE_FEATURE_ICON} + className="feature-chat-icon" + /> + </div> + <div className="ml-2 checkbox-txt"> + Homepage + <div className="d-flex justify-content-between"> + <div className="small-text"> + (This will be the first page seen on your domain) + </div> </div> </div> </div> + </Checkbox> + </Item> + </div> + {isUpgrade && ( + <div className="d-flex"> + <div className="d-flex align-items-center justify-content-between upgrade-section mt-2 mb-5"> + <div> + <div className="font-weight-bold"> + Make a good first impression + </div> + <div>Add a customizable landing page</div> + </div> + <div className="ml-5 button-wrapper"> + <a + href="https://dash.bitholla.com/billing" + target="_blank" + rel="noopener noreferrer" + > + <Button type="primary" className="w-100"> + Upgrade Now + </Button> + </a> + </div> </div> - </Checkbox> - </Item> + </div> + )} </div> - </div> - {isUpgrade ? ( + <div className="d-flex"> - <div className="d-flex align-items-center justify-content-between upgrade-section mt-2 mb-5"> - <div> - <div className="font-weight-bold"> - Make a good first impression + <div + className={classnames('interface-item', { + 'disabled-area': isUpgrade, + })} + > + <Item name="apps" valuePropName="checked"> + <Checkbox className="mt-3"> + <div className="d-flex align-items-center"> + <div className="feature-trade-box mr-1"> + <ReactSVG + src={STATIC_ICONS.APPS_FEATURE_ICON} + className="feature-apps-icon" + /> + </div> + <div className="ml-2 checkbox-txt"> + Apps + <div className="d-flex justify-content-between"> + <div className="small-text"> + (Give your users extra exchange applications) + </div> + </div> + </div> + </div> + </Checkbox> + </Item> + </div> + {isUpgrade && ( + <div className="d-flex"> + <div className="d-flex align-items-center justify-content-between upgrade-section mt-2 mb-5"> + <div> + <div className="font-weight-bold"> + First exchange app store + </div> + <div>Add more exchange functionality</div> + </div> + <div className="ml-5 button-wrapper"> + <a + href="https://dash.bitholla.com/billing" + target="_blank" + rel="noopener noreferrer" + > + <Button type="primary" className="w-100"> + Upgrade Now + </Button> + </a> + </div> </div> - <div>Add a customizable landing page</div> </div> - <div className="ml-5 button-wrapper"> - <a - href="https://dash.bitholla.com/billing" - target="_blank" - rel="noopener noreferrer" - > - <Button type="primary" className="w-100"> - Upgrade Now - </Button> - </a> - </div> - </div> + )} </div> - ) : null} + </div> <div> - <Button type="primary" htmlType="submit" disabled={isSubmit}> - Save - </Button> + <FormButton + type="primary" + htmlType="submit" + disabled={isSubmit} + buttonText="save" + /> </div> </Form> </div> diff --git a/web/src/containers/Admin/General/PublishSection.js b/web/src/containers/Admin/General/PublishSection.js index ebb2306292..92be29c659 100644 --- a/web/src/containers/Admin/General/PublishSection.js +++ b/web/src/containers/Admin/General/PublishSection.js @@ -1,5 +1,7 @@ import React from 'react'; -import { Button, Collapse } from 'antd'; +import { Collapse } from 'antd'; + +import FormButton from 'components/FormButton/Button'; const PublishSection = ({ title = '', @@ -54,17 +56,15 @@ const PublishSection = ({ ) : null} </Collapse> </div> - <Button + <FormButton type="primary" - className="green-btn minimal-btn" - loading={loadingButton && currentPublishType === currentkey} - onClick={() => handlePublish(currentkey)} + handleSubmit={() => handlePublish(currentkey)} disabled={ !isPublishDisable || (isPublishDisable && updatedKey !== currentkey) } - > - Publish - </Button> + className="green-btn minimal-btn" + buttonText="Publish" + /> </div> ); }; diff --git a/web/src/containers/Admin/General/action.js b/web/src/containers/Admin/General/action.js index 4c7745cbde..fd8f1eb023 100644 --- a/web/src/containers/Admin/General/action.js +++ b/web/src/containers/Admin/General/action.js @@ -28,8 +28,7 @@ export const getEmailStrings = (param) => { }; export const updateEmailStrings = (values) => { - values.html = values?.html?.replace(/"/g, '@@_BIT_@@'); - values.html = values?.html?.replace(/'/g, '@@_BIT_@@'); + values.html = values?.html?.replace(/\\"/g, "'"); const options = { method: 'PUT', body: JSON.stringify(values), diff --git a/web/src/containers/Admin/General/index.css b/web/src/containers/Admin/General/index.css index 8277affe30..c0359d7b4d 100644 --- a/web/src/containers/Admin/General/index.css +++ b/web/src/containers/Admin/General/index.css @@ -158,11 +158,27 @@ stroke: #808080; fill-opacity: 0.5; } +.interface-box .feature-apps-icon { + width: 42px; + margin: 4px 16px; + fill: #808080 !important; + fill-opacity: 0.5; +} +.feature-apps-icon .apps { + fill: #808080 !important; +} .interface-box .ant-checkbox-wrapper-checked .feature-icon, .interface-box .ant-checkbox-wrapper-checked .feature-chat-icon { stroke: #ffffff; fill-opacity: 1; } +.interface-box .ant-checkbox-wrapper-checked .feature-apps-icon { + fill: #ffffff !important; + fill-opacity: 1; +} +.feature-apps-icon .apps { + fill: #ffffff !important; +} .interface-box .checkbox-txt, .interface-box .small-text { color: #808080; @@ -349,6 +365,10 @@ h2, pointer-events: none; } +.general-wrapper .interface-item { + min-width: 418px; +} + .general-wrapper .description a { text-decoration: underline !important; } diff --git a/web/src/containers/Admin/ListUsers/ListUser.js b/web/src/containers/Admin/ListUsers/ListUser.js index 8f7d248ecf..5057784cdf 100644 --- a/web/src/containers/Admin/ListUsers/ListUser.js +++ b/web/src/containers/Admin/ListUsers/ListUser.js @@ -23,16 +23,16 @@ class ListUsers extends Component { } componentWillMount() { - this.requestUsers(this.state.page, this.state.limit); + this.requestUsers(this.state.page, this.state.limit, this.props.type); } - requestUsers = (page = 1, limit = 50) => { + requestUsers = (page = 1, limit = 50, pending_type = 'id') => { this.setState({ loading: true, error: '', }); - requestUsers({ pending: true, page, limit }) + requestUsers({ pending: true, page, limit, pending_type }) .then((response) => { this.setState({ users: diff --git a/web/src/containers/Admin/ListUsers/PendingUsers.js b/web/src/containers/Admin/ListUsers/PendingUsers.js new file mode 100644 index 0000000000..11892d4b8a --- /dev/null +++ b/web/src/containers/Admin/ListUsers/PendingUsers.js @@ -0,0 +1,38 @@ +import React, { Component } from 'react'; +import { Tabs } from 'antd'; +import { ListUsers } from '.'; + +const TabPane = Tabs.TabPane; + +class PendingUsers extends Component { + render() { + return ( + <div className="app_container-content user-container"> + <Tabs> + <TabPane tab="Pending Ids" key="PendingIds"> + <div className="m-top"> + <ListUsers + requestUser={this.props.requestUserData} + handleDownload={this.props.requestUsersDownload} + columns={this.props.columns} + type="id" + /> + </div> + </TabPane> + <TabPane tab="Pending Banks" key="Pendingbanks"> + <div className="m-top"> + <ListUsers + requestUser={this.props.requestUserData} + handleDownload={this.props.handleDownload} + columns={this.props.columns} + type="bank" + /> + </div> + </TabPane> + </Tabs> + </div> + ); + } +} + +export default PendingUsers; diff --git a/web/src/containers/Admin/ListUsers/index.js b/web/src/containers/Admin/ListUsers/index.js index d3684e3c1e..e60700c510 100644 --- a/web/src/containers/Admin/ListUsers/index.js +++ b/web/src/containers/Admin/ListUsers/index.js @@ -1,2 +1,3 @@ export { default as FullListUsers } from './FullList'; export { default as ListUsers } from './ListUser'; +export { default as PendingUsers } from './PendingUsers'; diff --git a/web/src/containers/Admin/Plugins/index.js b/web/src/containers/Admin/Plugins/index.js index e0711e0b7e..187da49255 100644 --- a/web/src/containers/Admin/Plugins/index.js +++ b/web/src/containers/Admin/Plugins/index.js @@ -18,6 +18,11 @@ const { Item } = Breadcrumb; class Plugins extends Component { constructor(props) { super(props); + const { + router: { + location: { query: { plugin } = {} }, + }, + } = this.props; this.state = { activeTab: '', loading: false, @@ -32,7 +37,7 @@ class Plugins extends Component { isVisible: false, isRemovePlugin: false, removePluginName: '', - tabKey: 'explore', + tabKey: plugin ? 'my_plugin' : 'explore', pluginCards: [], processing: false, }; @@ -75,7 +80,20 @@ class Plugins extends Component { return requestMyPlugins(params) .then((res) => { if (res && res.data) { - this.setState({ myPlugins: res.data }); + const { + router, + router: { + location: { pathname, query: { plugin } = {} }, + }, + } = this.props; + this.setState({ myPlugins: res.data }, () => { + const pluginData = res.data.find(({ name }) => name === plugin); + if (pluginData) { + this.handleOpenPlugin(pluginData); + this.handleBreadcrumb(); + router.push(pathname); + } + }); } }) .catch((err) => { @@ -183,7 +201,7 @@ class Plugins extends Component { if (plugin_type === 'add_plugin' && !isConfigure) { this.setState({ type: 'configure', - isConfigure: true + isConfigure: true, }); } } else { @@ -200,7 +218,7 @@ class Plugins extends Component { selectedPlugin: {}, type: '', isConfigure: false, - tabKey: 'explore' + tabKey: 'explore', }); }; diff --git a/web/src/containers/Admin/Settings/CustomizeEmailForm.js b/web/src/containers/Admin/Settings/CustomizeEmailForm.js index 712a923835..d71792a2d2 100644 --- a/web/src/containers/Admin/Settings/CustomizeEmailForm.js +++ b/web/src/containers/Admin/Settings/CustomizeEmailForm.js @@ -7,6 +7,7 @@ import debounce from 'lodash.debounce'; import { updateEmailStrings } from '../General/action'; import { STATIC_ICONS } from 'config/icons'; +import FormButton from 'components/FormButton/Button'; const { TextArea } = Input; const { Option } = Select; @@ -383,14 +384,13 @@ const CustomizeEmailForm = ({ )} </div> </div> - <Button + <FormButton type="primary" - className="green-btn" htmlType="submit" disabled={buttonSubmitting} - > - Save - </Button> + className="green-btn" + buttonText="Save" + /> </Form> <Modal visible={isModalVisible} diff --git a/web/src/containers/Admin/Tiers/CheckAndConfirm.js b/web/src/containers/Admin/Tiers/CheckAndConfirm.js index eaf3fa095c..92e13608f0 100644 --- a/web/src/containers/Admin/Tiers/CheckAndConfirm.js +++ b/web/src/containers/Admin/Tiers/CheckAndConfirm.js @@ -63,7 +63,8 @@ const CheckAndConfirm = ({ <span className="bold">{currentNative?.toUpperCase()}</span> to{' '} <span className="bold">{currentCoin.toUpperCase()}</span>? </div> - <div className="button-wrapper mt-4"> + <div className="switch-warn mt-3 mb-1">Asset switcher coming soon!</div> + <div className="button-wrapper"> <Button type="primary" className="green-btn" @@ -74,6 +75,7 @@ const CheckAndConfirm = ({ <Button type="primary" className="green-btn" + disabled onClick={() => handleConfirm('edit-limits')} > Confirm diff --git a/web/src/containers/Admin/Tiers/index.css b/web/src/containers/Admin/Tiers/index.css index 0faca30ce3..f9e7b4797f 100644 --- a/web/src/containers/Admin/Tiers/index.css +++ b/web/src/containers/Admin/Tiers/index.css @@ -198,3 +198,8 @@ .admin-tiers-wrapper .description .underline { color: #ffffff; } +.change-Limit-wrapper .switch-warn { + float: right; + font-size: 13px; + color: #f15a29; +} diff --git a/web/src/containers/Admin/Transactions/index.js b/web/src/containers/Admin/Transactions/index.js index 66a4546f65..e7d62dcafb 100644 --- a/web/src/containers/Admin/Transactions/index.js +++ b/web/src/containers/Admin/Transactions/index.js @@ -267,7 +267,7 @@ class Transactions extends Component { currentTablePage, pageSize, } = this.state; - const { showFilters, coins } = this.props; + const { showFilters, coins, icons } = this.props; const { hideUserColumn, @@ -279,6 +279,7 @@ class Transactions extends Component { <div> {showFilters && ( <Filters + icons={icons} coins={coins} onChange={this.onChangeQuery} onClick={this.onClickFilters} diff --git a/web/src/containers/Admin/User/index.js b/web/src/containers/Admin/User/index.js index a5375078f4..108e6ec893 100644 --- a/web/src/containers/Admin/User/index.js +++ b/web/src/containers/Admin/User/index.js @@ -16,7 +16,7 @@ import { AdminHocForm } from '../../../components'; import { requestUser, requestUsersDownload } from './actions'; import UserContent from './UserContent'; -import { ListUsers, FullListUsers } from '../ListUsers'; +import { FullListUsers, PendingUsers } from '../ListUsers'; import { requestMyPlugins } from '../Plugins/action'; // import { isSupport } from '../../../utils/token'; @@ -324,11 +324,11 @@ class App extends Component { ) : null} </TabPane> - <TabPane tab="User Verification" key="userVerification"> - <div className="list_users"> - <ListUsers - requestUser={this.requestUserData} - handleDownload={this.requestUsersDownload} + <TabPane tab="Pending Users" key="pendingUsers"> + <div className="m-top"> + <PendingUsers + requestUserData={this.requestUserData} + requestUsersDownload={this.requestUsersDownload} columns={COLUMNS} /> </div> diff --git a/web/src/containers/Admin/paths.js b/web/src/containers/Admin/paths.js index 8a344d0532..6ea53965ed 100644 --- a/web/src/containers/Admin/paths.js +++ b/web/src/containers/Admin/paths.js @@ -1,4 +1,4 @@ -import { APP_TITLE } from '../../config/constants'; +import { APP_TITLE } from 'config/constants'; export const PATHS = [ { diff --git a/web/src/containers/App/App.js b/web/src/containers/App/App.js index 9c03584f01..a15eb15acc 100644 --- a/web/src/containers/App/App.js +++ b/web/src/containers/App/App.js @@ -64,6 +64,7 @@ import AppFooter from '../../components/AppFooter'; import OperatorControls from 'containers/OperatorControls'; import MarketSelector from 'components/AppBar/MarketSelector'; import ConnectViaDesktop from 'containers/Stake/components/ConnectViaDesktop'; +import ConfigureApps from 'containers/Apps/ConfigureApps'; import { getClasesForLanguage, @@ -505,10 +506,19 @@ class App extends Component { case NOTIFICATIONS.METAMASK_ERROR: return ( <MessageDisplay - iconId="RED_WARNING" - iconPath={ICONS['RED_WARNING']} + iconId="META_MASK_NOT_FOUND" + iconPath={ICONS['META_MASK_NOT_FOUND']} onClick={this.onCloseDialog} text={data} + title={STRINGS['STAKE.INSTALL_METAMASK_TITLE']} + titleId={'STAKE.INSTALL_METAMASK_TITLE'} + /> + ); + case NOTIFICATIONS.CONFIGURE_APPS: + return ( + <ConfigureApps + onClose={this.onCloseDialog} + onRemove={data.onRemove} /> ); case CONNECT_VIA_DESKTOP: diff --git a/web/src/containers/App/_App.scss b/web/src/containers/App/_App.scss index 8213dfbd39..5f7683cc05 100644 --- a/web/src/containers/App/_App.scss +++ b/web/src/containers/App/_App.scss @@ -61,6 +61,7 @@ $inner_container-border: 1px solid $colors-super-pale-black; } .app_container-main { + transition: 0.3s; &.no_bottom_navigation { height: 100%; } diff --git a/web/src/containers/AppDetails/index.js b/web/src/containers/AppDetails/index.js new file mode 100644 index 0000000000..19c89ec537 --- /dev/null +++ b/web/src/containers/AppDetails/index.js @@ -0,0 +1,77 @@ +import React, { useState, useEffect } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { isMobile } from 'react-device-detect'; +import { openContactForm } from 'actions/appActions'; +import { IconTitle, HeaderSection, EditWrapper, SmartTarget } from 'components'; +import STRINGS from 'config/localizedStrings'; +import withConfig from 'components/ConfigProvider/withConfig'; +import { generateDynamicTarget } from 'utils/id'; +import { userAppsSelector } from 'containers/Apps/utils'; + +const Index = ({ openContactForm, icons: ICONS, router, userApps }) => { + const [mounted, setMounted] = useState(false); + const goBack = () => router.push('/apps'); + + const { + params: { app }, + } = router; + + if (!mounted) { + if (!app || !userApps.map(({ name }) => name).includes(app)) { + goBack(); + } + } + + const id = generateDynamicTarget(app, 'app', 'kit'); + + useEffect(() => { + setMounted(true); + }, []); + + return ( + <div className="presentation_container apply_rtl settings_container"> + {!isMobile && ( + <IconTitle + stringId="ACCOUNTS.TAB_APPS" + text={STRINGS['ACCOUNTS.TAB_APPS']} + textType="title" + iconPath={ICONS['TAB_SETTING']} + iconId={STRINGS['ACCOUNTS.TAB_APPS']} + /> + )} + + <HeaderSection title={app} openContactForm={openContactForm}> + <div className="header-content"> + <div> + <EditWrapper stringId="USER_APPS.APP_DETAILS.BACK_TO_APPS,USER_APPS.APP_DETAILS.BACK"> + {STRINGS.formatString( + STRINGS['USER_APPS.APP_DETAILS.BACK_PLACEHOLDER'], + <span + className="blue-link underline-text pointer" + onClick={goBack} + > + {STRINGS['USER_APPS.APP_DETAILS.BACK']} + </span>, + <span className="px-1"> + {STRINGS['USER_APPS.APP_DETAILS.BACK_TO_APPS']} + </span> + )} + </EditWrapper> + </div> + </div> + </HeaderSection> + <SmartTarget id={id} /> + </div> + ); +}; + +const mapStateToProps = (state) => ({ + userApps: userAppsSelector(state), +}); + +const mapDispatchToProps = (dispatch) => ({ + openContactForm: bindActionCreators(openContactForm, dispatch), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(withConfig(Index)); diff --git a/web/src/containers/Apps/All.js b/web/src/containers/Apps/All.js new file mode 100644 index 0000000000..7dcc699a09 --- /dev/null +++ b/web/src/containers/Apps/All.js @@ -0,0 +1,189 @@ +import React, { useState, useRef, useEffect } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { Input } from 'antd'; +import debounce from 'lodash.debounce'; +import { SearchOutlined } from '@ant-design/icons'; +import { updateUserSettings, setUserData } from 'actions/userAction'; +import { setSnackNotification } from 'actions/appActions'; +import { IconTitle, EditWrapper, Table, Button, Image } from 'components'; +import STRINGS from 'config/localizedStrings'; +import withConfig from 'components/ConfigProvider/withConfig'; +import { unique } from 'utils/data'; +import { isEnabled, appsSelector } from './utils'; + +const generateHeaders = (addApp, isAdded, ICONS) => { + return [ + { + stringId: 'USER_APPS.TABLE.APP_NAME', + label: STRINGS['USER_APPS.TABLE.APP_NAME'], + key: 'name', + }, + { + stringId: 'USER_APPS.TABLE.DESCRIPTION', + label: STRINGS['USER_APPS.TABLE.DESCRIPTION'], + key: 'description', + }, + { + label: '', + renderCell: ({ name }, key) => ( + <td key={`${key}-${name}-app`} className="text-align-center"> + {isAdded(name) ? ( + <Image + icon={ICONS['GREEN_CHECK']} + iconId={'GREEN_CHECK'} + wrapperClassName={'apps-table-check'} + /> + ) : ( + <Button + label={STRINGS['USER_APPS.TABLE.ADD']} + className="add-app-button" + onClick={() => addApp(name)} + /> + )} + </td> + ), + }, + ]; +}; + +const NoData = ({ onClick }) => ( + <div className="text-align-center"> + <div>{STRINGS['USER_APPS.TABLE.NOT_FOUND']}</div> + <div onClick={onClick} className="blue-link underline-text pointer"> + {STRINGS['USER_APPS.TABLE.RETRY']} + </div> + </div> +); + +const All = ({ + icons: ICONS, + apps, + settings: { apps: user_apps = [] }, + setUserData, + setActiveTab, + setSnackNotification, +}) => { + const [search, setSearch] = useState(); + const [data, setData] = useState(apps); + + const inputRef = useRef(null); + + const addApp = (name) => { + const settings = { + app: unique([...user_apps, name]), + }; + + updateUserSettings(settings) + .then(({ data }) => { + setUserData(data); + setActiveTab(1); + setSnackNotification({ + content: STRINGS['USER_APPS.ALL_APPS.ADD.SUCCESSFUL'], + }); + if (window) { + window.scroll({ + top: 0, + left: 0, + behavior: 'smooth', + }); + } + }) + .catch(() => { + setSnackNotification({ + content: STRINGS['USER_APPS.ALL_APPS.ADD.FAILED'], + }); + }); + }; + + const isAdded = (name) => { + return isEnabled(name, user_apps); + }; + + const retry = () => { + setSearch(''); + inputRef.current.focus({ + cursor: 'start', + }); + }; + + const onSearch = (search, apps) => { + if (search) { + const result = apps.filter(({ name }) => + name.toLowerCase().includes(search.toLowerCase()) + ); + setData(result); + } else { + setData(apps); + } + }; + + const debounced = useRef(debounce(onSearch, 1000)); + + useEffect(() => { + debounced.current(search, apps); + }, [search, apps]); + + return ( + <div> + <div className="settings-form-wrapper"> + <div className="settings-form apps-form"> + <IconTitle + stringId="USER_APPS.ALL_APPS.TITLE" + text={STRINGS['USER_APPS.ALL_APPS.TITLE']} + textType="title" + iconPath={ICONS['APPS_ALL']} + /> + <div className="py-4"> + <EditWrapper stringId="USER_APPS.ALL_APPS.SUBTITLE"> + {STRINGS['USER_APPS.ALL_APPS.SUBTITLE']} + </EditWrapper> + </div> + <div> + <Input + allowClear + prefix={<SearchOutlined className="secondary-text" />} + placeholder={STRINGS['USER_APPS.ALL_APPS.SEARCH_PLACEHOLDER']} + value={search} + onChange={({ target: { value } }) => setSearch(value)} + style={{ + width: 200, + }} + bordered={false} + className="kit-divider" + ref={inputRef} + /> + </div> + <Table + showHeaderNoData={true} + rowClassName="pt-2 pb-2" + headers={generateHeaders(addApp, isAdded, ICONS)} + showAll={true} + data={data} + rowKey={({ name }) => name} + displayPaginator={false} + {...(search ? { noData: <NoData onClick={retry} /> } : {})} + /> + </div> + </div> + </div> + ); +}; + +const mapStateToProps = (state) => { + const { + user: { settings }, + } = state; + + return { + apps: appsSelector(state), + settings, + }; +}; + +const mapDispatchToProps = (dispatch) => ({ + setUserData: bindActionCreators(setUserData, dispatch), + setSnackNotification: bindActionCreators(setSnackNotification, dispatch), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(withConfig(All)); diff --git a/web/src/containers/Apps/ConfigureApps.js b/web/src/containers/Apps/ConfigureApps.js new file mode 100644 index 0000000000..d7204da43b --- /dev/null +++ b/web/src/containers/Apps/ConfigureApps.js @@ -0,0 +1,124 @@ +import React, { useState } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { IconTitle, EditWrapper, Button, ActionNotification } from 'components'; +import STRINGS from 'config/localizedStrings'; +import withConfig from 'components/ConfigProvider/withConfig'; +import { openHelpdesk } from 'actions/appActions'; + +const ConfigureApps = ({ + onClose, + icons: ICONS, + openHelpdesk, + onRemove = () => {}, +}) => { + const [showRemove, setShowRemove] = useState(false); + const openNewForm = () => { + onClose(); + openHelpdesk({ category: 'bug' }); + }; + + return showRemove ? ( + <div className="help-wrapper"> + <IconTitle + iconId="APPS_REMOVE" + iconPath={ICONS['APPS_REMOVE']} + stringId="USER_APPS.REMOVE.TITLE" + text={STRINGS['USER_APPS.REMOVE.TITLE']} + textType="title" + underline={true} + className="w-100" + subtitle={STRINGS['USER_APPS.REMOVE.SUBTITLE']} + /> + <div> + <div className="my-5 mx-3"> + <div> + {STRINGS['USER_APPS.REMOVE.TEXT']} + <EditWrapper stringId="USER_APPS.REMOVE.TEXT" /> + </div> + </div> + + <div className="d-flex"> + <div className="w-50"> + <EditWrapper stringId="USER_APPS.REMOVE.BACK" /> + <Button + label={STRINGS['USER_APPS.REMOVE.BACK']} + onClick={() => setShowRemove(false)} + /> + </div> + <div className="separator" /> + <div className="w-50"> + <EditWrapper stringId="USER_APPS.REMOVE.CONFIRM" /> + <Button + label={STRINGS['USER_APPS.REMOVE.CONFIRM']} + onClick={onRemove} + /> + </div> + </div> + </div> + </div> + ) : ( + <div className="help-wrapper"> + <IconTitle + iconId="APPS_CONFIGURE" + iconPath={ICONS['APPS_CONFIGURE']} + stringId="USER_APPS.CONFIGURE.TITLE" + text={STRINGS['USER_APPS.CONFIGURE.TITLE']} + textType="title" + underline={true} + className="w-100" + subtitle={STRINGS['USER_APPS.CONFIGURE.SUBTITLE']} + /> + <div> + <div className="my-5 mx-3"> + <ActionNotification + stringId="USER_APPS.CONFIGURE.REMOVE" + text={STRINGS['USER_APPS.CONFIGURE.REMOVE']} + iconId="CANCEL_CROSS_ACTIVE" + iconPath={ICONS['CANCEL_CROSS_ACTIVE']} + onClick={() => setShowRemove(true)} + status="information" + textPosition="left" + className="remove-action" + /> + </div> + + <div className="my-5 mx-3"> + <div> + {STRINGS['USER_APPS.CONFIGURE.TEXT']} + <EditWrapper stringId="USER_APPS.CONFIGURE.TEXT" /> + </div> + </div> + + <div className="d-flex"> + <div className="w-50"> + <EditWrapper stringId="USER_APPS.CONFIGURE.BACK" /> + <Button + label={STRINGS['USER_APPS.CONFIGURE.BACK']} + onClick={onClose} + /> + </div> + <div className="separator" /> + <div className="w-50"> + <EditWrapper stringId="USER_APPS.CONFIGURE.HELP" /> + <Button + label={STRINGS['USER_APPS.CONFIGURE.HELP']} + onClick={openNewForm} + /> + </div> + </div> + </div> + </div> + ); +}; + +const mapStateToProps = () => ({}); + +const mapDispatchToProps = (dispatch) => ({ + openHelpdesk: bindActionCreators(openHelpdesk, dispatch), +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(withConfig(ConfigureApps)); diff --git a/web/src/containers/Apps/User.js b/web/src/containers/Apps/User.js new file mode 100644 index 0000000000..fbf7f87d79 --- /dev/null +++ b/web/src/containers/Apps/User.js @@ -0,0 +1,129 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { IconTitle, EditWrapper, Table } from 'components'; +import { updateUserSettings, setUserData } from 'actions/userAction'; +import { openConfigureApps, closeNotification } from 'actions/appActions'; +import STRINGS from 'config/localizedStrings'; +import withConfig from 'components/ConfigProvider/withConfig'; +import { withRouter } from 'react-router'; +import { userAppsSelector } from './utils'; + +const generateHeaders = (goToDetails, openConfigs) => { + return [ + { + stringId: 'USER_APPS.TABLE.APP_NAME', + label: STRINGS['USER_APPS.TABLE.APP_NAME'], + key: 'name', + }, + { + stringId: 'USER_APPS.TABLE.DESCRIPTION', + label: STRINGS['USER_APPS.TABLE.DESCRIPTION'], + key: 'description', + }, + { + stringId: 'USER_APPS.TABLE.CONFIGURE', + label: STRINGS['USER_APPS.TABLE.CONFIGURE'], + renderCell: ({ name }, key) => ( + <td key={`${key}-${name}-configure`}> + <span + className="blue-link underline-text pointer no-wrap" + onClick={() => openConfigs(name)} + > + {STRINGS['USER_APPS.TABLE.CONFIGURE']} + </span> + </td> + ), + }, + { + stringId: 'USER_APPS.TABLE.ACTION', + label: STRINGS['USER_APPS.TABLE.ACTION'], + renderCell: ({ name }, key) => ( + <td key={`${key}-${name}-action`}> + <span + className="blue-link underline-text pointer no-wrap" + onClick={() => goToDetails(name)} + > + {STRINGS['USER_APPS.TABLE.VIEW_APP']} + </span> + </td> + ), + }, + ]; +}; + +const User = ({ + icons: ICONS, + router, + userApps: data, + settings: { apps = [] }, + setUserData, + openConfigureApps, + closeNotification, +}) => { + const goToDetails = (name) => router.push(`apps/details/${name}`); + const openConfigs = (name) => openConfigureApps(() => onRemove(name)); + const onRemove = (name) => { + const settings = { + app: apps.filter((app) => app !== name), + }; + + updateUserSettings(settings) + .then(({ data }) => { + setUserData(data); + closeNotification(); + }) + .catch((err) => console.log('error')); + }; + + return ( + <div> + <div className="settings-form-wrapper"> + <div className="settings-form"> + <IconTitle + stringId="USER_APPS.MY_APPS.TITLE" + text={STRINGS['USER_APPS.MY_APPS.TITLE']} + textType="title" + iconPath={ICONS['APPS_USER']} + /> + <div className="py-4"> + <EditWrapper stringId="USER_APPS.MY_APPS.SUBTITLE"> + {STRINGS['USER_APPS.MY_APPS.SUBTITLE']} + </EditWrapper> + </div> + <Table + showHeaderNoData={true} + rowClassName="pt-2 pb-2" + headers={generateHeaders(goToDetails, openConfigs)} + showAll={true} + data={data} + rowKey={({ name }) => name} + displayPaginator={false} + /> + </div> + </div> + </div> + ); +}; + +const mapStateToProps = (state) => { + const { + user: { settings }, + } = state; + + return { + userApps: userAppsSelector(state), + settings, + }; +}; + +const mapDispatchToProps = (dispatch) => ({ + setUserData: bindActionCreators(setUserData, dispatch), + openConfigureApps: bindActionCreators(openConfigureApps, dispatch), + closeNotification: bindActionCreators(closeNotification, dispatch), +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(withRouter(withConfig(User))); diff --git a/web/src/containers/Apps/_Apps.scss b/web/src/containers/Apps/_Apps.scss new file mode 100644 index 0000000000..a32acfa386 --- /dev/null +++ b/web/src/containers/Apps/_Apps.scss @@ -0,0 +1,26 @@ +.add-app-button { + border-radius: 24px; + height: 24px !important; + min-width: 70px !important; + width: auto !important; + text-transform: none !important; +} + +.apps-form { + .ant-input { + color: $colors-main-black; + } + .ant-input-clear-icon { + color: $colors-black; + } +} + +.action_notification-wrapper { + &.remove-action { + position: relative !important; + } +} + +.apps-table-check { + width: 2rem !important; +} diff --git a/web/src/containers/Apps/index.js b/web/src/containers/Apps/index.js new file mode 100644 index 0000000000..765a84d0f0 --- /dev/null +++ b/web/src/containers/Apps/index.js @@ -0,0 +1,114 @@ +import React, { useState, useEffect } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import { isMobile } from 'react-device-detect'; +import STRINGS from 'config/localizedStrings'; +import withConfig from 'components/ConfigProvider/withConfig'; +import { + IconTitle, + HeaderSection, + EditWrapper, + CustomMobileTabs, + TabController, + MobileTabBar, +} from 'components'; +import { openContactForm } from 'actions/appActions'; +import All from './All'; +import User from './User'; + +const Index = ({ icons: ICONS, openContactForm }) => { + const [tabs, setTabs] = useState([]); + const [activeTab, setActiveTab] = useState(0); + + useEffect(() => { + updateTabs(); + }, []); + + const updateTabs = () => { + const tabs = [ + { + title: isMobile ? ( + <CustomMobileTabs + title={STRINGS['USER_APPS.ALL_APPS.TAB_TITLE']} + // icon={ICONS['SETTING_NOTIFICATION_ICON']} + /> + ) : ( + <div>{STRINGS['USER_APPS.ALL_APPS.TAB_TITLE']}</div> + ), + content: <All setActiveTab={setActiveTab} />, + }, + { + title: isMobile ? ( + <CustomMobileTabs + title={STRINGS['USER_APPS.MY_APPS.TAB_TITLE']} + // icon={ICONS['SETTING_NOTIFICATION_ICON']} + /> + ) : ( + <div>{STRINGS['USER_APPS.MY_APPS.TAB_TITLE']}</div> + ), + content: <User />, + }, + ]; + setTabs(tabs); + }; + + const renderContent = (tabs, activeTab) => + tabs[activeTab] && tabs[activeTab].content ? ( + tabs[activeTab].content + ) : ( + <div /> + ); + + return ( + <div className="presentation_container apply_rtl settings_container"> + {!isMobile && ( + <IconTitle + stringId="ACCOUNTS.TAB_APPS" + text={STRINGS['ACCOUNTS.TAB_APPS']} + textType="title" + iconPath={ICONS['TAB_APPS']} + iconId="TAB_APPS" + /> + )} + + <HeaderSection + stringId="USER_APPS.TITLE" + title={STRINGS['USER_APPS.TITLE']} + openContactForm={openContactForm} + > + <div className="header-content"> + <div> + <EditWrapper stringId="USER_APPS.SUBTITLE"> + {STRINGS['USER_APPS.SUBTITLE']} + </EditWrapper> + </div> + </div> + </HeaderSection> + + {!isMobile ? ( + <TabController + activeTab={activeTab} + setActiveTab={setActiveTab} + tabs={tabs} + /> + ) : ( + <MobileTabBar + activeTab={activeTab} + renderContent={renderContent} + setActiveTab={setActiveTab} + tabs={tabs} + /> + )} + + {isMobile ? <div className="my-4" /> : renderContent(tabs, activeTab)} + </div> + ); +}; + +const mapStateToProps = (state) => ({}); + +const mapDispatchToProps = (dispatch) => ({ + openContactForm: bindActionCreators(openContactForm, dispatch), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(withConfig(Index)); diff --git a/web/src/containers/Apps/utils.js b/web/src/containers/Apps/utils.js new file mode 100644 index 0000000000..7c92a7c5ae --- /dev/null +++ b/web/src/containers/Apps/utils.js @@ -0,0 +1,20 @@ +import { createSelector } from 'reselect'; + +const getPlugins = (state) => state.app.plugins; +const getUserApps = (state) => state.user.settings.apps || []; +export const appsSelector = createSelector([getPlugins], (plugins) => + plugins.filter( + ({ web_view }) => + web_view && + web_view.some(({ meta: { is_app, type } }) => is_app && type === 'kit') + ) +); + +export const userAppsSelector = createSelector( + [getUserApps, appsSelector], + (user_apps, apps) => { + return apps.filter(({ name }) => user_apps.includes(name)); + } +); + +export const isEnabled = (app, apps) => apps.includes(app); diff --git a/web/src/containers/AuthContainer/index.js b/web/src/containers/AuthContainer/index.js index b24744ad8e..44960c8eb9 100644 --- a/web/src/containers/AuthContainer/index.js +++ b/web/src/containers/AuthContainer/index.js @@ -7,9 +7,9 @@ import withConfig from 'components/ConfigProvider/withConfig'; import { AppFooter, Dialog } from 'components'; import { HelpfulResourcesForm } from 'containers'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; -import { getClasesForLanguage } from '../../utils/string'; -import { getThemeClass } from '../../utils/theme'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; +import { getClasesForLanguage } from 'utils/string'; +import { getThemeClass } from 'utils/theme'; import { getExchangeInfo, closeNotification, diff --git a/web/src/containers/Chat/index.js b/web/src/containers/Chat/index.js index 0272d457fa..e4f723151f 100644 --- a/web/src/containers/Chat/index.js +++ b/web/src/containers/Chat/index.js @@ -4,13 +4,10 @@ import { bindActionCreators } from 'redux'; import { isMobile } from 'react-device-detect'; import { setWsHeartbeat } from 'ws-heartbeat/client'; -import { ChatWrapper } from '../../components'; -import { WS_URL } from '../../config/constants'; -import { - setAnnouncements, - setChatUnreadMessages, -} from '../../actions/appActions'; -import { getToken } from '../../utils/token'; +import { ChatWrapper } from 'components'; +import { WS_URL } from 'config/constants'; +import { setAnnouncements, setChatUnreadMessages } from 'actions/appActions'; +import { getToken } from 'utils/token'; import { NORMAL_CLOSURE_CODE, isIntentionalClosure } from 'utils/webSocket'; const ENTER_KEY = 'Enter'; diff --git a/web/src/containers/ConfirmChangePassword/index.js b/web/src/containers/ConfirmChangePassword/index.js index bd9f184efe..26da083995 100644 --- a/web/src/containers/ConfirmChangePassword/index.js +++ b/web/src/containers/ConfirmChangePassword/index.js @@ -1,9 +1,9 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; -import { Dialog } from '../../components'; +import { Dialog } from 'components'; import ResetPasswordSuccess from 'containers/ResetPassword/ResetPasswordSuccess'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; class ConfirmChangePassword extends Component { state = { diff --git a/web/src/containers/ContactForm/index.js b/web/src/containers/ContactForm/index.js index da0fcf8d83..3371a892bc 100644 --- a/web/src/containers/ContactForm/index.js +++ b/web/src/containers/ContactForm/index.js @@ -1,10 +1,10 @@ import React, { Component } from 'react'; import { SubmissionError } from 'redux-form'; import { connect } from 'react-redux'; -import { HocForm, IconTitle, Notification } from '../../components'; -import { email as isEmail, required } from '../../components/Form/validations'; -import STRINGS from '../../config/localizedStrings'; -import { sendSupportMail, NOTIFICATIONS } from '../../actions/appActions'; +import { HocForm, IconTitle, Notification } from 'components'; +import { email as isEmail, required } from 'components/Form/validations'; +import STRINGS from 'config/localizedStrings'; +import { sendSupportMail, NOTIFICATIONS } from 'actions/appActions'; import withConfig from 'components/ConfigProvider/withConfig'; const FORM_NAME = 'ContactForm'; diff --git a/web/src/containers/Deposit/index.js b/web/src/containers/Deposit/index.js index 885bf21921..dab827277c 100644 --- a/web/src/containers/Deposit/index.js +++ b/web/src/containers/Deposit/index.js @@ -4,17 +4,14 @@ import { bindActionCreators } from 'redux'; import { formValueSelector } from 'redux-form'; import { connect } from 'react-redux'; import { isMobile } from 'react-device-detect'; -import { BALANCE_ERROR } from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; -import { getCurrencyFromName } from '../../utils/currency'; +import { BALANCE_ERROR } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; +import { getCurrencyFromName } from 'utils/currency'; import { createAddress, cleanCreateAddress } from 'actions/userAction'; import { NOTIFICATIONS } from 'actions/appActions'; import { DEFAULT_COIN_DATA } from 'config/constants'; -import { - openContactForm, - setSnackNotification, -} from '../../actions/appActions'; +import { openContactForm, setSnackNotification } from 'actions/appActions'; import { MobileBarBack, Dialog, Notification } from 'components'; import { diff --git a/web/src/containers/ExpiredExchange/index.js b/web/src/containers/ExpiredExchange/index.js index 6cb219ac48..13b0ff5a58 100644 --- a/web/src/containers/ExpiredExchange/index.js +++ b/web/src/containers/ExpiredExchange/index.js @@ -4,13 +4,12 @@ import { ReactSVG } from 'react-svg'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import moment from 'moment'; -import { getThemeClass } from '../../utils/theme'; - -import { FLEX_CENTER_CLASSES, EXCHANGE_URL } from '../../config/constants'; -import { getExchangeInfo } from '../../actions/appActions'; -import { logout } from '../../actions/authAction'; -import STRINGS from '../../config/localizedStrings'; -import { Button } from '../../components'; +import { getThemeClass } from 'utils/theme'; +import { FLEX_CENTER_CLASSES, EXCHANGE_URL } from 'config/constants'; +import { getExchangeInfo } from 'actions/appActions'; +import { logout } from 'actions/authAction'; +import STRINGS from 'config/localizedStrings'; +import { Button } from 'components'; import withConfig from 'components/ConfigProvider/withConfig'; diff --git a/web/src/containers/HelpfulResourcesForm/index.js b/web/src/containers/HelpfulResourcesForm/index.js index 7bf81f0c75..57465f0c57 100644 --- a/web/src/containers/HelpfulResourcesForm/index.js +++ b/web/src/containers/HelpfulResourcesForm/index.js @@ -4,8 +4,8 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import classnames from 'classnames'; import Image from 'components/Image'; -import { IconTitle, Notification, Button, BlueLink } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +import { IconTitle, Notification, Button, BlueLink } from 'components'; +import STRINGS from 'config/localizedStrings'; import { sendSupportMail, NOTIFICATIONS, diff --git a/web/src/containers/Home/_Home.scss b/web/src/containers/Home/_Home.scss index 3ba046dc36..8621fd53b0 100644 --- a/web/src/containers/Home/_Home.scss +++ b/web/src/containers/Home/_Home.scss @@ -366,7 +366,8 @@ $trade-tab--arrow-size: 0.4rem; display: flex; justify-content: center; align-items: center; - background-color: $app-sidebar-background; + background-color: transparent; + border-bottom: 1px $colors-border solid; opacity: 0.8; .card-section-wrapper { display: flex; diff --git a/web/src/containers/Home/index.js b/web/src/containers/Home/index.js index f366b37660..c2e1d9f0d8 100644 --- a/web/src/containers/Home/index.js +++ b/web/src/containers/Home/index.js @@ -9,7 +9,7 @@ import { isMobile } from 'react-device-detect'; import _floor from 'lodash/floor'; import { setWsHeartbeat } from 'ws-heartbeat/client'; import debounce from 'lodash.debounce'; -import { message } from 'antd'; +import { message, Spin } from 'antd'; import moment from 'moment'; import STRINGS from 'config/localizedStrings'; @@ -161,6 +161,7 @@ class Home extends Component { isAmountChanged: false, isHover: false, hoveredIndex: 0, + carouselLodaing: true, }; this.goToPair(pair); this.props.setPriceEssentials({ side: this.state.side }); @@ -210,6 +211,9 @@ class Home extends Component { this.setState({ isBrokerPaused: true }); } this.handleBrokerQuote(pair, side); + setTimeout(() => { + this.setState({ carouselLodaing: false }); + }, 3000); } componentDidUpdate(prevProps, prevState) { @@ -749,32 +753,67 @@ class Home extends Component { case 'carousel_section': { const { markets } = this.props; const { chartData } = this.state; - const marketsData = [...markets, ...markets, ...markets]; - const items = marketsData.map((market, index) => ( - <MarketCard - market={market} - onDragStart={this.handleDragStart} - role="presentation" - chartData={chartData} - /> - )); + let testMarket = []; + let loopCnt = 0; + if (markets.length < 12) { + if (markets.length === 1) { + loopCnt = 12; + } else if (markets.length === 2) { + loopCnt = 6; + } else if (markets.length === 3) { + loopCnt = 4; + } else if (markets.length === 4 || markets.length === 5) { + loopCnt = 3; + } else if (markets.length > 5 || markets.length < 12) { + loopCnt = 2; + } + + for (let i = 0; i < loopCnt; i++) { + testMarket = [...testMarket, ...markets]; + } + } else { + testMarket = [...markets]; + } + + const duration = parseInt((50 / 12) * testMarket.length); + const marketsData = [...testMarket, ...testMarket, ...testMarket]; return ( <div className="home_carousel_section "> - <div class="slideshow-wrapper"> - <div class="parent-slider d-flex"> - {items.map((sec, index) => { - return ( - <div - className="section" - onClick={() => this.sectionToNav(sec)} - > - {sec} - </div> - ); - })} + <Spin spinning={this.state.carouselLodaing}> + <div class="slideshow-wrapper"> + <div + class="parent-slider d-flex" + style={{ animationDuration: `${duration}s` }} + > + {marketsData.map((sec, index) => { + return ( + <div + className="section" + style={{ + borderRight: `${ + !this.state.carouselLodaing + ? '1px solid #60605d' + : 'none' + }`, + }} + key={index} + onClick={() => this.sectionToNav(sec)} + > + {!this.state.carouselLodaing ? ( + <MarketCard + market={sec} + onDragStart={this.handleDragStart} + role="presentation" + chartData={chartData} + /> + ) : null} + </div> + ); + })} + </div> </div> - </div> + </Spin> </div> ); } diff --git a/web/src/containers/Login/LoginForm.js b/web/src/containers/Login/LoginForm.js index 763e5f33a8..da9d91c5fe 100644 --- a/web/src/containers/Login/LoginForm.js +++ b/web/src/containers/Login/LoginForm.js @@ -5,11 +5,10 @@ import { password, email, normalizeEmail, -} from '../../components/Form/validations'; -import { AuthForm } from '../../components'; -import { getLanguage } from '../../utils/string'; - -import STRINGS from '../../config/localizedStrings'; +} from 'components/Form/validations'; +import { AuthForm } from 'components'; +import { getLanguage } from 'utils/string'; +import STRINGS from 'config/localizedStrings'; export const FORM_NAME = 'LoginForm'; diff --git a/web/src/containers/Login/index.js b/web/src/containers/Login/index.js index 9ad68884be..9c21eba5ad 100644 --- a/web/src/containers/Login/index.js +++ b/web/src/containers/Login/index.js @@ -10,14 +10,14 @@ import { performLogin, storeLoginResult, setLogoutMessage, -} from '../../actions/authAction'; +} from 'actions/authAction'; import LoginForm, { FORM_NAME } from './LoginForm'; -import { Dialog, OtpForm, IconTitle, Notification } from '../../components'; -import { NOTIFICATIONS } from '../../actions/appActions'; -import { errorHandler } from '../../components/OtpForm/utils'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; +import { Dialog, OtpForm, IconTitle, Notification } from 'components'; +import { NOTIFICATIONS } from 'actions/appActions'; +import { errorHandler } from 'components/OtpForm/utils'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; let errorTimeOut = null; diff --git a/web/src/containers/MobileHome/index.js b/web/src/containers/MobileHome/index.js index db271802b5..de2838025a 100644 --- a/web/src/containers/MobileHome/index.js +++ b/web/src/containers/MobileHome/index.js @@ -3,10 +3,10 @@ import classnames from 'classnames'; import { connect } from 'react-redux'; import { isBrowser, isMobile } from 'react-device-detect'; -import STRINGS from '../../config/localizedStrings'; -import { AppFooter, NotificationsList } from '../../components'; -import { getClasesForLanguage } from '../../utils/string'; -import { getThemeClass } from '../../utils/theme'; +import STRINGS from 'config/localizedStrings'; +import { AppFooter, NotificationsList } from 'components'; +import { getClasesForLanguage } from 'utils/string'; +import { getThemeClass } from 'utils/theme'; class Home extends Component { render() { diff --git a/web/src/containers/RequestResetPassword/RequestResetPasswordSuccess.js b/web/src/containers/RequestResetPassword/RequestResetPasswordSuccess.js index 666cf5a9c2..a9cdcd0e14 100644 --- a/web/src/containers/RequestResetPassword/RequestResetPasswordSuccess.js +++ b/web/src/containers/RequestResetPassword/RequestResetPasswordSuccess.js @@ -1,8 +1,8 @@ import React from 'react'; -import { ICONS } from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; +import { ICONS } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; -import { IconTitle, Button } from '../../components'; +import { IconTitle, Button } from 'components'; const RequestResetPasswordSuccess = ({ onLoginClick, onContactUs }) => ( <div className="auth_wrapper d-flex justify-content-center align-items-center flex-column"> diff --git a/web/src/containers/RequestResetPassword/ResetPasswordForm.js b/web/src/containers/RequestResetPassword/ResetPasswordForm.js index 50168494af..a53f158141 100644 --- a/web/src/containers/RequestResetPassword/ResetPasswordForm.js +++ b/web/src/containers/RequestResetPassword/ResetPasswordForm.js @@ -5,10 +5,10 @@ import { email, normalizeEmail, required, -} from '../../components/Form/validations'; -import { AuthForm } from '../../components'; -import STRINGS from '../../config/localizedStrings'; -import { getLanguage } from '../../utils/string'; +} from 'components/Form/validations'; +import { AuthForm } from 'components'; +import STRINGS from 'config/localizedStrings'; +import { getLanguage } from 'utils/string'; export const generateFormFields = (theme) => ({ email: { diff --git a/web/src/containers/RequestResetPassword/index.js b/web/src/containers/RequestResetPassword/index.js index d46cfaada5..cc42c206d1 100644 --- a/web/src/containers/RequestResetPassword/index.js +++ b/web/src/containers/RequestResetPassword/index.js @@ -3,20 +3,38 @@ import classnames from 'classnames'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { isMobile } from 'react-device-detect'; +import { Link } from 'react-router'; import { SubmissionError, change } from 'redux-form'; -import { requestResetPassword } from '../../actions/authAction'; +import { requestResetPassword } from 'actions/authAction'; import ResetPasswordForm, { generateFormFields } from './ResetPasswordForm'; -import { IconTitle, Dialog, MobileBarBack } from '../../components'; -import { ContactForm } from '../'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; +import { IconTitle, Dialog, MobileBarBack } from 'components'; +import { ContactForm } from 'containers'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; import RequestResetPasswordSuccess from './RequestResetPasswordSuccess'; import withConfig from 'components/ConfigProvider/withConfig'; import { openContactForm } from 'actions/appActions'; let errorTimeOut = null; +const BottomLink = () => ( + <> + <div className={classnames('f-1', 'link_wrapper')}> + {STRINGS['SIGN_UP.HAVE_ACCOUNT']} + <Link to="/login" className={classnames('blue-link')}> + {STRINGS['SIGN_UP.GOTO_LOGIN']} + </Link> + </div> + <div className={classnames('f-1', 'link_wrapper')}> + {STRINGS['LOGIN.NO_ACCOUNT']} + <Link to="/signup" className={classnames('blue-link')}> + {STRINGS['LOGIN.CREATE_ACCOUNT']} + </Link> + </div> + </> +); + class RequestResetPassword extends Component { constructor(props) { super(props); @@ -131,6 +149,7 @@ class RequestResetPassword extends Component { onSubmit={this.onSubmitRequestResetPassword} formFields={formFields} /> + {isMobile && <BottomLink />} </div> </div> )} @@ -149,6 +168,7 @@ class RequestResetPassword extends Component { onClose={this.onCloseDialog} /> </Dialog> + {!isMobile && <BottomLink />} </div> ); } diff --git a/web/src/containers/ResetPassword/ResetPasswordForm.js b/web/src/containers/ResetPassword/ResetPasswordForm.js index 1960678ddf..3a18063f1b 100644 --- a/web/src/containers/ResetPassword/ResetPasswordForm.js +++ b/web/src/containers/ResetPassword/ResetPasswordForm.js @@ -1,8 +1,8 @@ import React from 'react'; import { reduxForm } from 'redux-form'; -import { required, password } from '../../components/Form/validations'; -import { AuthForm } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +import { required, password } from 'components/Form/validations'; +import { AuthForm } from 'components'; +import STRINGS from 'config/localizedStrings'; export const generateFormFields = () => ({ password: { diff --git a/web/src/containers/ResetPassword/ResetPasswordSuccess.js b/web/src/containers/ResetPassword/ResetPasswordSuccess.js index 33986fbf93..966a750e39 100644 --- a/web/src/containers/ResetPassword/ResetPasswordSuccess.js +++ b/web/src/containers/ResetPassword/ResetPasswordSuccess.js @@ -1,6 +1,6 @@ import React from 'react'; -import { IconTitle, Button } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +import { IconTitle, Button } from 'components'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; const ResetPasswordSuccess = ({ @@ -31,7 +31,7 @@ const ResetPasswordSuccess = ({ {STRINGS['RESET_PASSWORD_SUCCESS.TEXT_1']} </div> )} - <Button label={label} onClick={onClick} className="button-margin" /> + <Button label={label} onClick={onClick} className="button-margin mt-5" /> </div> ); }; diff --git a/web/src/containers/ResetPassword/index.js b/web/src/containers/ResetPassword/index.js index 0a209bb7c2..b1ca9d4aae 100644 --- a/web/src/containers/ResetPassword/index.js +++ b/web/src/containers/ResetPassword/index.js @@ -3,13 +3,13 @@ import classnames from 'classnames'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { SubmissionError } from 'redux-form'; -import { resetPassword } from '../../actions/authAction'; +import { resetPassword } from 'actions/authAction'; import ResetPasswordForm from './ResetPasswordForm'; import ResetPasswordSuccess from './ResetPasswordSuccess'; -import { IconTitle, Dialog } from '../../components'; -import { ContactForm } from '../'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; +import { IconTitle, Dialog } from 'components'; +import { ContactForm } from 'containers'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import { openContactForm } from 'actions/appActions'; diff --git a/web/src/containers/Signup/SignupForm.js b/web/src/containers/Signup/SignupForm.js index b012aabebe..19545627f1 100644 --- a/web/src/containers/Signup/SignupForm.js +++ b/web/src/containers/Signup/SignupForm.js @@ -6,9 +6,9 @@ import { email, requiredWithCustomMessage, normalizeEmail, -} from '../../components/Form/validations'; -import { AuthForm, BlueLink } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +} from 'components/Form/validations'; +import { AuthForm, BlueLink } from 'components'; +import STRINGS from 'config/localizedStrings'; export const FORM_NAME = 'SignForm'; diff --git a/web/src/containers/Signup/SignupSuccess.js b/web/src/containers/Signup/SignupSuccess.js index 1e465f0337..529f63d3cd 100644 --- a/web/src/containers/Signup/SignupSuccess.js +++ b/web/src/containers/Signup/SignupSuccess.js @@ -1,30 +1,59 @@ import React from 'react'; import { Link } from 'react-router'; -import { IconTitle } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +import { IconTitle } from 'components'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; +import classnames from 'classnames'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; + +const BottomLink = () => ( + <> + <div className={classnames('f-1', 'link_wrapper')}> + {STRINGS['SIGN_UP.HAVE_ACCOUNT']} + <Link to="/login" className={classnames('blue-link')}> + {STRINGS['SIGN_UP.GOTO_LOGIN']} + </Link> + </div> + <div className={classnames('f-1', 'link_wrapper')}> + {STRINGS['LOGIN.NO_ACCOUNT']} + <Link to="/signup" className={classnames('blue-link')}> + {STRINGS['LOGIN.CREATE_ACCOUNT']} + </Link> + </div> + </> +); const SignupSuccess = ({ icons: ICONS, ...rest }) => { return ( - <div className="signup_success-wrapper d-flex justify-content-center align-items-center flex-column auth_wrapper"> - <IconTitle - iconId="CHECK" - iconPath={ICONS['CHECK']} - stringId="VERIFICATION_TEXTS.TITLE" - text={STRINGS['VERIFICATION_TEXTS.TITLE']} - textType="title" - className="w-100" - /> - <div className="signup_success-content"> - <p>{STRINGS['VERIFICATION_TEXTS.TEXT_1']}</p> - <p>{STRINGS['VERIFICATION_TEXTS.TEXT_2']}</p> - </div> - <div> - {STRINGS['SIGN_UP.NO_EMAIL']} - <Link to="/verify" className="blue-link"> - {STRINGS['SIGN_UP.REQUEST_EMAIL']} - </Link> + <div + className={classnames( + ...FLEX_CENTER_CLASSES, + 'flex-column', + 'f-1', + 'login_container' + )} + > + <div className="signup_success-wrapper d-flex justify-content-center align-items-center flex-column auth_wrapper"> + <IconTitle + iconId="CHECK" + iconPath={ICONS['CHECK']} + stringId="VERIFICATION_TEXTS.TITLE" + text={STRINGS['VERIFICATION_TEXTS.TITLE']} + textType="title" + className="w-100" + /> + <div className="signup_success-content"> + <p>{STRINGS['VERIFICATION_TEXTS.TEXT_1']}</p> + <p>{STRINGS['VERIFICATION_TEXTS.TEXT_2']}</p> + </div> + <div> + {STRINGS['SIGN_UP.NO_EMAIL']} + <Link to="/verify" className="blue-link"> + {STRINGS['SIGN_UP.REQUEST_EMAIL']} + </Link> + </div> </div> + <BottomLink /> </div> ); }; diff --git a/web/src/containers/Signup/index.js b/web/src/containers/Signup/index.js index fc23ff6b3a..4c02f863ac 100644 --- a/web/src/containers/Signup/index.js +++ b/web/src/containers/Signup/index.js @@ -5,13 +5,13 @@ import { connect } from 'react-redux'; import { isMobile } from 'react-device-detect'; import { SubmissionError, change } from 'redux-form'; import { bindActionCreators } from 'redux'; -import { performSignup } from '../../actions/authAction'; +import { performSignup } from 'actions/authAction'; import SignupForm, { generateFormFields, FORM_NAME } from './SignupForm'; import SignupSuccess from './SignupSuccess'; -import { ContactForm } from '../'; -import { IconTitle, Dialog, MobileBarBack } from '../../components'; +import { ContactForm } from 'containers'; +import { IconTitle, Dialog, MobileBarBack } from 'components'; import { FLEX_CENTER_CLASSES } from 'config/constants'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import { openContactForm } from 'actions/appActions'; diff --git a/web/src/containers/StakeDetails/_StakeDetails.scss b/web/src/containers/StakeDetails/_StakeDetails.scss index 25f89046ab..5bdc9e969b 100644 --- a/web/src/containers/StakeDetails/_StakeDetails.scss +++ b/web/src/containers/StakeDetails/_StakeDetails.scss @@ -180,6 +180,10 @@ border-radius: 0.5rem; margin: 1rem 0.5rem; font-weight: bold; + + &:hover { + opacity: 0.8; + } } .chart_mine { diff --git a/web/src/containers/Summary/MobileAccountTypeList.js b/web/src/containers/Summary/MobileAccountTypeList.js index f364c8a99b..330a03ed58 100644 --- a/web/src/containers/Summary/MobileAccountTypeList.js +++ b/web/src/containers/Summary/MobileAccountTypeList.js @@ -1,10 +1,9 @@ import React from 'react'; import classnames from 'classnames'; -import Image from 'components/Image'; - -import STRINGS from '../../config/localizedStrings'; +import { Image } from 'components'; +import STRINGS from 'config/localizedStrings'; import AccountTypeDetails from './components/AccountTypeDetails'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; import withConfig from 'components/ConfigProvider/withConfig'; const MobileAccountTypeList = ({ diff --git a/web/src/containers/Summary/MobileSummary.js b/web/src/containers/Summary/MobileSummary.js index d36f8a87d1..1926f7994b 100644 --- a/web/src/containers/Summary/MobileSummary.js +++ b/web/src/containers/Summary/MobileSummary.js @@ -12,9 +12,9 @@ import { BASE_CURRENCY, DEFAULT_COIN_DATA, SHOW_TOTAL_ASSETS, -} from '../../config/constants'; -// import { formatAverage, formatBaseAmount } from '../../utils/currency'; -import STRINGS from '../../config/localizedStrings'; +} from 'config/constants'; +// import { formatAverage, formatBaseAmount } from 'utils/currency'; +import STRINGS from 'config/localizedStrings'; const MobileSummary = ({ user, diff --git a/web/src/containers/Summary/_Summary.scss b/web/src/containers/Summary/_Summary.scss index f2b624f968..3adf9cd8e1 100644 --- a/web/src/containers/Summary/_Summary.scss +++ b/web/src/containers/Summary/_Summary.scss @@ -442,6 +442,7 @@ $trade-tab--arrow-size: 0.4rem; width: 3rem; svg { + width: 2.5rem; .btc0, .btc1 { fill: $coin-btc; diff --git a/web/src/containers/Summary/index.js b/web/src/containers/Summary/index.js index 93c8540615..4155701a5c 100644 --- a/web/src/containers/Summary/index.js +++ b/web/src/containers/Summary/index.js @@ -12,7 +12,7 @@ import AccountDetails from './components/AccountDetails'; import Markets from './components/Markets'; import MobileSummary from './MobileSummary'; -import { IconTitle } from '../../components'; +import { IconTitle } from 'components'; // import { logout } from '../../actions/authAction'; import { openFeesStructureandLimits, @@ -20,17 +20,17 @@ import { logoutconfirm, setNotification, NOTIFICATIONS, -} from '../../actions/appActions'; +} from 'actions/appActions'; import { BASE_CURRENCY, DEFAULT_COIN_DATA, // SHOW_SUMMARY_ACCOUNT_DETAILS, SHOW_TOTAL_ASSETS, -} from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; +} from 'config/constants'; +import STRINGS from 'config/localizedStrings'; import { formatAverage, formatBaseAmount } from 'utils/currency'; import { getLastMonthVolume } from './components/utils'; -import { getUserReferralCount } from '../../actions/userAction'; +import { getUserReferralCount } from 'actions/userAction'; import withConfig from 'components/ConfigProvider/withConfig'; import { openContactForm } from 'actions/appActions'; diff --git a/web/src/containers/TermsOfService/DepositFunds.js b/web/src/containers/TermsOfService/DepositFunds.js index 371d5c48b9..ef406a833b 100644 --- a/web/src/containers/TermsOfService/DepositFunds.js +++ b/web/src/containers/TermsOfService/DepositFunds.js @@ -1,8 +1,8 @@ import React from 'react'; import { ReactSVG } from 'react-svg'; -import { IconTitle, BlueLink, Button } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +import { IconTitle, BlueLink, Button } from 'components'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; const DepositFunds = (props) => { diff --git a/web/src/containers/TermsOfService/Form.js b/web/src/containers/TermsOfService/Form.js index f0a3713ef4..fe986555d1 100644 --- a/web/src/containers/TermsOfService/Form.js +++ b/web/src/containers/TermsOfService/Form.js @@ -2,11 +2,11 @@ import React from 'react'; import { reduxForm } from 'redux-form'; import { ReactSVG } from 'react-svg'; -import { Button } from '../../components'; -import renderFields from '../../components/Form/factoryFields'; -import STRINGS from '../../config/localizedStrings'; -import { ICONS } from '../../config/constants'; -import { getErrorLocalized } from '../../utils/errors'; +import { Button } from 'components'; +import renderFields from 'components/Form/factoryFields'; +import STRINGS from 'config/localizedStrings'; +import { ICONS } from 'config/constants'; +import { getErrorLocalized } from 'utils/errors'; export const FORM_NAME = 'termsAndConditionForm'; diff --git a/web/src/containers/TermsOfService/index.js b/web/src/containers/TermsOfService/index.js index 0b3d914114..551d8d632c 100644 --- a/web/src/containers/TermsOfService/index.js +++ b/web/src/containers/TermsOfService/index.js @@ -1,8 +1,8 @@ import React from 'react'; import TermsForm from './Form'; -import { requiredWithCustomMessage } from '../../components/Form/validations'; -import STRINGS from '../../config/localizedStrings'; +import { requiredWithCustomMessage } from 'components/Form/validations'; +import STRINGS from 'config/localizedStrings'; const formFields = { agreeTerms: { diff --git a/web/src/containers/Trade/MobileChart.js b/web/src/containers/Trade/MobileChart.js index 9db9f8dfdc..b281132b57 100644 --- a/web/src/containers/Trade/MobileChart.js +++ b/web/src/containers/Trade/MobileChart.js @@ -3,7 +3,7 @@ import classnames from 'classnames'; // import { Link } from 'react-router'; import { connect } from 'react-redux'; import TradeBlock from './components/TradeBlock'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import TradeHistory from './components/TradeHistory'; import TVChartContainer from './ChartContainer'; diff --git a/web/src/containers/Trade/MobileOrders.js b/web/src/containers/Trade/MobileOrders.js index 7beb1c2de8..a63a0221f9 100644 --- a/web/src/containers/Trade/MobileOrders.js +++ b/web/src/containers/Trade/MobileOrders.js @@ -3,8 +3,8 @@ import classnames from 'classnames'; import TradeBlock from './components/TradeBlock'; import ActiveOrders from './components/ActiveOrders'; import UserTrades from './components/UserTrades'; -import { ActionNotification } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +import { ActionNotification } from 'components'; +import STRINGS from 'config/localizedStrings'; import LogoutInfoOrder from './components/LogoutInfoOrder'; import withConfig from 'components/ConfigProvider/withConfig'; diff --git a/web/src/containers/Trade/MobileTrade.js b/web/src/containers/Trade/MobileTrade.js index 7e0da73df3..86b6cf861b 100644 --- a/web/src/containers/Trade/MobileTrade.js +++ b/web/src/containers/Trade/MobileTrade.js @@ -4,7 +4,7 @@ import classnames from 'classnames'; import TradeBlock from './components/TradeBlock'; import Orderbook from './components/Orderbook'; import OrderEntry from './components/OrderEntry'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; const MobileTrade = ({ orderbookReady, @@ -50,7 +50,10 @@ const MobileTrade = ({ setSizeRef={setSizeRef} /> </TradeBlock> - <TradeBlock title={STRINGS['ORDERBOOK']} className="order-entry w-50 orderBook-wrapper"> + <TradeBlock + title={STRINGS['ORDERBOOK']} + className="order-entry w-50 orderBook-wrapper" + > {orderbookReady && <Orderbook {...orderbookProps} />} </TradeBlock> </div> diff --git a/web/src/containers/Trade/components/Filters.js b/web/src/containers/Trade/components/Filters.js index b45bdd5a58..6213d51d98 100644 --- a/web/src/containers/Trade/components/Filters.js +++ b/web/src/containers/Trade/components/Filters.js @@ -1,12 +1,13 @@ -import React from 'react'; +import React, { useState } from 'react'; import { connect } from 'react-redux'; import { Select } from 'antd'; -import { CaretDownOutlined } from '@ant-design/icons'; +import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons'; import STRINGS from 'config/localizedStrings'; const { Option } = Select; const Filters = ({ pairs, pair, onChange }) => { + const [isOpen, setIsOpen] = useState(false); return ( <div> <Select @@ -17,7 +18,10 @@ const Filters = ({ pairs, pair, onChange }) => { className="custom-select-input-style elevated" dropdownClassName="custom-select-style" bordered={false} - suffixIcon={<CaretDownOutlined />} + suffixIcon={isOpen ? <CaretUpOutlined /> : <CaretDownOutlined />} + onClick={() => { + setIsOpen((prev) => !prev); + }} value={pair} onChange={onChange} > diff --git a/web/src/containers/Trade/components/OrderEntry.js b/web/src/containers/Trade/components/OrderEntry.js index 02df75aba0..2c970440a1 100644 --- a/web/src/containers/Trade/components/OrderEntry.js +++ b/web/src/containers/Trade/components/OrderEntry.js @@ -411,10 +411,12 @@ class OrderEntry extends Component { }; reset = () => { - const { change } = this.props; + const { change, resetSlider } = this.props; + this.setState({ sliderVal: 0 }); change(FORM_NAME, 'stop', ''); change(FORM_NAME, 'price', ''); change(FORM_NAME, 'size', ''); + resetSlider(); }; handleOrderBookChange = (name, value) => { @@ -438,20 +440,15 @@ class OrderEntry extends Component { increment_price, min_price, max_price, - coins, pair_base, pair_2, pair_base_display, pair_2_display, balance = {}, marketPrice, - pair = '', side = 'buy', } = props; - const { display_name } = coins[pair] || DEFAULT_COIN_DATA; - const { display_name: buy_display_name } = - coins[buyingPair] || DEFAULT_COIN_DATA; const { initialValues: { order_type }, } = this.state; @@ -526,7 +523,7 @@ class OrderEntry extends Component { maxValue(max_price), step(increment_price), ], - currency: buy_display_name, + currency: pair_2_display, setRef: this.props.setPriceRef, }, size: { @@ -561,13 +558,15 @@ class OrderEntry extends Component { min: min_size, max: max_size, validate: [required, minValue(min_size), maxValue(max_size)], - currency: display_name, + currency: pair_base_display, setRef: this.props.setSizeRef, }, slider: { name: 'size-slider', type: 'slider', onClick: this.setMax, + value: 0, + setRef: this.props.setSliderRef, }, postOnly: { name: 'post_only', diff --git a/web/src/containers/Trade/components/Orderbook.js b/web/src/containers/Trade/components/Orderbook.js index f4920ef821..982d4648f0 100644 --- a/web/src/containers/Trade/components/Orderbook.js +++ b/web/src/containers/Trade/components/Orderbook.js @@ -55,6 +55,7 @@ class Orderbook extends Component { priceDiff: 0, inProp: false, isAnimated: false, + isDropdownOpen: false, }; componentDidMount() { @@ -296,10 +297,17 @@ class Orderbook extends Component { bordered={false} defaultValue={false} size="small" + onClick={() => { + this.setState({ isDropdownOpend: !this.state.isDropdownOpen }); + }} suffixIcon={ - <CaretDownOutlined - onClick={() => this.dropdownVisibleChange(!isOpen)} - /> + this.isDropdownOpen ? ( + <CaretUpOutlined /> + ) : ( + <CaretDownOutlined + onClick={() => this.dropdownVisibleChange(!isOpen)} + /> + ) } value={isBase} onSelect={this.onSelect} diff --git a/web/src/containers/Trade/index.js b/web/src/containers/Trade/index.js index aff60446ca..a0fe61ab11 100644 --- a/web/src/containers/Trade/index.js +++ b/web/src/containers/Trade/index.js @@ -133,11 +133,11 @@ const defaultLayout = [ }, ]; -const getDefaultLayoutByTool = (tool) => - defaultLayout.find(({ i }) => i === tool) || {}; +const getLayoutByTool = (tool, layout = defaultLayout) => + layout.find(({ i }) => i === tool) || {}; -const layout = getLayout().map(({ w, h, x, y, i }) => { - const defaultItemLayout = getDefaultLayoutByTool(i); +const LAYOUT = getLayout().map(({ w, h, x, y, i }) => { + const defaultItemLayout = getLayoutByTool(i); const itemLayout = { ...defaultItemLayout }; if (defaultItemLayout.isResizable) { itemLayout.w = w; @@ -163,7 +163,7 @@ class Trade extends PureComponent { chartHeight: 0, chartWidth: 0, symbol: '', - layout: layout.length > 0 ? layout : defaultLayout, + layout: LAYOUT.length > 0 ? LAYOUT : defaultLayout, rowHeight, }; this.priceTimeOut = ''; @@ -208,8 +208,8 @@ class Trade extends PureComponent { .filter(([, { is_visible }]) => !!is_visible) .forEach(([tool]) => { if (!layout.find(({ i }) => i === tool)) { - const defaultItemLayout = getDefaultLayoutByTool(tool); - newItemsLayout.push({ ...defaultItemLayout, x: 0, y: Infinity }); + const defaultItemLayout = getLayoutByTool(tool); + newItemsLayout.push(defaultItemLayout); } }); this.setState({ layout: [...layout, ...newItemsLayout] }); @@ -358,6 +358,12 @@ class Trade extends PureComponent { } }; + setSliderRef = (sliderRef) => { + if (sliderRef) { + this.sliderRef = sliderRef; + } + }; + setActiveTab = (activeTab) => { const { setTradeTab } = this.props; setTradeTab(activeTab); @@ -429,6 +435,13 @@ class Trade extends PureComponent { }; }; + resetSlider = () => { + console.log(this.sliderRef); + if (this.sliderRef) { + this.sliderRef.reset(); + } + }; + subscribe = (pair) => { const { orderbookWs, wsInitialized } = this.state; if (orderbookWs && wsInitialized) { @@ -573,6 +586,8 @@ class Trade extends PureComponent { showPopup={settings.notification.popup_order_confirmation} setPriceRef={this.setPriceRef} setSizeRef={this.setSizeRef} + setSliderRef={this.setSliderRef} + resetSlider={this.resetSlider} /> </TradeBlock> </div> diff --git a/web/src/containers/TradeTabs/_TradeTabs.scss b/web/src/containers/TradeTabs/_TradeTabs.scss index e397ed91af..697c35df42 100644 --- a/web/src/containers/TradeTabs/_TradeTabs.scss +++ b/web/src/containers/TradeTabs/_TradeTabs.scss @@ -35,7 +35,7 @@ $toggle-margin: 2px; .toggle-action_button { width: $toggle-size * 3 !important; &.left { - opacity: 1 !important; + opacity: 1 !important; .toggle-action_button-display { $right-pos: $toggle-size + $toggle-margin * 2; right: calc(100% - #{$right-pos}) !important; @@ -54,6 +54,9 @@ $toggle-margin: 2px; margin: 0.5rem 0; padding: 0 0.5rem; text-transform: uppercase; + &:hover { + opacity: 0.5; + } } .link-separator { diff --git a/web/src/containers/TradeTabs/components/MarketRow.js b/web/src/containers/TradeTabs/components/MarketRow.js index 1443d3e4df..35c057aff7 100644 --- a/web/src/containers/TradeTabs/components/MarketRow.js +++ b/web/src/containers/TradeTabs/components/MarketRow.js @@ -51,7 +51,14 @@ class MarketRow extends Component { </td> <td className="td-chart"> <SparkLine - data={chartData[key] || []} + data={ + !chartData[key] || + (chartData[key] && + chartData[key].close && + chartData[key].close.length < 2) + ? { close: [0.1, 0.1, 0.1], open: [] } + : chartData[key] + } containerProps={{ style: { height: '100%', width: '100%' } }} /> </td> diff --git a/web/src/containers/TradeTabs/components/SparkLine.js b/web/src/containers/TradeTabs/components/SparkLine.js index 9443f260d1..ddf4bd2d12 100644 --- a/web/src/containers/TradeTabs/components/SparkLine.js +++ b/web/src/containers/TradeTabs/components/SparkLine.js @@ -7,7 +7,6 @@ class SparkLine extends Component { constructor(props) { super(props); const { data: { close = [], open = 0 } = {} } = this.props; - this.state = { chartOptions: { tooltip: { @@ -60,7 +59,10 @@ class SparkLine extends Component { } componentWillReceiveProps(nextProps) { - const { data } = this.props; + const { data, renderDefaultLine } = this.props; + if (data?.close?.length === 1 && renderDefaultLine) { + data.close.push(data.close[0]); + } if (JSON.stringify(data) !== JSON.stringify(nextProps.data)) { this.setState((prevState) => ({ ...prevState, @@ -69,8 +71,12 @@ class SparkLine extends Component { series: [ { ...prevState.chartOptions.series, - name: _get(nextProps, 'data.name') ? _get(nextProps, 'data.name') : _get(prevState, 'chartOptions.series.name'), - type: _get(nextProps, 'data.type') ? _get(nextProps, 'data.type') : _get(prevState, 'chartOptions.series.type'), + name: _get(nextProps, 'data.name') + ? _get(nextProps, 'data.name') + : _get(prevState, 'chartOptions.series.name'), + type: _get(nextProps, 'data.type') + ? _get(nextProps, 'data.type') + : _get(prevState, 'chartOptions.series.type'), data: nextProps.data.close, threshold: nextProps.data.open, }, diff --git a/web/src/containers/TradeTabs/components/_MarketList.scss b/web/src/containers/TradeTabs/components/_MarketList.scss index f52cc69eae..f97ee33fb6 100644 --- a/web/src/containers/TradeTabs/components/_MarketList.scss +++ b/web/src/containers/TradeTabs/components/_MarketList.scss @@ -11,6 +11,8 @@ margin: 0.3rem 0.3rem 0 0.3rem; svg { + width: 2.5rem !important; + height: 2.5rem !important; .btc0, .btc1 { fill: $coin-btc; diff --git a/web/src/containers/TransactionsHistory/HistoryDisplay.js b/web/src/containers/TransactionsHistory/HistoryDisplay.js index f49dc1cd31..23553b1c26 100644 --- a/web/src/containers/TransactionsHistory/HistoryDisplay.js +++ b/web/src/containers/TransactionsHistory/HistoryDisplay.js @@ -7,16 +7,15 @@ import { // CsvDownload, Loader, Dialog, -} from '../../components'; + EditWrapper, +} from 'components'; import classnames from 'classnames'; import { SubmissionError } from 'redux-form'; - -import STRINGS from '../../config/localizedStrings'; -import { EditWrapper } from 'components'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import { STATIC_ICONS } from 'config/icons'; import { searchTransaction } from 'actions/walletActions'; -import CheckDeposit from '../../components/CheckDeposit'; +import CheckDeposit from 'components/CheckDeposit'; const HistoryDisplay = (props) => { const { @@ -30,6 +29,7 @@ const HistoryDisplay = (props) => { handleNext, jumpToPage, handleDownload, + refetchData, icons: ICONS, activeTab, } = props; @@ -76,13 +76,13 @@ const HistoryDisplay = (props) => { <div className="title text-capitalize"> <EditWrapper stringId={stringId}>{title}</EditWrapper> {count > 0 && ( - <div className='download-icon'> + <div className="download-icon"> <ActionNotification stringId="TRANSACTION_HISTORY.TEXT_DOWNLOAD" text={STRINGS['TRANSACTION_HISTORY.TEXT_DOWNLOAD']} iconId="DATA" iconPath={ICONS['DATA']} - className="csv-action" + className="download-history" onClick={handleDownload} /> </div> @@ -97,6 +97,16 @@ const HistoryDisplay = (props) => { onClick={openDialog} /> ) : null} + <div className="download-icon"> + <ActionNotification + stringId="RESFRESH" + text={STRINGS['REFRESH']} + iconId="REFRESH" + iconPath={STATIC_ICONS['REFRESH']} + className="refresh-history" + onClick={refetchData} + /> + </div> </div> )} {filters} @@ -116,6 +126,7 @@ const HistoryDisplay = (props) => { title={title} handleNext={handleNext} jumpToPage={jumpToPage} + noData={props.noData} /> )} <Dialog @@ -126,8 +137,8 @@ const HistoryDisplay = (props) => { shouldCloseOnOverlayClick={false} style={{ 'z-index': 100 }} > - {dialogIsOpen - ? <CheckDeposit + {dialogIsOpen ? ( + <CheckDeposit onCloseDialog={onCloseDialog} onSubmit={requestDeposit} message={statusMessage} @@ -135,8 +146,7 @@ const HistoryDisplay = (props) => { initialValues={initialValue} props={props} /> - : null - } + ) : null} </Dialog> </div> ); diff --git a/web/src/containers/TransactionsHistory/_Filters.scss b/web/src/containers/TransactionsHistory/_Filters.scss index d064f470ab..6a6dbd6d46 100644 --- a/web/src/containers/TransactionsHistory/_Filters.scss +++ b/web/src/containers/TransactionsHistory/_Filters.scss @@ -20,6 +20,12 @@ } } + #trades-filters_size { + * { + transition: 0.2s; + } + } + .ant-radio-button-wrapper-checked::before, .ant-radio-button-wrapper::before { background-color: transparent !important; diff --git a/web/src/containers/TransactionsHistory/_TransactionsHistory.scss b/web/src/containers/TransactionsHistory/_TransactionsHistory.scss index c8d4890bb4..2625a7f300 100644 --- a/web/src/containers/TransactionsHistory/_TransactionsHistory.scss +++ b/web/src/containers/TransactionsHistory/_TransactionsHistory.scss @@ -159,8 +159,29 @@ } } .check-deposit-txt { - right: 150px !important; + right: 230px !important; + & svg { + padding-right: 0.3rem; + box-sizing: border-box; + border-right: 1px solid $trade-fill-indicator-text; + height: 100%; + } + } + + .download-history { + right: 85px !important; + & svg { + padding-right: 0.1rem; + box-sizing: content-box; + border-right: 1px solid $trade-fill-indicator-text; + height: 100%; + } } + + .refresh-history { + right: 10px !important; + } + .loader_wrapper { top: 0; left: 0; diff --git a/web/src/containers/TransactionsHistory/components/TradeAndOrderFilters.js b/web/src/containers/TransactionsHistory/components/TradeAndOrderFilters.js index 298418d098..8f284c4793 100644 --- a/web/src/containers/TransactionsHistory/components/TradeAndOrderFilters.js +++ b/web/src/containers/TransactionsHistory/components/TradeAndOrderFilters.js @@ -5,11 +5,12 @@ import moment from 'moment'; import { dateFilters } from '../filterUtils'; import STRINGS from '../../../config/localizedStrings'; +import { Image } from 'hollaex-web-lib'; const { Option } = Select; const { RangePicker } = DatePicker; -const Filters = ({ pairs, onSearch, formName, activeTab }) => { +const Filters = ({ pairs, onSearch, formName, activeTab, icons: ICONS }) => { const [form] = Form.useForm(); const [click, setClick] = useState([]); const [customSel, setCustomSel] = useState(false); @@ -149,16 +150,26 @@ const Filters = ({ pairs, onSearch, formName, activeTab }) => { width: 100, }} size="small" - className="custom-select-input-style elevated" + className="custom-select-input-style elevated filter-dropdown" dropdownClassName="custom-select-style" bordered={false} suffixIcon={<CaretDownOutlined />} > <Option value={null}>{STRINGS['ALL']}</Option> {Object.entries(pairs).map( - ([_, { name, pair_base_display, pair_2_display }]) => ( + ([_, { name, pair_base_display, pair_2_display, icon_id }]) => ( <Option key={name} value={name}> - {`${pair_base_display}-${pair_2_display}`} + <div className="d-flex filter-option"> + <Image + width="16px" + height="16px" + iconId={icon_id} + icon={ICONS[icon_id]} + wrapperClassName="coin-icons" + imageWrapperClassName="currency-ball-image-wrapper" + /> + <div>{`${pair_base_display}-${pair_2_display}`}</div> + </div> </Option> ) )} diff --git a/web/src/containers/TransactionsHistory/index.js b/web/src/containers/TransactionsHistory/index.js index 4c8a7e64e5..b0e052bcc6 100644 --- a/web/src/containers/TransactionsHistory/index.js +++ b/web/src/containers/TransactionsHistory/index.js @@ -44,6 +44,8 @@ import { import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; +import { STATIC_ICONS } from 'config/icons'; +import { Image } from 'hollaex-web-lib'; const GROUP_CLASSES = [...FLEX_CENTER_CLASSES, 'flex-column']; @@ -251,11 +253,12 @@ class TransactionsHistory extends Component { } generateFilters = () => { - const { pairs, coins } = this.props; + const { pairs, coins, icons } = this.props; this.setState({ filters: { orders: ( <TradeAndOrderFilters + icons={icons} pairs={pairs} onSearch={this.onSearch} formName="orders" @@ -264,6 +267,7 @@ class TransactionsHistory extends Component { ), trades: ( <TradeAndOrderFilters + icons={icons} pairs={pairs} onSearch={this.onSearch} formName="trades" @@ -272,6 +276,7 @@ class TransactionsHistory extends Component { ), deposits: ( <DepositAndWithdrawlFilters + icons={icons} coins={coins} onSearch={this.onSearch} formName="deposits" @@ -280,6 +285,7 @@ class TransactionsHistory extends Component { ), withdrawals: ( <DepositAndWithdrawlFilters + icons={icons} coins={coins} onSearch={this.onSearch} formName="withdrawals" @@ -415,6 +421,21 @@ class TransactionsHistory extends Component { withIcon: true, }; + const prepareNoData = (tab) => { + return ( + <div className="d-flex flex-column align-items-center"> + <Image + iconId={tab} + icon={STATIC_ICONS[tab]} + alt={tab} + width="40px" + height="40px" + /> + <span>{STRINGS[tab]}</span> + </div> + ); + }; + switch (activeTab) { case 1: props.stringId = 'ORDER_HISTORY'; @@ -427,6 +448,8 @@ class TransactionsHistory extends Component { props.jumpToPage = jumpToPage; props.handleDownload = () => downloadUserOrders(temp); props.filters = filters.orders; + props.noData = prepareNoData('NO_ACTIVE_ORDERS'); + props.refetchData = () => this.requestData(activeTab); break; case 0: props.stringId = 'TRANSACTION_HISTORY.TITLE_TRADES'; @@ -439,6 +462,8 @@ class TransactionsHistory extends Component { props.jumpToPage = jumpToPage; props.handleDownload = () => downloadUserTrades(temp); props.filters = filters.trades; + props.noData = prepareNoData('NO_ACTIVE_TRADES'); + props.refetchData = () => this.requestData(activeTab); break; case 2: props.stringId = 'TRANSACTION_HISTORY.TITLE_DEPOSITS'; @@ -450,6 +475,8 @@ class TransactionsHistory extends Component { props.jumpToPage = jumpToPage; props.handleDownload = () => downloadUserDeposit(temp); props.filters = filters.deposits; + props.noData = prepareNoData('NO_ACTIVE_DEPOSITS'); + props.refetchData = () => this.requestData(activeTab); break; case 3: props.stringId = 'TRANSACTION_HISTORY.TITLE_WITHDRAWALS'; @@ -461,6 +488,8 @@ class TransactionsHistory extends Component { props.jumpToPage = jumpToPage; props.handleDownload = () => downloadUserWithdrawal(temp); props.filters = filters.withdrawals; + props.noData = prepareNoData('NO_ACTIVE_WITHDRAWALS'); + props.refetchData = () => this.requestData(activeTab); break; default: return <div />; diff --git a/web/src/containers/TransactionsHistory/utils.js b/web/src/containers/TransactionsHistory/utils.js index 0c2f0c474c..27913392aa 100644 --- a/web/src/containers/TransactionsHistory/utils.js +++ b/web/src/containers/TransactionsHistory/utils.js @@ -5,16 +5,15 @@ import classnames from 'classnames'; import mathjs from 'mathjs'; import { isMobile } from 'react-device-detect'; -import STRINGS from '../../config/localizedStrings'; - -import { Image } from '../../components'; +import STRINGS from 'config/localizedStrings'; +import { Image } from 'components'; import { EXPLORERS_ENDPOINT, BASE_CURRENCY, CURRENCY_PRICE_FORMAT, DEFAULT_COIN_DATA, -} from '../../config/constants'; -import { getFormatTimestamp } from '../../utils/utils'; +} from 'config/constants'; +import { getFormatTimestamp } from 'utils/utils'; import { formatToCurrency, formatBaseAmount } from 'utils/currency'; notification.config({ diff --git a/web/src/containers/UserProfile/FeesBlock.js b/web/src/containers/UserProfile/FeesBlock.js index 18366e360e..0e075523c4 100644 --- a/web/src/containers/UserProfile/FeesBlock.js +++ b/web/src/containers/UserProfile/FeesBlock.js @@ -1,7 +1,7 @@ import React from 'react'; import classnames from 'classnames'; -import STRINGS from '../../config/localizedStrings'; -import { formatPercentage } from '../../utils/currency'; +import STRINGS from 'config/localizedStrings'; +import { formatPercentage } from 'utils/currency'; const FeeRow = ({ data = {}, headers = [], isUserLevel = false, row }) => { const { verification_level, ...rest } = data; diff --git a/web/src/containers/UserProfile/IdentificationFormValues.js b/web/src/containers/UserProfile/IdentificationFormValues.js index 022cdc1773..e2c0b532d6 100644 --- a/web/src/containers/UserProfile/IdentificationFormValues.js +++ b/web/src/containers/UserProfile/IdentificationFormValues.js @@ -1,8 +1,5 @@ -import { - COUNTRIES_OPTIONS, - NATIONAL_COUNTRY_VALUE, -} from '../../utils/countries'; -import STRINGS from '../../config/localizedStrings'; +import { COUNTRIES_OPTIONS, NATIONAL_COUNTRY_VALUE } from 'utils/countries'; +import STRINGS from 'config/localizedStrings'; import { isMobile } from 'react-device-detect'; export const generateFormValues = ( diff --git a/web/src/containers/UserProfile/InformationSection.js b/web/src/containers/UserProfile/InformationSection.js index 7aad3d93e5..e3fd6bc7fc 100644 --- a/web/src/containers/UserProfile/InformationSection.js +++ b/web/src/containers/UserProfile/InformationSection.js @@ -1,6 +1,6 @@ import React from 'react'; import Ionicon from 'react-ionicons'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; export const InformationSection = ({ text, onChangeValue, onChangeText }) => ( <div className="information_section d-flex flex-column"> diff --git a/web/src/containers/UserProfile/LevelsBlock.js b/web/src/containers/UserProfile/LevelsBlock.js index 7e44a27f2e..a564697a22 100644 --- a/web/src/containers/UserProfile/LevelsBlock.js +++ b/web/src/containers/UserProfile/LevelsBlock.js @@ -1,7 +1,7 @@ import React from 'react'; import classnames from 'classnames'; -import STRINGS from '../../config/localizedStrings'; -import { formatBaseAmount, formatBtcAmount } from '../../utils/currency'; +import STRINGS from 'config/localizedStrings'; +import { formatBaseAmount, formatBtcAmount } from 'utils/currency'; const getLimitValue = (limit = -1, format) => { if (limit === 0) { diff --git a/web/src/containers/UserProfile/MobileFormValues.js b/web/src/containers/UserProfile/MobileFormValues.js index f3bc7aa54e..cafee1fa07 100644 --- a/web/src/containers/UserProfile/MobileFormValues.js +++ b/web/src/containers/UserProfile/MobileFormValues.js @@ -1,5 +1,5 @@ -import { PHONE_OPTIONS } from '../../utils/countries'; -import STRINGS from '../../config/localizedStrings'; +import { PHONE_OPTIONS } from 'utils/countries'; +import STRINGS from 'config/localizedStrings'; import { isMobile } from 'react-device-detect'; export const generateFormValues = () => ({ diff --git a/web/src/containers/UserProfile/UpgradeWarning.js b/web/src/containers/UserProfile/UpgradeWarning.js index 0b2d38c639..a747686d15 100644 --- a/web/src/containers/UserProfile/UpgradeWarning.js +++ b/web/src/containers/UserProfile/UpgradeWarning.js @@ -1,5 +1,5 @@ import React from 'react'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; const UpgradeWarning = () => ( <div className="warning_text"> diff --git a/web/src/containers/UserProfile/index.js b/web/src/containers/UserProfile/index.js index bddffda618..da659f055e 100644 --- a/web/src/containers/UserProfile/index.js +++ b/web/src/containers/UserProfile/index.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { Accordion, Loader, Button } from '../../components'; +import { Accordion, Loader, Button } from 'components'; import Form from './Form'; import { generateFormValues as generateMobileFormValues } from './MobileFormValues'; import { @@ -10,8 +10,8 @@ import { } from './IdentificationFormValues'; import { InformationSection } from './InformationSection'; import { LevelSection } from './LevelSection'; -import { logout } from '../../actions/authAction'; -import STRINGS from '../../config/localizedStrings'; +import { logout } from 'actions/authAction'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import { isMobile } from 'react-device-detect'; import { openContactForm } from 'actions/appActions'; diff --git a/web/src/containers/UserSecurity/ApiKeyForm.js b/web/src/containers/UserSecurity/ApiKeyForm.js index a27ee06813..0059d4cdb2 100644 --- a/web/src/containers/UserSecurity/ApiKeyForm.js +++ b/web/src/containers/UserSecurity/ApiKeyForm.js @@ -1,8 +1,8 @@ import React from 'react'; -import STRINGS from '../../config/localizedStrings'; -import { getErrorLocalized } from '../../utils/errors'; -import renderFields from '../../components/Form/factoryFields'; -import { tokenKeyValidation } from '../../components/Form/validations'; +import STRINGS from 'config/localizedStrings'; +import { getErrorLocalized } from 'utils/errors'; +import renderFields from 'components/Form/factoryFields'; +import { tokenKeyValidation } from 'components/Form/validations'; import { reduxForm } from 'redux-form'; import { TYPE_GENERATE } from './ApiKeyModal'; diff --git a/web/src/containers/UserSecurity/ApiKeyHeaders.js b/web/src/containers/UserSecurity/ApiKeyHeaders.js index c38022ecf0..be93a06411 100644 --- a/web/src/containers/UserSecurity/ApiKeyHeaders.js +++ b/web/src/containers/UserSecurity/ApiKeyHeaders.js @@ -1,9 +1,9 @@ import React from 'react'; import Image from 'components/Image'; import classnames from 'classnames'; -import STRINGS from '../../config/localizedStrings'; -import { getFormatTimestamp } from '../../utils/utils'; -import { Tooltip } from '../../components'; +import STRINGS from 'config/localizedStrings'; +import { getFormatTimestamp } from 'utils/utils'; +import { Tooltip } from 'components'; import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons'; const NOT_REVOKED = 'pointer blue-link'; diff --git a/web/src/containers/UserSecurity/ChangePasswordForm.js b/web/src/containers/UserSecurity/ChangePasswordForm.js index 520b8f5046..6f77974961 100644 --- a/web/src/containers/UserSecurity/ChangePasswordForm.js +++ b/web/src/containers/UserSecurity/ChangePasswordForm.js @@ -2,19 +2,12 @@ import React from 'react'; import { reduxForm } from 'redux-form'; import { isMobile } from 'react-device-detect'; -import renderFields from '../../components/Form/factoryFields'; -import { Button } from '../../components'; -import { required, password } from '../../components/Form/validations'; +import renderFields from 'components/Form/factoryFields'; +import { Button, EditWrapper } from 'components'; +import STRINGS from 'config/localizedStrings'; -import STRINGS from '../../config/localizedStrings'; -import { EditWrapper } from 'components'; - -const validate = (values) => { +const validate = () => { const errors = {}; - if (values.new_password !== values.new_password_confirm) { - errors.new_password_confirm = STRINGS['VALIDATIONS.PASSWORDS_DONT_MATCH']; - } - return errors; }; @@ -23,7 +16,6 @@ export const generateFormValues = () => ({ type: 'password', stringId: 'ACCOUNT_SECURITY.CHANGE_PASSWORD.FORM.CURRENT_PASSWORD.label,ACCOUNT_SECURITY.CHANGE_PASSWORD.FORM.CURRENT_PASSWORD.placeholder', - validate: [required, password], label: STRINGS['ACCOUNT_SECURITY.CHANGE_PASSWORD.FORM.CURRENT_PASSWORD.label'], placeholder: @@ -37,7 +29,6 @@ export const generateFormValues = () => ({ type: 'password', stringId: 'ACCOUNT_SECURITY.CHANGE_PASSWORD.FORM.NEW_PASSWORD.label,ACCOUNT_SECURITY.CHANGE_PASSWORD.FORM.NEW_PASSWORD.placeholder', - validate: [required, password], label: STRINGS['ACCOUNT_SECURITY.CHANGE_PASSWORD.FORM.NEW_PASSWORD.label'], placeholder: STRINGS['ACCOUNT_SECURITY.CHANGE_PASSWORD.FORM.NEW_PASSWORD.placeholder'], @@ -48,7 +39,6 @@ export const generateFormValues = () => ({ type: 'password', stringId: 'ACCOUNT_SECURITY.CHANGE_PASSWORD.FORM.NEW_PASSWORD_REPEAT.label,ACCOUNT_SECURITY.CHANGE_PASSWORD.FORM.NEW_PASSWORD_REPEAT.placeholder', - validate: [required], label: STRINGS[ 'ACCOUNT_SECURITY.CHANGE_PASSWORD.FORM.NEW_PASSWORD_REPEAT.label' @@ -67,6 +57,7 @@ const Form = ({ submitting, pristine, error, + _error, valid, initialValues, formFields, @@ -74,6 +65,7 @@ const Form = ({ <form onSubmit={handleSubmit} className="change-password-form-wrapper"> <div className="change-password-form"> {renderFields(formFields)} + {_error && <div className="warning_text">{_error}</div>} {error && <div className="warning_text">{error}</div>} </div> <div className="d-flex justify-content-center mb-4"> diff --git a/web/src/containers/UserSecurity/DeveloperSection.js b/web/src/containers/UserSecurity/DeveloperSection.js index 813e2e33ab..f0ac5179cb 100644 --- a/web/src/containers/UserSecurity/DeveloperSection.js +++ b/web/src/containers/UserSecurity/DeveloperSection.js @@ -1,9 +1,9 @@ import React from 'react'; -import { MIN_LEVEL_FOR_TOKENS } from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; -import { FieldError } from '../../components/Form/FormFields/FieldWrapper'; +import { MIN_LEVEL_FOR_TOKENS } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; +import { FieldError } from 'components/Form/FormFields/FieldWrapper'; import ApiKeyContainer from './ApiKey'; -import DumbField from '../../components/Form/FormFields/DumbField'; +import DumbField from 'components/Form/FormFields/DumbField'; import { EditWrapper } from 'components'; const NoLevel = () => ( diff --git a/web/src/containers/UserSecurity/FreezeSection.js b/web/src/containers/UserSecurity/FreezeSection.js index 64702daf6e..75c6ab3f7b 100644 --- a/web/src/containers/UserSecurity/FreezeSection.js +++ b/web/src/containers/UserSecurity/FreezeSection.js @@ -1,7 +1,7 @@ import React from 'react'; -import { FieldError } from '../../components/Form/FormFields/FieldWrapper'; -import { Button } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +import { FieldError } from 'components/Form/FormFields/FieldWrapper'; +import { Button } from 'components'; +import STRINGS from 'config/localizedStrings'; export const FreezeSection = ({ handleSubmit }) => ( <div> diff --git a/web/src/containers/UserSecurity/OTP.js b/web/src/containers/UserSecurity/OTP.js index 85135b5c5c..6608c6bccd 100644 --- a/web/src/containers/UserSecurity/OTP.js +++ b/web/src/containers/UserSecurity/OTP.js @@ -1,10 +1,9 @@ import React from 'react'; -import { CheckboxButton, IconTitle } from '../../components'; +import { CheckboxButton, IconTitle, EditWrapper } from 'components'; import QRCode from 'qrcode.react'; import OTPForm from './OTPForm'; -import { EditWrapper } from 'components'; - -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; +import { Image } from 'hollaex-web-lib'; export const renderOTPForm = ( secret, @@ -88,20 +87,32 @@ export const OTP = ({ </div> )} </div> - <CheckboxButton - stringId="ACCOUNT_SECURITY.OTP.CONTENT.ENABLE,ACCOUNT_SECURITY.OTP.CONTENT.DISABLE" - label={ - STRINGS[ - `ACCOUNT_SECURITY.OTP.CONTENT.${otp_enabled ? 'DISABLE' : 'ENABLE'}` - ] - } - onClick={requestOTP} - disabled={data.requesting} - loading={data.requesting} - checked={otp_enabled} - icons={icons} - > - {children} - </CheckboxButton> + <div className="d-flex w-100 justify-content-center align-items-center mt-5"> + <CheckboxButton + stringId="ACCOUNT_SECURITY.OTP.CONTENT.ENABLE,ACCOUNT_SECURITY.OTP.CONTENT.DISABLE" + label={ + STRINGS[ + `ACCOUNT_SECURITY.OTP.CONTENT.${otp_enabled ? 'DISABLE' : 'ENABLE'}` + ] + } + onClick={requestOTP} + disabled={data.requesting} + loading={data.requesting} + checked={otp_enabled} + icons={icons} + customCheckIcon="SECURE" + > + {children} + </CheckboxButton> + {otp_enabled && ( + <Image + iconId={'SUCCESS_BLACK'} + icon={icons['SUCCESS_BLACK']} + wrapperClassName="OTP_Success ml-2" + width="20px" + height="20px" + /> + )} + </div> </div> ); diff --git a/web/src/containers/UserSecurity/OTPForm.js b/web/src/containers/UserSecurity/OTPForm.js index 0297aaa05d..f33d62aa41 100644 --- a/web/src/containers/UserSecurity/OTPForm.js +++ b/web/src/containers/UserSecurity/OTPForm.js @@ -1,10 +1,9 @@ import React from 'react'; import { reduxForm } from 'redux-form'; -import { required } from '../../components/Form/validations'; -import renderFields from '../../components/Form/factoryFields'; -import { Button } from '../../components'; -import STRINGS from '../../config/localizedStrings'; -import { EditWrapper } from 'components'; +import { required } from 'components/Form/validations'; +import renderFields from 'components/Form/factoryFields'; +import { Button, EditWrapper } from 'components'; +import STRINGS from 'config/localizedStrings'; const Form = ({ handleSubmit, submitting, pristine, error, valid }) => { const formFields = { diff --git a/web/src/containers/UserSecurity/_UserSecurity.scss b/web/src/containers/UserSecurity/_UserSecurity.scss index 56d97d4b97..d45e8798cd 100644 --- a/web/src/containers/UserSecurity/_UserSecurity.scss +++ b/web/src/containers/UserSecurity/_UserSecurity.scss @@ -11,6 +11,15 @@ } } +.OTP_Success { + width: 30px; + height: 30px; + svg { + width: 30px; + height: 30px; + } +} + .otp_form-wrapper { display: flex; flex-direction: column; @@ -215,6 +224,10 @@ $padding-input: 4rem; flex-direction: row; align-items: center; } + + .checkbutton-input-wrapper { + margin-top: 0px !important; + } } .layout-mobile { @@ -329,6 +342,7 @@ $padding-input: 4rem; .user-security-wrapper { .tab_controller-tabs { .tab_item { + transition: 0.3s; font-size: 12px !important; } } diff --git a/web/src/containers/UserSecurity/index.js b/web/src/containers/UserSecurity/index.js index edaaf3fcce..f340a1040b 100644 --- a/web/src/containers/UserSecurity/index.js +++ b/web/src/containers/UserSecurity/index.js @@ -35,9 +35,9 @@ import { DeveloperSection } from './DeveloperSection'; import { generateLogins } from './utils_logins'; import { RECORD_LIMIT } from './constants'; import LoginDisplay from './LoginDisplay'; -import { getUserLogins } from '../../actions/userAction'; +import { getUserLogins } from 'actions/userAction'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; // import { ICONS } from 'config/constants'; @@ -52,6 +52,7 @@ class UserVerification extends Component { activeTab: 0, jumpToPage: 0, freeze: false, + error: '', updatedPassword: {}, }; @@ -101,11 +102,17 @@ class UserVerification extends Component { prevProps.user.otp.requesting !== this.props.user.otp.requesting || prevProps.user.otp.activated !== this.props.user.otp.activated || prevProps.user.otp_enabled !== this.props.user.otp_enabled || + prevState.error !== this.state.error || prevProps.activeLanguage !== this.props.activeLanguage || this.state.activeTab !== prevState.activeTab ) { this.calculateTabs(this.props.user, this.state.activeTab); } + if (this.state.activeTab !== prevState.activeTab) { + this.setState({ + error: undefined, + }); + } if ( JSON.stringify(prevState.activeTab) !== JSON.stringify(this.state.activeTab) @@ -236,6 +243,7 @@ class UserVerification extends Component { ), content: activeTab === 1 && ( <ChangePasswordForm + _error={this.state.error} onSubmit={this.onSubmitChangePassword} formFields={formValues} /> @@ -381,16 +389,21 @@ class UserVerification extends Component { }); }; + setOtpModalsState = (values) => { + this.setState({ + dialogIsOpen: true, + modalText: undefined, + updatedPassword: { + old_password: values.old_password, + new_password: values.new_password, + }, + }); + }; + onSubmitChangePassword = (values) => { const { otp_enabled } = this.props.user; if (otp_enabled) { - this.setState({ - dialogIsOpen: true, - updatedPassword: { - old_password: values.old_password, - new_password: values.new_password, - }, - }); + this.setOtpModalsState(values); } else { return resetPassword({ old_password: values.old_password, @@ -449,6 +462,12 @@ class UserVerification extends Component { if (!_error) { message.error(STRINGS['CHANGE_PASSWORD_FAILED']); } + if (_error !== 'Invalid OTP Code') { + this.setState({ + dialogIsOpen: false, + error: _error, + }); + } throw new SubmissionError({ _error }); }); } else { diff --git a/web/src/containers/UserSecurity/utils_logins.js b/web/src/containers/UserSecurity/utils_logins.js index aec2a0f02a..59f501f975 100644 --- a/web/src/containers/UserSecurity/utils_logins.js +++ b/web/src/containers/UserSecurity/utils_logins.js @@ -1,6 +1,6 @@ import React from 'react'; -import { getFormatTimestamp } from '../../utils/utils'; -import STRINGS from '../../config/localizedStrings'; +import { getFormatTimestamp } from 'utils/utils'; +import STRINGS from 'config/localizedStrings'; export const generateLogins = () => { return [ diff --git a/web/src/containers/UserSettings/AudioForm.js b/web/src/containers/UserSettings/AudioForm.js index b7d3cb9487..12b4a3af13 100644 --- a/web/src/containers/UserSettings/AudioForm.js +++ b/web/src/containers/UserSettings/AudioForm.js @@ -1,10 +1,10 @@ import React, { Component } from 'react'; import { reduxForm } from 'redux-form'; -import renderFields from '../../components/Form/factoryFields'; -import { Button, IconTitle } from '../../components'; -import { getErrorLocalized } from '../../utils/errors'; -import STRINGS from '../../config/localizedStrings'; +import renderFields from 'components/Form/factoryFields'; +import { Button, IconTitle } from 'components'; +import { getErrorLocalized } from 'utils/errors'; +import STRINGS from 'config/localizedStrings'; import { DEFAULT_TOGGLE_OPTIONS } from 'config/options'; import { EditWrapper } from 'components'; diff --git a/web/src/containers/UserSettings/LanguageForm.js b/web/src/containers/UserSettings/LanguageForm.js index d9bb878a72..b1603d1864 100644 --- a/web/src/containers/UserSettings/LanguageForm.js +++ b/web/src/containers/UserSettings/LanguageForm.js @@ -1,13 +1,11 @@ import React, { Component } from 'react'; import { reduxForm } from 'redux-form'; import { isMobile } from 'react-device-detect'; - -import renderFields from '../../components/Form/factoryFields'; -import { Button, IconTitle } from '../../components'; -import { required } from '../../components/Form/validations'; -import { getErrorLocalized } from '../../utils/errors'; -import STRINGS from '../../config/localizedStrings'; -import { EditWrapper } from 'components'; +import renderFields from 'components/Form/factoryFields'; +import { Button, IconTitle, EditWrapper } from 'components'; +import { required } from 'components/Form/validations'; +import { getErrorLocalized } from 'utils/errors'; +import STRINGS from 'config/localizedStrings'; export const generateLanguageFormValues = (values = '') => { const langValues = STRINGS.SETTINGS_LANGUAGE_OPTIONS.filter((filterValue) => { diff --git a/web/src/containers/UserSettings/NotificationForm.js b/web/src/containers/UserSettings/NotificationForm.js index bf0202d138..d047a373f4 100644 --- a/web/src/containers/UserSettings/NotificationForm.js +++ b/web/src/containers/UserSettings/NotificationForm.js @@ -1,12 +1,11 @@ import React, { Component } from 'react'; import { reduxForm } from 'redux-form'; -import renderFields from '../../components/Form/factoryFields'; -import { Button, IconTitle } from '../../components'; -import { getErrorLocalized } from '../../utils/errors'; -import STRINGS from '../../config/localizedStrings'; +import renderFields from 'components/Form/factoryFields'; +import { Button, IconTitle, EditWrapper } from 'components'; +import { getErrorLocalized } from 'utils/errors'; +import STRINGS from 'config/localizedStrings'; import { DEFAULT_TOGGLE_OPTIONS } from 'config/options'; -import { EditWrapper } from 'components'; export const generateNotificationFormValues = () => ({ popup_order_confirmation: { diff --git a/web/src/containers/UserSettings/SetOrderPortfolio.js b/web/src/containers/UserSettings/SetOrderPortfolio.js index 3e58c1cf45..bcc7d8711f 100644 --- a/web/src/containers/UserSettings/SetOrderPortfolio.js +++ b/web/src/containers/UserSettings/SetOrderPortfolio.js @@ -1,15 +1,11 @@ import React from 'react'; import { reduxForm } from 'redux-form'; -import renderFields from '../../components/Form/factoryFields'; -import { getErrorLocalized } from '../../utils/errors'; -import { - required, - minValue, - maxValue, -} from '../../components/Form/validations'; -import { IconTitle, Button } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +import renderFields from 'components/Form/factoryFields'; +import { getErrorLocalized } from 'utils/errors'; +import { required, minValue, maxValue } from 'components/Form/validations'; +import { IconTitle, Button } from 'components'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; const fields = { diff --git a/web/src/containers/UserSettings/SettingsForm.js b/web/src/containers/UserSettings/SettingsForm.js index 3ec33ba18f..f665621135 100644 --- a/web/src/containers/UserSettings/SettingsForm.js +++ b/web/src/containers/UserSettings/SettingsForm.js @@ -1,17 +1,16 @@ import React, { Component } from 'react'; import { reduxForm } from 'redux-form'; import { isMobile } from 'react-device-detect'; -import renderFields from '../../components/Form/factoryFields'; -import { Button, IconTitle } from '../../components'; +import renderFields from 'components/Form/factoryFields'; +import { Button, IconTitle, EditWrapper } from 'components'; import { required, minValue, maxValue, step, -} from '../../components/Form/validations'; -import { getErrorLocalized } from '../../utils/errors'; -import STRINGS from '../../config/localizedStrings'; -import { EditWrapper } from 'components'; +} from 'components/Form/validations'; +import { getErrorLocalized } from 'utils/errors'; +import STRINGS from 'config/localizedStrings'; const orderbook_level_step = 1; const orderbook_level_min = 1; diff --git a/web/src/containers/UserSettings/UsernameForm.js b/web/src/containers/UserSettings/UsernameForm.js index 787619c81d..d3945f94e2 100644 --- a/web/src/containers/UserSettings/UsernameForm.js +++ b/web/src/containers/UserSettings/UsernameForm.js @@ -2,13 +2,12 @@ import React, { Component } from 'react'; import { reduxForm } from 'redux-form'; import { isMobile } from 'react-device-detect'; -import renderFields from '../../components/Form/factoryFields'; -import { FieldError } from '../../components/Form/FormFields/FieldWrapper'; -import { Button, IconTitle } from '../../components'; -import { required, username } from '../../components/Form/validations'; -import { getErrorLocalized } from '../../utils/errors'; -import STRINGS from '../../config/localizedStrings'; -import { EditWrapper } from 'components'; +import renderFields from 'components/Form/factoryFields'; +import { FieldError } from 'components/Form/FormFields/FieldWrapper'; +import { Button, IconTitle, EditWrapper } from 'components'; +import { required, username } from 'components/Form/validations'; +import { getErrorLocalized } from 'utils/errors'; +import STRINGS from 'config/localizedStrings'; export const generateUsernameFormValues = (disabled = false) => ({ username: { diff --git a/web/src/containers/UserSettings/index.js b/web/src/containers/UserSettings/index.js index 46b39591c4..e79d1ebe2e 100644 --- a/web/src/containers/UserSettings/index.js +++ b/web/src/containers/UserSettings/index.js @@ -12,13 +12,13 @@ import { openRiskPortfolioOrderWarning, closeNotification, } from 'actions/appActions'; -import { logout } from '../../actions/authAction'; +import { logout } from 'actions/authAction'; import { updateUserSettings, setUserData, setUsername, setUsernameStore, -} from '../../actions/userAction'; +} from 'actions/userAction'; import { IconTitle, HeaderSection, @@ -28,7 +28,8 @@ import { MobileTabBar, Loader, TabController, -} from '../../components'; + EditWrapper, +} from 'components'; import SettingsForm, { generateFormValues } from './SettingsForm'; import UsernameForm, { generateUsernameFormValues } from './UsernameForm'; import LanguageForm, { generateLanguageFormValues } from './LanguageForm'; @@ -38,9 +39,8 @@ import NotificationForm, { import AudioCueForm, { generateAudioCueFormValues } from './AudioForm'; import RiskForm, { generateWarningFormValues } from './RiskForm'; -import STRINGS from '../../config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; -import { EditWrapper } from 'components'; class UserSettings extends Component { state = { @@ -64,15 +64,30 @@ class UserSettings extends Component { } if (window.location.search && window.location.search.includes('signals')) { this.setState({ activeTab: 0 }); - } else if (window.location.search && window.location.search.includes('interface')) { + } else if ( + window.location.search && + window.location.search.includes('interface') + ) { this.setState({ activeTab: 1 }); - } else if (window.location.search && window.location.search.includes('language')) { + } else if ( + window.location.search && + window.location.search.includes('language') + ) { this.setState({ activeTab: 2 }); - } else if (window.location.search && window.location.search.includes('audioCue')) { + } else if ( + window.location.search && + window.location.search.includes('audioCue') + ) { this.setState({ activeTab: 3 }); - } else if (window.location.search && window.location.search.includes('manageRisk')) { + } else if ( + window.location.search && + window.location.search.includes('manageRisk') + ) { this.setState({ activeTab: 4 }); - } else if (window.location.search && window.location.search.includes('chat')) { + } else if ( + window.location.search && + window.location.search.includes('chat') + ) { this.setState({ activeTab: 5 }); } this.openCurrentTab(); @@ -80,7 +95,7 @@ class UserSettings extends Component { UNSAFE_componentWillReceiveProps(nextProps) { if (nextProps.activeLanguage !== this.props.activeLanguage) { - this.updateTabs(this.props, this.state.activeTab); + this.updateTabs(nextProps, this.state.activeTab); } if ( JSON.stringify(this.props.settings) !== JSON.stringify(nextProps.settings) @@ -112,7 +127,10 @@ class UserSettings extends Component { } componentDidUpdate(prevProps, prevState) { - if (JSON.stringify(prevState.activeTab) !== JSON.stringify(this.state.activeTab)) { + if ( + JSON.stringify(prevState.activeTab) !== + JSON.stringify(this.state.activeTab) + ) { this.openCurrentTab(); } } @@ -121,7 +139,8 @@ class UserSettings extends Component { let currentTab = ''; if (this.state.activeTab === 0) { currentTab = 'signals'; - } if (this.state.activeTab === 1) { + } + if (this.state.activeTab === 1) { currentTab = 'interface'; } else if (this.state.activeTab === 2) { currentTab = 'language'; @@ -142,7 +161,10 @@ class UserSettings extends Component { }); }; - updateTabs = ({ username = '', settings = {}, coins = {} }, activeTab) => { + updateTabs = ( + { activeLanguage = '', username = '', settings = {}, coins = {} }, + activeTab + ) => { const { constants = {}, icons: ICONS, @@ -250,7 +272,7 @@ class UserSettings extends Component { this.onSubmitSettings(formProps, 'language') } formFields={languageFormValue} - initialValues={{ language: settings.language }} + initialValues={{ language: activeLanguage }} ICONS={ICONS} /> ), @@ -381,8 +403,9 @@ class UserSettings extends Component { .then(({ data }) => { this.props.setUserData(data); if (data.settings) { - if (data.settings.language) + if (data.settings.language) { this.props.changeLanguage(data.settings.language); + } if (data.settings.interface && data.settings.interface.theme) { this.props.changeTheme(data.settings.interface.theme); localStorage.setItem('theme', data.settings.interface.theme); diff --git a/web/src/containers/Verification/DocumentsVerification.js b/web/src/containers/Verification/DocumentsVerification.js index a4d0f77867..8e949cbc3d 100644 --- a/web/src/containers/Verification/DocumentsVerification.js +++ b/web/src/containers/Verification/DocumentsVerification.js @@ -4,18 +4,18 @@ import moment from 'moment'; import { isBefore, requiredWithCustomMessage, -} from '../../components/Form/validations'; -import renderFields from '../../components/Form/factoryFields'; -import { Button, IconTitle, HeaderSection } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +} from 'components/Form/validations'; +import renderFields from 'components/Form/factoryFields'; +import { Button, IconTitle, HeaderSection } from 'components'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import { IdentificationFormSection, PORSection, SelfieWithPhotoId, } from './HeaderSection'; -import { getErrorLocalized } from '../../utils/errors'; -import { updateDocuments } from '../../actions/userAction'; +import { getErrorLocalized } from 'utils/errors'; +import { updateDocuments } from 'actions/userAction'; import Image from 'components/Image'; import { isMobile } from 'react-device-detect'; diff --git a/web/src/containers/Verification/DocumentsVerificationHome.js b/web/src/containers/Verification/DocumentsVerificationHome.js index 90831706b1..8035e7fd3b 100644 --- a/web/src/containers/Verification/DocumentsVerificationHome.js +++ b/web/src/containers/Verification/DocumentsVerificationHome.js @@ -3,9 +3,9 @@ import moment from 'moment'; import Image from 'components/Image'; import classnames from 'classnames'; -import { Button, PanelInformationRow } from '../../components'; -import STRINGS from '../../config/localizedStrings'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; +import { Button, PanelInformationRow } from 'components'; +import STRINGS from 'config/localizedStrings'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; import withConfig from 'components/ConfigProvider/withConfig'; import { EditWrapper } from 'components'; diff --git a/web/src/containers/Verification/IdentityVerification.js b/web/src/containers/Verification/IdentityVerification.js index d6e1fcb75e..7101c29d45 100644 --- a/web/src/containers/Verification/IdentityVerification.js +++ b/web/src/containers/Verification/IdentityVerification.js @@ -5,17 +5,15 @@ import { required, requiredBoolean, isBefore, -} from '../../components/Form/validations'; -import renderFields from '../../components/Form/factoryFields'; -import { Button, IconTitle, HeaderSection } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +} from 'components/Form/validations'; +import renderFields from 'components/Form/factoryFields'; +import { Button, IconTitle, HeaderSection, EditWrapper } from 'components'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; -import { COUNTRIES_OPTIONS } from '../../utils/countries'; - +import { COUNTRIES_OPTIONS } from 'utils/countries'; import { isMobile } from 'react-device-detect'; -import { getErrorLocalized } from '../../utils/errors'; -import { updateUser } from '../../actions/userAction'; -import { EditWrapper } from 'components'; +import { getErrorLocalized } from 'utils/errors'; +import { updateUser } from 'actions/userAction'; const FORM_NAME = 'IdentityVerification'; diff --git a/web/src/containers/Verification/IdentityVerificationHome.js b/web/src/containers/Verification/IdentityVerificationHome.js index 2501ab76c0..5195a2c434 100644 --- a/web/src/containers/Verification/IdentityVerificationHome.js +++ b/web/src/containers/Verification/IdentityVerificationHome.js @@ -1,9 +1,9 @@ import React from 'react'; -import { Button, PanelInformationRow } from '../../components'; +import { Button, PanelInformationRow } from 'components'; import { getCountry } from './utils'; -import STRINGS from '../../config/localizedStrings'; -import { getFormatTimestamp } from '../../utils/utils'; +import STRINGS from 'config/localizedStrings'; +import { getFormatTimestamp } from 'utils/utils'; import { EditWrapper } from 'components'; const formatBirthday = { diff --git a/web/src/containers/Verification/MobileVerification.js b/web/src/containers/Verification/MobileVerification.js index 9c35773441..e02d86d05d 100644 --- a/web/src/containers/Verification/MobileVerification.js +++ b/web/src/containers/Verification/MobileVerification.js @@ -8,23 +8,20 @@ import { } from 'redux-form'; import { isMobile } from 'react-device-detect'; -import { required } from '../../components/Form/validations'; -import renderFields from '../../components/Form/factoryFields'; +import { required } from 'components/Form/validations'; +import renderFields from 'components/Form/factoryFields'; import { Button, IconTitle, ElapsedTimer, HeaderSection, -} from '../../components'; -import STRINGS from '../../config/localizedStrings'; + EditWrapper, +} from 'components'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; -import { PHONE_OPTIONS } from '../../utils/countries'; -import { getErrorLocalized } from '../../utils/errors'; -import { - verifySmsCode, - requestSmsCode, -} from '../../actions/verificationActions'; -import { EditWrapper } from 'components'; +import { PHONE_OPTIONS } from 'utils/countries'; +import { getErrorLocalized } from 'utils/errors'; +import { verifySmsCode, requestSmsCode } from 'actions/verificationActions'; const FORM_NAME = 'MobileVerification'; let loadingTimeOut = ''; diff --git a/web/src/containers/Verification/MobileVerificationHome.js b/web/src/containers/Verification/MobileVerificationHome.js index 7a20cadda0..7111e4c69c 100644 --- a/web/src/containers/Verification/MobileVerificationHome.js +++ b/web/src/containers/Verification/MobileVerificationHome.js @@ -1,9 +1,7 @@ import React from 'react'; - import { getCountryFromNumber } from './utils'; -import { Button, PanelInformationRow } from '../../components'; -import STRINGS from '../../config/localizedStrings'; -import { EditWrapper } from 'components'; +import { Button, PanelInformationRow, EditWrapper } from 'components'; +import STRINGS from 'config/localizedStrings'; const MobileVerificationHome = ({ user, setActivePageContent }) => { const { phone_number } = user; diff --git a/web/src/containers/Verification/utils.js b/web/src/containers/Verification/utils.js index 4b0679eb45..79ebc7d817 100644 --- a/web/src/containers/Verification/utils.js +++ b/web/src/containers/Verification/utils.js @@ -65,8 +65,8 @@ export const documentInitialValues = ({ nationality, id_data = {} }) => { export const getCountry = (country) => { const filterValue = COUNTRIES.filter( ({ value, name }) => - value?.toUpperCase() === country.toUpperCase() || - name?.toUpperCase() === country.toUpperCase() + value?.toUpperCase() === country?.toUpperCase() || + name?.toUpperCase() === country?.toUpperCase() ); if (filterValue.length) return filterValue[0]; return initialCountry; diff --git a/web/src/containers/VerificationEmailCode/index.js b/web/src/containers/VerificationEmailCode/index.js index 519b7cabf3..2e234b2cea 100644 --- a/web/src/containers/VerificationEmailCode/index.js +++ b/web/src/containers/VerificationEmailCode/index.js @@ -6,11 +6,11 @@ import { isUUID } from 'validator'; import { verifyVerificationCode, checkVerificationCode, -} from '../../actions/authAction'; +} from 'actions/authAction'; -import { IconTitle, Loader, Button } from '../../components'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; +import { IconTitle, Loader, Button } from 'components'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; class VerifyEmailCode extends Component { diff --git a/web/src/containers/VerificationEmailRequest/EmailRequestForm.js b/web/src/containers/VerificationEmailRequest/EmailRequestForm.js index fb3361129a..a02835f4a8 100644 --- a/web/src/containers/VerificationEmailRequest/EmailRequestForm.js +++ b/web/src/containers/VerificationEmailRequest/EmailRequestForm.js @@ -4,9 +4,9 @@ import { requiredWithCustomMessage, email, normalizeEmail, -} from '../../components/Form/validations'; -import { AuthForm } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +} from 'components/Form/validations'; +import { AuthForm } from 'components'; +import STRINGS from 'config/localizedStrings'; export const generateFormFields = () => ({ email: { diff --git a/web/src/containers/VerificationEmailRequest/EmailRequestSuccess.js b/web/src/containers/VerificationEmailRequest/EmailRequestSuccess.js index 71e0844ee1..f375250225 100644 --- a/web/src/containers/VerificationEmailRequest/EmailRequestSuccess.js +++ b/web/src/containers/VerificationEmailRequest/EmailRequestSuccess.js @@ -1,9 +1,9 @@ import React from 'react'; import classnames from 'classnames'; -import { IconTitle, Button } from '../../components'; -import STRINGS from '../../config/localizedStrings'; +import { IconTitle, Button } from 'components'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; const EmailRequestSuccess = ({ onClick, icons: ICONS, ...rest }) => { return ( diff --git a/web/src/containers/VerificationEmailRequest/index.js b/web/src/containers/VerificationEmailRequest/index.js index b2bb56fdf9..57795bd28e 100644 --- a/web/src/containers/VerificationEmailRequest/index.js +++ b/web/src/containers/VerificationEmailRequest/index.js @@ -5,23 +5,31 @@ import { bindActionCreators } from 'redux'; import { Link } from 'react-router'; import { isMobile } from 'react-device-detect'; import { SubmissionError } from 'redux-form'; -import { requestVerificationEmail } from '../../actions/authAction'; +import { requestVerificationEmail } from 'actions/authAction'; import EmailRequestForm, { generateFormFields } from './EmailRequestForm'; import EmailRequestSuccess from './EmailRequestSuccess'; -import { IconTitle, Dialog, MobileBarBack } from '../../components'; -import { ContactForm } from '../'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; +import { IconTitle, Dialog, MobileBarBack } from 'components'; +import { ContactForm } from 'containers'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import { openContactForm } from 'actions/appActions'; const BottomLink = () => ( - <div className={classnames('f-1', 'link_wrapper')}> - {STRINGS['VERIFICATION_EMAIL_REQUEST.NO_EMAIL']} - <Link to="/verify" className={classnames('blue-link')}> - {STRINGS['VERIFICATION_EMAIL_REQUEST.REQUEST_EMAIL']} - </Link> - </div> + <> + <div className={classnames('f-1', 'link_wrapper')}> + {STRINGS['SIGN_UP.HAVE_ACCOUNT']} + <Link to="/login" className={classnames('blue-link')}> + {STRINGS['SIGN_UP.GOTO_LOGIN']} + </Link> + </div> + <div className={classnames('f-1', 'link_wrapper')}> + {STRINGS['LOGIN.NO_ACCOUNT']} + <Link to="/signup" className={classnames('blue-link')}> + {STRINGS['LOGIN.CREATE_ACCOUNT']} + </Link> + </div> + </> ); class VerifyEmailRequest extends Component { @@ -113,8 +121,9 @@ class VerifyEmailRequest extends Component { 'login_container' )} > - {isMobile && <MobileBarBack onBackClick={this.onGoBack} />} - + {isMobile && !showContactForm && ( + <MobileBarBack onBackClick={this.onGoBack} /> + )} <div className={classnames( ...FLEX_CENTER_CLASSES, @@ -124,16 +133,6 @@ class VerifyEmailRequest extends Component { 'w-100' )} > - <IconTitle - iconId="EXCHANGE_LOGO" - iconPath={ICONS['EXCHANGE_LOGO']} - stringId="VERIFICATION_EMAIL_REQUEST.TITLE" - text={STRINGS['VERIFICATION_EMAIL_REQUEST.TITLE']} - textType="title" - underline={true} - imageWrapperClassName="auth_logo-wrapper" - className="w-100 holla-logo" - /> <div className={classnames( ...FLEX_CENTER_CLASSES, @@ -143,6 +142,23 @@ class VerifyEmailRequest extends Component { 'w-100' )} > + <IconTitle + iconId="EXCHANGE_LOGO" + iconPath={ICONS['EXCHANGE_LOGO']} + stringId="VERIFICATION_EMAIL_REQUEST.TITLE" + text={STRINGS['VERIFICATION_EMAIL_REQUEST.TITLE']} + textType="title" + underline={true} + imageWrapperClassName="auth_logo-wrapper" + className="w-100 holla-logo" + subtitle={STRINGS['VERIFICATION_EMAIL_REQUEST.SUBTITLE']} + actionProps={{ + text: STRINGS['VERIFICATION_EMAIL_REQUEST.SUPPORT'], + iconPath: ICONS['BLUE_QUESTION'], + onClick: openContactForm, + useSvg: true, + }} + /> <EmailRequestForm onSubmit={this.onSubmitEmailRequest} formFields={formFields} diff --git a/web/src/containers/Wallet/AssetsBlock.js b/web/src/containers/Wallet/AssetsBlock.js index 9b99c555b6..f34667e8aa 100644 --- a/web/src/containers/Wallet/AssetsBlock.js +++ b/web/src/containers/Wallet/AssetsBlock.js @@ -208,7 +208,15 @@ const AssetsBlock = ({ <tbody> {sortedSearchResults.map( ( - [key, { min, allow_deposit, allow_withdrawal, oraclePrice }], + [ + key, + { + increment_unit, + allow_deposit, + allow_withdrawal, + oraclePrice, + }, + ], index ) => { const balanceValue = balance[`${key}_balance`]; @@ -227,10 +235,10 @@ const AssetsBlock = ({ const baseCoin = coins[BASE_CURRENCY] || DEFAULT_COIN_DATA; const balanceText = key === BASE_CURRENCY - ? formatToCurrency(balanceValue, min) + ? formatToCurrency(balanceValue, increment_unit) : formatToCurrency( calculateOraclePrice(balanceValue, oraclePrice), - baseCoin.min + baseCoin.increment_unit ); return ( <tr className="table-row table-bottom-border" key={key}> @@ -245,7 +253,7 @@ const AssetsBlock = ({ </td> <td className="td-name td-fit"> {sortedSearchResults && loading ? ( - <div className="d-flex align-items-center"> + <div className="d-flex align-items-center wallet-hover cursor-pointer"> <Link to={`/wallet/${key.toLowerCase()}`}> <Image iconId={icon_id} @@ -268,12 +276,15 @@ const AssetsBlock = ({ )} </td> <td className="td-amount"> - {sortedSearchResults && baseCoin && loading ? ( + {sortedSearchResults && + baseCoin && + loading && + increment_unit ? ( <div className="d-flex"> <div className="mr-4"> {STRINGS.formatString( CURRENCY_PRICE_FORMAT, - formatToCurrency(balanceValue, min, true), + formatToCurrency(balanceValue, increment_unit), display_name )} </div> @@ -301,7 +312,7 @@ const AssetsBlock = ({ stringId="WALLET_BUTTON_BASE_DEPOSIT" text={STRINGS['WALLET_BUTTON_BASE_DEPOSIT']} iconId="BLUE_PLUS" - iconPath={ICONS['BLUE_PLUS']} + iconPath={ICONS['BLUE_DEPOSIT_ICON']} onClick={() => navigate(`wallet/${key}/deposit`)} className="csv-action action-button-wrapper" showActionText={isMobile} @@ -311,7 +322,7 @@ const AssetsBlock = ({ stringId="WALLET_BUTTON_BASE_WITHDRAW" text={STRINGS['WALLET_BUTTON_BASE_WITHDRAW']} iconId="BLUE_PLUS" - iconPath={ICONS['BLUE_PLUS']} + iconPath={ICONS['BLUE_WITHROW_ICON']} onClick={() => navigate(`wallet/${key}/withdraw`)} className="csv-action action-button-wrapper" showActionText={isMobile} @@ -324,8 +335,8 @@ const AssetsBlock = ({ <ActionNotification stringId="TRADE_TAB_TRADE" text={STRINGS['TRADE_TAB_TRADE']} - iconId="BLUE_PLUS" - iconPath={ICONS['BLUE_PLUS']} + iconId="BLUE_TRADE_ICON" + iconPath={ICONS['BLUE_TRADE_ICON']} onClick={() => goToTrade(pair)} className="csv-action" showActionText={isMobile} @@ -338,8 +349,8 @@ const AssetsBlock = ({ <ActionNotification stringId="STAKE.EARN" text={STRINGS['STAKE.EARN']} - iconId="BLUE_PLUS" - iconPath={ICONS['BLUE_PLUS']} + iconId="BLUE_EARN_ICON" + iconPath={ICONS['BLUE_EARN_ICON']} onClick={() => navigate('/stake')} className="csv-action" showActionText={isMobile} diff --git a/web/src/containers/Wallet/CurrencyWallet.js b/web/src/containers/Wallet/CurrencyWallet.js index 2d3fcfe08e..e74b81359a 100644 --- a/web/src/containers/Wallet/CurrencyWallet.js +++ b/web/src/containers/Wallet/CurrencyWallet.js @@ -9,14 +9,14 @@ import { ActionNotification, MobileBarBack, Image, -} from '../../components'; -import { FLEX_CENTER_CLASSES, DEFAULT_COIN_DATA } from '../../config/constants'; +} from 'components'; +import { FLEX_CENTER_CLASSES, DEFAULT_COIN_DATA } from 'config/constants'; import { formatToCurrency, generateWalletActionsText, getCurrencyFromName, -} from '../../utils/currency'; -import STRINGS from '../../config/localizedStrings'; +} from 'utils/currency'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import { STATIC_ICONS } from 'config/icons'; @@ -74,8 +74,8 @@ class Wallet extends Component { iconId={icon_id} icon={ICONS[icon_id]} wrapperClassName="coin-icons" - width='32px' - height='32px' + width="32px" + height="32px" imageWrapperClassName="currency-ball-image-wrapper" /> <div className="with_price-block_amount-value"> diff --git a/web/src/containers/Wallet/MainWallet.js b/web/src/containers/Wallet/MainWallet.js index e02e97f302..f03a6e752e 100644 --- a/web/src/containers/Wallet/MainWallet.js +++ b/web/src/containers/Wallet/MainWallet.js @@ -139,11 +139,12 @@ class Wallet extends Component { { features: { stake_page = false } = {} } = {}, contracts = {} ) => { - const { min, display_name } = coins[BASE_CURRENCY] || DEFAULT_COIN_DATA; + const { increment_unit, display_name } = + coins[BASE_CURRENCY] || DEFAULT_COIN_DATA; const totalAssets = STRINGS.formatString( CURRENCY_PRICE_FORMAT, display_name, - formatToCurrency(total, min) + formatToCurrency(total, increment_unit) ); const searchResult = this.getSearchResult(coins, balance, oraclePrices); @@ -182,7 +183,7 @@ class Wallet extends Component { text: STRINGS['TRADE_HISTORY'], status: 'information', iconId: 'PAPER_CLIP', - iconPath: STATIC_ICONS['PAPER_CLIP'], + iconPath: STATIC_ICONS['CLOCK'], allowClick: true, className: isOpen ? 'paper-clip-icon' diff --git a/web/src/containers/Wallet/_Wallet.scss b/web/src/containers/Wallet/_Wallet.scss index 147710c275..7f0d7a527d 100644 --- a/web/src/containers/Wallet/_Wallet.scss +++ b/web/src/containers/Wallet/_Wallet.scss @@ -2,6 +2,10 @@ $wrapper-border: 1px solid $colors-main-black; $wrapper-button-margin: 2.5rem; $header-margin: 2rem; +.wallet-hover:hover { + opacity: 0.5; +} + .layout-mobile { .button-container { min-height: 4.5rem; diff --git a/web/src/containers/Withdraw/ReviewEmailContent.js b/web/src/containers/Withdraw/ReviewEmailContent.js index 5977d68649..29a65a7abb 100644 --- a/web/src/containers/Withdraw/ReviewEmailContent.js +++ b/web/src/containers/Withdraw/ReviewEmailContent.js @@ -1,8 +1,6 @@ import React from 'react'; -import { Button, IconTitle } from '../../components'; -import { EditWrapper } from 'components'; - -import STRINGS from '../../config/localizedStrings'; +import { Button, IconTitle, EditWrapper } from 'components'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; const ReviewEmailContent = ({ onConfirmEmail, icons: ICONS }) => { diff --git a/web/src/containers/Withdraw/ReviewModalContent.js b/web/src/containers/Withdraw/ReviewModalContent.js index 194efd3ebc..092f897111 100644 --- a/web/src/containers/Withdraw/ReviewModalContent.js +++ b/web/src/containers/Withdraw/ReviewModalContent.js @@ -49,7 +49,7 @@ const ReviewModalContent = ({ const fee_type = data.fee_type ? data.fee_type : ''; const isPercentage = fee_type === 'percentage'; const hasDifferentFeeCoin = - !isPercentage && fee_coin && fee_coin !== currency; + !isPercentage && !!fee_coin && fee_coin !== currency; let min_fee; let max_fee; @@ -76,7 +76,7 @@ const ReviewModalContent = ({ const feePrice = math.number(math.multiply(fee, price)); - const totalTransaction = hasDifferentFeeCoin + const totalTransaction = !!hasDifferentFeeCoin ? math.number(math.fraction(data.amount)) : math.number(math.add(math.fraction(data.amount), fee)); @@ -89,7 +89,7 @@ const ReviewModalContent = ({ const { display_name: fee_coin_display } = coins[fee_coin] || DEFAULT_COIN_DATA; - const withdrawFeeMessage = hasDifferentFeeCoin + const withdrawFeeMessage = !!hasDifferentFeeCoin ? STRINGS.formatString( STRINGS['WITHDRAW_PAGE.MESSAGE_FEE_COIN'], STRINGS.formatString(CURRENCY_PRICE_FORMAT, fee, fee_coin_display) diff --git a/web/src/containers/WithdrawConfirmation/index.js b/web/src/containers/WithdrawConfirmation/index.js index 1986f78aea..af92e35ebd 100644 --- a/web/src/containers/WithdrawConfirmation/index.js +++ b/web/src/containers/WithdrawConfirmation/index.js @@ -1,10 +1,10 @@ import React, { Component } from 'react'; import classnames from 'classnames'; -import { IconTitle, Button, Loader } from '../../components'; -import { performConfirmWithdrawal } from '../../actions/walletActions'; -import { FLEX_CENTER_CLASSES } from '../../config/constants'; -import STRINGS from '../../config/localizedStrings'; +import { IconTitle, Button, Loader } from 'components'; +import { performConfirmWithdrawal } from 'actions/walletActions'; +import { FLEX_CENTER_CLASSES } from 'config/constants'; +import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import { EditWrapper } from 'components'; diff --git a/web/src/containers/_containers.scss b/web/src/containers/_containers.scss index b3a47b0043..4b015bbec5 100644 --- a/web/src/containers/_containers.scss +++ b/web/src/containers/_containers.scss @@ -26,3 +26,4 @@ @import './ConfirmChangePassword/ConfirmChangePassword'; @import './StakeDetails/StakeDetails'; @import './Stake/Stake'; +@import './Apps/Apps'; diff --git a/web/src/containers/index.js b/web/src/containers/index.js index 0d72f6f0d3..202c8176ec 100644 --- a/web/src/containers/index.js +++ b/web/src/containers/index.js @@ -31,6 +31,8 @@ export { default as TermsOfService } from './TermsOfService'; export { default as DepositFunds } from './TermsOfService/DepositFunds'; export { default as Stake } from './Stake'; export { default as StakeDetails } from './StakeDetails'; +export { default as Apps } from './Apps'; +export { default as AppDetails } from './AppDetails'; // ADMIN PAGE export { default as AdminDashboard } from './Admin/Dashboard'; @@ -64,3 +66,4 @@ export { default as Roles } from './Admin/Roles'; export { default as Resources } from './Admin/Resources'; export { default as Pairs } from './Admin/Trades'; export { default as Fiatmarkets } from './Admin/Fiat'; +export { default as AdminApps } from './Admin/Apps'; diff --git a/web/src/helpers/boot.js b/web/src/helpers/boot.js new file mode 100644 index 0000000000..3f3970f6e1 --- /dev/null +++ b/web/src/helpers/boot.js @@ -0,0 +1,36 @@ +import ThemeBuilder from 'helpers/themeBuilder'; +import { defaultIconsKey } from 'utils/icon'; + +const getBooting = () => { + return document.querySelector('.app-booting'); +}; + +const getRoot = () => { + return document.getElementById('root'); +}; + +const getLoadingImage = () => { + return document.getElementById('app-booting-image'); +}; + +export const setLoadingImage = ({ icons }) => { + const theme = localStorage.getItem('theme'); + getLoadingImage().src = + (icons[theme] && icons[theme]['EXCHANGE_LOADER']) || + icons[defaultIconsKey]['EXCHANGE_LOADER']; +}; + +export const setLoadingStyle = ({ color: themes }) => { + const theme = localStorage.getItem('theme'); + ThemeBuilder(theme, themes); +}; + +export const showBooting = () => { + getBooting().style.display = 'flex'; + getRoot().style.display = 'none'; +}; + +export const hideBooting = () => { + getBooting().style.display = 'none'; + getRoot().style.display = 'block'; +}; diff --git a/web/src/index.css b/web/src/index.css index 4ead8902b4..0d66afa8f7 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -165,6 +165,9 @@ table th { .blue-link { color: var(--specials_buttons-links-and-highlights) !important; } +.blue-link:hover { + opacity: 0.5; } + .arrow { border: solid grey; border-width: 0 3px 3px 0; @@ -253,9 +256,30 @@ table th { .custom-select-style.ant-select-dropdown { background-color: var(--base_background); } +.filter-option { + gap: 1rem; } + .filter-option .coin-icons { + width: 13px !important; + height: 13px !important; } + .filter-option .currency-ball-image-wrapper { + width: 13px; + height: 13px; } + +.filter-dropdown { + width: 150px !important; } + .custom-select-input-style.no-border .ant-select-selector { border: none !important; } +.custom-select-input-style .coin-icons { + width: 16px; + height: 16px; } + +.custom-select-input-style .currency-ball-image-wrapper { + width: 16px; + height: 16px; + margin-right: 15px; } + .custom-select-input-style .ant-select-selector { border-radius: 0.35rem !important; border-color: var(--calculated_important-border) !important; @@ -344,6 +368,9 @@ table th { .inline-flex { display: inline-flex !important; } +.no-wrap { + white-space: nowrap !important; } + .app_container { min-height: 100vh; background-color: var(--base_background); @@ -362,8 +389,8 @@ table th { height: auto; flex: 1; } .app_container.layout-mobile .app_container-content { - min-height: calc( 100vh - 10rem); - max-height: calc( 100vh - 10rem); + min-height: calc( 100vh - 10rem); + max-height: calc( 100vh - 10rem); max-width: 100vw; overflow-y: scroll; } .app_container.layout-mobile .app_container-content.chart-embed { @@ -376,11 +403,13 @@ table th { max-height: calc(100vh); max-width: 100vw; overflow-y: scroll; } - .app_container.layout-mobile .app_container-content .app_container-main.no_bottom_navigation { - height: 100%; } + .app_container.layout-mobile .app_container-content .app_container-main { + transition: 0.3s; } + .app_container.layout-mobile .app_container-content .app_container-main.no_bottom_navigation { + height: 100%; } .app_container.layout-mobile .content-with-bar { - min-height: calc( 100vh - 17rem); - max-height: calc( 100vh - 17rem); + min-height: calc( 100vh - 17rem); + max-height: calc( 100vh - 17rem); max-width: 100vw; padding: 1rem; margin: 0; @@ -841,6 +870,13 @@ table th { .user_security-wrapper > *:not(:last-child) { margin-bottom: 2rem; } +.OTP_Success { + width: 30px; + height: 30px; } + .OTP_Success svg { + width: 30px; + height: 30px; } + .otp_form-wrapper { display: flex; flex-direction: column; @@ -974,6 +1010,9 @@ table th { flex-direction: row; align-items: center; } +.user-security-container .checkbutton-input-wrapper { + margin-top: 0px !important; } + .layout-mobile .user_security-wrapper .warning_text { font-size: 13px !important; } @@ -1037,6 +1076,7 @@ table th { .change-password-form-wrapper .change-password-form .input_field-input::placeholder { font-size: 12px; } .user-security-wrapper .tab_controller-tabs .tab_item { + transition: 0.3s; font-size: 12px !important; } } .edit_token.overlay { @@ -1404,7 +1444,8 @@ table th { display: flex; justify-content: center; align-items: center; - background-color: var(--base_wallet-sidebar-and-popup); + background-color: transparent; + border-bottom: 1px var(--calculated_secondary-border) solid; opacity: 0.8; } .html_card_section .card-section-wrapper { display: flex; @@ -1516,6 +1557,9 @@ table th { .home_container .html_card_section .card-section-wrapper .card-section .header_txt { font-size: 14px; } } +.wallet-hover:hover { + opacity: 0.5; } + .layout-mobile .button-container { min-height: 4.5rem; } @@ -1981,6 +2025,9 @@ table th { .transaction-history-wrapper .ant-radio-button-wrapper:active, .transaction-history-wrapper .ant-radio-button-wrapper:hover { color: var(--labels_important-active-labels-text-graphics); } +.transaction-history-wrapper #trades-filters_size * { + transition: 0.2s; } + .transaction-history-wrapper .ant-radio-button-wrapper-checked::before, .transaction-history-wrapper .ant-radio-button-wrapper::before { background-color: transparent !important; } @@ -2180,7 +2227,21 @@ table th { border-radius: 20px; margin-right: 10px; } .history_block-wrapper .check-deposit-txt { - right: 150px !important; } + right: 230px !important; } + .history_block-wrapper .check-deposit-txt svg { + padding-right: 0.3rem; + box-sizing: border-box; + border-right: 1px solid var(--labels_secondary-inactive-label-text-graphics); + height: 100%; } + .history_block-wrapper .download-history { + right: 85px !important; } + .history_block-wrapper .download-history svg { + padding-right: 0.1rem; + box-sizing: content-box; + border-right: 1px solid var(--labels_secondary-inactive-label-text-graphics); + height: 100%; } + .history_block-wrapper .refresh-history { + right: 10px !important; } .history_block-wrapper .loader_wrapper { top: 0; left: 0; } @@ -3238,8 +3299,8 @@ table th { .layout-mobile .quote-container { background-color: transparent; overflow-y: scroll; - min-height: calc( 100vh - 17rem); - max-height: calc( 100vh - 17rem); } + min-height: calc( 100vh - 17rem); + max-height: calc( 100vh - 17rem); } .layout-mobile .quote-container .quick_trade-wrapper { flex: 1 1; min-width: 95vw !important; @@ -3393,7 +3454,7 @@ table th { .layout-mobile .presentation_container.verification_container { padding-top: 0 !important; - max-height: calc( 100vh - 10rem); } + max-height: calc( 100vh - 10rem); } .layout-mobile .presentation_container.verification_container .header-content { font-size: 13px !important; } @@ -3762,36 +3823,38 @@ table th { margin-bottom: 8px; } .summary-container .assets-wrapper .coin-price-container .coin-price { width: 3rem; } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .btc0, - .summary-container .assets-wrapper .coin-price-container .coin-price svg .btc1 { - fill: var(--coin-btc); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .eth0, - .summary-container .assets-wrapper .coin-price-container .coin-price svg .eth1 { - fill: var(--coin-eth); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .bch-icon { - fill: var(--coin-bch); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .xrp-icon { - fill: var(--coin-xrp); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .xmr-icon { - fill: var(--coin-xmr); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .ada-icon { - fill: var(--coin-ada); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .bnb-icon { - fill: var(--coin-bnb); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .dai-icon { - fill: var(--coin-dai); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .eos-icon { - fill: var(--coin-eos); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .ltc-icon { - fill: var(--coin-ltc); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .trx-icon { - fill: var(--coin-trx); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .tusd-icon { - fill: var(--coin-tusd); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .xlm-icon { - fill: var(--coin-xlm); } - .summary-container .assets-wrapper .coin-price-container .coin-price svg .default-icon { - fill: var(--labels_secondary-inactive-label-text-graphics) !important; } + .summary-container .assets-wrapper .coin-price-container .coin-price svg { + width: 2.5rem; } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .btc0, + .summary-container .assets-wrapper .coin-price-container .coin-price svg .btc1 { + fill: var(--coin-btc); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .eth0, + .summary-container .assets-wrapper .coin-price-container .coin-price svg .eth1 { + fill: var(--coin-eth); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .bch-icon { + fill: var(--coin-bch); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .xrp-icon { + fill: var(--coin-xrp); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .xmr-icon { + fill: var(--coin-xmr); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .ada-icon { + fill: var(--coin-ada); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .bnb-icon { + fill: var(--coin-bnb); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .dai-icon { + fill: var(--coin-dai); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .eos-icon { + fill: var(--coin-eos); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .ltc-icon { + fill: var(--coin-ltc); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .trx-icon { + fill: var(--coin-trx); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .tusd-icon { + fill: var(--coin-tusd); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .xlm-icon { + fill: var(--coin-xlm); } + .summary-container .assets-wrapper .coin-price-container .coin-price svg .default-icon { + fill: var(--labels_secondary-inactive-label-text-graphics) !important; } .summary-container .asset_wrapper_width { width: 100%; } .summary-container .xht_asset_wrapper_width { @@ -4096,36 +4159,39 @@ table th { .market-list__container .market-list__block .market-list__coin-icons { width: 2.8rem; margin: 0.3rem 0.3rem 0 0.3rem; } - .market-list__container .market-list__block .market-list__coin-icons svg .btc0, - .market-list__container .market-list__block .market-list__coin-icons svg .btc1 { - fill: var(--coin-btc); } - .market-list__container .market-list__block .market-list__coin-icons svg .eth0, - .market-list__container .market-list__block .market-list__coin-icons svg .eth1 { - fill: var(--coin-eth); } - .market-list__container .market-list__block .market-list__coin-icons svg .bch-icon { - fill: var(--coin-bch); } - .market-list__container .market-list__block .market-list__coin-icons svg .xrp-icon { - fill: var(--coin-xrp); } - .market-list__container .market-list__block .market-list__coin-icons svg .xmr-icon { - fill: var(--coin-xmr); } - .market-list__container .market-list__block .market-list__coin-icons svg .ada-icon { - fill: var(--coin-ada); } - .market-list__container .market-list__block .market-list__coin-icons svg .bnb-icon { - fill: var(--coin-bnb); } - .market-list__container .market-list__block .market-list__coin-icons svg .dai-icon { - fill: var(--coin-dai); } - .market-list__container .market-list__block .market-list__coin-icons svg .eos-icon { - fill: var(--coin-eos); } - .market-list__container .market-list__block .market-list__coin-icons svg .ltc-icon { - fill: var(--coin-ltc); } - .market-list__container .market-list__block .market-list__coin-icons svg .trx-icon { - fill: var(--coin-trx); } - .market-list__container .market-list__block .market-list__coin-icons svg .tusd-icon { - fill: var(--coin-tusd); } - .market-list__container .market-list__block .market-list__coin-icons svg .xlm-icon { - fill: var(--coin-xlm); } - .market-list__container .market-list__block .market-list__coin-icons svg .default-icon { - fill: var(--labels_secondary-inactive-label-text-graphics) !important; } + .market-list__container .market-list__block .market-list__coin-icons svg { + width: 2.5rem !important; + height: 2.5rem !important; } + .market-list__container .market-list__block .market-list__coin-icons svg .btc0, + .market-list__container .market-list__block .market-list__coin-icons svg .btc1 { + fill: var(--coin-btc); } + .market-list__container .market-list__block .market-list__coin-icons svg .eth0, + .market-list__container .market-list__block .market-list__coin-icons svg .eth1 { + fill: var(--coin-eth); } + .market-list__container .market-list__block .market-list__coin-icons svg .bch-icon { + fill: var(--coin-bch); } + .market-list__container .market-list__block .market-list__coin-icons svg .xrp-icon { + fill: var(--coin-xrp); } + .market-list__container .market-list__block .market-list__coin-icons svg .xmr-icon { + fill: var(--coin-xmr); } + .market-list__container .market-list__block .market-list__coin-icons svg .ada-icon { + fill: var(--coin-ada); } + .market-list__container .market-list__block .market-list__coin-icons svg .bnb-icon { + fill: var(--coin-bnb); } + .market-list__container .market-list__block .market-list__coin-icons svg .dai-icon { + fill: var(--coin-dai); } + .market-list__container .market-list__block .market-list__coin-icons svg .eos-icon { + fill: var(--coin-eos); } + .market-list__container .market-list__block .market-list__coin-icons svg .ltc-icon { + fill: var(--coin-ltc); } + .market-list__container .market-list__block .market-list__coin-icons svg .trx-icon { + fill: var(--coin-trx); } + .market-list__container .market-list__block .market-list__coin-icons svg .tusd-icon { + fill: var(--coin-tusd); } + .market-list__container .market-list__block .market-list__coin-icons svg .xlm-icon { + fill: var(--coin-xlm); } + .market-list__container .market-list__block .market-list__coin-icons svg .default-icon { + fill: var(--labels_secondary-inactive-label-text-graphics) !important; } .market-list__container .market-list__block .market-list__block-table { width: 100%; @@ -4253,6 +4319,8 @@ table th { margin: 0.5rem 0; padding: 0 0.5rem; text-transform: uppercase; } + .trade_tabs-container .trade_tabs-link:hover { + opacity: 0.5; } .trade_tabs-container .link-separator { border-right: 1px solid var(--calculated_secondary-border); } .trade_tabs-container .trade_tabs-search-field { @@ -5302,6 +5370,8 @@ table th { border-radius: 0.5rem; margin: 1rem 0.5rem; font-weight: bold; } + .staking-account__connect:hover { + opacity: 0.8; } .chart_mine { fill-opacity: 0.7; @@ -5391,6 +5461,25 @@ table th { .area-disabled { opacity: 0.5; } +.add-app-button { + border-radius: 24px; + height: 24px !important; + min-width: 70px !important; + width: auto !important; + text-transform: none !important; } + +.apps-form .ant-input { + color: var(--labels_important-active-labels-text-graphics); } + +.apps-form .ant-input-clear-icon { + color: var(--labels_secondary-inactive-label-text-graphics); } + +.action_notification-wrapper.remove-action { + position: relative !important; } + +.apps-table-check { + width: 2rem !important; } + .sidebar-row { min-height: 3rem; min-width: 10rem; } @@ -5488,6 +5577,7 @@ table th { .layout-mobile .tab_controller-tabs, .layout-mobile .tab_item { + transition: 0.3s; font-size: 1.5rem !important; } .tab_controller-tabs { @@ -5533,8 +5623,7 @@ table th { height: 0.5px; opacity: 0.7; } .modal-market-menu .app-bar-search-field { - flex-direction: row; - padding-left: 0.5rem; } + flex-direction: row; } .modal-market-menu .app-bar-add-tab-search { height: 4rem; } .modal-market-menu .app-bar-tab-menu-list { @@ -5556,7 +5645,7 @@ table th { padding: 0.3rem 0; } .modal-market-menu .app-bar-add-tab-content .scroll-view { overflow-y: auto; - height: calc( 100vh - 19rem - 8rem); } + height: calc( 100vh - 19rem - 8rem); } .modal-market-menu .app-bar-tab-overflow-content { background-color: var(--base_background); color: var(--labels_secondary-inactive-label-text-graphics); @@ -5981,7 +6070,11 @@ table th { font-size: 0.8rem; line-height: 1; font-weight: bold; } + .app_bar .opacity-1 { + opacity: 1 !important; } .app_bar .app-bar-account-menu { + transition: 0.9s; + opacity: 0; display: block; position: absolute; top: 36px; @@ -6013,7 +6106,8 @@ table th { .app_bar .app-bar-account-menu .app-bar-account-list-icon svg .tab-history-st, .app_bar .app-bar-account-menu .app-bar-account-list-icon svg .help-question, .app_bar .app-bar-account-menu .app-bar-account-list-icon svg .tab-signout, - .app_bar .app-bar-account-menu .app-bar-account-list-icon svg .tab-api0 { + .app_bar .app-bar-account-menu .app-bar-account-list-icon svg .tab-api0, + .app_bar .app-bar-account-menu .app-bar-account-list-icon svg .apps { fill: var(--labels_secondary-inactive-label-text-graphics); } .app_bar .app-bar-account-menu .app-bar-account-list-icon svg .account-active-1 { fill: var(--calculated_base_top-bar-navigation_text-inactive); } @@ -6120,6 +6214,9 @@ table th { cursor: pointer; font-size: 11px; } +.capitalize { + text-transform: capitalize; } + .home_app_bar { position: relative; width: 100%; @@ -6202,6 +6299,7 @@ table th { position: relative; max-width: calc(100vw - 40rem); } .app-menu-bar .app-menu-bar-content { + transition: 0.3s; color: var(--calculated_base_top-bar-navigation_text-inactive); cursor: pointer; margin: 0 15px; @@ -6214,6 +6312,8 @@ table th { .app-menu-bar .app-menu-bar-content-item { margin: auto; position: relative; } + .app-menu-bar .app-menu-bar-content-item:hover { + opacity: 0.5; } .app-menu-bar .app-menu-bar-icon { margin-right: 0.4rem; width: 1rem; } @@ -6825,7 +6925,8 @@ table th { .market-selector-dropdown.ant-dropdown-trigger { height: 100% !important; - width: 100% !important; } + width: 100% !important; + box-sizing: content-box; } .app-menu-bar-wrapper { flex-grow: 1; @@ -6877,6 +6978,7 @@ table th { font-size: 1.2rem !important; } } .check_title-container { + transition: 0.3s; display: flex; flex-direction: column; justify-content: center; @@ -7027,6 +7129,9 @@ table th { .header_title-wrapper .header_title-icon svg .verification-bank { fill: var(--labels_important-active-labels-text-graphics); } +.tab_item-deactive:hover { + opacity: 0.5; } + .custom-tab-wrapper .tab_item { color: var(--labels_secondary-inactive-label-text-graphics); height: 11.5rem; @@ -7035,6 +7140,7 @@ table th { min-width: 10rem; } .custom-tab-wrapper .tab_item-active { + transition: 0.3s; border: 1px solid var(--calculated_important-border); color: var(--labels_important-active-labels-text-graphics) !important; font-weight: bold; } @@ -7611,6 +7717,13 @@ table th { cursor: not-allowed; color: var(--labels_secondary-inactive-label-text-graphics); } +.dropdown-option-open { + margin: 0px !important; } + .dropdown-option-open img { + height: 1rem; + margin-right: 0.25rem; + margin-bottom: 0.25rem; } + .disabled .field-children { color: var(--labels_secondary-inactive-label-text-graphics); } .disabled .field-children .dropdown-triangle:after { @@ -7706,6 +7819,17 @@ table th { .field-children .field-valid svg { width: 1.25rem; height: 1.25rem; } + .field-children .clear-field { + width: 1.25rem !important; + height: 1.25rem !important; + width: 1.25rem; + height: 1.25rem; + position: absolute; + right: 0px; + bottom: 0.5rem; } + .field-children .clear-field svg { + width: 1.25rem; + height: 1.25rem; } .input-box-field { width: 100%; @@ -7839,6 +7963,45 @@ table th { .layout-mobile .field_warning_wrapper { padding-bottom: 1rem; } +.mainContainer { + display: flex; + width: fit-content; + margin: auto; + position: relative; + justify-content: center; + align-items: center; } + .mainContainer input { + width: 30px; + height: 30px; + border-radius: 0.5rem; + border: 1px solid var(--calculated_secondary-border); + background: var(--base_background); + text-align: center; + font-size: large; } + .mainContainer .masterInput { + position: absolute; + width: 100%; + top: 8px; + opacity: 0 !important; } + .mainContainer .seperator { + width: 2rem; + border: 1px solid var(--labels_secondary-inactive-label-text-graphics); + background: var(--labels_secondary-inactive-label-text-graphics); } + +.active { + border: 1px solid var(--labels_secondary-inactive-label-text-graphics) !important; } + +.error { + border: 1px solid red !important; } + +.warning_text { + text-align: center; } + +.group { + padding: 1rem; } + .group input { + margin: 0rem 0.25rem; } + .input_icon { margin-right: 0.25rem; width: 1.2rem; } @@ -8105,6 +8268,9 @@ table th { .direction_rtl .trade_input-input-currency { left: 0; } +.size-slider .ant-slider * { + transition: 0.1s; } + .size-slider .ant-slider-with-marks { margin-bottom: 10px; } @@ -8276,14 +8442,14 @@ table th { right: 0 !important; min-width: 100vw; max-width: 100vw; - min-height: calc( 100vh - 4rem); - max-height: calc( 100vh - 4rem); + min-height: calc( 100vh - 4rem); + max-height: calc( 100vh - 4rem); border-radius: 0 !important; padding: 0 !important; } .layout-mobile .ReactModal__Content .dialog-mobile-content { padding: 2.5rem !important; - min-height: calc( 100vh - 8rem); - max-height: calc( 100vh - 8rem); + min-height: calc( 100vh - 8rem); + max-height: calc( 100vh - 8rem); display: flex; } .layout-mobile.LogoutModal .ReactModal__Content { @@ -8691,9 +8857,20 @@ table th { border-top: 1px solid var(--calculated_secondary-border); margin: 1rem 0; position: relative; } - .otp_form-title-wrapper .otp_form-title-text { - font-weight: bold; - font-size: 1.1rem; } + +.otp_form-info-text { + font-weight: bold; + font-size: 1.1rem; + width: 100%; + text-align: center !important; } + +.otp_form-subnote-text { + font-weight: 400; + font-size: 1.1rem; + opacity: 0.7; + width: 100%; + margin-top: 5rem; + text-align: center !important; } .otp_form-fields { margin-bottom: 1rem; } @@ -10251,8 +10428,9 @@ table th { height: 3.5rem; left: calc(50vw - 10rem); padding: 0.3rem 0.5rem !important; - position: absolute; - width: 20rem; + position: fixed; + min-width: 20rem; + max-width: 30rem; z-index: 9999; -webkit-box-shadow: 2px 2px 3px 2px rgba(0, 0, 0, 0.4); -moz-box-shadow: 2px 2px 3px 2px rgba(0, 0, 0, 0.4); @@ -10430,7 +10608,7 @@ table th { margin-left: 0.5rem; } .app_footer-container .footer-row-content .footer_separter .footer-txt { width: 23rem; - margin-left: 1.5rem; + margin-left: 2rem !important; margin-top: 0.5rem; } .app_footer-container .footer-row-content .footer_separter .footer-logo { background-size: contain; @@ -10729,6 +10907,7 @@ table th { width: 20px; } .app-side-bar .app-menu-bar-side_list { + transition: 0.3s; height: 60px; padding: 18px 17px; cursor: pointer; @@ -10755,6 +10934,7 @@ table th { .app-side-bar .list_active .tab-signout, .app-side-bar .list_active .tab-history-st, .app-side-bar .list_active .stake-page-icon, + .app-side-bar .list_active .apps, .app-side-bar .app-menu-bar-side_list:hover .tab-summary0, .app-side-bar .app-menu-bar-side_list:hover .tab-wallet0, .app-side-bar .app-menu-bar-side_list:hover .tab-security0, @@ -10764,7 +10944,8 @@ table th { .app-side-bar .app-menu-bar-side_list:hover .help-question, .app-side-bar .app-menu-bar-side_list:hover .tab-signout, .app-side-bar .app-menu-bar-side_list:hover .tab-history-st, - .app-side-bar .app-menu-bar-side_list:hover .stake-page-icon { + .app-side-bar .app-menu-bar-side_list:hover .stake-page-icon, + .app-side-bar .app-menu-bar-side_list:hover .apps { fill: var(--calculated_base_top-bar-navigation_text) !important; } .app-side-bar .list_active { @@ -10943,7 +11124,11 @@ body { color: var(--labels_important-active-labels-text-graphics); font-size: 1.1rem !important; font-family: "Open Sans" !important; - height: 100%; } + height: 100%; + transition: all 0.3s; } + +.half-opacity { + opacity: 0.5; } .direction_rtl.apply_rtl { direction: rtl; } @@ -10979,11 +11164,17 @@ body { left: 0; top: calc(50% - 0.75rem); } +.blockchain-search { + filter: brightness(0) invert(0.8); } + input, input:focus { outline: none; border: none; } +.onHoverOpacity:hover { + opacity: 0.5; } + input[type='number'] { -moz-appearance: textfield; appearance: textfield; } @@ -11053,7 +11244,10 @@ svg .incoming-btc-01, svg .incoming-coin-01, svg .coin-btc-5, svg .stake-page-icon, -svg .fiat-kyc { +svg .fiat-kyc, +svg .all-apps, +svg .my-apps, +svg .apps { fill: var(--labels_secondary-inactive-label-text-graphics); } svg .account-inactive { diff --git a/web/src/index.js b/web/src/index.js index 03d0b495f7..fcabd49b29 100644 --- a/web/src/index.js +++ b/web/src/index.js @@ -75,6 +75,12 @@ import { } from 'utils/plugin'; import { drawFavIcon } from 'helpers/vanilla'; import { setupManifest } from 'helpers/manifest'; +import { + hideBooting, + showBooting, + setLoadingImage, + setLoadingStyle, +} from 'helpers/boot'; consoleKitInfo(); consolePluginDevModeInfo(); @@ -191,16 +197,6 @@ const getConfigs = async () => { store.dispatch(setInjectedValues(injected_values)); store.dispatch(setInjectedHTML(injected_html)); - const { - data: { data: plugins = [] } = { data: [] }, - } = await requestPlugins(); - - const allPlugins = IS_PLUGIN_DEV_MODE ? await mergePlugins(plugins) : plugins; - - store.dispatch(setPlugins(allPlugins)); - store.dispatch(setWebViews(allPlugins)); - store.dispatch(setHelpdeskInfo(allPlugins)); - const appConfigs = merge({}, defaultConfig, remoteConfigs, { coin_icons, captcha, @@ -208,6 +204,27 @@ const getConfigs = async () => { defaults, }); + setLoadingStyle(appConfigs); + setLoadingImage(appConfigs); + + try { + const { + data: { data: plugins = [] } = { data: [] }, + } = await requestPlugins(); + + const allPlugins = IS_PLUGIN_DEV_MODE + ? await mergePlugins(plugins) + : plugins; + + store.dispatch(setPlugins(allPlugins)); + store.dispatch(setWebViews(allPlugins)); + store.dispatch(setHelpdeskInfo(allPlugins)); + } catch (err) { + console.error(err); + showBooting(); + throw err; + } + const { app: { plugins_injected_html }, } = store.getState(); @@ -235,7 +252,7 @@ const bootstrapApp = ( app: { remoteRoutes, plugins, - info: { name }, + constants: { api_name: name }, }, } = store.getState(); @@ -274,6 +291,7 @@ const initialize = async () => { injected_html, plugins_injected_html ); + hideBooting(); } catch (err) { console.error('Initialization failed!\n', err); setTimeout(initialize, 3000); diff --git a/web/src/index.scss b/web/src/index.scss index 441253dea7..4a40e35def 100644 --- a/web/src/index.scss +++ b/web/src/index.scss @@ -50,11 +50,8 @@ body { // padding-top: 3rem; // } -.language_rtl { -} - -* { - transition: all 0.3s; +.half-opacity { + opacity: 0.5; } .direction_rtl { @@ -100,12 +97,20 @@ body { } } +.blockchain-search { + filter: brightness(0) invert(0.8); +} + input, input:focus { outline: none; border: none; } +.onHoverOpacity:hover { + opacity: 0.5; +} + input[type='number'] { -moz-appearance: textfield; appearance: textfield; @@ -190,7 +195,10 @@ svg { .incoming-coin-01, .coin-btc-5, .stake-page-icon, - .fiat-kyc { + .fiat-kyc, + .all-apps, + .my-apps, + .apps { fill: $colors-black; } diff --git a/web/src/reducers/appReducer.js b/web/src/reducers/appReducer.js index 37f18fdb38..42b9614bd8 100644 --- a/web/src/reducers/appReducer.js +++ b/web/src/reducers/appReducer.js @@ -494,10 +494,14 @@ const reducer = (state = INITIAL_STATE, { type, payload = {} }) => { is_verification_tab, is_wallet, is_ultimate_fiat, + is_app, type, currency, } = meta; - if (is_page) { + + if (is_app) { + target = generateDynamicTarget(name, 'app', type); + } else if (is_page) { target = generateDynamicTarget(name, 'page'); } else if (is_verification_tab && type) { target = generateDynamicTarget(name, 'verification', type); diff --git a/web/src/reducers/userReducer.js b/web/src/reducers/userReducer.js index dd88c6e033..87c262f959 100644 --- a/web/src/reducers/userReducer.js +++ b/web/src/reducers/userReducer.js @@ -116,6 +116,7 @@ const INITIAL_STATE = { order_portfolio_percentage: 80, popup_warning: true, }, + apps: [], }, addressRequest: INITIAL_ADDRESS_OBJECT, limits: INITIAL_LIMIT_OBJECT, diff --git a/web/src/routes.js b/web/src/routes.js index ace566c1e8..509c4c1f74 100644 --- a/web/src/routes.js +++ b/web/src/routes.js @@ -28,6 +28,8 @@ import { AddTradeTabs, Stake, StakeDetails, + Apps, + AppDetails, // ADMIN User, AppWrapper as AdminContainer, @@ -56,6 +58,7 @@ import { Resources, Pairs, Fiatmarkets, + AdminApps, } from './containers'; import chat from './containers/Admin/Chat'; @@ -348,6 +351,13 @@ export const generateRoutes = (routes = []) => { component={Account} onEnter={requireAuth} /> + <Route path="apps" name="Apps" component={Apps} onEnter={requireAuth} /> + <Route + path="apps/details/:app" + name="AppDetails" + component={AppDetails} + onEnter={requireAuth} + /> <Route path="summary" name="Summary" @@ -535,6 +545,11 @@ export const generateRoutes = (routes = []) => { name="Admin plugins" component={withAdminProps(Plugins, 'plugins')} /> + <Route + path="/admin/apps" + name="Admin apps" + component={withAdminProps(AdminApps, 'apps')} + /> {/* <Route path="/admin/plugins/:services" name="Admin plugins" diff --git a/web/src/utils/currency.js b/web/src/utils/currency.js index c96b9dd90d..179a2bd42f 100644 --- a/web/src/utils/currency.js +++ b/web/src/utils/currency.js @@ -4,6 +4,7 @@ import store from 'store'; import STRINGS from '../config/localizedStrings'; import { BASE_CURRENCY, DEFAULT_COIN_DATA } from '../config/constants'; import { findPath, convertPathToPairNames } from './data'; +import { isNaN } from 'lodash'; export const BTC_FORMAT = '0,0.[0000]'; export const ETH_FORMAT = '0,0.[0000]'; @@ -31,7 +32,7 @@ export const AVERAGE_FORMAT = '3a'; // }; export const roundNumber = (number = 0, decimals = 4) => { - if (number === 0) { + if (number === 0 || number === Infinity || isNaN(number)) { return 0; } else if (decimals > 0) { const multipliedNumber = math.multiply( @@ -68,7 +69,11 @@ export const getFormat = (min = 0, fullFormat) => { export const formatToCurrency = (amount = 0, min = 0, fullFormat = false) => { let formatObj = getFormat(min, fullFormat); - return numbro(roundNumber(amount, formatObj.digit)).format(formatObj.format); + let _amount = amount; + if (min >= 1) { + _amount = math.subtract(amount, math.mod(amount, min)); + } + return numbro(roundNumber(_amount, formatObj.digit)).format(formatObj.format); }; export const formatToSimple = (amount = 0, min = 0, fullFormat = false) => { diff --git a/web/src/utils/icon.js b/web/src/utils/icon.js index 928fbd39f2..b080ff8487 100644 --- a/web/src/utils/icon.js +++ b/web/src/utils/icon.js @@ -2,7 +2,7 @@ import defaultIcons from 'config/icons'; import merge from 'lodash.merge'; import { generateGlobalId } from 'utils/id'; -const defaultIconsKey = 'dark'; +export const defaultIconsKey = 'dark'; export const generateCoinIconId = (symbol) => `${symbol.toUpperCase()}_ICON`; diff --git a/web/src/utils/id.js b/web/src/utils/id.js index e25c4c3b79..29f0bbba7a 100644 --- a/web/src/utils/id.js +++ b/web/src/utils/id.js @@ -10,6 +10,8 @@ export const generateDynamicTarget = ( const name = pluginName.toUpperCase(); const sub = subType.toUpperCase(); switch (type) { + case 'app': + return `APPLICATION__${name}__${sub}`; case 'verification': return `REMOTE_VERIFICATION_TAB__${name}__${sub}`; case 'page': diff --git a/web/src/utils/reducer.js b/web/src/utils/reducer.js index 410bca8055..d7a2391298 100644 --- a/web/src/utils/reducer.js +++ b/web/src/utils/reducer.js @@ -1,4 +1,5 @@ import { generateCoinIconId } from 'utils/icon'; +import { DEFAULT_COIN_DATA } from 'config/constants'; export const modifyCoinsData = (coins) => { Object.entries(coins).forEach(([key, data]) => { @@ -13,8 +14,9 @@ export const modifyCoinsData = (coins) => { export const modifyPairsData = (pairs, coins) => { Object.entries(pairs).forEach(([key, data]) => { const { pair_base, pair_2 } = data; - const { display_name: pair_base_display, icon_id } = coins[pair_base]; - const { display_name: pair_2_display } = coins[pair_2]; + const { display_name: pair_base_display, icon_id } = + coins[pair_base] || DEFAULT_COIN_DATA; + const { display_name: pair_2_display } = coins[pair_2] || DEFAULT_COIN_DATA; const display_name = `${pair_base_display}/${pair_2_display}`; data.pair_base_display = pair_base_display; diff --git a/web/src/utils/utils.js b/web/src/utils/utils.js index d662a57c43..8fe84658f2 100644 --- a/web/src/utils/utils.js +++ b/web/src/utils/utils.js @@ -104,6 +104,9 @@ export const constructSettings = (state = {}, settings) => { if (settings.language) { settingsData.language = settings.language; } + if (settings.app) { + settingsData.apps = settings.app; + } // ToDo: need to these code after end point update. if (